有时需要获取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("/",""));
}
}
}
}
}
如果您觉得我的文章给了您帮助,请为我买一杯饮料吧!我将非常感激并坚持为大家提供更多帮助!
![](https://i-blog.csdnimg.cn/blog_migrate/f30eca065cc4cea8d7d097d6cc8c5cbd.jpeg)