您的位置:首页 > 移动开发

用于获取spring所有支持的请求url,也就是{@link RequestMapping}的url

2016-03-17 17:32 417 查看
反正从网上没搜索出来,只好自己来。

用于获取spring所有支持的请求,也就是{@link RequestMapping}的url

想测试一下服务器是否所有接口均正确无误,需要对所有的接口都请求一次,但是无奈接口太多,一个个写是不可能的。文档虽然都有,但是也很分散。

寻找过程:

1. 启动服务器,观察日志,日志开启debug模式,可以看到。

[03-17 16:02:05,959] DEBUG [tartStop-1][] o.s.w.s.m.m.a.RequestMappingHandlerMapping[100] - Looking for request mappings in application context: Root WebApplicationContext: startup date [Thu Mar 17 16:02:03 CST 2016]; root of context hierarchy
[03-17 16:02:05,975] INFO  [tartStop-1][] o.s.w.s.m.m.a.RequestMappingHandlerMapping[181] - Mapped 这里是接口信息。必需隐去
[03-17 16:02:05,976] INFO  [tartStop-1][] o.s.w.s.m.m.a.RequestMappingHandlerMapping[181] - Mapped 这里是接口信息。必需隐去
[03-17 16:02:05,976] INFO  [tartStop-1][] o.s.w.s.m.m.a.RequestMappingHandlerMapping[181] - Mapped 这里是接口信息。必需隐去
[


那么在此类
RequestMappingHandlerMapping
中寻找该日志输出,包括寻找其父类。即可在类
AbstractHandlerMethodMapping
看到源码。

protected void initHandlerMethods() {
if (logger.isDebugEnabled()) {
logger.debug("Looking for request mappings in application context: " + getApplicationContext());
}

String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
getApplicationContext().getBeanNamesForType(Object.class));

for (String beanName : beanNames) {
if (isHandler(getApplicationContext().getType(beanName))){
detectHandlerMethods(beanName);//在这里
}
}
handlerMethodsInitialized(getHandlerMethods());
}


其中
detectHandlerMethods(beanName);
会调用
registerHandlerMethod(handler, method, mapping);
,registerHandlerMethod 函数是关键。

protected void registerHandlerMethod(Object handler, Method method, T mapping) {
HandlerMethod newHandlerMethod = createHandlerMethod(handler, method);
HandlerMethod oldHandlerMethod = handlerMethods.get(mapping);
if (oldHandlerMethod != null && !oldHandlerMethod.equals(newHandlerMethod)) {
throw new IllegalStateException("Ambiguous mapping found. Cannot map '" + newHandlerMethod.getBean()
+ "' bean method \n" + newHandlerMethod + "\nto " + mapping + ": There is already '"
+ oldHandlerMethod.getBean() + "' bean method\n" + oldHandlerMethod + " mapped.");
}

this.handlerMethods.put(mapping, newHandlerMethod);//这就是存储的变量,url映射到处理函数
if (logger.isInfoEnabled()) {
logger.info("Mapped \"" + mapping + "\" onto " + newHandlerMethod);
}

Set<String> patterns = getMappingPathPatterns(mapping);
for (String pattern : patterns) {
if (!getPathMatcher().isPattern(pattern)) {
this.urlMap.add(pattern, mapping);//这就是存储的变量,url字符串到urlMapping对象的
}
}
}


可以看到,它就存储在
handlerMethods
变量中,而且这个变量提供了get方法,所以,spring是提供了获取所有url的接口的。但是urlMap对象没有get函数,需要通过反射去获取。

3. 那么直接获取就可以了。

我们创建一个接口用于返回所有的接口信息。记得加上过滤器进行验证权限,或者只能在本机使用,避免被其他人获取到。

/**
* 用于获取spring所有支持的请求,也就是{@link RequestMapping}的url
*
* @return
*/
@RequestMapping("getAllService")
public Result getAllService() {
RequestMappingHandlerMapping requestMappingHandlerMapping = SpringIocUtil.getBean(RequestMappingHandlerMapping.class);
//        Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
try {
Field field = AbstractHandlerMethodMapping.class.getDeclaredField("urlMap");
MultiValueMap<String, RequestMappingInfo> urlMap = (MultiValueMap<String, RequestMappingInfo>) field.get(requestMappingHandlerMapping);
return ResultUtils.result(urlMap);
} catch (Exception e) {
e.printStackTrace();
}
return ResultUtils.result(null);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: