1. Spring Web MVC

1.Spring Web MVC

Spring Web MVC是基于Servlet API构建的原始Web框架,从一开始就已包含在Spring框架中。正式名称“ Spring Web MVC”来自其源模块(spring-webmvc)的名称,但它通常被称为“ Spring MVC”。

与Spring Web MVC并行,Spring Framework 5.0引入了一个reactive-stack框架,其名称“ Spring WebFlux”也基于其源模块(spring-webflux)。本节介绍Spring Web MVC。在下一节 介绍Spring WebFlux。

有关基本信息以及与Servlet容器和Java EE版本范围的兼容性,请参见Spring Framework Wiki。

1.1。DispatcherServlet

与其他许多Web框架一样,Spring MVC围绕前端控制器模式进行设计,在该模式下,中央Servlet DispatcherServlet提供了用于请求处理的共享算法,而实际工作是由可配置的委托组件执行的。 该模型非常灵活,并支持多种工作流程。

与任何Servlet一样,都需要使用Java配置或在web.xml中根据Servlet规范声明和映射DispatcherServlet。 反过来,DispatcherServlet使用Spring配置发现请求映射,视图解析,异常处理等所需的委托组件。

以下Java配置示例注册并初始化DispatcherServlet,该容器由Servlet容器自动检测到(请参阅Servlet Config):

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletCxt) {

        // Load Spring web application configuration
        AnnotationConfigWebApplicationContext ac = new AnnotationConfigWebApplicationContext();
        ac.register(AppConfig.class);
        ac.refresh();

        // Create and register the DispatcherServlet
        DispatcherServlet servlet = new DispatcherServlet(ac);
        ServletRegistration.Dynamic registration = servletCxt.addServlet("app", servlet);
        registration.setLoadOnStartup(1);
        registration.addMapping("/app/*");
    }
}

除了直接使用ServletContext API外,您还可以扩展AbstractAnnotationConfigDispatcherServletInitializer并覆盖特定方法(请参见Context Hierarchy下的示例)。

以下web.xml配置示例注册并初始化DispatcherServlet:

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/app-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value></param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>

</web-app>

Spring Boot遵循不同的初始化顺序。 Spring Boot并没有陷入Servlet容器的生命周期,而是使用Spring配置来引导自身和嵌入式Servlet容器。 在Spring配置中检测到过滤器和Servlet声明,并在Servlet容器中注册。 有关更多详细信息,请参见Spring Boot文档。

1.1.1。上下文层次

DispatcherServlet期望WebApplicationContext(纯ApplicationContext的扩展)为其自身的配置。 WebApplicationContext具有指向ServletContext和与其关联的Servlet的链接。 它还绑定到ServletContext,以便应用程序可以在RequestContextUtils上使用静态方法来查找WebApplicationContext(如果需要访问它们)。

对于许多应用程序,拥有一个WebApplicationContext很简单,也足够了。也可以有一个上下文层次结构,其中一个根WebApplicationContext在多个DispatcherServlet(或其他Servlet)实例之间共享,每个实例都有自己的子WebApplicationContext配置。有关上下文层次结构特性的更多信息,请参阅ApplicationContext的其他功能。

根WebApplicationContext通常包含基础结构bean,例如需要在多个Servlet实例之间共享的数据存储库和业务服务。 这些Bean是有效继承的,可以在Servlet特定子WebApplicationContext中重写(即重新声明),该子WebApplicationContext通常包含给定Servlet本地的Bean。 下图显示了这种关系:
在这里插入图片描述

下面的示例配置一个WebApplicationContext层次结构:

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[] { RootConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { App1Config.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/app1/*" };
    }
}

如果不需要应用程序上下文层次结构,则应用程序可以通过getRootConfigClasses()返回所有配置,并从getServletConfigClasses()返回null。

以下示例显示了web.xml等效项:

<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/root-context.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app1</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/app1-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app1</servlet-name>
        <url-pattern>/app1/*</url-pattern>
    </servlet-mapping>

</web-app>

如果不需要应用程序上下文层次结构,则应用程序可以仅配置“根”上下文,并将contextConfigLocationServlet参数保留为空。

1.1.2。特殊Bean类型

DispatcherServlet委托给特殊的bean处理请求并呈现适当的响应。 所谓“特殊bean”,是指实现框架协定的Spring管理对象实例。 这些通常带有内置合同,但是您可以自定义它们的属性并扩展或替换它们。

下表列出了DispatcherServlet检测到的特殊bean:
在这里插入图片描述
在这里插入图片描述

1.1.3。Web MVC配置

应用程序可以声明处理请求所需的特殊Bean类型中列出的基础结构Bean。 DispatcherServlet检查每个特殊bean的WebApplicationContext。 如果没有匹配的bean类型,它将使用DispatcherServlet.properties中列出的默认类型。

在大多数情况下,MVC Config是最佳起点。 它使用Java或XML声明所需的bean,并提供更高级别的配置回调API对其进行自定义。

Spring Boot依靠MVC Java配置来配置Spring MVC,并提供许多额外的方便选项。

1.1.4。Servlet配置
在Servlet 3.0+环境中,您可以选择以编程方式配置Servlet容器,以替代方式或与web.xml文件结合使用。以下示例注册一个DispatcherServlet:

import org.springframework.web.WebApplicationInitializer;

public class MyWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {
        XmlWebApplicationContext appContext = new XmlWebApplicationContext();
        appContext.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");

        ServletRegistration.Dynamic registration = container.addServlet("dispatcher", new DispatcherServlet(appContext));
        registration.setLoadOnStartup(1);
        registration.addMapping("/");
    }
}

WebApplicationInitializer是Spring MVC提供的接口,可确保检测到您的实现并将其自动用于初始化任何Servlet 3容器。 WebApplicationInitializer的抽象基类实现名为AbstractDispatcherServletInitializer,它通过覆盖指定Servlet映射和DispatcherServlet配置位置的方法,使注册DispatcherServlet更容易。

对于使用基于Java的Spring配置的应用程序,建议这样做,如以下示例所示:

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return null;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[] { MyWebConfig.class };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

如果使用基于XML的Spring配置,则应直接从扩展 AbstractDispatcherServletInitializer,如以下示例所示:

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        XmlWebApplicationContext cxt = new XmlWebApplicationContext();
        cxt.setConfigLocation("/WEB-INF/spring/dispatcher-config.xml");
        return cxt;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }
}

AbstractDispatcherServletInitializer还提供了一种方便的方法来添加Filter实例,并将其自动映射到DispatcherServlet,如以下示例所示:

public class MyWebAppInitializer extends AbstractDispatcherServletInitializer {

    // ...

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[] {
            new HiddenHttpMethodFilter(), new CharacterEncodingFilter() };
    }
}

每个过滤器都会根据其具体类型添加一个默认名称,并自动映射到DispatcherServlet。

AbstractDispatcherServletInitializer的受保护方法isAsyncSupported提供了一个位置,以启用对DispatcherServlet及其映射的所有过滤器的异步支持。 默认情况下,此标志设置为true。

最后,如果您需要进一步自定义DispatcherServlet本身,则可以覆盖createDispatcherServlet方法。

1.1.5. Processing

该DispatcherServlet过程要求如下:

  1. 将WebApplicationContext搜索并绑定到请求中,作为控制器和流程中其他元素可以使用的属性。 默认情况下,它绑定在DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE键下。

  2. 语言环境解析器绑定到请求,以使流程中的元素解析在处理请求(呈现视图,准备数据等)时要使用的语言环境。如果不需要语言环境解析,则不需要语言环境解析器。

  3. 主题解析器绑定到请求,以使诸如视图之类的元素确定要使用的主题。如果不使用主题,则可以将其忽略。

  4. 如果指定multipart 文件解析器,则将检查请求中是否有multiparts。 如果找到multiparts,则将该请求包装在MultipartHttpServletRequest中,以供流程中的其他元素进一步处理。 有关多部分处理的更多信息,请参见Multipart Resolver。

  5. 搜索适当的处理程序。如果找到处理程序,则运行与该处理程序(预处理、后处理程序和控制器)关联的执行链,以准备呈现的模型。另外,对于带注释的控制器,响应可以被呈现(在HandlerAdapter中)而不是返回一个视图。

  6. 如果返回模型,则呈现视图。如果没有返回任何模型(可能是由于预处理器或后处理器拦截了该请求,可能出于安全原因),则不会呈现任何视图,因为该请求可能已经被满足。

WebApplicationContext中声明的HandlerExceptionResolver Bean用于解决在请求处理期间引发的异常。 这些异常解析器允许定制逻辑以解决异常。 有关更多详细信息,请参见异常。

Spring DispatcherServlet还支持Servlet API所指定的last-modification-date的返回。 确定特定请求的最后修改日期的过程非常简单:DispatcherServlet查找适当的处理程序映射,并测试找到的处理程序是否实现了LastModified接口。 如果是这样,则将LastModified接口的long getLastModified(request)方法的值返回给客户端。

您可以通过将Servlet初始化参数(init-param元素)添加到web.xml文件中的Servlet声明中,来定制各个DispatcherServlet实例。 下表列出了受支持的参数:在这里插入图片描述

1.1.6。拦截

所有HandlerMapping实现都支持处理程序拦截器,当您要将特定功能应用于某些请求时(例如,检查主体),该拦截器很有用。 拦截器必须使用三种方法从org.springframework.web.servlet包中实现HandlerInterceptor,这三种方法应具有足够的灵活性来执行各种预处理和后处理:

  1. preHandle(…):在实际的处理程序运行之前

  2. postHandle(…):处理程序运行后

  3. afterCompletion(…):完成完整的请求后

preHandle(…)方法返回一个布尔值。 您可以使用此方法来中断或继续执行链的处理。 当此方法返回true时,处理程序执行链将继续。 当它返回false时,DispatcherServlet假定拦截器本身已经处理了请求(例如,渲染了适当的视图),并且不会继续执行执行链中的其他拦截器和实际处理程序。

有关如何配置拦截器的示例,请参见MVC配置部分中的拦截器。 您还可以通过在各个HandlerMapping实现上使用setter直接注册它们。

请注意,在@ResponseBody和ResponseEntity方法中,postHandle的用处不大,在HandlerAdapter内和postHandle之前编写和提交响应的方法。 这意味着对响应进行任何更改为时已晚,例如添加额外的标头。 对于这种情况,您可以实现ResponseBodyAdvice并将其声明为Controller Advice Bean或直接在RequestMappingHandlerAdapter上对其进行配置。

1.1.7。异常

如果异常在请求映射期间发生或从请求处理程序(例如@Controller)抛出,则DispatcherServlet委托给HandlerExceptionResolver Bean链来解决该异常并提供替代处理,通常是错误响应。

下表列出了可用的HandlerExceptionResolver实现:
在这里插入图片描述

解析器链

您可以通过在Spring配置中声明多个HandlerExceptionResolver bean并根据需要设置其order属性来形成异常解析器链。 order属性越高,异常解析器的定位就越晚。

HandlerExceptionResolver的约定指定它可以返回:

  1. 指向错误视图的ModelAndView。

  2. 如果在解析器中处理了异常,则为空的ModelAndView。

  3. 如果该异常仍未解决,则为null,以供后续解析器尝试;如果该异常仍在末尾,则允许将其冒泡到Servlet容器。

容器错误页面

如果任何HandlerExceptionResolver都无法解决异常,因此该异常可以传播,或者如果响应状态设置为错误状态(即4xx,5xx),则Servlet容器可以在HTML中呈现默认错误页面。 要自定义容器的默认错误页面,可以在web.xml中声明错误页面映射。 以下示例显示了如何执行此操作:

/error

给定前面的示例,当异常冒出或响应具有错误状态时,Servlet容器在容器内向配置的URL(例如/ error)进行ERROR调度。 然后由DispatcherServlet处理它,可能将其映射到@Controller,可以实现该错误以使用模型返回错误视图名称或呈现JSON响应,如以下示例所示:

@RestController
public class ErrorController {

    @RequestMapping(path = "/error")
    public Map<String, Object> handle(HttpServletRequest request) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("status", request.getAttribute("javax.servlet.error.status_code"));
        map.put("reason", request.getAttribute("javax.servlet.error.message"));
        return map;
    }
}

Servlet API没有提供在Java中创建错误页面映射的方法。 但是,您可以同时使用WebApplicationInitializer和最小的web.xml。

1.1.8。View Resolution

Spring MVC定义了ViewResolver和View接口,使您可以在浏览器中呈现模型,而无需将您绑定到特定的视图技术。ViewResolver 提供视图名称和实际视图之间的映射。View在移交给特定的视图技术之前,先解决数据准备问题。

下表提供了有关ViewResolver层次结构的更多详细信息:
在这里插入图片描述
在这里插入图片描述

处理方式
Web助焊剂

您可以通过声明多个解析器bean,并在必要时通过设置order属性以指定顺序来链接视图解析器。请记住,order属性越高,视图解析器在链中的定位就越晚。

a的协定ViewResolver指定它可以返回null来指示找不到该视图。但是,对于JSP和InternalResourceViewResolver,确定JSP是否存在的唯一方法是通过进行调度 RequestDispatcher。因此,您必须始终将InternalResourceViewResolver View解析器的总体顺序配置为末尾。

配置视图分辨率就像将ViewResolverbean 添加到Spring配置中一样简单。所述MVC配置提供了一种专用配置API 视图解析器和用于将逻辑较少 视图控制器,其可用于HTML模板呈现有用而不控制器逻辑。

处理

您可以通过声明多个解析器bean,并在必要时通过设置order属性以指定顺序来链接视图解析器。 请记住,order属性越高,视图解析器在链中的定位就越晚。

ViewResolver的协定指定它可以返回null来指示找不到该视图。 但是,对于JSP和InternalResourceViewResolver,确定JSP是否存在的唯一方法是通过RequestDispatcher进行调度。 因此,您必须始终将InternalResourceViewResolver配置为在视图解析器的总体顺序中排在最后。

配置视图解析就像在Spring配置中添加ViewResolver bean一样简单。MVC配置为视图解析器和添加无逻辑视图控制器提供了专用的配置API,这对于没有控制器逻辑的HTML模板呈现非常有用。

Redirecting

视图名称中的特殊redirect:前缀使您可以执行重定向。 UrlBasedViewResolver(及其子类)将其识别为需要重定向的指令。 视图名称的其余部分是重定向URL。

最终效果与控制器返回RedirectView的效果相同,但是现在控制器本身可以根据逻辑视图名称进行操作。 逻辑视图名称(如redirect:/ myapp / some / resource)相对于当前Servlet上下文进行重定向,而名称如redirect:https://myhost.com/some/arbitrary/path则重定向至绝对URL。

请注意,如果使用@ResponseStatus注释控制器方法,则注释值优先于RedirectView设置的响应状态。

Forwarding

ContentNegotiatingViewResolver不会解析视图本身,而是委派给其他视图解析器,并选择类似于客户端请求的表示形式的视图。 可以从Accept标头或查询参数(例如,“ / path?format = pdf”)中确定表示形式。

ContentNegotiatingViewResolver通过将请求媒体类型与与其每个ViewResolvers关联的View支持的媒体类型(也称为Content-Type)进行比较,从而选择合适的View处理该请求。 列表中具有兼容Content-Type的第一个View将表示形式返回给客户端。 如果ViewResolver链无法提供兼容的视图,请查阅通过DefaultViews属性指定的视图列表。 后一个选项适用于单身视图,无论逻辑视图名称如何,该视图都可以呈现当前资源的适当表示形式。 Accept标头可以包含通配符(例如text / *),在这种情况下,其Content-Type为text / xml的View是兼容的匹配。

有关配置详细信息,请参见MVC Config下的查看解析器。

内容约定

ContentNegotiatingViewResolver不会解析视图本身,而是委派给其他视图解析器,并选择类似于客户端请求的表示形式的视图。 可以从Accept标头或查询参数(例如,“ / path?format = pdf”)中确定表示形式。

ContentNegotiatingViewResolver通过将请求媒体类型与与其每个ViewResolvers关联的View支持的媒体类型(也称为Content-Type)进行比较,从而选择合适的View处理该请求。 列表中具有兼容Content-Type的第一个View将表示形式返回给客户端。 如果ViewResolver链无法提供兼容的视图,请查阅通过DefaultViews属性指定的视图列表。 后一个选项适用于单身视图,无论逻辑视图名称如何,该视图都可以呈现当前资源的适当表示形式。 Accept标头可以包含通配符(例如text / *),在这种情况下,其Content-Type为text / xml的View是兼容的匹配。

有关配置详细信息,请参见MVC Config下的查看解析器。

1.1.9。区域设置

正如Spring Web MVC框架所做的那样,Spring体系结构的大多数部分都支持国际化。DispatcherServlet使您可以使用客户端的语言环境自动解析消息。这是通过LocaleResolver对象完成的。

收到请求时,将DispatcherServlet查找语言环境解析器,如果找到请求,它将尝试使用它来设置语言环境。通过使用该RequestContext.getLocale() 方法,您始终可以检索由语言环境解析器解析的语言环境。

除了自动的语言环境解析之外,您还可以在处理程序映射上附加一个拦截器(有关处理程序映射拦截器的更多信息,请参见拦截),以在特定情况下(例如,基于请求中的参数)更改语言环境。

语言环境解析器和拦截器在org.springframework.web.servlet.i18n程序包中定义, 并以常规方式在应用程序上下文中配置。Spring包含以下选择的语言环境解析器。

  1. Time Zone
  2. Header Resolver
  3. Cookie Resolver
  4. Session Resolver
  5. Locale Interceptor

Time Zone

除了获取客户的语言环境外,了解其时区通常也很有用。该LocaleContextResolver界面提供了扩展LocaleResolver,使解析程序可以提供更丰富的内容LocaleContext,其中可能包含时区信息。

如果可用,则TimeZone可以使用RequestContext.getTimeZone()方法获得 用户的信息。Spring的注册的任何日期/时间Converter和Formatter对象 都会自动使用时区信息ConversionService。

Header Resolver

此语言环境解析器检查accept-language客户端(例如,Web浏览器)发送的请求中的标头。通常,此头字段包含客户端操作系统的语言环境。请注意,此解析器不支持时区信息。

Cookie Resolver

此语言环境解析器检查Cookie客户端上可能存在的,以查看是否 指定Locale或TimeZone。如果是这样,它将使用指定的详细信息。通过使用此语言环境解析器的属性,可以指定Cookie的名称以及最长期限。以下示例定义了一个CookieLocaleResolver:

在这里插入图片描述

Session Resolver

将SessionLocaleResolver允许您检索Locale和TimeZone从可能与用户的请求相关的会话。相反 CookieLocaleResolver,此策略将本地选择的语言环境设置存储在Servlet容器的中HttpSession。结果,这些设置对于每个会话都是临时的,因此在每个会话结束时会丢失。

请注意,与外部会话管理机制(例如Spring Session项目)没有直接关系。这将针对current SessionLocaleResolver评估和修改相应的HttpSession属性HttpServletRequest。

Locale Interceptor

您可以通过将定义添加LocaleChangeInterceptor到其中之一 来启用语言环境的更改HandlerMapping。它检测请求中的参数并相应地更改语言环境,setLocale从而LocaleResolver在调度程序的应用程序上下文中调用方法。下一个示例显示,调用*.view包含siteLanguage现在名为参数的参数的所有资源都会更改语言环境。因此,例如,对URL的请求https://www.sf.net/home.view?siteLanguage=nl将站点语言更改为荷兰语。以下示例显示如何拦截语言环境:

<bean id="localeChangeInterceptor"
        class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="siteLanguage"/>
</bean>

<bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>

<bean id="urlMapping"
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="interceptors">
        <list>
            <ref bean="localeChangeInterceptor"/>
        </list>
    </property>
    <property name="mappings">
        <value>/**/*.view=someController</value>
    </property>
</bean>

1.1.10。主题

您可以应用Spring Web MVC框架主题来设置应用程序的整体外观,从而增强用户体验。主题是静态资源(通常是样式表和图像)的集合,这些资源会影响应用程序的视觉样式。

定义主题

要在Web应用程序中使用主题,必须设置org.springframework.ui.context.ThemeSource接口的实现 。该WebApplicationContext 接口可以扩展,ThemeSource但将其职责委托给专用的实现。默认情况下,委托是org.springframework.ui.context.support.ResourceBundleThemeSource从类路径的根加载属性文件的 实现。要使用自定义ThemeSource 实现或配置的基本名称前缀ResourceBundleThemeSource,可以在应用程序上下文中使用保留名称注册Bean themeSource。Web应用程序上下文会自动检测到具有该名称的bean并使用它。

使用时ResourceBundleThemeSource,将在一个简单的属性文件中定义一个主题。属性文件列出了组成主题的资源,如以下示例所示:

styleSheet=/themes/cool/style.css
background=/themes/cool/img/coolBg.jpg

属性的键是引用视图代码中主题元素的名称。 对于JSP,通常使用spring:theme定制标记来执行此操作,该标记与spring:message标记非常相似。 以下JSP片段使用上一示例中定义的主题来自定义外观:

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
    <head>
        <link rel="stylesheet" href="<spring:theme code='styleSheet'/>" type="text/css"/>
    </head>
    <body style="background=<spring:theme code='background'/>">
        ...
    </body>
</html>

默认情况下,ResourceBundleThemeSource使用空的基本名称前缀。结果,从类路径的根加载属性文件。因此,您可以将 cool.properties主题定义放在类路径根目录中的目录中(例如in中/WEB-INF/classes)。在ResourceBundleThemeSource使用标准的Java资源包加载机制,允许主题的国际化。例如,我们可以使用/WEB-INF/classes/cool_nl.properties引用带有荷兰文字的特殊背景图片。

解决主题

定义主题后,如上一节所述,您可以决定使用哪个主题。在DispatcherServlet查找名为豆themeResolver 找出哪个ThemeResolver使用实施。主题解析器的工作方式与LocaleResolver。它可以检测用于特定请求的主题,还可以更改请求的主题。下表描述了Spring提供的主题解析器:
在这里插入图片描述
Spring还提供了ThemeChangeInterceptor,可以使用简单的请求参数对每个请求进行主题更改。

1.1.11。Multipart Resolver

MultipartResolver从org.springframework.web.multipart包中提取是一种分析Multipart 请求(包括文件上传)的策略。有一种基于Commons FileUpload的实现,另一种基于Servlet 3.0多部分请求解析。

要启用Multipart 处理,您需要MultipartResolver在DispatcherServletSpring配置中声明一个名称为的Bean multipartResolver。在DispatcherServlet检测到它,并将其应用于传入请求。当与内容类型的POST multipart/form-data被接收时,分解器解析该内容和包装了当前HttpServletRequest作为MultipartHttpServletRequest在揭除它们作为请求参数提供到解析部件的访问。

Apache Commons FileUpload

要使用Apache Commons FileUpload,可以配置CommonsMultipartResolver名称为的类型的Bean multipartResolver。您还需要commons-fileupload依赖于类路径。

Servlet 3.0

需要通过Servlet容器配置启用Servlet 3.0多部分解析。为此:

  1. 在Java中,在Servlet注册上设置MultipartConfigElement。

  2. 在web.xml中,将“ ”部分添加到Servlet声明中。

以下示例显示了如何在Servlet注册上设置MultipartConfigElement:

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    // ...

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {

        // Optionally also set maxFileSize, maxRequestSize, fileSizeThreshold
        registration.setMultipartConfig(new MultipartConfigElement("/tmp"));
    }

}

Servlet 3.0配置到位后,您可以添加名称为multipartResolver的StandardServletMultipartResolver类型的Bean。

1.1.12。日志

Spring MVC中的DEBUG级别的日志被设计为紧凑,最少且人性化的。 它侧重于高价值的信息,这些信息一遍又一遍地有用,而其他信息则仅在调试特定问题时才有用。

TRACE级别的日志记录通常遵循与DEBUG相同的原则(例如,也不应是消防水带),但可用于调试任何问题。 此外,某些日志消息在TRACE和DEBUG上可能显示不同级别的详细信息。

良好的日志记录来自使用日志的经验。 如果发现任何不符合既定目标的东西,请告诉我们。

敏感数据

调试和跟踪日志记录可能会记录敏感信息。 这就是默认情况下屏蔽请求参数和标头,并且必须通过DispatcherServlet上的enableLoggingRequestDetails属性显式启用它们的完整登录的原因。

以下示例显示了如何使用Java配置来执行此操作:

public class MyInitializer
        extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return ... ;
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return ... ;
    }

    @Override
    protected String[] getServletMappings() {
        return ... ;
    }

    @Override
    protected void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setInitParameter("enableLoggingRequestDetails", "true");
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值