ディレクトリ
序文
SpringMVCは主流のWeb MVCフレームワークの一つです。
一部の学生はそれに慣れていない場合は、そのエントリのブログを参照してください。http://www.cnblogs.com/fangjian0423/p/springMVC-introduction.html
私たちは、アドレスhttp経由でブラウザを使用:// IP:ポート/のcontextPath /パスへのアクセス、SpringMVCは、エンド・ユーザーに、この期間中に何が起こったのか、最後に、アクセス方法コントローラであるということですか。
読者が何が起こったのか、最後にこのプロセスを知っているので、本論文では、要求とコントローラの間のマッピングをどのように扱うかSpringMVCを分析します。
ソースコード解析
ソースコードを分析する前に、まずいくつかのことを見てください。
1.このプロセスは、重要なインタフェースとクラスです。
HandlerMethodカテゴリ:
Spring3.1のバージョンの後に導入。クラスメソッドは、他の多くの要素の値を返し、パラメータの注釈方法をカプセル化する方法です。
そのサブクラスは、2つの重要な特性WebDataBinderFactoryとHandlerMethodArgumentResolverCompositeを持ってInvocableHandlerMethod、明確に要求処理です。
InvocableHandlerMethodサブクラスServletInvocableHandlerMethodは、重要な特性HandlerMethodReturnValueHandlerCompositeを持って明確に処理される応答です。
各要求のためのこのクラスServletInvocableHandlerMethod HandlerAdapter処理は、それぞれ、(上述の特性をHandlerAdapterによって設定される)インスタンス化し、リクエストを処理するために戻ります。(インスタンス化ServletInvocableHandlerMethod重要な属性は、上記設定されRequestMappingHandlerAdapter源)
MethodParameterカテゴリ:
HandlerMethodクラス属性の型パラメータ、MethodParameter配列です。MethodParameter方法は、情報パラメータ特定のツール、位置パラメータ、タイプ、注釈、パラメータ名などを含むインデックス情報のパッケージです。
インスタンス化をHandlerMethod、コンストラクタは、この配列を初期化し、その後HandlerAdapterで要求を処理する初期化データの一部のみが、他の特性を改善する、適切なHandlerMethodArgumentResolverインタフェース処理に引き渡さ。
一例として、クラスにDeptController:
@Controller
@RequestMapping(value = "/dept")
public classDeptController{
@Autowired
private IDeptService deptService;
@RequestMapping("/update")
@ResponseBody
public String update(Dept dept) {
deptService.saveOrUpdate(dept);
return "success";
}
}
(ただ、データを初期化)
(処理後HandlerAdapterデータ)
RequestConditionインタフェース:
Spring3.1のバージョンの後に導入。要求条件は、のcompareTo、getMatchingCondition操作を組み合わせることができる、SpringMVCベースにマッピングされます。このインターフェイスは、キーのインターフェイス、適切なマップを見つけることができたのgetMatchingCondition方法と一致するようにマッピングされます。
RequestMappingInfoカテゴリ:
Spring3.1のバージョンの後に導入。これは、各種の要求のパッケージであるとクラスマッピング条件RequestConditionインタフェースを実装しています。
有各种RequestCondition实现类属性,patternsCondition,methodsCondition,paramsCondition,headersCondition,consumesCondition以及producesCondition,这个请求条件看属性名也了解,分别代表http请求的路径模式、方法、参数、头部等信息。
RequestMappingHandlerMapping类:
处理请求与HandlerMethod映射关系的一个类。
2.Web服务器启动的时候,SpringMVC到底做了什么。
先看AbstractHandlerMethodMapping的initHandlerMethods方法中。
我们进入createRequestMappingInfo方法看下是如何构造RequestMappingInfo对象的。
PatternsRequestCondition构造函数:
类对应的RequestMappingInfo存在的话,跟方法对应的RequestMappingInfo进行combine操作。
然后使用符合条件的method来注册各种HandlerMethod。
下面我们来看下各种RequestCondition接口的实现类的combine操作。
PatternsRequestCondition:
RequestMethodsRequestCondition:
方法的请求条件,用个set直接add即可。
其他相关的RequestConditon实现类读者可自行查看源码。
最终,RequestMappingHandlerMapping中两个比较重要的属性
private final Map<T, HandlerMethod> handlerMethods = new LinkedHashMap<T, HandlerMethod>();
private final MultiValueMap<String, T> urlMap = new LinkedMultiValueMap<String, T>();
T为RequestMappingInfo。
构造完成。
我们知道,SpringMVC的分发器DispatcherServlet会根据浏览器的请求地址获得HandlerExecutionChain。
这个过程我们看是如何实现的。
首先看HandlerMethod的获得(直接看关键代码了):
这里的比较器是使用RequestMappingInfo的compareTo方法(RequestCondition接口定义的)。
然后构造HandlerExecutionChain加上拦截器
实例
写了这么多,来点例子让我们验证一下吧。
@Controller
@RequestMapping(value = "/wildcard")
public classTestWildcardController{
@RequestMapping("/test/**")
@ResponseBody
public String test1(ModelAndView view) {
view.setViewName("/test/test");
view.addObject("attr", "TestWildcardController -> /test/**");
return view;
}
@RequestMapping("/test/*")
@ResponseBody
public String test2(ModelAndView view) {
view.setViewName("/test/test");
view.addObject("attr", "TestWildcardController -> /test*");
return view;
}
@RequestMapping("test?")
@ResponseBody
public String test3(ModelAndView view) {
view.setViewName("/test/test");
view.addObject("attr", "TestWildcardController -> test?");
return view;
}
@RequestMapping("test/*")
@ResponseBody
public String test4(ModelAndView view) {
view.setViewName("/test/test");
view.addObject("attr", "TestWildcardController -> test/*");
return view;
}
}
由于这里的每个pattern都带了*因此,都不会加入到urlMap中,但是handlerMethods还是有的。
当我们访问:http://localhost:8888/SpringMVCDemo/wildcard/test1的时候。
会先根据 "/wildcard/test1" 找urlMap对应的RequestMappingInfo集合,找不到的话取handlerMethods集合中所有的key集合(也就是RequestMappingInfo集合)。
然后进行匹配,匹配根据RequestCondition的getMatchingCondition方法。
最终匹配到2个RequestMappingInfo:
然后会使用比较器进行排序。
之前也分析过,比较器是有优先级的。
我们看到,RequestMappingInfo除了pattern,其他属性都是一样的。
我们看下PatternsRequestCondition比较的逻辑:
因此,/test*的通配符比/test?的多,因此,最终选择了/test?
直接比较优先于通配符。
@Controller
@RequestMapping(value = "/priority")
public classTestPriorityController{
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public String test1(ModelAndView view) {
view.setViewName("/test/test");
view.addObject("attr", "其他condition相同,带有method属性的优先级高");
return view;
}
@RequestMapping()
@ResponseBody
public String test2(ModelAndView view) {
view.setViewName("/test/test");
view.addObject("attr", "其他condition相同,不带method属性的优先级高");
return view;
}
}
这里例子,其他requestCondition都一样,只有RequestMethodCondition不一样。
看出,方法多的优先级越多。
至于其他的RequestCondition,大家自行查看源码吧。
资源文件映射
以上分析均是基于Controller方法的映射(RequestMappingHandlerMapping)。
SpringMVC中还有静态文件的映射,SimpleUrlHandlerMapping。
DispatcherServlet找对应的HandlerExecutionChain的时候会遍历属性handlerMappings,这个一个实现了HandlerMapping接口的集合。
由于我们在*-dispatcher.xml中加入了以下配置:
<mvc:resourceslocation="/static/"mapping="/static/**"/>
Spring解析配置文件会使用ResourcesBeanDefinitionParser进行解析的时候,会实例化出SimpleUrlHandlerMapping。
其中注册的HandlerMethod为ResourceHttpRequestHandler。
访问地址:http://localhost:8888/SpringMVCDemo/static/js/jquery-1.11.0.js
地址匹配到/static/**。
最终SimpleUrlHandlerMapping找到对应的Handler -> ResourceHttpRequestHandler。
ResourceHttpRequestHandler进行handleRequest的时候,直接输出资源文件的文本内容。
总结
大致上整理了一下SpringMVC对请求的处理,包括其中比较关键的类和接口,希望对读者有帮助。
让自己对SpringMVC有了更深入的认识,也为之后分析数据绑定,拦截器、HandlerAdapter等打下基础。
参考资料
http://jinnianshilongnian.iteye.com/blog/1684403
http://my.oschina.net/HeliosFly/blog/212329
---------------------
作者:format丶
来源:CNBLOGS
原文:https://www.cnblogs.com/fangjian0423/p/springMVC-request-mapping.html
版权声明:本文为作者原创文章,转载请附上博文链接!