欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

获取spring mvc映射的所有请求路径

程序员文章站 2022-03-18 12:56:52
...

      有时需要获取spring mvc映射的所有请求路径,比如在权限控制的功能模块中,而要配置某个资源与角色的对应关系,那么如果可以自动获取系统中所有的请求路径,那么可以在配置时方便许多。

 

第一步、获取指定包名下所有带@Controller注解的类。实现类代码如下

package com.ternnetwork.baseframework.util;

import java.io.IOException;  
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashSet;  
import java.util.LinkedList;  
import java.util.List;  
import java.util.Set;  
  
import org.apache.commons.logging.Log;  
import org.apache.commons.logging.LogFactory;  
import org.springframework.core.io.Resource;  
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;  
import org.springframework.core.io.support.ResourcePatternResolver;  
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;  
import org.springframework.core.type.classreading.MetadataReader;  
import org.springframework.core.type.classreading.MetadataReaderFactory;  
import org.springframework.core.type.filter.AnnotationTypeFilter;  
import org.springframework.core.type.filter.TypeFilter;  
import org.springframework.util.ClassUtils;  
  
  
public class PackageClassesScaner {  
      
    protected final Log logger = LogFactory.getLog(getClass());  
      
    private static final String RESOURCE_PATTERN = "/**/*.class";  
      
    private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();  
      
    private List<String> packagesList= new LinkedList<String>();  
      
    private List<TypeFilter> typeFilters = new LinkedList<TypeFilter>();  
      
    private Set<Class<?>> classSet= new HashSet<Class<?>>();  
      
    /** 
     * 构造函数 
     * @param packagesToScan 指定哪些包需要被扫描,支持多个包"package.a,package.b"并对每个包都会递归搜索 
     * @param annotationFilter 指定扫描包中含有特定注解标记的bean,支持多个注解 
     */  
    public PackageClassesScaner(String[] packagesToScan, Class<? extends Annotation>... annotationFilter){  
        if (packagesToScan != null) {  
            for (String packagePath : packagesToScan) {  
                this.packagesList.add(packagePath);  
            }  
        }  
        if (annotationFilter != null){  
            for (Class<? extends Annotation> annotation : annotationFilter) {  
                typeFilters.add(new AnnotationTypeFilter(annotation, false));  
            }  
        }  
    }  
      
    /** 
     * 将符合条件的Bean以Class集合的形式返回 
     * @return 
     * @throws IOException 
     * @throws ClassNotFoundException 
     */  
    public Set<Class<?>> getClassSet() throws IOException, ClassNotFoundException {  
        this.classSet.clear();  
        if (!this.packagesList.isEmpty()) {  
                for (String pkg : this.packagesList) {  
                    String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +  
                            ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN;  
                    Resource[] resources = this.resourcePatternResolver.getResources(pattern);  
                    MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver);  
                    for (Resource resource : resources) {  
                        if (resource.isReadable()) {  
                            MetadataReader reader = readerFactory.getMetadataReader(resource);  
                            String className = reader.getClassMetadata().getClassName();  
                            if (matchesEntityTypeFilter(reader, readerFactory)) {  
                                this.classSet.add(Class.forName(className));  
                            }  
                        }  
                    }  
                }  
        }  
        //输出日志  
        if (logger.isInfoEnabled()){  
            for (Class<?> clazz : this.classSet) {  
                logger.info(String.format("Found class:%s", clazz.getName()));  
            }  
        }  
        return this.classSet;  
    }  
      
      
  
    /** 
     * 检查当前扫描到的Bean含有任何一个指定的注解标记 
     * @param reader 
     * @param readerFactory 
     * @return 
     * @throws IOException 
     */  
    private boolean matchesEntityTypeFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException {  
        if (!this.typeFilters.isEmpty()) {  
            for (TypeFilter filter : this.typeFilters) {  
                if (filter.match(reader, readerFactory)) {  
                    return true;  
                }  
            }  
        }  
        return false;  
    }  
    
    public List<String> getClassesNameList(){
    	 List<String> retVal=new ArrayList<String>();
	    
		try {
			Set<Class<?>> set= getClassSet();
			for(Class cls:set){
				retVal.add(cls.getName());
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
			return retVal;
			
    }
}

 

 

第二步、获取第一步得到所有类中带有@RequestMapping注解的path属性值并组装完成的请求路径

 

package com.ternnetwork.baseframework.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

public class MvcRequestMappingUtil {
	
	
	public static void main(String[] ags){
		//demo  填写你需要的包名
		String[] packagesToScan={"com.ternnetwork"};
		List<String> mvcRequestMappingList=MvcRequestMappingUtil.getMvcRequestMappingList(packagesToScan);
	}
	
	public static List<String> getMvcRequestMappingList(String[] packagesToScan){
		PackageClassesScaner packageClassesScaner=new PackageClassesScaner(packagesToScan,Controller.class);
		return getMvcRequestMappingList(packageClassesScaner.getClassesNameList());
	} 
	
	
	public static List<String> getMvcRequestMappingList(List<String> classNameList){
		
		List<String> retVal=new ArrayList<String>();
		for(String className:classNameList){
			getMvcRequestMappingListByClass(retVal, className);
		}
		return retVal;
		
	}


	private static void getMvcRequestMappingListByClass(List<String> retVal, String className) {
		try {
			
			Class<?> cls=Class.forName(className);
		
			Annotation[] classAnnotations=cls.getAnnotations();//得到类级别的所有注解

			int classRequestMappingCount=0;//类级别的RequestMapping统计
			
			for(Annotation classAnnotation:classAnnotations){
				
			    if(classAnnotation instanceof RequestMapping){
			    	
			    	classRequestMappingCount=classRequestMappingCount+1;
			    	
			    	Method annotationMethod = classAnnotation.getClass().getDeclaredMethod("value", null); 
			    	
		            String[] annotationValues = (String[])annotationMethod.invoke(classAnnotation, null);
		            
		            for (String classRequestMappingPath : annotationValues) {
		            	getMvcRequestMappingListByMethod(retVal, cls, classRequestMappingPath);  
		            }  
			    	
			    }
			}
			
		    if(classRequestMappingCount==0){//如果没有类级别的RequestMapping
		    	getMvcRequestMappingListByMethod(retVal, cls,""); 
		    }
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}


	private static void getMvcRequestMappingListByMethod(List<String> retVal, Class<?> cls, String classRequestMappingPath)throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
		Method[] methods =cls.getDeclaredMethods();
		for (Method method : methods) {  
		    if (method.isAnnotationPresent(RequestMapping.class)) {  
		        Annotation methodAnnotation = method.getAnnotation(RequestMapping.class);  
		        Method   methodAnnotationMethod=methodAnnotation.getClass().getDeclaredMethod("value", null);  
		        String[] values=(String[]) methodAnnotationMethod.invoke(methodAnnotation, null);  
		        for (String methodRequestMappingPath : values) {  
		        	methodRequestMappingPath=classRequestMappingPath.concat(methodRequestMappingPath).replace("*", "").replace("//", "/");
		        	retVal.add(methodRequestMappingPath.replaceFirst("/",""));
		        }  
		    }  
		}
	}
	

}

 

 

 

如果您觉得我的文章给了您帮助,请为我买一杯饮料吧!我将非常感激并坚持为大家提供更多帮助!
获取spring mvc映射的所有请求路径
            
    
    博客分类: 算法框架 获取 spring mvc 所有请求路径