Back

SpringMVC的运行流程及九大组件

运行流程

  • 用户发送请求至前置控制器DispatcherServlet
  • DispatcherServlet收到请求调用HandlerMapping处理器映射器。
  • 处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
  • DispatcherServlet通过HandlerAdapter处理器适配器调用处理器
  • 执行处理器/后端控制器Controller
  • Controller执行完成返回ModelAndView
  • HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet
  • DispatcherServlet将ModelAndView传给视图解析器ViewReslover
  • ViewReslover解析后返回具体View
  • DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)。
  • DispatcherServlet响应用户。

从上面可以看出,DispatcherServlet有接收请求,响应结果,转发等作用。有了DispatcherServlet之后,可以减少组件之间的耦合度。

九大组件

HandlerMapping

处理器映射器:根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet

HandlerAdapter

适配器。因为SpringMVC中的Handler可以是任意的形式,但是Servlet需要的处理方法的结构却是固定的,都是以request和response为参数的方法。HandlerAdapter的作用就是让固定的Servlet处理方法调用Handler(Controller)来进行处理。

有篇文章总结的很好:Handler是用来干活的工具;HandlerMapping用于根据需要干的活找到相应的工具;HandlerAdapter是使用工具干活的人。

HandlerExceptionResolver

异常处理:自定义异常处理类继承此类或其子类,实现resolveException方法。如下:

@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {
	...
	/**
	 * 针对请求处理异常
	 */
	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		boolean isHttpApi = isHttpApi(handler);
		HandleResult result = handleException(ex);
		if (isReturnReponseBody(handler) || isHttpApi) {
			if(isHttpApi){
				result =  apiHandleException(ex);
			}
			
			ModelAndView modelAndView = new ModelAndView();
			//处理异常
			response.setContentType("application/json;charset=UTF-8");
			byte[] bytes = JSON.toJSONBytes(Result.fail(result.getCode(), result.getMessage()), SerializerFeature.DisableCircularReferenceDetect, SerializerFeature.WriteMapNullValue);
			try {
				response.getOutputStream().write(bytes);
				response.getOutputStream().flush();
			} catch (IOException e) {
				log.error("打印错误信息出错!", e);
			}
			modelAndView.clear();
			return modelAndView;
		}else {
			Map<String, String> model = Maps.newHashMap();
			model.put("code", result.getCode());
			model.put("message", result.getMessage());
			return new ModelAndView("500", model);
		}
	}
	...
}

ViewResolver

视图解析器:当Controller将请求处理结果放入到ModelAndView中以后,DispatcherServlet会根据ModelAndView选择合适的视图进行渲染。ViewResolver接口有众多实现类,根据viewName创建合适类型的View实现。配置如下:

<bean class="org.Springframework.web.servlet.view.InternalResourceViewResolve">
	<property name="prefix" value="/WEB-INF/views/" />
	<property name="suffix" value=".jsp" />
</bean>

RequestToViewNameTranslator

当Controller处理器方法没有返回一个View对象或逻辑视图名称,并且在该方法中没有直接往response的输出流里面写数据的时候,Spring就会采用约定好的方式提供一个逻辑视图名称。可通过实现接口org.Springframework.web.servlet.RequestToViewNameTranslator接口的getViewName方法来实现。

LocaleResolver

国际化配置

  • Spring的国际化配置三种方式
    • 基于URL参数的配置:通过URL参数来控制国际化
      1. 页面: <a href="myTest.jsp?locale=zh_CN">简体中文</a>
      2. 配置文件:<bean id="localeResolver" class="org.Springframework.web.servlet.i18n.AcceptHeaderLocaleResolver"/>
    • 基于session的配置:通过检验用户会话中预置的属性来解析区域,最常用的是根据用户本次会话过程中的语言设定决定语言种类,如果该会话不存在,它会根据accept-language HTTP头部确定默认区域。配置<bean id="localeResolver" class="org.Springframework.web.servlet.i18n.SessionLocaleResolver"/>
    • 基于Cookie的国际化配置:用于通过浏览器的cookie设置取得Locale对象,这种策略在应用程序不支持会话或者状态必须保存在客户端时有用。<bean id="localeResolver" class="org.Springframework.web.servlet.i18n.CookieLocaleResolver"/>

ThemeResolver

解析主题。一个主题就是一组静态资源(比如样式表、图片等),它们可以影响应用程序的视觉效果。

  • SpringMVC中跟主题相关的类
    • ThemeResolver:主题解析器
    • ThemeSource:主题资源
    • Theme:主题接口
    • ThemeChangeInterceptor:根据用户请求来改变主题(需要在handlerMapping中配置拦截器<property name="interceptors"><list><ref local="themeChangeInterceptor" /></list></property>)
  • ThemeResolver子类
    • AbstractThemeResolver:SessionThemeResolver和FixedThemeResolver继承的抽象类
    • SessionThemeResolver:用户的主题保存在HTTP session中
    • CookieThemeResolver:用于实现用户所选的主题,以cookie的形式存放在客户端的机器上
    • FixedThemeResolver:用于选择一个固定的主题

MultipartResolver

MultipartResolver 用于处理文件上传,当收到请求时 DispatcherServlet 的 checkMultipart() 方法会调用 MultipartResolver 的 isMultipart() 方法判断请求中是否包含文件。如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest (继承了 HttpServletRequest) 对象中,最后传递给 Controller.

  • MultipartResolver子类
    • CommonsMultipartResolver:使用 commons Fileupload来处理 multipart请求,所以在使用时,必须要引入相应的jar包。而像SpringBoot是不支持CommonsMultipartResolver
    • StandardServletMultipartResolver:基于Servlet3.0来处理multipart请求的,所以不需要引用其他jar包,从Tomcat7.0.x的版本开始就支持 Servlet 3.0了
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus