spring 扫描指定包下的RequestMapping
1.自定义扫描包路径注解
1).@EnableScanRequestURI 定义扫描包路径注解
package com.wmang.scan.client.annotation;
import com.wmang.scan.client.config.ScanRequestUriConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author: wmang
* @date: 2020/3/11 11:34
* @description: log打印执行耗时时间
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import({ScanRequestUriConfiguration.class})
public @interface EnableScanRequestURI {
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
}
2).@IgnoreURI忽略指定url注解
package com.wmang.scan.client.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author: wmang
* @date: 2020/3/11 11:34
* @description: log打印执行耗时时间
*/
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreURI {
String value() default "";
}
2.扫描包实现逻辑
1). 定义配置类,加载注解.拦截注解定义包路径下的mapping
package com.wmang.scan.client.config;
import com.wmang.scan.client.annotation.EnableScanRequestURI;
import com.wmang.scan.client.annotation.IgnoreURI;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;
/**
* @author wmang
*/
@Slf4j
@Configuration
public class ScanRequestUriConfiguration implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware, InitializingBean {
public static final String SCAN_REQUEST_ANNOTATION_VALUE = "value";
public static final String SCAN_REQUEST_ANNOTATION_BASEPACKAGES = "basepackages";
private ResourceLoader resourceLoader;
private Environment environment;
@Autowired
private RequestMappingHandlerMapping mapping;
private static String[] basePackages;
private RequestUrlCache requestUrlCache = RequestUrlCache.getInstance();
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
this.registerRequestURI(metadata, registry);
}
private void registerRequestURI(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
Map<String, Object> defaultAttrs = metadata.getAnnotationAttributes(EnableScanRequestURI.class.getName(), true);
if(null != defaultAttrs && !defaultAttrs.isEmpty()){
basePackages = ((String[]) (defaultAttrs.containsKey(SCAN_REQUEST_ANNOTATION_VALUE) ? defaultAttrs.get(SCAN_REQUEST_ANNOTATION_VALUE) : defaultAttrs.get(SCAN_REQUEST_ANNOTATION_BASEPACKAGES)));
}
}
@Override
public void afterPropertiesSet() throws Exception {
if (null != basePackages && basePackages.length > 0) {
Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
for (RequestMappingInfo mappingInfo : map.keySet()) {
PatternsRequestCondition patternsRequestCondition = mappingInfo.getPatternsCondition();
String reqUrl = "";
for (String url : patternsRequestCondition.getPatterns()) {
reqUrl = url;
}
HandlerMethod handlerMethod = map.get(mappingInfo);
Method method = handlerMethod.getMethod();
String methodType = getMethodType(method);
Class classz = method.getDeclaringClass();
if (!conditionPackages(basePackages, classz)) {
continue;
}
IgnoreURI ignoreURI = method.getAnnotation(IgnoreURI.class);
if (null != ignoreURI) {
continue;
}
RequestUrlCache.RequestUrl requestUrl = new RequestUrlCache.RequestUrl();
requestUrl.setUrl(reqUrl);
requestUrl.setMethodType(methodType);
requestUrlCache.getRequestUrls().add(requestUrl);
requestUrlCache.getRequestMappingInfoMap().put(requestUrl, mappingInfo);
requestUrlCache.getMethodHashMap().put(mappingInfo, handlerMethod);
log.info("请求地址: {},方法类型:{},包名:{},类名:{},方法名称:{}", reqUrl, methodType, classz.getPackage(), classz.getName(), method.getName());
}
}
}
private String getMethodType(Method method) {
String methodType = HttpMethod.GET.name();
Annotation[] annotations = method.getDeclaredAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof PutMapping) {
methodType = HttpMethod.PUT.name();
break;
}
if (annotation instanceof PostMapping) {
methodType = HttpMethod.POST.name();
break;
}
if (annotation instanceof PatchMapping) {
methodType = HttpMethod.PATCH.name();
break;
}
if (annotation instanceof DeleteMapping) {
methodType = HttpMethod.DELETE.name();
break;
}
}
return methodType;
}
private boolean conditionPackages(String[] basePackages, Class classz) {
boolean flag = false;
String pkg = classz.getPackage().getName();
for (String basePackage : basePackages) {
flag = pkg.contains(basePackage);
if (flag) {
break;
}
}
return flag;
}
}
2).RequestUrlCache扫描出来的mapping缓存
package com.wmang.scan.client.config;
import lombok.Data;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author: wmang
* @date: 2020/3/17 13:23
* @description: requestMapping 缓存器
*/
@Data
public class RequestUrlCache {
private static RequestUrlCache requestUrlCache;
private Set<RequestUrl> requestUrls = new HashSet<>();
private Map<RequestUrl, RequestMappingInfo> requestMappingInfoMap = new HashMap<>();
private Map<RequestMappingInfo, HandlerMethod> methodHashMap = new HashMap<>();
protected RequestUrlCache() {
requestUrls = new HashSet<>();
requestMappingInfoMap = new HashMap<>();
methodHashMap = new HashMap<>();
}
public static RequestUrlCache getInstance() {
if (null == requestUrlCache) {
requestUrlCache = new RequestUrlCache();
}
return requestUrlCache;
}
@Data
public static class RequestUrl {
private String url;
private String methodType;
}
}
3.使用方法
直接在spring主方法上使用注解EnableScanRequestURI,然后指定扫描包即可
如果需要使用扫描出来的url,直接用缓存类RequestUrlCache获取即可.
@Slf4j
@EnableScheduling
@SpringBootApplication(scanBasePackages = {"com.wmang.scan.carrier", "com.wmang.scan.common"})
@EnableDiscoveryClient
@EnableScanRequestURI(basePackages = "com.wmang.scan.eureka")
public class CarrierServiceApplication {
public static void main(String[] args) {
SpringApplication.run(CarrierServiceApplication.class, args);
log.info("服务启动完成...");
}
}