一、架构图
场景:浏览器发起一个请求,比如list.do,请求会先进入web.xml中;web.xml中配置了一个前端控制器DispatcherServlet。list.do满足过滤条件,则会进入这个前端控制器。
前端控制器用来初始化springmvc容器。容器中有三大组件:处理器映射器、处理器适配器和视图解析器。
- 处理器映射器HandlerMapping:用来帮助我们找到相应的Controller;
- 处理器适配器HandlerAdapter:用来帮助我们找到Controller里面相应的方法;返回结果ModelAndView,这里的view是一个jsp,jsp是不能直接放到浏览器进行渲染的,所以需要视图解析器。
- 视图解析器ViewResolver:获取结果ModelAndView,渲染成静态页面html。
三大组件是默认配置的,不需要我们手动配置。在源码spring-webmvc-4.2.4.RELEASE-sources.jar中的DispatcherServlet.properties文件中可以看到,当然我们也可以在springmvc.xml中覆盖配置。
注意:还可以在处理器映射器中设置拦截器:HandlerInterceptor 拦截器(图一3、图二4)。在处理器映射中通过配置拦截器(包括处理器执行前、执行后、执行后进行拦截)将使功能更强大。
二、细说dispatcherServlet的三大核心组件
1、处理器映射器HandlerMapping
在源码spring-webmvc-4.2.4.RELEASE-sources.jar中的DispatcherServlet.properties可以看到:对于HandlerMapping的配置支持两种方式。
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
- org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping(传统开发方式,现在没人用了)
- org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping(看源码会发现是过时的注解开发方式,偶尔有人会使用)
- org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping(最新版本的注解开发方式,推荐)
传统开发方式的配置:<bean name="/list.do" class="com.ly.springmvc.controller.ItemsController"></bean>---废弃
注解开发方式的配置:包扫描: <context:component-scan base-package="com.ly.springmvc.controller"></context:component-scan>
最新注解开发方式的配置:<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>---太难记了,用注解驱动替代,废弃
以下是对应得部分源码:
2、处理器适配器HandlerAdapter
在源码spring-webmvc-4.2.4.RELEASE-sources.jar中的DispatcherServlet.properties可以看到:对于HandlerAdapter的配置支持三种方式。
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
- org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter(没人用)
- org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter(传统开发方式,可以使用,正式生产不会用)
SimpleControllerHandlerAdapter.java调用handleRequest(...)方法,对于我们写的第一个传统方式的ItemsController.java类
- 3. org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter(看源码会发现是:过时的注解开发方式,偶尔有人还在用)
- 4. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter(最新版本的注解开发方式,推荐)
最新注解开发方式的配置:<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>---太难记了,用注解驱动替代,废弃
3、注解驱动<mvc:annotation-driven/>
由于<!-- 配置注解开发方式最新版本的处理器映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"></bean>
<!-- 配置注解开发方式最新版本的处理器适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"></bean>这两行太难记了,所以产生了注解驱动。
======快捷键ctrl+shift+t查找源码。======AnnotationDrivenBeanDefinitionParser.java加载了RequestMappingHandlerMapping.java和RequestMappingHandlerAdapter.java类,所以你就知道为什么这一这句话就能替代上面两句进行优化了。
4、视图解析器ViewResolver
在源码spring-webmvc-4.2.4.RELEASE-sources.jar中的DispatcherServlet.properties可以看到:对于ViewResolver的配置。
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
找到对应的InternalResourceViewResolver.java,继承自父类UrlBasedViewResolver.java,参数prefix和suffix可以对程序进行优化。
![]()
视图解析器前缀和后缀的配置:同时删掉xxxController对跳转页面路径及文件修饰符。即:将modelAndView.setViewName("WEB-INF/jsp/itemList.jsp") --> modelAndView.setViewName("itemList");
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean>
配置视图解析器后,测试结果如下:添加修改了list.do,list2.do保持原样======结果,list.do可以访问,list2.do显示404,url重复了