乐趣区

关于java:10个知识点让你读懂spring-MVC容器

前言

随着 Spring Boot 逐渐全面笼罩到咱们的我的项目之中,咱们曾经根本忘却当年经典的 Servlet + Spring MVC 的组合,那让人相熟的 web.xml 配置。而本文,咱们想先抛开 Spring Boot 到一旁,回到从前,一起来看看 Servlet 是怎么和 Spring MVC 集成,怎么来初始化 Spring 容器的。

  • Spring MVC 概述
  • 注解驱动的控制器
  • 解决办法的数据绑定
  • 试图和视图解析器
  • 本地化
  • 文件上传
  • WebSocket
  • 动态资源解决
  • 拦截器
  • 异样解决

一、Spring MVC 的概述

MVC:Model + View + Controller(数据模型 + 视图 + 控制器)

三层架构

三层架构:Presentation tier + Application tier + Data tier(展现层 + 应用层 + 数据拜访层)

MVC 和三层架构的关系

MVC 和三层架构的关系,MVC 只存在三层架构的展现层。

M 理论是数据模型,是蕴含数据的对象。在 Spring MVC 里,有一个专门的类叫 Model,用来和 V 之间的数据交互、传值。
V 指的是视图界面,蕴含 JSP、freeMarker、Velocity、Thymeleaf、Tile 等。
C 就是控制器(Spring MVC 的注解 @Controller 的类)。

三层架构是整个利用的的架构,是由 Spring 框架负责管理的,个别我的项目构造中都由 Service 层、Dao 层,这两个反馈在应用层和数据拜访层。

Spring MVC 框架围绕 DispatcherServlet 这个外围开展,它负责截获申请并将其分派给相应的处理器解决。Spring MVC 框架包含注解驱动控制器、申请及响应的信息处理、视图解析、本地化解析、上传文件解析、异样解决以及表单标签绑定等内容。

体系结构

Spring MVC 是基于 Model 2 实现的技术框架。Spring MVC 通过一个 DispatcherServlet 接管所有申请,并将具体工作委托给其余组件进行解决。

Spring MVC 体系结构

  1. 客户端收回一个 HTTP 申请,Web 应用服务器接管到这个申请,如果匹配 DispatcherServlet 的申请映射门路(在 web.xml 中指定),Web 容器将该申请转交给 DispatcherServlet 解决。
  2. DispatcherServlet 接管到这个申请后,将依据申请的信息(包含 URL、HTTP 办法、申请报文头、申请参数、Cookie 等)及 HandlerMapping 的配置找到解决申请的处理器(Handler)。可将 HandlerMapping 看成路由控制器,将 Handler 看成指标主机。值得注意的是:Spring MVC 中并没有定义一个 Handler 接口,实际上任何一个 Object 都能够成为申请处理器。
  3. 当 DispatcherServlet 依据 HandlerMapping 失去对应以后申请的 Handler 后,通过 HandlerAdapter 对 Handler 进行封装,再以对立的适配器接口调用 Handler。HandlerAdapter 是 Spring MVC 的框架级接口,顾名思义 HandlerAdapter 是一个适配器,它用对立的接口对各种 Handler 办法进行调用。
  4. 处理器实现业务逻辑的解决后将运回一个 ModelAndView 给 DispatcherServlet,ModelAndView 蕴含了视图逻辑名和模型数据信息。
  5. ModelAndView 中蕴含的是“逻辑视图名”而非真正的视图对象,DispatcherServlet 借由 ViewResolver 实现逻辑视图名到实在视图对象的解析工作。
  6. 当失去实在的视图对象 View 后,DispatcherServlet 就应用这个 View 对象对 ModelAndView 中的模型数据进行视图渲染。
  7. 最终客户端失去的响应音讯,可能是一个一般的 HTML 页而,也可能是一个 XML 或 JSON 串,甚至是一张图片或一个 PDF 文档等不同的媒体模式。

《2020 最新 Java 根底精讲视频教程和学习路线!》

配置 DispatcherServlet

能够在 web.xml 中配置一个 Servlet,并通过指定其解决的 URL。

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0">

    <!-- (1)从类门路下加载 Spring 配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application-context.xml</param-value>
    </context-param>

    <!-- (2)负责启动 Spring 容器的监听器,它将援用 (1) 处的上下文参数取得 Spring 配置文件的地址 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- (3)配置 DispatcherServlet -->
    <servlet>
        <servlet-name>web</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    
    <!-- (4)指定解决的 URL 门路 -->
    <servlet-mapping>
        <servlet-name>web</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>
复制代码
  1. 在 (1) 处,通过 contextConfigLocation 参数指定业务层 Spring 容器的配置文件(多个配置文件用 , 宰割)。
  2. 在 (2) 处,ContextLoaderListener 是一个 ServletLoaderListener,它通过 contextConfigLocation 指定的 Spring 配置文件启动业务层的 Spring 容器。
  3. 在 (3) 处,配置了名为 web 的 DispatcherServlet,它默认加载 /WEB-INF/web-servlet.xml(-servlet.xml)的 Spring 配置文件,启动 Web 层的 Spring 容器。Web 层容器将作为业务层容器的子容器,Web 层容器能够拜访业务层容器的 Bean,而业务层容器拜访不了 Web 层容器的 Bean。
  4. 在 (4) 处,通过指定 DispatcherServlet 解决 /* 全副的 HTTP 申请。一个 web.xml 能够配置多个 DispatcherServlet,通过其对应的配置,让每个 DispatcherServlet 解决不同的申请。

DispatcherServlet 的配置参数

能够通过的属性指定配置参数:

  1.  namespace 参数:DispatcherServlet 对应的命名空间,默认是 WEB-INF/-servlet.xml。在显式配置该参数后,新的配置文件对应的门路是 WEB-INF/.xml,例如如果将 namespace 设置为 sample,则对应的 Spring 配置文件为 WEB-INFmple.xml。
  2. contextConfigLocation:如果 DispatcherServlet 上下文对应的 Spring 配置文件有多个,则能够应用该属性依照 Spring 资源门路的形式指定,如 classpath:sample1.xml,classpath:sample2.xml。
  3. publishContext:默认为 true。DispatcherServlet 依据该属性决定是否将 WebApplicationContext 公布到 ServletContext 的属性列表中,不便调用者可借由 ServletContext 找到 WebApplicationContext 实例,对应的属性名为 DispatcherServlet#getServletContextAttributeName()的返回值。
  4. publishEvents:默认为 true。当 DispatcherServlet 解决完一个申请后,是否须要向容器公布一个 ServletRequestHandleEvent 事件。

Spring 容器配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-4.0.xsd
       http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

    <context:component-scan base-package="com.ankeetc.web"/>
    <!-- 会主动注册 RequestMappingHandlerMapping 与 RequestMappingHandlerAdapter 两个 Bean,这是 SpringMVC 为 @Controllers 散发申请所必须的 -->
    <!-- 并提供了数据绑定反对、@NumberFormatannotation 反对、@DateTimeFormat 反对、@Valid 反对、读写 XML 的反对和读写 JSON 的反对等性能。-->
    <mvc:annotation-driven />

</beans>
复制代码

基于编程的配置

Spring 4.0 曾经全面反对 Servlet 3.0,能够应用编程的形式配置 Servlet 容器。在 Servlet 3.0 环境中,容器会在类门路中查找实现 javax.servlet.ServletContainerInitializer 接口的类,如果发现实现类,就会用它来配置 Servlet 容器。Spring 提供了这个接口的实现,名为 SpringServletContainerInitializer,这个类反过来又查找实现 WebApplicationInitializer 的类并将配置的工作交给它们来实现。Spring 还提供了一个 WebApplicationInitializer 根底实现类 AbstractAnnotationConfigDispatcherServletInitializer,使得它在注册 DispatcherServlet 时只须要简略地指定它的 Servlet 映射即可。

public class WebApplicationInitilalizer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {ServletRegistration.Dynamic registration = servletContext.addServlet("web", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}
复制代码

 DispatcherServlet 的外部逻辑

 protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);
        initLocaleResolver(context);
        initThemeResolver(context);
        initHandlerMappings(context);
        initHandlerAdapters(context);
        initHandlerExceptionResolvers(context);
        initRequestToViewNameTranslator(context);
        initViewResolvers(context);
        initFlashMapManager(context);
    }
复制代码

DispatcherServlet#initStrategies()办法将在 WebApplicationContext 初始化后执行,此时 Spring 上下文中的 Bean 曾经初始化结束,该办法通过反射查找并拆卸 Spring 容器中用户自定义的 Bean,如果找不到就拆卸默认的组件实例。

默认组件

在 DispatcherServlet.properties 配置文件里边,指定了 DispatcherServlet 所应用的默认组件。如果用户心愿采纳非默认的组件,只需在 Spring 配置文件中配置自定义的组件 Bean 即可。

# 本地化解析器
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.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,
    org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

# 处理器适配器
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.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,
    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.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
复制代码

DispatcherServlet 拆卸各型组件的逻辑

二、注解驱动的控制器

 @RequestMapping 映射申请

  1. 在 POJO 类上标注 @Controller,再通过 context:component-scan 扫描到该类,能够是 POJO 成为一个能解决 HTTP 申请的控制器。
  2. 在控制器的类定义和办法定义处都能够应用 @RequestMapping 映射对应的解决办法。
  3. @RequestMapping 岂但反对规范的 URL,还反对 Ant 格调和 {XXX} 占位符的 URL。
  4. @RequestMapping 和 value、method、params 及 headers 别离示意申请门路、申请办法、申请参数及报文头的映射条件。

获取申请内容

  1. 能够通过 @RequestParam、@RequestHeader、@PathVariable 获取 HTTP 申请信息。
  2. 能够应用 @CookieValue 让办法入参绑定某个 Cookie 值
  3. 能够应用 @MatrixVariable 注解将申请中的矩阵变量绑定到处理器的办法参数中。
  4. 能够应用命令 / 表单对象(就是一个 POJO)绑定申请参数值,Spring 会依照申请参数名和对象属性名匹配的形式,主动为该对象填充属性。
  5. 能够应用 Servlet API 的类作为解决办法的入参,如 HttpServletRequest、HttpServletResponse、HttpSession;如果应用 HttpServletResponse 返回相应,则解决办法返回着设置成 void 即可;在 org.springframework.web.context.request 定义了若干个可代理 Servlet 原生 API 类的接口,如 WebRequest 和 NativeWebRequest。
  6. 能够应用 java.io 中的 InputStream、Reader、OutputStream、Writer 作为办法的入参。
  7. 还能够应用 java.util.Locale、java.security.Principal 作为入参。

应用 HttpMessageConverter

HttpMessageConverter 接口能够将申请信息转换为一个对象(类型为 T),并将对象(类型为 T)绑定到申请办法的参数中或输入为响应信息。DispatcherServlet 默认曾经装置了 RequestMethodHandlerAdapter 作为 HandlerAdapter 组件的实现类,HttpMessageConverter 即由 RequestMethodHandlerAdapter 应用,将申请信息转换为对象,或将对象转换为响应信息。

HttpMessageConverter 的实现类

Spring 为 HttpMessageConverter 提供了泛滥的实现类:

实现类

实现类

默认的 HttpMessageConverter

RequestMappingHandlerAdapter 曾经默认拆卸了以下的 HttpMessageConverter:

  • StringHttpMessageConverter
  • ByteArrayHttpMessageConverter
  • SourceHttpMessageConverter
  • AllEncompassingFormHttpMessageConverter

拆卸其余类型的 HttpMessageConverter

如果须要拆卸其余类型的 HttpMessageConverter,能够在 Spring 的 Web 容器上下文中自行定义一个 RequestMappingHandlerAdapter,注册若干 HttpMessageConverter。如果在 Spring web 容器中显式定义了一个 RequestMappingHandlerAdapter,则 Spring MVC 将应用它 笼罩 默认的 RequestMappingHandlerAdapter。

应用 HttpMessageConverter

  1. 能够应用 @RequestBody、@ResponseBody 对解决办法进行标注
  2. 能够应用 HttpEntity、ResponseEntity 作为解决办法的入参或返回值

RestTemplate 是 Spring 的模板类,能够应用该类调用 Web 服务端的服务,它反对 Rest 格调的 URL。

论断
  1. 当控制器解决办法应用到 @RequestBody、@ResponseBody 或 HttpEntity、ResponseEntity 时,Spring MVC 才会应用注册的 HttpMessageConvertor 对申请、相应音讯进行解决。
  2. 当控制器解决办法应用到 @RequestBody、@ResponseBody 或 HttpEntity、ResponseEntity 时,Spring 首先依据申请头或响应的 Accept 属性抉择匹配的 HttpMessageConverter,进而依据参数类型或泛型类型的过滤失去匹配的 HttpMessageConverter,若找不到可用的 HttpMessageConverter 将报错。
  3. @RequestBody、@ResponseBody 不须要成对呈现。

解决 XML 和 JSON

Spring MVC 提供了几个解决 XML 和 JSON 格局的申请、响应音讯的 HttpMessageConverter:

  • MarshallingHttpMessageConverter:解决 XML
  • Jaxb2RootElementHttpMessageConverter:解决 XML,底层应用 JAXB
  • MappingJackson2HttpMessageConverter:解决 JSON 格局

只有在 Spring Web 容器中为 RequestMappingHandlerAdapter 拆卸好相应的 HttpMessageConverter,并在交互中通过申请的 Accept 指定 MIME 类型,Spring MVC 就能够是服务器段的解决办法和客户端通明的通过 XML 或 JSON 格局进行通信。

 <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/>
            </list>
        </property>
    </bean>
复制代码

应用 @RestController

@RestController 曾经标注了 @ResponseBody 和 @Controller,能够间接在控制器上标注该注解,就不必在每个 @RequestMapping 办法上增加 @ResponseBody 了。

AsyncRestTemplate

Spring 4.0 提供了 AsyncRestTemplate 用于以异步无阻塞的形式进行服务拜访。

public class WebApplicationInitilalizer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {ServletRegistration.Dynamic registration = servletContext.addServlet("web", new DispatcherServlet());
        registration.setLoadOnStartup(1);
        // 此处要设置为 true
        registration.setAsyncSupported(true);
        registration.addMapping("/");
    }
}

@RestController
public class AsyncController {@RequestMapping(value = "/async", method = RequestMethod.GET)
    public Callable<String> async() {System.out.println("hello!");
        return new Callable<String>() {
            @Override
            public String call() throws Exception {TimeUnit.SECONDS.sleep(5);
                return "ASYNC";
            }
        };
    }
}
public class Main {public static void main(String[] args) {AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate();

        ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.getForEntity("http://localhost:8080/async", String.class);

        System.out.println("return");
        future.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() {
            @Override
            public void onFailure(Throwable ex) {System.out.println("Failure");
            }

            @Override
            public void onSuccess(ResponseEntity<String> result) {System.out.println("Success");
            }
        });
    }
}
复制代码

解决模型数据

Spring MVC 提供了多种路径输入模型数据:

  1. ModelAndView:当解决办法返回值类型为 ModelAndView 时,办法体即可通过该对象增加模型数据;
  2. @ModelAttribute:在办法入参标注该注解后,入参的对象就会放到数据模型中;
  3. Map 和 Model:如果办法入参为 org.framework.ui.Model、org.framework.ui.ModelMap、java.util.Map,当解决办法返回时,Map 中的数据会主动增加到模型中;
  4. @SessionAttributes:将模型中的某个属性暂存到 HttpSession 中,以便多个申请之间能够共享这个属性。

三、解决办法的数据绑定

Spring 会依据申请办法签名的不同,将申请中的信息以肯定形式转换并绑定到申请办法的入参中,还会进行数据转换、数据格式化及数据校验等。

数据绑定流程

数据绑定

Spring MVC 通过反射对指标签名进行剖析,将申请音讯绑定到解决办法的入参中。数据绑定的核心部件是 DataBinder。Spring MVC 主框架将 ServletRequest 对象及解决办法的入参对象实例传递给 DataBinder,DataBinder 首先调用拆卸在 Spring Web 上下文中的 ConversionService 组件进行数据类型转换、数据格式化等工作,将 ServletRequest 中的音讯填充到入参对象中,而后调用 Validator 组件对己经绑定了申请音讯数据的入参对象进行数据合法性校验,最 终生成数据绑定后果 BindingResult 对象。BindingResult 蕴含了已实现数据绑定的入参 对象,还蕴含相应的校验谬误对象。Spring MVC 抽取 BindingResult 中的入参对象及校验谬误对象,将它们赋给解决办法的相应入参。

数据转换

类型转换模块位于 org.framework.core.convert 包中,同时因为历史起因,Spring 还反对 JDK 的 PropertyEditor。

ConversionService 简介

ConversionService 是 Spring 类型转换体系的外围接口,它定义了以下 4 个办法:

  • boolean canConvert(Class sourceType, Class targetType):判断是否能够将一个 Java 类转换为另一个 Java 类。
  • Boolean canConvert(TypeDescriptor sourceType, TypeDescriptor targetType):需转换的类将以成员变量的形式呈现在宿主类中。TypeDescriptor 岂但形容了需转换类的信息,还形容了从宿主类的上下文信息,如成员变量上的注解,成员变量是否以数组、汇合或 Map 的形式出现等。类型转换逻辑能够利用这些信息做出 各种灵便的管制。
  • T convert(Object source, Class targetType):将原类型对象转换为指标类型对象。
  • Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType):
    将对象从原类型对象转换为指标类型对象,此时往往会用到所在宿主类的高低 文信息。

第一个和第三个接口办法相似于 PmpertyEditor,它们不关注类型对象所在的上下文 信息,只简略地实现两个类型对象的转换,惟一的区别在于这两个办法反对任意两个类型的转换。而第二个和第四个接口办法会参考类型对象所在宿主类的上下文信息,并利用这些信息进行类型转换。

应用 ConversionService

能够利用 org.springframework.context.support.ConversionServiceFactoryBean 在 Spring 的 上下文中定义一个 ConversionService。Spring 将自动识别出上下文中的 ConversionService,并在 Bean 属性配置及 Spring MVC 解决办法入参绑定等场合应用它进行数据转换。该 FactoryBean 创立 ConversionService 内建了很多转换器,可实现大多数 Java 类型的转换工作。除了包含将 String 对象转换为各种根底类型的对象外,还包含 String、Number、Array、Collection、Map、Properties 及 Object 之间的转换器。可通过 ConversionServiceFactoryBean 的 converters 属性注册自定义的类型转换器:

 <bean class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <list>
                <bean class="com.ankeetc.MyConverter"/>
            </list>
        </property>
    </bean>
复制代码

Spring 反对的转换器

Spring 在 org.springframework.core.convert.converter 包中定义了 3 种类型的转换器接口,实现任意一个转换器接口都能够作为自定义转换器注册到 ConversionServiceFactoryBean 中。这 3 种类型的转换器接口别离为:

  • Converter<S, T>:将 S 类型的对象转换为 T 类型的对象
  • GenericConverter:依据源类对象及指标类对象所在的宿主类的上下文信息进行类型转换工作。该类还有一个子接口 ConditionalGenericConverter,它增加了一个接口办法依据源类型及指标类型所在宿主类的上下文信息决定是否要进行类型转换。
  • ConverterFactory:

ConversionServiceFactoryBean 的 converters 属性可承受 Converter、ConverterFactory、GenericConverter 或 ConditionalGenericConverter 接口的实现类,并把这些转换器的转换逻辑对立封装到一个 ConversionService 实例对象中(GenericConversionService)。Spring 在 Bean 属性配置及 Spring MVC 申请音讯绑定时将利用这个 ConversionService 实例实现类型转换工作。

在 Spring 中应用 @lnitBinder 和 WebBindingInitializer 拆卸自定义编辑器

Spring 也反对 JavaBeans 的 PropertyEditor。能够在控制器中应用 @InitBinder 增加自定义的编辑器,也能够通过 WebBindingInitializer 拆卸在全局范畴内应用的编辑器。

 @InitBinder
    public void initBinder(WebDataBinder binder) {binder.registerCustomEditor(User.class, new PropertyEditorSupport() {
            @Override
            public void setAsText(String text) throws IllegalArgumentException {User user = new User();
                user.setName(text);

                this.setValue(user);
            }
        });
    }
复制代码

如果心愿在全局范畴内应用,则可实现 WebBindingInitializer 接口并在该实现类中注册。

  1. 实现 WebBindingInitializer 接口并在 initBinder 接口办法中注册了自定义的编辑器。
  2. 在 Spring 上下文中通过 RequestMappingHandlerAdapter 拆卸自定义的 Initializer。

程序

对于同一个类型对象来说,如果既在 ConversionService 中拆卸了自定义转换器,又通过 WebBindinglnitializer 拆卸了自定义编辑器,同时还在控制器中通过 @InitBinder 装 配了自定义编辑器,那么 Spring MVC 将按以下优先程序查找对应类型的编辑器:

  1. 查问通过 @InitBinder 拆卸的自定义编辑器。
  2. 查问通过 ConversionService 拆卸的自定义转换器。
  3. 查问通过 WebBindingInitializer 拆卸的自定义编辑器。

数据格式化

Spring 的转换器并不提供输出及输入信息格式化的工作,个别须要转换的源类型数据(个别是字符串)都是具备肯定格局的,在不同的本地化环境中,同一类型的数据还会相应地出现不同的显示格局。Spring 引入了一个新的格式化框架,这个框架位于 org.springframework.format 类包中。

最重要的 Formatter 接口
注解驱动格式化 AnnotationFormatterFactory

为了让注解和格式化的属性类型关联起来,Spring 在 Formatter 所在的包中还提供了一个 AnnotationFormatterFactory 接口。

启用注解驱动格式化性能

对属性对象的输出 / 输入进行格式化,从实质上讲仍然属于“类型转换”的领域。Spring 就是基于对象转换框架植入“格式化”性能的。Spring 在格式化模块中定义了一个实现 ConversionService 接口的 FormattingConversionService 实现类,该实现类扩大了 GenericConversionService,因而它既具备类型转换性能,又具备格式化性能。
FormattingConversionService 也领有一个对应的 FormattingConversionServiceFactoryBean 工厂类,后者用于在 Spring 上下文中结构一个 FormattingConversionService。通过这个工厂类,既能够注册自定义的转换器,还能够注册自定义的注解驱动逻辑。因为 FormattingConversionServiceFactoryBean 在外部会主动注册 NumberFormatAnnotationFormatterFactory 和 JodaDateTimeFormatAnnotationFormatterFactory,因而拆卸了 FormattingConversionServiceFactoryBean 后,就能够在 Spring MVC 入参绑定及模型数据输入时应用注解驱动的格式化性能。
值得注意的是,mvc:annotation-driven/ 标签外部默认创立的 ConversionService 实例就是一个 FormattingConversionServiceFactoryBean。

数据校验

Spring 领有本人独立的数据校验框架,同时反对 JSR-303 规范的校验框架。Spring 的 DataBinder 在进行数据绑定时,可同时调用校验框架实现数据校验工作。在 Spring MVC 中,则可间接通过注解驱动的形式进行数据校验。
LocalValidatorFactoryBean 既实现了 Spring 的 Validator 接口,又实现了 JSR-303 的 Validator 接口。只有在 Spring 容器中定义了一个 LocalValidatorFactoryBean,即可将其注入须要数据校验的 Bean 中。值得注意的是,Spring 自身没有提供 JSR-303 的实现,所以必须将 JSR-303 的实现 者(如 Hibernate Validator)的 JAR 文件放到类门路下,Spring 将主动加载并拆卸好 JSR-303 的实现者。
mvc:annotation-driven/ 会默认拆卸一个 LocalValidatorFactoryBean,通过在解决办法的入参上标注 @Valid 注解,即可让 Spring MVC 在实现数据绑定后执行数据校验工作。

四、视图和视图解析器

五、本地化

Spring 提供了以下 4 个本地化解析器。

  • AcceptHeaderLocaleResolver: 依据 HTTP 报文头的 Accept-Language 参数确定本 地化类型。如果没有显式定义本地化解析器,则 Spring MVC 默认采纳 AcceptHeaderLocaleResolver。
  • CookieLocaleResolver: 依据指定的 Cookie 值确定本地化类型。
  • SessionLocaleResolver: 依据 Session 中特定的属性值确定本地化类型。
  • LocaleChangeInterceptor: 从申请参数中获取本次申请对应的本地化类型。

六、文件上传

Spring MVC 为文件上传提供了间接反对,这种反对是通过即插即用的 MultipartResolver 实现的。Spring 应用 Jakarta Commons FileUpload 技术实现了一个 MultipartResolver 实现 类:CommonsMultipartResolver。
在 Spring MVC 上下文中默认没有拆卸 MultipartResolver, 因而默认状况下不能 解决文件的上传工作。如果想应用 Spring 的文件上传性能,则须要先在上下文中配置 MultipartResolver。

七、WebSocket

八、动态资源解决

  1. mvc:default-servlet-handler/:在 smart-servlet.xml 中配置 mvc:default-servlet-handler/ 后,会在 Spring MVC 上下文中定义一个 org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler,它将充当一个检查员的角色,对进入 DispatcherServlet 的 URL 进行筛查。如果发现是动态资源的申请,就将该申请转由 Web 应用服务器默认的 Servlet 解决;如果不是动态资源 的申请,则由 DispatcherServlet 持续解决。
  2. mvc:resources/:mvc:default-servlet-handler/ 将动态资源的解决经由 Spring MVC 框架交回 Web 应 用服务器。而 mvc:resources/ 更进一步,由 SpringMVC 框架本人解决动态资源,并添 加一些有用的附加性能。

九、拦截器

当收到申请时,DispatcherServlet 将申请交给处理器映射(HandlerMapping),让它找出对应该申请的 HandlerExecutionChain 对象。在解说 HandlerMapping 之前,有必要 认识一下这个 HandlerExecutionChain 对象。

HandlerExecutionChain

HandlerExecutionChain 负责解决申请并返回 ModelAndView 的解决执行链,它蕴含一个解决该申请的处理器 (Handler),同时包含若干个对该申请施行拦挡的拦截器(HandlerInterceptor)。当 HandlerMapping 返回 HandlerExecutionChain 后,DispatcherServlet 将申请交给定义在 HandlerExecutionChain 中的拦截器和处理器一并处理。
位于处理器链末端的是一个 Handler,DispatcherServlet 通过 Handler Adapter 适配器对 Handler 进行封装,并按对立的适配器接口对 Handler 解决办法进行调用。能够在 web-servlet.xml中配置多个拦截器, 每个拦截器都能够指定一个匹配的映射门路,以限度拦截器的作用范畴。

十、异样解决

Spring MVC 通过 HandlerExceptionResolver 处理程序的异样,包含处理器映射、数据绑定及处理器执行时产生的异样。HandlerExceptionResolver 仅有一个接口办法:Modelandview resolveException(HttpServletRequest request HttpServletResponse response Object handler, Exception ex)。当产生异样时,Spring MVC 将调用 resolveException 办法,并转到 ModelAndView 对应的视图中,作为一个异样报告页面反馈给用户。

实现类

HandlerExceptionResolver 领有 4 个实现类

  1. DefaultHandlerExceptionResolver:默认拆卸了该类,将对应异样转换为错误码
  2. SimpleMappingExceptionResolver:对所有异样进行对立解决
  3. AnnotationMethodHandlerExceptionResolver:默认注册了该类,容许通过 @ExceptionHandler 注解指定解决特定的异样
  4. ResponseStatusExceptionResolver

文章到这里就完结了

小编这里总结一份 springMVC 的思维导图,想理解的小伙伴能够看看呢

链接:https://juejin.cn/post/690223…

退出移动版