一、springmvc核心组件详解
1.1、HandlerMapping处理器映射器
- 主要作用:给前端控制器返回一个HandlerExecutionChain 对象(包含一个Handler (后端控制器)对象、多个HandlerInterceptor 拦截器)对象。
1、BeanNameUrlHandlerMapping
<!—beanName Url映射器 -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
将后端处理器(控制器)bean的id或name作为请求的url;是springmvc处理器映射器的默认配置值。
2、SimpleUrlHandlerMapping
<!--注册自定义处理器-->
<bean id="indexController" name="/index.action" class="com.chuan.hello.controller.MyController"/>
<!--配置处理器映射器-->
<!--<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/index1.action">indexController</prop>
<prop key="/index2.action">indexController</prop>
</props>
</property>
<!-- order值越小,映射处理器优先级越高 -->
<property name="order" value="1"></property>
</bean>
SimpleUrlHandlerMapping处理器映射器可以定义多个url映射到一个后端控制器
order的值表示映射处理器的优先级,值越小处理器优先级越高;值不能为零和负数,如果为零或者负数则表示当前处理器没有设置order值,该处理器映射器的优先级最低。
1.2、HandlerAdapter处理器适配器
1、SimpleControllerHandlerAdapter简单控制器处理器适配器
配置如下:
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
如果使用此适配器,那么后端控制器都必须实现org.springframework.web.servlet.mvc.Controller接口
2、HttpRequestHandlerAdapterHTTP请求处理器适配器
配置如下:
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
controller实现如下:
publicclass MyHandler implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("msg", "HelloWorld!");
request.getRequestDispatcher("/WEB-INF/jsp/home.jsp").forward(request, response);
}
}
注意:
1)使用HttpRequestHandlerAdapterHTTP请求处理器适配器,则后端控制器必须实现org.springframework.web.HttpRequestHandler接口;
2)从代码可知此后端控制器不返回ModelAndView了,只能通过request和response进行相应的请求响应
1.3、controller后端控制器
1、AbstractController
- 最简单的控制器,一个类只能处理一个请求,实现抽象类中的handleRequestInternal方法
public class UserController extends AbstractController {
@Override
protected ModelAndView handleRequestInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","hello word!!!");
modelAndView.setViewName("home");
return modelAndView;
}
}
- AbstractController 实现了controller接口,是controller接口的子类
public abstract class AbstractController extends WebContentGenerator implements Controller {
private boolean synchronizeOnSession;
public AbstractController() {
this(true);
}
public AbstractController(boolean restrictDefaultSupportedMethods) {
super(restrictDefaultSupportedMethods);
this.synchronizeOnSession = false;
}
- 设置处理器的请求方式
<bean id="homeController" class="com.chuan.hello.controller.UserController">
<property name="supportedMethods" value="POST"/>
</bean>
这样设置以后,该处理器将不会处理get方式的请求。
2、MultiActionController
- 可以将多个请求处理方法放入一个控制器(controller类)中。
public class PeopleController extends MultiActionController {
public ModelAndView doFirst(HttpServletRequest request, HttpServletResponse response){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","hello doFirst!!!");
modelAndView.setViewName("home");
return modelAndView;
}
public ModelAndView doSecond(HttpServletRequest request, HttpServletResponse response){
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("msg","hello doSecond!!!");
modelAndView.setViewName("home");
return modelAndView;
}
}
- springmvc.xml配置
<!--注册自定义处理器-->
<bean id="indexController" class="com.chuan.hello.controller.MyController"/>
<bean id="homeController" class="com.chuan.hello.controller.UserController">
<property name="supportedMethods" value="POST"/>
</bean>
<bean id="peopleController" class="com.chuan.hello.controller.PeopleController"/>
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/index1.action" value="indexController"/>
<entry key="/index2.action" value="indexController"/>
<entry key="/home.action" value="homeController"/>
<entry key="/*.action" value="peopleController"/>
</map>
</property>
</bean>
-
测试结果
-
为什么通过访问MultiActionController 实现类中的 方法名+.action 的路径能够直接处理相应的请求
点开MultiActionController 的源码进行分析:
public class MultiActionController extends AbstractController implements LastModified {
public final void setMethodNameResolver(MethodNameResolver methodNameResolver) {
this.methodNameResolver = methodNameResolver;
}
public final MethodNameResolver getMethodNameResolver() {
return this.methodNameResolver;
}
MultiActionController 默认使用了MethodNameResolver ,方法名解析器的作用是决定URL到Controller.method()的映射,比如URI 为http://localhost:8080/hello/doSecond.action对应的就是PeopleController 类中的doSecond方法; springmvc 中默认的方法名解析器是InternalPathMethodNameResolver。
- PropertiesMethodNameResolver:根据请求URL匹配method
springmvc.xml中的配置
<bean id="peopleController" class="com.chuan.hello.controller.PeopleController">
<!--注册propertiesMethodNameResolver方法名解析器-->
<property name="methodNameResolver" ref="propertiesMethodNameResolver"/>
</bean>
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/index1.action" value="indexController"/>
<entry key="/index2.action" value="indexController"/>
<entry key="/home.action" value="homeController"/>
<entry key="/*.action" value="peopleController"/>
</map>
</property>
</bean>
<!--配置方法名解析器-->
<bean id="propertiesMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
<property name="mappings">
<props>
<prop key="/my_first.action" >doFirst</prop>
<prop key="/my_second.action" >doSecond</prop>
</props>
</property>
</bean>
测试结果:
- ParameterMethodNameResolver:根据请求参数匹配method
spring.xml:
<bean id="peopleController" class="com.chuan.hello.controller.PeopleController">
<!--注册parameterMethodNameResolver方法名解析器-->
<property name="methodNameResolver" ref="parameterMethodNameResolver"/>
</bean>
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/index1.action" value="indexController"/>
<entry key="/index2.action" value="indexController"/>
<entry key="/home.action" value="homeController"/>
<entry key="/*.action" value="peopleController"/>
</map>
</property>
</bean>
<!--配置方法名解析器-->
<bean id="parameterMethodNameResolver" class="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<!-- 指定参数key映射方法,即xxx?method=sb,执行Controller的sb() -->
<property name="paramName" value="method"/>
</bean>
paramName是设置方法请求URL的参数名,如下图,请求路径中参数method的值对应的就是controller中的doFirst方法
注意:paramName如果不设置,则其默认的value值为action,则下图的请求路径变为:http://localhost:8080/hello/dofirst.action?action=doFirst
测试结果:
1.4、视图解析器
- springmvc默认的视图解析器:InternalResourceViewResolver内部资源视图解析器;InternalResourceViewResolver用于将提供的URI解析为实际URI,允许映射网页与请求。
1、BeanNameViewResolver
- 定义:根据视图bean的名字解析当前的视图
- springmvc.xml配置:
<bean id="testController" class="com.chuan.hello.controller.TestController"/>
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/index1.action" value="indexController"/>
<entry key="/index2.action" value="indexController"/>
<entry key="/home.action" value="homeController"/>
<entry key="/*.action" value="peopleController"/>
<entry key="/test.action" value="testController"/>
</map>
</property>
</bean>
<!--配置内部资源视图-->
<bean id="home" class="org.springframework.web.servlet.view.JstlView">
<property name="url" value="/WEB-INF/jsp/home.jsp"/>
</bean>
<!--配置外部资源视图:天猫-->
<bean id="tmall" class="org.springframework.web.servlet.view.RedirectView">
<property name="url" value="http://jx.tmall.com/"/>
</bean>
<!--配置外部资源视图:京东-->
<bean id="jd" class="org.springframework.web.servlet.view.RedirectView">
<property name="url" value="www.jd.com"/>
</bean>
- TestController处理器
public class TestController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
return new ModelAndView("tmall");
}
}
- 测试 http://localhost:8080/hello/test.action
- 404找不到资源原因:
id名为tmall的视图属于外部路径资源,而springmvc默认的视图解析器InternalResourceViewResolver为内部资源视图解析器,无法解析外部资源的视图请求。 - 解决方案:在springmvc.xml配置中加入BeanNameViewResolver的配置
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
- 再次测试url:http://localhost:8080/hello/test.action
成功访问了天猫官网
2、XmlViewResolver: xml文件视图解析器
- 自定义一个myViews.xml文件,并将上述例子中的三个视图拷贝到此文件中
<!--配置内部资源视图-->
<bean id="home" class="org.springframework.web.servlet.view.JstlView">
<property name="url" value="/WEB-INF/jsp/home.jsp"/>
</bean>
<!--配置外部资源视图:天猫-->
<bean id="tmall" class="org.springframework.web.servlet.view.RedirectView">
<property name="url" value="http://jx.tmall.com/"/>
</bean>
<!--配置外部资源视图:京东-->
<bean id="jd" class="org.springframework.web.servlet.view.RedirectView">
<property name="url" value="www.jd.com"/>
</bean>
- springmvc.xml配置
<bean id="testController" class="com.chuan.hello.controller.TestController"/>
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/index1.action" value="indexController"/>
<entry key="/index2.action" value="indexController"/>
<entry key="/home.action" value="homeController"/>
<entry key="/*.action" value="peopleController"/>
<entry key="/test.action" value="testController"/>
</map>
</property>
</bean>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
<!--注册要解析的xml视图文件-->
<property name="location" value="classpath:myViews.xml"/>
</bean>
location:注册要解析的xml视图文件
- 测试
3、ResourceBundleViewResolver: 配置文件视图解析器
- 自定义views.properties
tmall.(class)=org.springframework.web.servlet.view.RedirectView
tmall.url=http://jx.tmall.com/
jd.(class)=org.springframework.web.servlet.view.RedirectView
jd.url=www.jd.com
home.(class)=org.springframework.web.servlet.view.JstlView
home.url=/WEB-INF/jsp/home.jsp
- springmvc 配置
<bean id="testController" class="com.chuan.hello.controller.TestController"/>
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/index1.action" value="indexController"/>
<entry key="/index2.action" value="indexController"/>
<entry key="/home.action" value="homeController"/>
<entry key="/*.action" value="peopleController"/>
<entry key="/test.action" value="testController"/>
</map>
</property>
</bean>
<!--配置视图解析器-->
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
</bean>
- 测试结果
4、视图解析器优先级
- 使用场景:多个视图解析器共存
- 自定义OrderController
public class OrderController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
return new ModelAndView("orderView");
}
}
- springmvc.xml配置文件
<bean id="orderController" class="com.chuan.hello.controller.OrderController"/>
<!--配置处理器映射器-->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="urlMap">
<map>
<entry key="/order.action" value="orderController"/>
</map>
</property>
</bean>
<!--配置外部资源视图:京东-->
<bean id="orderView" class="org.springframework.web.servlet.view.RedirectView">
<property name="url" value="www.jd.com"/>
</bean>
<!--配置视图解析器-->
<!--注册配置文件视图解析器:ResourceBundleViewResolver-->
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
</bean>
<!--注册xml文件视图解析器:XmlViewResolver-->
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
<!--注册要解析的xml视图文件-->
<property name="location" value="classpath:myViews.xml"/>
</bean>
<!--注册BeanNameViewResolver视图解析器-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
如上所示:BeanNameViewResolver对应的是京东的url地址
- myViews.xml配置
<!--配置内部资源视图-->
<bean id="orderView" class="org.springframework.web.servlet.view.JstlView">
<property name="url" value="/WEB-INF/jsp/home.jsp"/>
</bean>
如上所示:XmlViewResolver对应的是内部资源home.jsp的url地址
- views.properties配置
orderView.(class)=org.springframework.web.servlet.view.RedirectView
orderView.url=http://jx.tmall.com/
如上所示:ResourceBundleViewResolver对应的是内部资源天猫的url地址
-
测试: http://localhost:8080/hello/order.action
测试结果表明在不设置order的值得情况下,ResourceBundleViewResolver视图解析器的优先级别最高;
为什么ResourceBundleViewResolver的优先级最高?
因为在springmvc.xml文件中ResourceBundleViewResolver最先配置;
默认情况下在视图解析器的order值未设定时,视图解析器的优先级由springmvc配置文件中各个视图解析器的配置顺序决定。 -
-
给上述三个视图解析器设置order值
-
<!--注册配置文件视图解析器:ResourceBundleViewResolver-->
<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
<property name="order" value="5"/>
</bean>
<!--注册xml文件视图解析器:XmlViewResolver-->
<bean class="org.springframework.web.servlet.view.XmlViewResolver">
<!--注册要解析的xml视图文件-->
<property name="location" value="classpath:myViews.xml"/>
<property name="order" value="1"/>
</bean>
<!--注册BeanNameViewResolver视图解析器-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
<property name="order" value="3"/>
</bean>
- 再次测试: http://localhost:8080/hello/order.action
返回的是工程内部的视图home.jsp,即此时优先级最高的是XmlViewResolver。 - 总结:order的值表示映射处理器的优先级,值越小处理器优先级越高; 值不能为零和负数,如果为零或者负数则表示当前处理器没有设置order值,则该处理器映射器的优先级最低。
1.5、DispatcherServlet.properties配置文件
1、DispatcherServlet.properties源码
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
2、配置文件详解
DispatcherServlet.properties是springmvc默认加载的配置文件,里面声明了springmvc核心组件的默认值,
HandlerMapping处理器映射器的默认值为BeanNameUrlHandlerMapping和RequestMappingHandlerMapping;
视图解析器的默认值就是InternalResourceViewResolver;
处理器适配器的默认值是HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter。