Spring+SpringMVC+Thymeleaf 示例

发布时间 2023-07-16 18:08:34作者: 不安分的黑娃

参考资料

开发工具

1 环境准备

  • spring tool suit 4.7.1.RELEASE
  • thymeleaf eclipse 插件
  • jdk 1.8
  • mysql 5.6
  • tomcat 8.5
  • apache maven 3.6

2 使用 maven 模板构建 war 工程

2.1 File -> New-> Other

image

2.2 选择【Maven Project】

image

勾选【Use default Workspace location】->【Next】

image

2.3 选择 maven 模板

image

2.4 输入 Group Id 、Artifact Id、package

image

2.5 生成的项目工程

控制台输出:

[INFO] Using property: package = org.lihw.spring.springmvc.webxml
Confirm properties configuration:
groupId: org.lihw
artifactId: spring-springmvc-webxml
version: 0.0.1-SNAPSHOT
package: org.lihw.spring.springmvc.webxml
 Y: : 
[INFO] ----------------------------------------------------------------------------
[INFO] Using following parameters for creating project from Archetype: maven-archetype-webapp:1.4
[INFO] ----------------------------------------------------------------------------
[INFO] Parameter: groupId, Value: org.lihw
[INFO] Parameter: artifactId, Value: spring-springmvc-webxml
[INFO] Parameter: version, Value: 0.0.1-SNAPSHOT
[INFO] Parameter: package, Value: org.lihw.spring.springmvc.webxml
[INFO] Parameter: packageInPathFormat, Value: org/lihw/spring/springmvc/webxml
[INFO] Parameter: package, Value: org.lihw.spring.springmvc.webxml
[INFO] Parameter: groupId, Value: org.lihw
[INFO] Parameter: artifactId, Value: spring-springmvc-webxml
[INFO] Parameter: version, Value: 0.0.1-SNAPSHOT
[INFO] Project created from Archetype in dir: C:\work\workspace\spring-springmvc-webxml
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:41 min
[INFO] Finished at: 2023-07-09T10:08:08+08:00
[INFO] ------------------------------------------------------------------------

image

2.6 配置项目

主要是更换 JDK 版本

选中工程,点击右键,并选择【properties】

image

左侧先择【Java Build Path】,然后点击右侧的 【Libraries】tab页

image

选中 1.7 点击【Remove】 移除:

image

移除 1.7 后,点击【Add Library】

image

选择 【JRE System Library】

image

【Execution environment】-> 【Environments】

image

安装 Jdk 1.8 的包

image

image

image

勾选安装后的 JDK 1.8 :

image

image

点击【Apply】,之后选择左侧的【Java Compiler】
image

选择编译版本 1.8 后,点击【Apply】:

image

左侧菜单选择【Project Facets】后,调整 右侧的 Java 版本:
image

2.7 完整工程目录

配置完项目后的 Maven 工程目录结构:

image

3 配置 Spring MVC

3.1 引入 Spring jar

  <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!-- spring jar 版本 -->
        <spring.version>5.3.8</spring.version>
        <!-- aspectj 版本 -->
        <aspectj.version>1.9.6</aspectj.version>
        <!-- jackson 版本 -->
        <jackson.version>2.12.7</jackson.version>
    </properties>

    <dependencies>
        <!-- spring jar -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-expression</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- spring 事务管理 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>${aspectj.version}</version>
            <scope>compile</scope>
        </dependency>
        <!-- spring jar -->

        <!-- json library -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>2.12.7</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.7</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.12.7</version>
        </dependency>

        <!-- javax.servlet api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

3.2 配置 web.xml

参见 :https://www.cnblogs.com/lihw-study/p/17538541.html

3.2.1 配置 DispatcherServlet & DispatcherServlet 映射

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
    https://www.oracle.com/webfolder/technetwork/jsc/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_NO_1" version="3.0">

  <!-- 指定 Root WebApplicationContext xml配置文件 -->
  <context-param>
  <!-- 如果不指定这个属性,那么,自动会去加载  WEB-INF/applicationContext.xml  -->
      <param-name>contextConfigLocation</param-name>
      <param-value></param-value>
  </context-param>

  <!-- 1、定义上下文监听,初始化 Root WebApplicationContext(使多个 dispatcherServlet 间共享 Bean) -->
  <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  
  <!-- 2、定义 dispatcherServlet -->
  <servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- contextConfigLocation: dispatcherServlet 初始化自己的 WebApplicationContext -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring-context.xml</param-value>
    </init-param>
    <!-- web应用一启动就初始化这个servlet -->
    <load-on-startup>1</load-on-startup>
    
    <!-- 上传配置-->
    <multipart-config>
      <location> d:/upload</location>
      <!--max-file-size:单个文件最大大小:5MB-->
      <max-file-size>-1</max-file-size>
      <!-- max-request-size:所有文件最大大小-->
      <max-request-size>-1</max-request-size>
      <!-- 超过 file-size-threshold 时会被写到磁盘-->
      <file-size-threshold>0</file-size-threshold>
    </multipart-config>
  </servlet>
  
  <!-- 3、定义 dispatcherServlet-->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <!-- 注意:dispatcherServlet必须是“/”, 不能是“/*”;   -->
    <!-- 如果是“/*”,那么当返回modelAndView是个jsp时,它会继续走这个servlet去找“/WEB-INF/.../*.jsp”对应的controller -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
      <welcome-file>index.html</welcome-file>
  </welcome-file-list>
</web-app>

将/src/main/webapp/index.jsp 重命名为 index.html。

3.2.2 处理 web.xml 内容校验错误

如果提示错误:
image

选中项目,点击右键,选择【properties】,

image

然后在左侧点击 【Project Facets】,右侧调整【Dynamic Web Module】为 3.0 ,点击 【Apply】即可。

image

3.3 新建 Controller

推荐使用 @Controller 方式声明 Controller,而非实现 org.springframework.web.servlet.mvc.Controller 接口

package org.lihw.spring.springmvc.controller;

import org.lihw.spring.springmvc.response.Response;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

/**
 * @description echo controller 
 * @author limo
 *
 */
@Controller
@RequestMapping("/echo")
public class EchoController {
	
	
	
	
	/**
	 * @description 返回 json view
	 * <code>@RequestBody</code> 和<code>@ResponseBody</code> 需配合 HttpMessageConverter 使用
	 * 注:可通过 mvc:annotation-driven 或者 @EnableWebMvc 开启默认的 HttpMessageConverter
	 * (参见:https://docs.spring.io/spring-framework/docs/4.3.9.RELEASE/spring-framework-reference/htmlsingle/#mvc-config-enable)
	 * 
	 * @param request
	 * @return
	 */
	@RequestMapping(path = "/body", method = RequestMethod.POST)
	@ResponseBody 
	public Response<Object> body(@RequestBody Object request){
		return Response.success(request);
	}
}


public class Response<T> {
	
	private String code;
	
	private String message;
	
	private T data;

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}
	
	
	public static <T> Response<T> success(T data){
		Response response = new Response();
		response.setCode("000000");
		response.setData(data);
		response.setMessage("成功");
		return response;
	}
}

3.4 新建 spring-context.xml & spring-mvc.xml

spring-context.xml 开启扫描 @Component 标记的类:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"	
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context 
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 导入 Spring MVC 相关配置 -->
    <import resource="spring-mvc.xml" />
    
    <!-- 扫描 @Component(其派生的注解) 标记的 Bean, 等同于 @ComponentScan 注解  -->
    <context:component-scan base-package="org.lihw.spring.springmvc" ></context:component-scan>    
</beans>

spring-mvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
						http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
						http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
						http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
	<!-- 开启注解驱动等同于 @EnableWebMvc -->
	<mvc:annotation-driven></mvc:annotation-driven>
    <!-- 使用 default servlet 处理静态资源,比如:index.html、error 页面等 -->
	<mvc:default-servlet-handler/>  
</beans>

3.5 集成 Thymeleaf

如果不使用 thymeleaf 那么可跳过 3.5 即可。

pom.xml 引入 thymeleaf jar 包:


        <!-- 集成 thymeleaf  -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring5</artifactId>
            <version>3.0.15.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.thymeleaf/thymeleaf -->
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
            <version>3.0.15.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/ognl/ognl -->
        <dependency>
            <groupId>ognl</groupId>
            <artifactId>ognl</artifactId>
            <version>3.1.26</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.attoparser/attoparser -->
        <dependency>
            <groupId>org.attoparser</groupId>
            <artifactId>attoparser</artifactId>
            <version>2.0.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.unbescape/unbescape -->
        <dependency>
            <groupId>org.unbescape</groupId>
            <artifactId>unbescape</artifactId>
            <version>1.1.6.RELEASE</version>
        </dependency>

3.5.1 添加 application.properties

application.properties 文件位于 src/main/resources/ 下

application.properties 添加:

#  配置文件,便于其他地方以 ${...} 占位符方式使用
chaset.encoding = UTF-8

3.5.2 spring-context.xml 添加 property-placeholder 读取配置文件

spring-context.xml 添加 property-placeholder 读取配置文件:

    <!-- 读取 properties 属性配置文件,多个可用逗号分隔 -->
    <context:property-placeholder file-encoding="utf-8" location="classpath:application.properties"/>

3.5.3 新增spring-thymeleaf.xml

spring-thymeleaf.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context 
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<!-- SpringResourceTemplateResolver automatically integrates with Spring's own -->
	<!-- resource resolution infrastructure, which is highly recommended.          -->
	<bean id="templateResolver"
	       class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
	  <property name="prefix" value="/WEB-INF/templates/" />
	  <property name="suffix" value=".html" />
	  <!-- HTML is the default value, added here for the sake of clarity.          -->
	  <property name="templateMode" value="HTML" />
	  <!-- Template cache is true by default. Set to false if you want             -->
	  <!-- templates to be automatically updated when modified.                    -->
	  <property name="cacheable" value="true" />
	  <property name="characterEncoding" value="${chaset.encoding}"></property>
	</bean>
	    
	<!-- SpringTemplateEngine automatically applies SpringStandardDialect and      -->
	<!-- enables Spring's own MessageSource message resolution mechanisms.         -->
	<bean id="templateEngine"
	      class="org.thymeleaf.spring5.SpringTemplateEngine">
	  <property name="templateResolver" ref="templateResolver" />
	  <!-- Enabling the SpringEL compiler with Spring 4.2.4 or newer can speed up  -->
	  <!-- execution in most scenarios, but might be incompatible with specific    -->
	  <!-- cases when expressions in one template are reused across different data -->
	  <!-- ypes, so this flag is "false" by default for safer backwards            -->
	  <!-- compatibility.                                                          -->
	  <property name="enableSpringELCompiler" value="true" />
	</bean>
	
	<!-- 视图解析器 -->
	<bean class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
	  <property name="templateEngine" ref="templateEngine" />
	  <property name="order" value="1" />
	  <!-- 
	  <property name="viewNames" value="*.html,*.xhtml" />
	   -->
	  <property name="characterEncoding" value="${chaset.encoding}"></property>
	</bean>
</beans>

3.5.4 spring-mvc.xml 导入 spring-thymeleaf.xml

spring-mvc.xml 增加:

    <!-- 引入 thymeleaf 配置 -->
	<import resource="spring-thymeleaf.xml" />

3.5.5 调整 EchoController & 添加 UserController

EchoController 增加:

    /**
	 * @description 将前端访问的 content,拼接“服务器收到:”后返回  echo.html 页面显示
	 * @param content
	 * @return
	 */
	@RequestMapping(method = RequestMethod.GET, path = "/{content}")
	public ModelAndView echo(@PathVariable("content") String content) {
		ModelAndView echoView = new ModelAndView();
		String message = "服务器收到:" + content;
		echoView.setViewName("echo");
		echoView.addObject("content", message);
		return echoView;
	}

UserController:

package org.lihw.spring.springmvc.controller;

import java.util.Date;

import org.lihw.spring.springmvc.response.Response;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.fasterxml.jackson.annotation.JsonFormat;

/**
 * @description user controller 
 * @author limo
 *
 */
@Controller
public class UserController {

	/**
	 * @description 获取用户详情,返回 detail.html页面展示
	 * @return
	 */
	@RequestMapping(path = "/detail", method = RequestMethod.GET)
	public ModelAndView detail() {
		User user = new User();
		user.setName("black");
		user.setPhone("182XXXXXXXX");
		user.setAge(18);
		user.setAddress("xx市xx区xx小区");
		user.setBirthday(new Date());

		ModelAndView detailView = new ModelAndView();
		detailView.setViewName("detail");
		detailView.addObject("user", user);
		return detailView;
	}
	
	/**
	 * @description 注册用户,并返回json格式的成功响应 
	 * @param user
	 * @return
	 */
	@RequestMapping(path = "/register", method = RequestMethod.POST)
	@ResponseBody
	public Response<User> register(@RequestBody User user) {
		return Response.success(user);
	}
}

/**
 * @description  用户信息
 * @author limo
 *
 */

class User {

	private String name;

	private Integer age;

	private String phone;

	private String address;

	@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
	private Date birthday;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public Date getBirthday() {
		return birthday;
	}

	public void setBirthday(Date birthday) {
		this.birthday = birthday;
	}
}

3.5.6 添加模板 echo.html & detail.html

在 /src/main/webapp/WEB-INF/templates 添加:

  • echo.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>echo page</title>
</head>
<body>
    <p th:text="${content}"></p>
</body>
</html>
  • detail.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>detail page</title>
</head>
<body>
    <p th:text="${user.name}"></p>
    <p th:text="${user.age}"></p>
    <p th:text="${user.phone}"></p>
    <p th:text="${user.address}"></p>
    <p th:text="${#dates.format(user.birthday,'yyyy-MM-dd HH:mm:ss')}"></p>
</body>
</html>

至此 thymleaf 集成完成。

4 部署到 tomcat

4.1 使用 Maven build 打出 war 包

4.2 将 war 包放于 apache-tomcat-8.5.61\webapps 下

4.3 调整 apache-tomcat-8.5.61\conf\server.xml

server.xml 文件的 <Host>标签下新增 Context

<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">
    ...
    <!-- docBase war报名或webapps下文件夹名;path:上下文path -->
    <Context docBase="war包名" path="/api"> </Context>
</Host>

4.4 启动 tomcat

双击 apache-tomcat-8.5.61\bin\startup.bat

   ...
   
13-Jul-2023 23:37:02.306 信息 [localhost-startStop-1] org.springframework.web.context.ContextLoader.initWebApplicationContext Root WebApplicationContext: initialization started
13-Jul-2023 23:37:02.818 信息 [localhost-startStop-1] org.springframework.web.context.ContextLoader.initWebApplicationContext Root WebApplicationContext initialized in 249 ms
13-Jul-2023 23:37:02.910 信息 [localhost-startStop-1] org.springframework.web.servlet.FrameworkServlet.initServletBean Initializing Servlet 'dispatcherServlet'
13-Jul-2023 23:37:03.592 警告 [localhost-startStop-1] org.springframework.web.servlet.view.ContentNegotiatingViewResolver.afterPropertiesSet No ViewResolvers configured
13-Jul-2023 23:37:03.593 警告 [localhost-startStop-1] org.springframework.web.servlet.view.ContentNegotiatingViewResolver.afterPropertiesSet No ViewResolvers configured
13-Jul-2023 23:37:03.824 信息 [localhost-startStop-1] org.springframework.web.servlet.FrameworkServlet.initServletBean Completed initialization in 913 ms
   
   ...
   
13-Jul-2023 23:37:06.121 信息 [main] org.apache.coyote.AbstractProtocol.start 开始协议处理句柄["http-nio-8080"]
13-Jul-2023 23:37:06.130 信息 [main] org.apache.catalina.startup.Catalina.start Server startup in 9443 ms

如果 CMD 窗口打印日志乱码,可编辑 apache-tomcat-8.5.61\conf\logging.properties 文件的 “java.util.logging.ConsoleHandler.encoding” 设置为 GBK

5 测试验证

5.1 首页

浏览器访问 : http://localhost:8080/api

image

5.2 echo 页面

浏览器访问 : http://localhost:8080/api/echo/black

image

5.3 user 页面(如果配置了 Thymeleaf)

浏览器访问 : http://localhost:8080/api/detail

image

补充资料

STS 开启spring xml 自动提示

image

image

image

MVC 处理请求模型:

image

DispatcherServlet 依赖的组件:

  • HandlerMapping Maps incoming requests to handlers and a list of pre- and post-processors (handler interceptors) based on some criteria the details of which vary by HandlerMapping implementation. The most popular implementation supports annotated controllers but other implementations exists as well.
    HandlerAdapter Helps the DispatcherServlet to invoke a handler mapped to a request regardless of the handler is actually invoked. For example, invoking an annotated controller requires resolving various annotations. Thus the main purpose of a HandlerAdapter is to shield the DispatcherServlet from such details.
    HandlerExceptionResolver Maps exceptions to views also allowing for more complex exception handling code.
    ViewResolver Resolves logical String-based view names to actual View types.
    LocaleResolver & LocaleContextResolver Resolves the locale a client is using and possibly their time zone, in order to be able to offer internationalized views
    ThemeResolver Resolves themes your web application can use, for example, to offer personalized layouts
    MultipartResolver Parses multi-part requests for example to support processing file uploads from HTML forms.
    FlashMapManager Stores and retrieves the "input" and the "output" FlashMap that can be used to pass attributes from one request to another, usually across a redirect.

org.springframework.web.servlet 包的 DispatcherServlet.properties 文件配置了HandlerMapping 等类的默认实现(ApplicationContext 没有配置对应的 Bean 那么 DispatcherServlet会采取该配置文件配置作为兜底方案):

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.method.annotation.RequestMappingHandlerMapping,\
	org.springframework.web.servlet.function.support.RouterFunctionMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\
	org.springframework.web.servlet.function.support.HandlerFunctionAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
	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