实例说明:该实例重写 RequestMappingHandlerMapping 类的部分方法,达到给指定包下的所有控制器(Controller/Handler)设置统一的请求前缀。 这里以在接口前加版本号为例:/uri —>> /v2/uri
自定义前缀控制器处理器
接口,可以实现不同前缀的控制器处理器
/*** @author zsy* @Date 2022/7/4 11:52*/public interface TypeMappingHandler {/*** 处理的控制器所处的包名** @return handler package*/String getPackageName();/*** 处理的控制器所处的包名数组** @return handler packages*/String[] getPackageNames();/*** 要添加的前缀** @return prefix*/String getPrefix();/*** 是否匹配** @param handlerType 控制器类型* @return 控制器类的包名与要处理的包名是否一致*/boolean isPattern(Class<?> handlerType);/*** 修改默认 RequestMappingInfo** @param original springmvc构造的RequestMapping信息* @return 添加完前缀的RequestMappingInfo(如果包名匹配)*/RequestMappingInfo combineRequestMappingInfo(RequestMappingInfo original);}
实现类
@Slf4j@Componentpublic class InternalTypeMappingHandler implements TypeMappingHandler {@Overridepublic String getPackageName() {return "com.tyros.v2.controller";}@Overridepublic String[] getPackageNames() {// 支持多包名return new String[0];}@Overridepublic String getPrefix() {return "v2";}@Overridepublic boolean isPattern(Class<?> handlerType) {boolean flag = false;if (ArrayUtil.isNotEmpty(getPackageNames()) && Objects.nonNull(handlerType)) {for (String packageName : getPackageNames()) {flag = handlerType.getPackage().getName().startsWith(packageName);if (flag) {break;}}} else if (Objects.nonNull(handlerType)) {flag = handlerType.getPackage().getName().startsWith(getPackageName());}return flag;}@Overridepublic RequestMappingInfo combineRequestMappingInfo(RequestMappingInfo original) {RequestMappingInfo target = RequestMappingInfo.paths(getPrefix()).build().combine(original);if (log.isInfoEnabled()) {log.info("Build RequestMapping Success, {} -->> {}", original, target);}return target;}}
实现 RequestMappingHandlerMapping
public class TypeControlRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
/**
* 类型控制器
*/
protected Set<TypeMappingHandler> typeMappingHandlers;
/**
* 当前是否拥有类型控制器
*/
protected boolean hasTypeHandler = false;
@Override
public void afterPropertiesSet() {
// 初始化类型控制器类型集合
initVersionHandlers();
super.afterPropertiesSet();
}
@Override
@Nullable
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
if (Objects.nonNull(info)) {
for (TypeMappingHandler typeMappingHandler : typeMappingHandlers) {
if (typeMappingHandler.isPattern(handlerType)) {
return typeMappingHandler.combineRequestMappingInfo(info);
}
}
}
return info;
}
/**
* 初始化版本控制器集合
*/
protected void initVersionHandlers() {
typeMappingHandlers = new HashSet<>(obtainApplicationContext().getBeansOfType(TypeMappingHandler.class).values());
hasTypeHandler = !CollectionUtils.isEmpty(typeMappingHandlers);
}
}
注册映射处理器
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class TypeControlWebMvcRegistrations implements WebMvcRegistrations {
@Override
public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
return new TypeControlRequestMappingHandlerMapping();
}
}
