抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

摘要:本文学习了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.xml
1
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">
<!-- 配置DispatcherServlet前端控制器 -->
<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>

<!-- 配置DispatcherServlet映射URL -->
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<!-- 解决POST请求中文乱码问题 -->
<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.xml
1
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>

创建前端控制器,实现控制器接口:

java
1
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.jsp
1
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.jsp
1
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配置映射,需要显示配置映射:

xml
1
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名称配置映射,默认自带映射:

xml
1
2
<!-- 配置控制器,自动将/开头的名称注册为URL映射,无需手动配置控制器映射 -->
<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/

示例:

xml
1
2
<!-- 配置静态资源映射 -->
<mvc:resources mapping="/static/**" location="/static/"/>

2 半注解配置

从Spring的2.5版本开始,引入了基于注解的配置方式。

2.1 基本配置

修改spring-mvc.xml配置文件:

spring-mvc.xml
1
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>

修改前端控制器,使用注解代替配置:

java
1
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注解配置映射:

java
1
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 引用自定义的校验器 校验器的引用

示例:

xml
1
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接口:

java
1
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容器,支持在Web环境中使用注解的方式获取配置
AnnotationConfigWebApplicationContext webContext = new AnnotationConfigWebApplicationContext();
// 注册Web容器配置类,比如Controller控制器类
webContext.register(WebConfig.class);

// 配置DispatcherServlet前端控制器
DispatcherServlet dispatcherServlet = new DispatcherServlet(webContext);
ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher", dispatcherServlet);
// 配置DispatcherServlet映射URL
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接口:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {
// 配置JSP视图解析器
@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;
}
}

有两种方式配置视图解析器:

java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 通过重写WebMvcConfigurer接口的configureViewResolvers()方法配置
@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);
}
// 通过使用Spring框架的@Bean注解配置,建议使用这种方式,开发工具支持较好
@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抽象类。

示例:

java
1
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 {
// 指定根容器配置类,在Spring容器中创建,具有唯一性
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[0];
}
// 指定Web容器配置类,在SpringMVC容器中创建,可以有多个
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] {WebConfig.class};
}
// 指定映射路径
@Override
protected String[] getServletMappings() {
// 设置DispatcherServlet的映射路径
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容器配置类中配置静态资源映射:

java
1
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容器配置类中配置消息转换器,防止中文乱码:

java
1
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++) {
// 修改原始StringHttpMessageConverter转换器
if (converters.get(i) instanceof StringHttpMessageConverter) {
// 设置UTF-8编码
StringHttpMessageConverter custom = new StringHttpMessageConverter(StandardCharsets.UTF_8);
// 设置为false可以避免响应头过大
custom.setWriteAcceptCharset(false);
// 替换原始StringHttpMessageConverter转换器
converters.set(i, custom);
break;
}
}
}
// ...
}

评论