spring mvc学习二

1 概述

  • MultipartResolver 位于HandlerMapping之前,用于文件上传的请求

  • HandlerInterceptor 将对处理流程进行拦截,拦截的位置有三处

  • HandleAdaptor 帮助我们使用其他类型的Handler

  • HandleExceptionResolver 用于处理Handler出现的异常情况

  • LocaleResolver 根据用户不同的locale显示不同的视图

  • ThemeResolver 用户可以选择不同的主题

1.2 文件上传与MultipartResolver

RFC增加了新的multipart/from-data编码方式来支持基于表单的文件上传。客户端浏览器将按照RFC所规定的格式,对表单内容进行编码,服务器则根据其格式对其进行解码,获得客户端表单提交的数据以及上传的文件。

public interface MultipartResolver {
   boolean isMultipart(HttpServletRequest var1);

   MultipartHttpServletRequest resolveMultipart(HttpServletRequest var1) throws MultipartException;

   void cleanupMultipart(MultipartHttpServletRequest var1);
}

当web请求到达DispatcherServlet并等待处理时,会首先从webapplicationContext中找到名称为multipartResolver的实例,并通过isMultipart方法检查当前web请求是否为multipart类型,是则调用resolveMultipart()返回MultipartHttpServletRequest用于后继流程使用

public interface MultipartHttpServletRequest extends HttpServletRequest, MultipartRequest {

	@Nullable
	HttpMethod getRequestMethod();

	HttpHeaders getRequestHeaders();

	@Nullable
	HttpHeaders getMultipartHeaders(String paramOrFileName);

}

MultipartHttpServlrtRequest的能力来自它的父接口MultipartRequest,可以通过其直接获取MultipartFile类所封装的上传后的文件。

无论怎样我们最后获取的的后世MultipartFile我们可以通过数据自动绑定进行自动设置。

1.3 Handler与HandlerAdaptor

任何用于web请求的处理对象称为Handler,controller是handler的一种特殊类型。HandlerMappping通过HandlerExecutionChain返回一个Object对象 为了判断到底使用的是什么类型的Handle,DispatcherServlet将职责转交给HandleAdaptor来解决用if eles硬编码形式的判断

public interface HandlerAdapter {
    boolean supports(Object var1);

    @Nullable
    ModelAndView handle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;

    long getLastModified(HttpServletRequest var1, Object var2);
}

DispatcherServlet从HandleMapping获得一个Handle之后将询问HandleAdaptor的supports()方法以便了解当前HandleAdaptor是否支持HandleMapping返回的Handle类型的调用,如果为true,DisPatcherServlet则调用HandleAdaptor的handle方法,方法执行后将返回ModelAndVIew,之后的工作就由ViewResolver接手了

1.4 框架拦截流程与HandleInterInteceptor

HandleMapping返回的用于处理具体web请求的Handler对象,是通过一个HandlerExecutionChain对象进行封装的。

HandleExecutionChain是一个数据载体,包含两方面数据,一个是用于处理web请求的Handler,另一个则是随同一起返回的HandleInterceptor,其可以在Handle执行前后对处理流程进行拦截

HandlerInterceptor接口


public interface HandlerInterceptor {


	default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		return true;
	}


	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable ModelAndView modelAndView) throws Exception {
	}

	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
			@Nullable Exception ex) throws Exception {
	}

}

定义了三个拦截方法,

  • preHandle 该拦截方法将在相应的HandleAdaptor调用具体的Handle处理web请求之前进行执行。boolean返回值表示是否继续进行流程处理。

  • postHandle 该拦截方法的执行时机为HandlerAdaptor调用具体的Handler 处理完web请求之后,在视图的解析和渲染之前,通过该方法获取Handler执行后的结果,即modelAndView,返回类型为void,不可以阻断后继处理流程

  • afterCompletion 在整个流程结束后,不管是否发生异常,afterCompletion的拦截方法将被执行。我们可以在这该阶段对其进行异常的处理或者是资源的清楚

HandlerInterceptor的发源地属于AbstractHandleMapiing,提供了setInterceptors方法进行注册Interceptor

public void setInterceptors(Object... interceptors) {
		this.interceptors.addAll(Arrays.asList(interceptors));
	}

HandlerInterceptor与Servlet Filter的区别

HandleInterceptor位于DispatcherServclet后面,拥有更细度的拦截点可以在Handler执行之前,Handler执行之后,以及整个DispatcherServlet进行必要的拦截

Filter位于DispatcherServlet之前,Filter序列在Servlet层面对DispatcherServlet进行拦截。

我们可以使用DelegatingFilterProxy,来实现对Filter需要在web.xml中配置的解耦,即DeleatingFilterProxy在web.xml中承担Filter的原始使命。而委派的对象可以位于ioc容器里面。

1.5 异常处理与HandleExceptionResolver

HandleExceptionResolver提供了框架内统一异常处理方式,对异常的处理范围限于Handler的查找与Handler的执行期间

如果Handler执行过程中没有任何异常,将以modelAndView的形式返回后继的视图和模型数据。,而出现异常情况则HandlerExceptionResolver将接手异常情况进行处理,完成后返回ModelAndView,其所包含的信息是错误信息页面和相关异常信息。

public interface HandlerExceptionResolver {

	ModelAndView resolveException(
			HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);

}

其定义了一个resolveException(..)方法,负责处理与相关Handler所关联的某种异常,并将处理结果用modelAndView进行返回. 使用Properties管理具体的异常类型与转向错误的页面之间的映射关系。

1.6 国际视图与localResolver

resolverViewName(viewName,locale)方法除了接受要解析的视图名作为参数,还接受一个locale类型对象,根据locale的不同返回不同的实例。 其可以通过Http的Accept-Language协议头解析,或者读取用户浏览器存储的cookie进行获取所对应的Locale值。通过localeResolverr接口定义各种可能的locale值获取/解析方式进行统一的策略。

public interface LocaleResolver {

	Locale resolveLocale(HttpServletRequest request);


	void setLocale(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable Locale locale);

}

resolveLocale负责根据当前Locale解析策略获取当前请求对应的Locale值,setLocale对当前策略默认取得的locale值进行变更。

  • AcceptHeaderLocaleResolver http的accept-language协议头随同web请求发送给服务器段进行处理

  • SessionLocaleResolver 将根据指定的键值从session中获取对应的locale

  • CookieLocaleResolver 读取客户端的指定cookie获取相应的locale值

首先会将通过获取的localeresolver实例,进行解析后获取的locale值,以localeContext的形式进行绑定到当前线程,然后viewResolver就可以使用该LocaleResolver所返回的locale进行视图查找了。最后进行清理,将恢复以localeContext的形式绑定到当前线程的locale信息。

locale的变更原理 使用cookieLcaleResolver LocaleChangeInterceptor根据一个请求参数获取要切换到locale信息,然后通过相应LocaleResolver实现类的setLocale方法,使用新获取的Locale信息替换掉所使用的LocaleResolver默认策略所返回的策略值

其实只要给拦截器,返回合适的locale就行

1.7 主题与ThemeResolver

ThemeSource负责管理各个主题的那些静态资源

public interface ThemeSource {
    @Nullable
    Theme getTheme(String var1);
}

themeSource可以根据指定的主题名称查找并返回对应丰富的theme实例,客户端可以使用theme实例中相应的资源来定制视图的显示。

ResourceBundleThemeSource允许我们以properties文件定义,每个主题所持有的各个资源。

为了获取并管理用户所选择的主题。spring mvc提供了ThemeResolver其主要工作是解析对应当前请求是什么

public interface ThemeResolver {

	String resolveThemeName(HttpServletRequest request);

	void setThemeName(HttpServletRequest request, @Nullable HttpServletResponse response, @Nullable String themeName);

}
end
  • 作者:王富贵(联系作者)
  • 发表时间:2021-08-17 12:10
  • 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 转载声明:如果是转载栈主转载的文章,请附上原文链接
  • 评论