SpringMVC三大组件源码分析
1.处理器映射器
其实就是RequestMappingHandlerMapping
我们通常采用注解的方式@RequestMapping()
或者XML配置的方式进行
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerM
apping"/>
路径映射是在服务器启动的时候就会初始化映射的路径,并把路径名为key放在名为registry的Map中了。
2.处理器适配器
处理器适配器就是采用适配器模式进行对不同情况进行处理,将各个类各司其职。
例如,在控制器的写法上不止一个
第一种:采用实现 Controller接口的办法实现控制器
public class ControllerDemo2 implements Controller {
public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {
ModelAndView mv = new ModelAndView();
mv.setViewName("success");
return mv;
}
}
在SpringMVC.xml中配置
<!-- 基于实现Controller接口配置控制器的方式-->
<bean id="simpleControllerHandlerAdapter " class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"> </bean>
<bean name="/demohello2" class="com.test.controller.ControllerDemo2"> </bean>
其实现类就是SimpleControllerHandlerAdapter
第二种:采用实现 HttpRequestHandler接口的办法实现控制器
public class ControllerDemo3 implements HttpRequestHandler {
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("/WEB-INF/pages/success.jsp").forward(request,response);
}
}
在SpringMVC.xml中配置
<!-- 基于实现HttpRequestHandle接口的配置控制器方式-->
<bean id=" httpRequestHandlerAdapter " class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"> </bean>
<bean name="/demohello3" class="com.test.controller.ControllerDemo3"></bean>
其实现类就是HttpRequestHandlerAdapter
第三种:这种就是我们平常开发中常用的@Controller注解构建控制器
@Controller
public class ControllerDemo1 {
@RequestMapping("/hello")
public String sayHello(){
System.out.println("Demo1控制器执行了。。。");
return "success";
}
}
在SpringMVC.xml中配置
<bean id="requestMappingHandlerAdapter"
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingH
andlerAdapter">
</bean>
可一般我们都会直接配置
<mvc:annotation-driven></mvc:annotation-driven>
其实现类就是RequestMappingHandlerAdapter
3.视图解析器
首先,我们得先了解一下 SpringMVC 中的视图。视图的作用是渲染模型数据,将模型里的数据以某种形式呈现给客户。为了实现视图模型和具体实现技术的解耦,Spring 在 org.springframework.web.servlet 包中定义了一个高度抽象的 View 接口。我们的视图是无状态的,所以他们不会有线程安全的问题。无状态是指对于每一个请求,都会创建一个 View
对象。
在 SpringMVC 中常用的视图类型:
分类 | 视图类型 | 说明 |
---|---|---|
URL 视图 | InternalResourceView | 将 JSP 或者其他资源封装成一个视图, 是InternaleResourceViewResolver默 认使用的视图类型 |
JstlView | 它是当我们在页面中使用了 JSTL 标签 库的国际化标签后,需要采用的类型。 | |
文档类视图 | AbstractPdfView | PDF 文档视图的抽象类 |
AbstarctXlsView | Excel 文档视图的抽象类,该类是 4.2 版本 之后才有的 。之前使用 的是 AbstractExcelView。 | |
XML 视图 | MappingJackson2XmlView | 将模型数据封装成 XML 格式数据。它是 从 4.1 版本之后才加入的。 |
接下来就是了解视图解析器的作用。View Resolver 负责将处理结果生成 View 视图,View Resolver 首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果,通过页面展示给用户。视图对象是由视图解析器负责实例化。
视图解析器的作用是将逻辑视图转为物理视图,所有的视图解析器都必须实现 ViewResolver 接口。
SpringMVC 为逻辑视图名的解析提供了不同的策略,可以在 Spring WEB 上下文中配置一种或多种解析策略,
并指定他们之间的先后顺序。每一种映射策略对应一个具体的视图解析器实现类。程序员可以选择一种视图解析器
或混用多种视图解析器。可以通过 order 属性指定解析器的优先顺序,order 越小优先级越高,SpringMVC 会按
视图解析器顺序的优先顺序对逻辑视图名进行解析,直到解析成功并返回视图对象,否则抛出 ServletException
异常。
不需要使用视图解析器的场景
在分析之前,我们先需要回顾下控制器方法的返回值,此处我们都是以注解@Controller 配置控制器为例。
控制器的方法返回值其实支持三种方式:
第一种:String 类型。借助视图解析器,可以在指定位置为我们找到指定扩展名的视图。视图可以是 JSP,HTML 或者其他的控制器方法上的 RequestMapping 映射地址。前往指定视图的方式,默认是请求转发,可以通过redirect:前缀控制其使用重定向。
第二种:void,即没有返回值。因为我们在控制器方法的参数中可以直接使用原始 SerlvetAPI 对象HttpServletRequest 和 HttpServletResponse 对象,所以无论是转发还是重定向都可以轻松实现,而无需使用返回值。
第三种:ModelAndView 类型。其实我们跟踪源码可以发现在 DispatcherServlet 中的 doDispatch 方法执行时,HandlerAdapter 的 handle 方法的返回值就是 ModelAndView,只有我们的控制器方法定义为 void时,才不会返回此类型。当返回值是 String 的时候也会创建 ModelAndView 并返回。
通过上面三种控制器方法返回值,我们可以再深入的剖析一下我们请求之后接收响应的方式,其实无外乎就三种。
第一种:请求转发
第二种:重定向
第三种:直接使用 Response 对象获取流对象输入。可以是字节流也可以是字符流。
接下来我们就分析,这三种方式的本质区别。
其中请求转发和重定向的区别相信大家已经很熟悉了。但是它们的共同点呢?就是都会引发页面的跳转。在我们的实际开发中,如果我们不需要页面跳转,即基于 ajax 的异步请求,用 json 数据交互时,即可不配置任何视图解析器。前后端交互是通过 json 数据的,利用@RequestBody 和@ResponseBody 实现数据到 java对象的绑定(当然还要借助 Jackson 开源框架)。