简单来讲,就是使用Java 配置替代以的xml配置。MVC Java配置和MVC XML namespace提供了适用于大多数应用程序的默认配置,并提供了一个用于自定义的配置API。
【1】启用MVC Configuration
在Java配置中,你可以使用@EnableWebMvc
注解启用MVC configuration
。如下所示:
@Configuration @EnableWebMvc public class WebConfig { }
在XML配置中,你可以使用<mvc:annotation-driven>
注解来启用MVC配置。如下所示:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven/> </beans>
前面的示例注册了大量SpringMVC基础结构bean,并适应类路径上可用的依赖项(例如,JSON、XML和其他的有效负载转换器)。
【2】MVC配置API
在Java 配置中 你可以实现WebMvcConfigurer 接口,如下所示:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { // Implement configuration methods... }
WebMvcConfigurer接口提供了一系列回调函数供你自定义配置。接口源码与说明如下:
public interface WebMvcConfigurer { //帮助配置HandlerMapping路径匹配选项,例如是否使用解析的PathPatterns或与PathPatterns匹配的字符串模式, //是否匹配尾部斜杠等。 default void configurePathMatch(PathMatchConfigurer configurer) { } //配置内容协商/转换 default void configureContentNegotiation(ContentNegotiationConfigurer configurer) { } /** * Configure asynchronous request handling options. */ //配置异步请求处理 default void configureAsyncSupport(AsyncSupportConfigurer configurer) { } //配置一个处理器处理仍旧未被处理的请求,通常是转发哦到Servlet容器的"default"servlet //这方面的一个常见用例是DispatcherServlet映射到“/”从而覆盖Servlet容器对静态资源的默认处理。 default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { } //注册额外的Converters和Formatters default void addFormatters(FormatterRegistry registry) { } //添加SpringMVC生命周期拦截器,用于控制器方法调用和资源处理程序请求的预处理和后处理。 //可以注册拦截器以应用于所有请求,也可以将拦截器限制为URL 的子集。 default void addInterceptors(InterceptorRegistry registry) { } 添加处理程序以处理静态资源,例如web应用程序根目录下、classpath下和其他位置下的图像、js和css文件 default void addResourceHandlers(ResourceHandlerRegistry registry) { } //配置跨域请求处理 default void addCorsMappings(CorsRegistry registry) { } //配置预先配置了响应状态代码和/或视图的简单自动控制器,以呈现响应主体。 //这在不需要自定义控制器逻辑的情况下非常有用,例如,呈现主页、执行简单的站点URL重定向、 //返回包含HTML内容的404状态、返回不包含任何内容的204状态等等。 default void addViewControllers(ViewControllerRegistry registry) { } //配置视图解析器,将从控制器返回的基于字符串的视图名称转换为具体的org.springframework.web.servlet.view实现, //以便使用执行渲染。 default void configureViewResolvers(ViewResolverRegistry registry) { } //添加解析器以支持自定义控制器方法参数类型。 //这不会覆盖解析处理程序方法参数的内置支持。 //要自定义参数解析的内置支持,请直接配置RequestMappingHandlerAdapter default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { } //添加处理器以支持自定义控制器方法返回值类型。 //这不会覆盖springMVC对返回值处理的内置支持,如果想覆盖可以直接配置RequestMappingHandlerAdapter default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) { } //配置HttpMessageConverters用于从request读取并写入response。如果没有添加converter,将会注册一系列默认的。 //注意,通过该方法添加Converter,将会关闭默认converters的注册。如果只是想添加额外的Converter, //建议使用extendMessageConverters方法 default void configureMessageConverters(List<HttpMessageConverter<?>> converters) { } //注册默认converters后,运行你进行添加自定义转换器(也可以修改converters,通常不建议) default void extendMessageConverters(List<HttpMessageConverter<?>> converters) { } //配置异常解析器。给定的resolvers开始可能为空,如果为空,框架会配置一系列默认的解析器, //参考WebMvcConfigurationSupport#addDefaultHandlerExceptionResolvers(List,ContentNegotiationManager) //或者,如果列表中添加了任何异常解析程序,则应用程序将有效地接管并必须提供完全初始化的异常解析程序。 //你可以选择使用extendHandlerExceptionResolvers方法,该方法允许你对默认配置的异常解析器进行扩展或修改 default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { } //扩展或修改默认配置的异常解析器列表 default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { } //提供一个自定义的Validator替换掉框架默认创建的 //在JSR-303中,默认实现是org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean //返回值为null表示使用默认配置。 @Nullable default Validator getValidator() { return null; } /** * Provide a custom {@link MessageCodesResolver} for building message codes * from data binding and validation error codes. Leave the return value as * {@code null} to keep the default. */ //提供自定义MessageCodesResolver,用于从数据绑定和验证错误代码生成消息代码。 //返回值为null表示使用默认配置。 @Nullable default MessageCodesResolver getMessageCodesResolver() { return null; } }
【3】类型转换
默认情况下,会配置各种数字和日期类型的格式化器,并支持通过字段上的@NumberFormat
和@DateTimeFormat
进行自定义。
如下实例,在Java config中注册自定义formatters 格式化器和converters类型转换器:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { // ... } }
类似的,xml中配置如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven conversion-service="conversionService"/> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="org.example.MyConverter"/> </set> </property> <property name="formatters"> <set> <bean class="org.example.MyFormatter"/> <bean class="org.example.MyAnnotationFormatterFactory"/> </set> </property> <property name="formatterRegistrars"> <set> <bean class="org.example.MyFormatterRegistrar"/> </set> </property> </bean> </beans>
默认情况下,SpringMVC在解析和格式化日期值时考虑请求区域设置。这适用于将日期表示为“input”表单字段的字符串的表单。但是,对于"date" and "time" form fields,浏览器使用HTML规范中定义的固定格式。对于这种情况,日期和时间格式可以按如下方式自定义:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addFormatters(FormatterRegistry registry) { DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); registrar.setUseIsoFormat(true); registrar.registerFormatters(registry); } }
【4】Validation
默认情况下,如果类路径上存在Bean 校验器
(例如Hibernate Validator
),则LocalValidatorFactoryBean
将注册为全局验证程序,以便@Valid
和@Validated
与控制器方法参数一起使用。v
在Java 配置中,你可以定义一个全局的Validator
实例,如下所示:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public Validator getValidator() { // ... } }
等同的xml配置如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven validator="globalValidator"/> </beans>
你也可以选择局部注册Validator
,如下所示:
@Controller public class MyController { @InitBinder protected void initBinder(WebDataBinder binder) { binder.addValidators(new FooValidator()); } }
如果需要在某处注入LocalValidatoryFactoryBean
,请创建一个bean
并用@Primary
标记它,以避免与MVC配置中声明的bean冲突。
【5】拦截器
在Java配置中,您可以注册拦截器以应用于传入的请求,如下例所示:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LocaleChangeInterceptor()); registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**"); registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*"); } }
等同的xml配置如下:
<mvc:interceptors> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/> <mvc:interceptor> <mvc:mapping path="/**"/> <mvc:exclude-mapping path="/admin/**"/> <bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/secure/*"/> <bean class="org.example.SecurityInterceptor"/> </mvc:interceptor> </mvc:interceptors>
【6】Content Types
您可以配置SpringMVC如何根据请求确定请求的内容类型(例如,Accept头、URL路径扩展、查询参数等)。
默认情况下,值检测Accept 头。如果必须使用基于URL的内容类型解析,请考虑在路径扩展上使用查询参数策略。
在Java配置中,您可以自定义请求的内容类型解析,如下例所示:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.mediaType("json", MediaType.APPLICATION_JSON); configurer.mediaType("xml", MediaType.APPLICATION_XML); } }
等同的xml配置如下所示:
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/> <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"> <property name="mediaTypes"> <value> json=application/json xml=application/xml </value> </property> </bean>
【7】Message Converters
在Java config中你可以自定义HttpMessageConverter 通过覆盖configureMessageConverters()方法(替换SpringMVC提供的默认converters )或者覆盖extendMessageConverters()方法(自定义默认的converters或者额外添加converters)。
以下示例使用自定义的ObjectMapper(而不是默认的ObjectMapper)添加XML和Jackson JSON转换器:
@Configuration @EnableWebMvc public class WebConfiguration implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder() .indentOutput(true) .dateFormat(new SimpleDateFormat("yyyy-MM-dd")) .modulesToInstall(new ParameterNamesModule()); converters.add(new MappingJackson2HttpMessageConverter(builder.build())); converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); } }
在前面的示例中,Jackson2ObjectMapperBuilder 用于为MappingJackson2HttpMessageConverter 和MappingJackson2XmlHttpMessageConverter 创建通用配置,启用indentation 、自定义日期格式和 jackson-module-parameter-names模块的注册,它增加了对访问参数名的支持(Java8中添加的一个特性)。
此生成器自定义Jackson的默认属性,如下所示:
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES 被禁用
MapperFeature.DEFAULT_VIEW_INCLUSION 被禁用
如果在类路径上检测到以下知名模块,它还会自动注册这些模块:
jackson-datatype-joda: Support for Joda-Time types.
jackson-datatype-jsr310: Support for Java 8 Date and Time API types.
jackson-datatype-jdk8: Support for other Java 8 types, such as Optional.
jackson-module-kotlin: Support for Kotlin classes and data classes.
启用Jackson XML支持的缩进需要woodstox-core-asl依赖项和jackson-dataformat-xml 依赖项。
还有其他有趣的Jackson模块:
jackson-datatype-money: Support for javax.money types (unofficial module).
jackson-datatype-hibernate: Support for Hibernate-specific types and properties (including lazy-loading aspects).
等同的xml配置如下所示:
<mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper" ref="objectMapper"/> </bean> <bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter"> <property name="objectMapper" ref="xmlMapper"/> </bean> </mvc:message-converters> </mvc:annotation-driven> <bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" p:indentOutput="true" p:simpleDateFormat="yyyy-MM-dd" p:modulesToInstall="com.fasterxml.jackson.module.paramnames.ParameterNamesModule"/> <bean id="xmlMapper" parent="objectMapper" p:createXmlMapper="true"/>
【8】 View Controllers
这是定义ParameterableViewController
的快捷方式,该控制器在调用时立即转发到视图。可以在静态情况下使用它,也就是当视图生成响应之前没有Java控制器逻辑运行。
以下Java配置示例将请求/
转发到名为home
的视图:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("home"); } }
等同的xml配置如下所示:
<mvc:view-controller path="/" view-name="home"/>
当一个标注了@RequestMapping方法匹配到URL,则view controller不能再处理该URL。
如果@RequestMapping方法映射到任何HTTP方法的某个URL,则视图控制器不能用于处理同一URL。这是因为URL与带注解控制器的匹配被认为是端点所有权的足够强的声明,因此可以将405(METHOD_NOT_ALLOWED)、415(UNSUPPORTED_MEDIA_TYPE)或类似响应发送到客户端以帮助调试。因此,建议避免在带注解的控制器和视图控制器view controller之间拆分URL处理。
【9】 视图解析器
MVC configuration 简化了视图解析器的注册。以下Java配置示例通过使用JSP
和Jackson
作为JSON
呈现的默认视图来配置内容协商视图解析:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.enableContentNegotiation(new MappingJackson2JsonView()); registry.jsp(); } }
等同的xml配置如下:
<mvc:view-resolvers> <mvc:content-negotiation> <mvc:default-views> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/> </mvc:default-views> </mvc:content-negotiation> <mvc:jsp/> </mvc:view-resolvers>
但是,请注意,FreeMarker、Tiles、Groovy Markup和script templates也需要配置底层视图技术。
MVC命名空间提供专用元素。以下示例适用于FreeMarker:
<mvc:view-resolvers> <mvc:content-negotiation> <mvc:default-views> <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/> </mvc:default-views> </mvc:content-negotiation> <mvc:freemarker cache="false"/> </mvc:view-resolvers> <mvc:freemarker-configurer> <mvc:template-loader-path location="/freemarker"/> </mvc:freemarker-configurer>
在Java配置中,您可以添加相应的Configurer bean
,如下例所示:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureViewResolvers(ViewResolverRegistry registry) { registry.enableContentNegotiation(new MappingJackson2JsonView()); registry.freeMarker().cache(false); } @Bean public FreeMarkerConfigurer freeMarkerConfigurer() { FreeMarkerConfigurer configurer = new FreeMarkerConfigurer(); configurer.setTemplateLoaderPath("/freemarker"); return configurer; } }
【10】Static Resources
此选项提供了一种方便的方法,可以从Resource-based 的位置列表中快速访问静态资源。
在下一个示例中,给定一个以/resources开头的请求,然后在web应用程序根目录下/public或在classpath:/static/目录下的类路径上查找和提供静态资源。
这些资源的使用期限为一年,以确保最大限度地利用浏览器缓存,并减少浏览器发出的HTTP请求。最后Last-Modified 的信息是从Resource#lastModified推导出来的,因此HTTP请求需要支持“Last-Modified”头。
Java 配置实例如下:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/public", "classpath:/static/") .setCacheControl(CacheControl.maxAge(Duration.ofDays(365))); } }
等同的xml配置如下:
<mvc:resources mapping="/resources/**" location="/public, classpath:/static/" cache-period="31556926" />
资源处理程序还支持ResourceResolver 实现链和ResourceTransformer 实现链,您可以使用它们创建用于处理优化资源的工具链。
您可以基于从内容、固定应用程序版本或其他内容计算的MD5哈希将VersionResourceResolver用于已版本化的资源URL。ContentVersionStrategy (MD5哈希)是一个不错的选择 — 除了一些值得注意的例外,比如模块加载器使用的JavaScript资源。
下面实例展示了在Java配置如何使用VersionResourceResolver :
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/resources/**") .addResourceLocations("/public/") .resourceChain(true) .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**")); } }
等同的xml配置如下所示:
<mvc:resources mapping="/resources/**" location="/public/"> <mvc:resource-chain resource-cache="true"> <mvc:resolvers> <mvc:version-resolver> <mvc:content-version-strategy patterns="/**"/> </mvc:version-resolver> </mvc:resolvers> </mvc:resource-chain> </mvc:resources>
然后,您可以使用ResourceUrlProvider 重写URL并应用整个解析程序和转换器链 — 例如,插入版本。MVC配置提供了一个ResourceUrlProvider bean,以便可以将其注入到其他配置中。您还可以使用ResourceUrlEncodingFilter 对Thymeleaf、JSP、FreeMarker和其他依赖HttpServletResponse#encodeURL的URL标记的文件进行透明重写。
请注意,当同时使用EncodedResourceResolver (例如,用于服务Gzip或brotli编码的资源)和VersionResourceResolver时,必须按此顺序注册它们。这确保了基于内容的版本始终基于未编码的文件可靠地计算。
WebJars 还通过WebJarsResourceResolver 得到支持,当org.webjars:webjars-locator-core核心库出现在类路径上时,WebJarsResourceResolver资源解析器会自动注册。解析器可以重写URL以包含jar的版本,还可以匹配没有版本的传入URL — 例如,从/jquery/jquery.min.js到/jquery/1.2.0/jquery.min.js。
【11】Default Servlet
SpringMVC允许将DispatcherServlet映射到/(从而覆盖容器的默认Servlet的映射),同时仍然允许容器的默认Servlet处理静态资源请求。它使用/**的URL映射配置DefaultServletHttpRequestHandler,并且相对于其他URL映射具有最低优先级。
DefaultServletHttpRequestHandler转发所有请求到default Servlet.因此,它必须在所有其他URL HandlerMappings的顺序中保持最后一个。如果使用<mvc:annotation-driven>,就是这种情况。或者,如果设置自己的自定义HandlerMapping实例,请确保将其order属性设置为低于DefaultServletHttpRequestHandler的值,即Integer.MAX_VALUE。DefaultServletHttpRequestHandler中处理请求方法如下所示:
@Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { Assert.state(this.servletContext != null, "No ServletContext set"); RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName); if (rd == null) { throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" + this.defaultServletName + "'"); } rd.forward(request, response); }
以下示例显示如何使用默认设置启用该功能:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
等同的xml配置如下所示:
<mvc:default-servlet-handler/>
重写/Servlet映射的注意事项是,必须按名称而不是路径检索默认Servlet的RequestDispatcher。DefaultServletHttpRequestHandler 尝试在启动时自动检测容器的默认Servlet,使用大多数主要Servlet容器(包括Tomcat、Jetty、GlassFish、JBoss、Resin、WebLogic和WebSphere)的已知名称列表。如果默认Servlet已使用不同的名称进行自定义配置,或者如果在默认Servlet名称未知的情况下使用不同的Servlet容器,则必须显式提供默认Servlet的名称,如以下示例所示:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable("myCustomDefaultServlet"); } }
下示例显示了如何在XML中实现相同的配置:
<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>
【12】Path Matching
您可以自定义与路径匹配和URL处理相关的选项。更多详情参考PathMatchConfigurer.
以下示例显示如何在Java配置中自定义路径匹配:
@Configuration @EnableWebMvc public class WebConfig implements WebMvcConfigurer { @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer .setPatternParser(new PathPatternParser()) .addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class)); } private PathPatternParser patternParser() { // ... } }
以下示例显示了如何在XML中实现相同的配置:
<mvc:annotation-driven> <mvc:path-matching trailing-slash="false" path-helper="pathHelper" path-matcher="pathMatcher"/> </mvc:annotation-driven> <bean id="pathHelper" class="org.example.app.MyPathHelper"/> <bean id="pathMatcher" class="org.example.app.MyPathMatcher"/>
【13】Advanced Java Config
@EnableWebMvc
导入了DelegatingWebMvcConfiguration
其作用如下:
- 为SpringMVC应用程序提供默认Spring配置
- 检测并委托WebMVCConfiguer实现以自定义该配置。
对于高级模式,您可以删除@EnableWebMvc
并直接从DelegatingWebMvcConfiguration
配置扩展,而不是实现WebMVC配置,如下例所示:
@Configuration public class WebConfig extends DelegatingWebMvcConfiguration { // ... }
您可以在WebConfig中保留现有方法,但现在还可以覆盖基类中的bean声明,并且在类路径上仍然可以有任意数量的其他WebMVCConfiguer
实现。
【14】Advanced XML Config
MVC命名空间没有高级模式。如果需要在bean上自定义一个不能更改的属性,可以使用Spring ApplicationContext
的BeanPostProcessor
生命周期挂钩,如下例所示:
@Component public class MyPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { // ... } }
注意,您需要将MyPostProcessor
声明为bean,可以用XML显式地声明,也可以通过<component scan/>
声明使其被检测。
【15】创建初始化类,代替web.xml
在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置Servlet容器。 Spring提供了这个接口的实现,名为org.springframework.web.SpringServletContainerInitializer。
SpringServletContainerInitializer这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。
Spring3.2引入了一个便利的WebApplicationInitializer基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer,当我们的类扩展了AbstractAnnotationConfigDispatcherServletInitializer并将其部署到Servlet3.0容器的时候,容器会自动发现它,并用它来配置Servlet上下文。
WebApplicationInitializer实现类图示
//web工程的初始化类,用来代替web.xml public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer { /** * 指定spring的配置类 * @return */ @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringConfig.class}; } /** * 指定springMVC的配置类 * @return */ @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{WebConfig.class}; } /** * 指定DispatcherServlet的映射规则,即url-pattern * @return */ @Override protected String[] getServletMappings() { return new String[]{"/"}; } /** * 注册过滤器 * @return */ @Override protected Filter[] getServletFilters() { CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter(); characterEncodingFilter.setEncoding("UTF-8"); characterEncodingFilter.setForceResponseEncoding(true); HiddenHttpMethodFilter hiddenHttpMethodFilter = new HiddenHttpMethodFilter(); return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter}; } }
创建SpringConfig配置类,代替spring的配置文件
ssm整合之后,spring的配置信息写在此类中
@Configuration public class SpringConfig { //... }
【16】创建WebConfig配置类,代替SpringMVC的配置文件
/** * 代替SpringMVC的配置文件: * 1、扫描组件 2、视图解析器 3、view-controller 4、default-servlet-handler * 5、mvc注解驱动 6、文件上传解析器 7、异常处理 8、拦截器 */ //将当前类标识为一个配置类 @Configuration //1、扫描组件 @ComponentScan("com.mvc.controller") //5、mvc注解驱动 @EnableWebMvc public class WebConfig implements WebMvcConfigurer { //4、default-servlet-handler @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } //8、拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { TestInterceptor testInterceptor = new TestInterceptor(); registry.addInterceptor(testInterceptor).addPathPatterns("/**"); } //3、view-controller @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/hello").setViewName("hello"); } //6、文件上传解析器 @Bean public MultipartResolver multipartResolver(){ CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(); return commonsMultipartResolver; } //7、异常处理 @Override public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) { SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver(); Properties prop = new Properties(); prop.setProperty("java.lang.ArithmeticException", "error"); exceptionResolver.setExceptionMappings(prop); exceptionResolver.setExceptionAttribute("exception"); resolvers.add(exceptionResolver); } //配置生成模板解析器 @Bean public ITemplateResolver templateResolver() { WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext(); // ServletContextTemplateResolver需要一个ServletContext作为构造参数,可通过WebApplicationContext 的方法获得 ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver( webApplicationContext.getServletContext()); templateResolver.setPrefix("/WEB-INF/templates/"); templateResolver.setSuffix(".html"); templateResolver.setCharacterEncoding("UTF-8"); templateResolver.setTemplateMode(TemplateMode.HTML); return templateResolver; } //生成模板引擎并为模板引擎注入模板解析器 @Bean public SpringTemplateEngine templateEngine(ITemplateResolver templateResolver) { SpringTemplateEngine templateEngine = new SpringTemplateEngine(); templateEngine.setTemplateResolver(templateResolver); return templateEngine; } //生成视图解析器并未解析器注入模板引擎 @Bean public ViewResolver viewResolver(SpringTemplateEngine templateEngine) { ThymeleafViewResolver viewResolver = new ThymeleafViewResolver(); viewResolver.setCharacterEncoding("UTF-8"); viewResolver.setTemplateEngine(templateEngine); return viewResolver; } }