摘要:本文学习了SpringMVC的配置方式。
环境
Windows 10 企业版 LTSC 21H2
Java 1.8
Tomcat 8.5.50
Maven 3.6.3
Spring 5.2.25.RELEASE
1 XML配置
现在很少使用XML配置,一般都是使用半注解配置或全注解配置。
1.1 基本配置
创建web.xml配置文件:
web.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
<servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
<filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>characterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> </web-app>
|
创建spring-mvc.xml配置文件:
spring-mvc.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="demo" class="com.example.controller.DemoController"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/demo">demo</prop> </props> </property> </bean>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> <property name="contentType" value="text/html;charset=UTF-8"/> </bean> </beans>
|
创建前端控制器,实现控制器接口:
java1 2 3 4 5 6 7 8 9 10 11 12 13
| public class DemoController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) { ModelAndView mav = new ModelAndView(); mav.setViewName("demo"); mav.addObject("message", "欢迎"); return mav; } }
|
创建首页,在webapp目录下创建index.jsp页面:
index.jsp1 2 3 4 5 6 7 8 9 10 11 12 13
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <div> <a href="${pageContext.request.contextPath}/demo">请求接口</a> </div> </body> </html>
|
创建视图,在views目录下创建demo.jsp页面:
demo.jsp1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>信息</title> </head> <body> <div> <p><strong>查看消息:</strong>${message}</p> </div> <div> <a href="${pageContext.request.contextPath}/">返回首页</a> </div> </body> </html>
|
1.2 配置映射
1.2.1 SimpleUrlHandlerMapping
基于URL配置映射,需要显示配置映射:
xml1 2 3 4 5 6 7 8 9 10 11
| <bean id="demoController" class="com.example.controller.DemoController"/>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/demo">demoController</prop> </props> </property> </bean>
|
1.2.2 BeanNameUrlHandlerMapping
基于Bean名称配置映射,默认自带映射:
xml1 2
| <bean name="/demo" id="demoController" class="com.example.controller.DemoController"/>
|
1.2.3 RequestMappingHandlerMapping
基于@RequestMapping注解配置映射。
1.3 静态资源
在spring-mvc.xml配置文件中使用mvc:resources标签配置静态资源映射,自动创建SimpleUrlHandlerMapping控制器映射。
常用属性:
| 属性名 |
作用 |
取值 |
| mapping |
URL映射路径 |
路径字符串,支持通配符 |
| location |
资源存放路径 |
路径字符串,支持绝对路径和相对路径:
- Web应用根目录:/static/
- ClassPath目录:classpath:/META-INF/resources/
|
示例:
xml1 2
| <mvc:resources mapping="/static/**" location="/static/"/>
|
2 半注解配置
从Spring的2.5版本开始,引入了基于注解的配置方式。
2.1 基本配置
修改spring-mvc.xml配置文件:
spring-mvc.xml1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?xml version="1.0" encoding="UTF-8"?> <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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.example.controller"/>
<mvc:annotation-driven/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/"/> <property name="suffix" value=".jsp"/> <property name="contentType" value="text/html;charset=UTF-8"/> </bean> </beans>
|
修改前端控制器,使用注解代替配置:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Controller public class DemoController { @RequestMapping(value = "/demo") public ModelAndView demo() { ModelAndView mav = new ModelAndView(); mav.setViewName("demo"); mav.addObject("message", "欢迎"); return mav; } }
|
2.2 配置映射
2.2.1 SimpleUrlHandlerMapping
基于URL配置映射,需要显示配置映射。
2.2.2 BeanNameUrlHandlerMapping
基于Bean名称配置映射,默认自带映射。
2.2.3 RequestMappingHandlerMapping
基于@RequestMapping注解配置映射:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Controller public class DemoController { @RequestMapping(value = "/demo") public ModelAndView demo() { ModelAndView mav = new ModelAndView(); mav.setViewName("demo"); mav.addObject("message", "欢迎"); return mav; } }
|
2.3 注解驱动
在spring-mvc.xml配置文件中使用mvc:annotation-driven标签启用注解驱动,自动创建RequestMappingHandlerMapping控制器映射。
启用注解驱动后,可以使用以下注解:
- 使用
@RequestMapping注解配置路径和控制器方法的映射。
- 使用
@RequestParam注解和@PathVariable注解获取请求参数。
- 使用
@RequestBody注解和@ResponseBody注解处理JSON数据。
- 使用
@ModelAttribute注解处理模型数据。
常用属性:
| 属性名 |
作用 |
取值 |
| conversion-service |
引用自定义的类型转换服务 |
类型转换服务的引用 |
| validator |
引用自定义的校验器 |
校验器的引用 |
示例:
xml1 2
| <mvc:annotation-driven/>
|
3 全注解配置
从Spring的3.1版本开始,引入了全注解配置方式:
- 使用
@EnableWebMvc注解替代mvc:annotation-driven标签启用注解驱动。需要Servlet的2.5以上的版本支持。
- 使用WebApplicationInitializer接口替代
web.xml配置文件。需要Servlet的3.0以上的版本支持。
3.1 基本配置
创建Web初始化类,代替web.xml配置文件,需要实现WebApplicationInitializer接口:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class WebInitializer implements WebApplicationInitializer { @Override public void onStartup(ServletContext servletContext) throws ServletException { AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext(); webContext.register(WebConfig.class);
DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext); ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", dispatcherServlet); registration.addMapping("/"); registration.setLoadOnStartup(1);
FilterRegistration.Dynamic encodingFilter = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class); encodingFilter.setInitParameter("encoding", "UTF-8"); encodingFilter.setInitParameter("forceEncoding", "true"); encodingFilter.addMappingForUrlPatterns(null, true, "/*"); } }
|
创建Web容器配置类,代替spring-mvc.xml配置文件,需要实现WebMvcConfigurer接口:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Configuration @EnableWebMvc @ComponentScan("com.example.controller") public class WebConfig implements WebMvcConfigurer { @Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); resolver.setContentType("text/html;charset=UTF-8"); return resolver; } }
|
有两种方式配置视图解析器:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| @Override public void configureViewResolvers(ViewResolverRegistry registry) { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); resolver.setContentType("text/html;charset=UTF-8"); registry.viewResolver(resolver); }
@Bean public ViewResolver viewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix("/WEB-INF/views/"); resolver.setSuffix(".jsp"); resolver.setContentType("text/html;charset=UTF-8"); return resolver; }
|
3.2 配置说明
3.2.1 Web初始化类
从Servlet的3.0版本开始,JavaEE规范提供了一套动态注册机制,让Spring框架可以使用WebApplicationInitializer接口代替web.xml配置文件,以编程的方式配置组件。
Servlet规范提供了SPI容器启动扩展机制,允许框架在Servlet容器启动时动态注册组件,提供ServletContainerInitializer接口作为标准扩展点,在Servlet容器启动时发现所有实现类,并调用实现类的onStartup()方法。
Spring基于Servlet规范,通过SpringServletContainerInitializer类实现了ServletContainerInitializer接口,其作用是:
- 使用Servlet规范提供的
@HandlesTypes注解指定WebApplicationInitializer接口,让Servlet容器在启动时发现所有实现了WebApplicationInitializer接口的类。
- 将实现了WebApplicationInitializer接口的类作为参数,传入SpringServletContainerInitializer类的
onStartup()方法中。
- 在SpringServletContainerInitializer类的
onStartup()方法中调用WebApplicationInitializer接口的onStartup()方法,从而实现了WebApplicationInitializer接口的功能。
- 实现WebApplicationInitializer接口并重写
onStartup()方法,代替web.xml配置文件创建DispatcherServlet等组件。
为了进一步简化开发,Spring还提供了实现了WebApplicationInitializer接口的AbstractAnnotationConfigDispatcherServletInitializer抽象类。
示例:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRootConfigClasses() { return new Class[0]; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[] {WebConfig.class}; } @Override protected String[] getServletMappings() { return new String[] {"/"}; } @Override protected Filter[] getServletFilters() { CharacterEncodingFilter encodingFilter = new CharacterEncodingFilter(); encodingFilter.setEncoding("UTF-8"); encodingFilter.setForceEncoding(true); return new Filter[] {encodingFilter}; } }
|
3.2.2 根容器配置类
根容器配置类用于创建Spring核心容器,需要使用注解:
- 使用
@Configuration注解标记为配置类。
- 使用
@ComponentScan注解扫描组件类,注册组件到容器。
3.2.3 Web容器配置类
Web容器配置类用于创建Web容器,除了需要实现WebMvcConfigurer接口,还需要使用注解:
- 使用
@Configuration注解标记为配置类。
- 使用
@ComponentScan注解扫描控制器类,注册控制器到容器。
- 使用
@EnableWebMvc注解启用注解驱动,可以通过注解启用核心功能。
WebMvcConfigurer接口是Web容器配置的核心接口,提供了一系列可重写的方法:
- 配置视图解析器:通过重写
configureViewResolvers()方法配置。
- 配置静态资源映射:通过重写
addResourceHandlers()方法配置。
- 配置拦截器:通过重写
addInterceptors()方法配置。
- 配置跨域映射:通过重写
addCorsMappings()方法配置。
3.2.4 全局配置类
使用@ControllerAdvice注解配合其他注解可以实现不同的功能:
- 在配置类中使用
@ModelAttribute注解定义全局模型对象。
- 在配置类中使用
@InitBinder注解定义全局数据绑定规则。
- 在配置类中使用
@ExceptionHandler注解定义全局异常处理器。
3.3 静态资源
在Web容器配置类中配置静态资源映射:
java1 2 3 4 5 6 7 8 9 10 11 12
| @Configuration @EnableWebMvc @ComponentScan("com.example.controller") public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**") .addResourceLocations("/static/"); } }
|
3.4 消息转换器
在Web容器配置类中配置消息转换器,防止中文乱码:
java1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| @Configuration @EnableWebMvc @ComponentScan("com.example.controller") public class WebConfig implements WebMvcConfigurer { @Override public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { for (int i = 0; i < converters.size(); i++) { if (converters.get(i) instanceof StringHttpMessageConverter) { StringHttpMessageConverter custom = new StringHttpMessageConverter(StandardCharsets.UTF_8); custom.setWriteAcceptCharset(false); converters.set(i, custom); break; } } } }
|
条