Spring MVC手动注册requestMapping
之前写过一个Api Mock的小工具,没有什么高大上的技术,比较值得一提的是手动注册requestMapping。一般情况下,controller都是提前写好的,例如:
/**
* 检查接口序号是否已经占用
* */
@RequestMapping(value = "/getApiInfoByIndex.do", method = RequestMethod.POST)
@ResponseBody
public IResult getApiInfoByIndex(String index) {
return new ResultBean<ApiBean>(requestMappingService.getApiInfoByIndex(index));
}
像这样写一个处理路由的方法,然后我们才能发起请求,然后被方法处理。而在Api Mock工具中,并不知道路由会是什么,这个是用户指定的,所以需要动态的去注册。
Spring MVC是如何注册requestMapping的呢?通过翻看源码,这一部分工作由RequestMappingHandlerMapping这个类完成。RequestMappingHandlerMapping的父类AbstractHandlerMethodMapping中,提供了注册和注销的两个方法:
public void registerMapping(T mapping, Object handler, Method method) {
this.mappingRegistry.register(mapping, handler, method);
}
public void unregisterMapping(T mapping) {
this.mappingRegistry.unregister(mapping);
}
mapping需要提供一个RequestMappingInfo类的实例,RequestMappingInfo其实就是@RequestMapping注解里面提供信息的一个包装类。按照我们一般的@RquestMapping的写法,我们只需要提供一个url和requestMethod就够了,而正好RequestMappingInfo提供的构造函数对很多参数都做了判空处理。因此对应着,我们只需要提供PatternsRequestCondition和RequestMehtodsRequestCondition两个参数即可,分别对应@RequestMapping里面的ur和rquestMethod。
public final class RequestMappingInfo implements RequestCondition<RequestMappingInfo> {
private final String name;
private final PatternsRequestCondition patternsCondition;
private final RequestMethodsRequestCondition methodsCondition;
private final ParamsRequestCondition paramsCondition;
private final HeadersRequestCondition headersCondition;
private final ConsumesRequestCondition consumesCondition;
private final ProducesRequestCondition producesCondition;
private final RequestConditionHolder customConditionHolder;
public RequestMappingInfo(String name, PatternsRequestCondition patterns, RequestMethodsRequestCondition methods, ParamsRequestCondition params, HeadersRequestCondition headers, ConsumesRequestCondition consumes, ProducesRequestCondition produces, RequestCondition<?> custom) {
this.name = StringUtils.hasText(name)?name:null;
this.patternsCondition = patterns != null?patterns:new PatternsRequestCondition(new String[0]);
this.methodsCondition = methods != null?methods:new RequestMethodsRequestCondition(new RequestMethod[0]);
this.paramsCondition = params != null?params:new ParamsRequestCondition(new String[0]);
this.headersCondition = headers != null?headers:new HeadersRequestCondition(new String[0]);
this.consumesCondition = consumes != null?consumes:new ConsumesRequestCondition(new String[0]);
this.producesCondition = produces != null?produces:new ProducesRequestCondition(new String[0]);
this.customConditionHolder = new RequestConditionHolder(custom);
}
hanlder表示处理该url的类的实例,从源码中可以看到,提供实例的beanName就可以了。mehtod就更简单了,就是实例中的哪个方法来处理这个url,我们可以通过反射获取到。
前面分析了一波,下面就是具体的操作方法了:
1、首先创建一个处理动态url的Controller和方法。
@Controller
@Slf4j
public class ApiController {
@ResponseBody
public String index1() {
ApiBean apiBean = Constants.requestMappings.get("1");
return getReturnMsg(apiBean.getMsg());
}
// 省略...
}
处理的方法index1中,我们并没有加上@RequestMapping注解,这个requestMapping我们将稍候进行注册。
2、进行注册
RequestMappingHandlerMapping requestMappingHandlerMapping = webApplicationContext.getBean(RequestMappingHandlerMapping.class);
Method targetMethod = ReflectionUtils.findMethod(ApiController.class, getHandlerMethodName(index)); // 找到处理该路由的方法
PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition(api);
RequestMethodsRequestCondition requestMethodsRequestCondition = new RequestMethodsRequestCondition(getRequestMethod(requestMethod));
RequestMappingInfo mapping_info = new RequestMappingInfo(patternsRequestCondition, requestMethodsRequestCondition, null, null, null, null, null);
requestMappingHandlerMapping.registerMapping(mapping_info, "apiController", targetMethod); // 注册映射处理
这就是注册的核心代码,提供handler,method,生成requestMappingInfo对象,然后进行注册。这个注册是立即生效的,不需要重启应用。但是要注意防止重复注册,spring mvc似乎并没有判断重复。
3、注销
RequestMappingHandlerMapping requestMappingHandlerMapping = webApplicationContext.getBean(RequestMappingHandlerMapping.class);
PatternsRequestCondition patternsRequestCondition = new PatternsRequestCondition(api);
RequestMethodsRequestCondition requestMethodsRequestCondition = new RequestMethodsRequestCondition(getRequestMethod(requestMethod));
RequestMappingInfo mapping_info = new RequestMappingInfo(patternsRequestCondition, requestMethodsRequestCondition, null, null, null, null, null);
requestMappingHandlerMapping.unregisterMapping(mapping_info); // 注销
注销比较简单,只需要提供requestMapingInfo对象即可。
运行效果:
1、注册api
2、请求注册的api
上一篇: 调用MySQL中数据库元数据的方法
推荐阅读
-
Spring MVC手动注册requestMapping
-
Spring Mvc中传递参数方法之url/requestMapping详解
-
Spring Mvc中传递参数方法之url/requestMapping详解
-
Spring MVC温故而知新系列教程之请求映射RequestMapping注解
-
Spring MVC温故而知新系列教程之请求映射RequestMapping注解
-
Spring MVC+mybatis实现注册登录功能
-
Spring MVC+mybatis实现注册登录功能
-
你知道@RequestMapping的name属性有什么用吗?【享学Spring MVC】
-
Spring mvc中@RequestMapping 6个基本用法小结 springmvc
-
Spring mvc中@RequestMapping 6个基本用法小结 springmvc