SpringMVC
将web工程配置到Tomcat中
- 选择tomcat server
- 修改名字
- 将项目部署到Tomcat中
- 修改上下文路径(可以不修改,我觉得太长了换个短的)
- 回到Server进行相应设置,点击OK即可
springMVC环境搭建
- 项目结构
- 创建一个普通的Maven工程,或者可以直接选择一个web工程创建,我习惯自己创建
- 在pom.xml添加web打包方式,点击File->Project Structure 选择所创建的项目,可以看到多出一个Web,但是会爆红,点击如何所示右上角+,添加xml文件,注意路径不对需要自己调整,完成之后就可以了(…/src/main/webapp/WEB-INF/web.xml):
E:\IDEA\IDEAProjects\NewSSM\spring_mvc_rest\src\main\webapp\WEB-INF\web.xml
<packaging>war</packaging>
- 在pom.xml中添加相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>NewSSM</artifactId>
<groupId>com.itzhh.ssm</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring_mvc_helloworld</artifactId>
<packaging>war</packaging>
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
</dependencies>
</project>
- 配置web.xml
<?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_4_0.xsd"
version="4.0">
<!-- 配置SpringMVC的前端控制器,对浏览器发送的请求统一进行处理 -->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 通过初始化参数指定SpringMVC配置文件的位置和名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 使用classpath:表示从类路径查找配置文件,例如maven工程中的
src/main/resources -->
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<!--
作为框架的核心组件,在启动过程中有大量的初始化操作要做
而这些操作放在第一次请求时才执行会严重影响访问速度
因此需要通过此标签将启动控制DispatcherServlet的初始化时间提前到服务器启动时
-->
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<!--
设置springMVC的核心控制器所能处理的请求的请求路径
/所匹配的请求可以是/login或.html或.js或.css方式的请求路径
但是/不能匹配.jsp请求路径的请求
-->
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 创建springMVC的配置文件springmvc.xml
<?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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 自动扫描包-->
<context:component-scan base-package="com.itzhh.mvc.controller"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
</beans>
- 创建测试页面index.html和success.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>index.html</h1>
<a th:href="@{/hello}">测试springMVC</a><br/>
<a href="/hello">测试绝对路径</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>成功</title>
</head>
<body>
<h1>success</h1>
</body>
</html>
- 创建Controller访问页面
package com.itzhh.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* Author: zhh
* Date: 2023-01-02 21:53
* Description: <描述>
*/
@Controller
public class HelloController {
// @RequestMapping注解:处理请求和控制器方法之间的映射关系
// @RequestMapping注解的value属性可以通过请求地址匹配请求,/表示的当前工程的上下文路径
// localhost:8080/springMVC/
@RequestMapping("/")
public String index(){
//设置逻辑视图名称
return "index";
}
@RequestMapping("/hello")
public String hello(){
return "success";
}
}
- 启动项目
- 结果
SpringMVC常用注解
@RequestMapping
- 作用是将请求和处理请求的控制器方法关联起来,建立映射关系
位置:
- 标识一个类:设置映射请求的请求路径的初始信息
- 标识一个方法:设置映射请求请求路径的具体信息
value属性
- 通过请求的请求地址匹配请求映射
- value属性是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址所对应的请求
- value属性必须设置,至少通过请求地址匹配请求映射
method属性
- 通过请求的请求方式(get或post)匹配请求映射
- method属性是一个RequestMethod类型的数组,表示该请求映射能够匹配多种请求方式的请求
- 若当前请求的请求地址满足请求映射的value属性,但是请求方式不满足method属性,则浏览器报错405:Request method ‘POST’ not supported
- 目前浏览器只支持get和post,若在form表单提交时,为method设置了其他请求方式的字符串(put或delete),则按照默认的请求方式get处理
- 除了表单和提交Ajax方式是post,其余默认都是get,简单而言
支持ant风格的路径
- ?:表示任意的单个字符
- *:表示任意的0个或多个字符
- **:表示任意层数的任意目录
- 注意:在使用** 时,只能使用/**/xxx的方式
支持路径中的占位符
<a th:href="@{/test2/abv/40474}">测试路径参数</a>
@RequestMapping("/test2/{username}/{password}")
public String test2(@PathVariable("username") String username, @PathVariable("password") String password){
System.out.println("username: " + username+" password: " + password);
return "success";
}
获取请求参数
通过ServletAPI获取
@RequestMapping("/testParam")
public String testParam(HttpServletRequest request){
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println("username:"+username+",password:"+password);
return "success";
}
通过控制器方法的形参获取请求参数
在控制器方法的形参位置,设置和请求参数同名的形参,当浏览器发送请求,匹配到请求映射时,在DispatcherServlet中就会将请求参数赋值给相应的形参
@RequestMapping("/login1")
public String login(String username, String password){
System.out.println("username: " + username+" password: " + password);
return "success";
}
<form th:action="@{/login1}" method="post">
账号<input type="text" name="username"><br>
密码<input type="password" name="password"><br>
<input type="submit" name="login" value="登录">
<input type="submit" name="register" value="注册">
</form>
- 若请求所传输的请求参数中有多个同名的请求参数,此时可以在控制器方法的形参中设置字符串数组或者字符串类型的形参接收此请求参数
- 若使用字符串数组类型的形参,此参数的数组中包含了每一个数据
- 若使用字符串类型的形参,此参数的值为每个数据中间使用逗号拼接的结果
通过 @RequestParam
-
@RequestParam是将请求参数和控制器方法的形参创建映射关系
-
一共有三个属性:
value:指定为形参赋值的请求参数的参数名
required:设置是否必须传输此请求参数,默认值为true -
defaultValue:不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值为""时,则使用默认值为形参赋值
@RequestHeader和@CookieValue(了解)
- @RequestHeader是将请求头信息和控制器方法的形参创建映射关系
- @CookieValue是将cookie数据和控制器方法的形参创建映射关系
- 一共有三个属性:value、required、defaultValue,用法同@RequestParam
通过POJO获取请求参数
- 可以在控制器方法的形参位置设置一个实体类类型的形参,此时若浏览器传输的请求参数的参数名和实体类中的属性名一致,那么请求参数就会为此属性赋值
@RequestMapping(value = "/login2",method = {RequestMethod.POST,RequestMethod.GET})
public String login2(User user){
System.out.println("username: " + user.getUsername()+" password: " + user.getPassword());
return "success";
}
全部测试代码
package com.itzhh.mvc.controller;
import com.itzhh.mvc.pojo.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Author: zhh
* Date: 2023-01-02 21:53
* Description: <描述>
*/
@Controller
public class HelloController {
// @RequestMapping注解:处理请求和控制器方法之间的映射关系
// @RequestMapping注解的value属性可以通过请求地址匹配请求,/表示的当前工程的上下文路径
// localhost:8080/springMVC/
@RequestMapping("/")
public String index(){
//设置逻辑视图名称
return "index";
}
@RequestMapping("/hello")
public String hello(){
return "success";
}
@RequestMapping(value = {"/test","/test1"},method = {RequestMethod.GET, RequestMethod.POST})
public String test(@RequestParam(value = "username",
required = false,
defaultValue = "zhh") String username,@RequestParam(value = "password",
defaultValue = "123456") String password){
System.out.println("username: " + username+" password: " + password);
return "success";
}
@RequestMapping("/login")
public String login(String username, String password){
System.out.println("username: " + username+" password: " + password);
return "login";
}
@RequestMapping(value = "/login1",method = {RequestMethod.GET,RequestMethod.POST})
public String login1(String username, String password){
System.out.println("username: " + username+" password: " + password);
return "success";
}
@RequestMapping(value = "/login2",method = {RequestMethod.POST,RequestMethod.GET})
public String login2(User user){
System.out.println("username: " + user.getUsername()+" password: " + user.getPassword());
return "success";
}
@RequestMapping("/test2/{username}/{password}")
public String test2(@PathVariable("username") String username, @PathVariable("password") String password){
System.out.println("username: " + username+" password: " + password);
return "success";
}
}
package com.itzhh.mvc.pojo;
/**
* Author: zhh
* Date: 2023-01-12 13:48
* Description: <描述>
*/
public class User {
private Integer id;
private String username;
private String password;
private String email;
private String phone;
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", email='" + email + '\'' +
", phone='" + phone + '\'' +
'}';
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public User() {
}
public User(Integer id, String username, String password, String email, String phone) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.phone = phone;
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录界面</title>
</head>
<body>
<div>
<h1 style="background-color: aqua" >欢迎来到体检预约系统</h1>
</div>
<div>
<form th:action="@{/login1}" method="post">
账号<input type="text" name="username"><br>
密码<input type="password" name="password"><br>
<input type="submit" name="login" value="登录">
<input type="submit" name="register" value="注册">
</form>
</div>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>index.html</h1>
<a th:href="@{/hello}">测试springMVC</a><br/>
<a href="/hello">测试绝对路径</a>
<form method="post" th:action="@{/test}" >
用户名<input type="text" name="username"><br>
密 码<input type="password" name="password"><br>
<input type="submit">
</form>
<a th:href="@{/login}">前往登录界面</a>
<a th:href="@{/login.html}">前往登录界面</a>
<a th:href="@{/login2(username='xyz',password=12345)}">测试实体类接收参数</a>
<a th:href="@{/test2/abv/40474}">测试路径参数</a>
</body>
</html>
解决获取请求参数的乱码问题
-
Tomcat7 post和get方式都会有乱码问题
get方式直接找到xml文件修改,网上搜一下就行。 -
Tomcat8 get方式不存在乱码问题,解决post方式乱码问题
在web.xml中添加编码过滤器
<!-- 配置springmvc的编码过滤器-->
<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>
- 注意:SpringMVC中处理编码的过滤器一定要配置到其他过滤器之前,否则无效
视图
- 视图的作用渲染数据,将模型Model中的数据展示给用户
- SpringMVC视图的种类很多,默认有转发视图和重定向视图
- 若使用的视图技术为Thymeleaf,在SpringMVC的配置文件中配置了Thymeleaf的视图解析器,由此视图解析器解析之后所得到的是ThymeleafView
ThymeleafView
当控制器方法中所设置的视图名称没有任何前缀时,此时的视图名称会被SpringMVC配置文件中所配置的视图解析器解析,视图名称拼接视图前缀和视图后缀所得到的最终路径,会通过转发的方式实现跳转
@RequestMapping("/hello")
public String hello(){
return "success";
}
转发视图
- SpringMVC中默认的转发视图是InternalResourceView
- 当控制器方法中所设置的视图名称以"forward:"为前缀时,创建InternalResourceView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"forward:"去掉,剩余部分作为最终路径通过转发的方式实现跳转
- 格式:
"forword:/路径"
@RequestMapping("/testForward")
public String testForward(){
return "forward:/hello";
}
重定向视图
- SpringMVC中默认的重定向视图是RedirectView
- 当控制器方法中所设置的视图名称以"redirect:"为前缀时,创建RedirectView视图,此时的视图名称不会被SpringMVC配置文件中所配置的视图解析器解析,而是会将前缀"redirect:"去掉,剩余部分作为最终路径通过重定向的方式实现跳转
- 格式:
"redirect:/路径"
@RequestMapping("/testRedirect")
public String testRedirect(){
return "redirect:/hello";
}
视图控制器view-controller
-
当控制器方法中,仅仅用来实现页面跳转,即只需要设置视图名称时,可以将处理器方法使用viewcontroller标签进行表示
-
比如首页(在beans标签里直接写)
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
- 当SpringMVC中设置任何一个view-controller时,其他控制器中的请求映射将全部失效,此时需要在SpringMVC的核心配置文件中设置开启mvc注解驱动的标签:
<mvc:annotation-driven />
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包-->
<context:component-scan base-package="com.itzhh.mvc.controller"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<!--开启mvc注解驱动-->
<mvc:annotation-driven></mvc:annotation-driven>
<!-- path:设置处理的请求地址
view-name:设置请求地址所对应的视图名称
-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
</beans>
域对象共享数据
使用ServletAPI向request域对象共享数据
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request){
request.setAttribute("testScope","hello,servletAPI");
return "success";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>成功</title>
</head>
<body>
<h1>success</h1>
<p th:text="${testScope}"></p>
</body>
</html>
使用ModelAndView向request域对象共享数据
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
/*
ModelAndView有Model和View的功能
Model主要用于向请求域共享数据
View主要用于设置视图,实现页面跳转
*/
ModelAndView modelAndView=new ModelAndView();
//向请求域共享数据
modelAndView.addObject("testScope","hello,ModelAndView");
//设置视图,实现页面跳转
modelAndView.setViewName("success");
return modelAndView;
}
使用Model向request域对象共享数据
@RequestMapping("/testModel")
public String tesModel(Model model) {
model.addAttribute("testScope","hello,Model");
return "success";
}
使用map向request域对象共享数据
@RequestMapping("/testMap")
public String tesMap(Map<String,Object> map) {
map.put("testScope","hello,Map");
return "success";
}
使用ModelMap向request域对象共享数据
@RequestMapping("/testModelMap")
public String tesModelMap(ModelMap modelMap) {
modelMap.addAttribute("testScope","hello,ModelMap");
return "success";
}
Model、ModelMap、Map的关系
- Model、ModelMap、Map类型的参数其实本质上都是 BindingAwareModelMap 类型的
public interface Model{}
public class ModelMap extends LinkedHashMap<String, Object> {}
public class ExtendedModelMap extends ModelMap implements Model {}
public class BindingAwareModelMap extends ExtendedModelMap {}
向session域共享数据
@RequestMapping("/testSession")
public String tesSession(HttpSession session) {
session.setAttribute("testSessionScope","hello,session");
return "success";
}
- 注意获取的时候需要加上session
<p th:text="${session.testSessionScope}"></p>
向application域共享数据
@RequestMapping("/testApplication")
public String tesApplication(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("testApplicationScope","hello,application");
return "success";
}
- 注意获取的时候需要加上application
<p th:text="${application.testApplicationScope}"></p>
整体代码
package com.itzhh.mvc.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* Author: zhh
* Date: 2023-01-13 15:26
* Description: <描述>
*/
@Controller
public class TestController {
@RequestMapping("/testServletAPI")
public String testServletAPI(HttpServletRequest request){
request.setAttribute("testScope","hello,servletAPI");
return "success";
}
@RequestMapping("/testModelAndView")
public ModelAndView testModelAndView(){
/*
ModelAndView有Model和View的功能
Model主要用于向请求域共享数据
View主要用于设置视图,实现页面跳转
*/
ModelAndView modelAndView=new ModelAndView();
//向请求域共享数据
modelAndView.addObject("testScope","hello,ModelAndView");
//设置视图,实现页面跳转
modelAndView.setViewName("success");
return modelAndView;
}
@RequestMapping("/testModel")
public String tesModel(Model model) {
model.addAttribute("testScope","hello,Model");
return "success";
}
@RequestMapping("/testMap")
public String tesMap(Map<String,Object> map) {
map.put("testScope","hello,Map");
return "success";
}
@RequestMapping("/testModelMap")
public String tesModelMap(ModelMap modelMap) {
modelMap.addAttribute("testScope","hello,ModelMap");
return "success";
}
@RequestMapping("/testSession")
public String tesSession(HttpSession session) {
session.setAttribute("testSessionScope","hello,session");
return "success";
}
@RequestMapping("/testApplication")
public String tesApplication(HttpSession session){
ServletContext application = session.getServletContext();
application.setAttribute("testApplicationScope","hello,application");
return "success";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>index.html</h1>
<a th:href="@{/hello}">测试springMVC</a><br/>
<a href="/hello">测试绝对路径</a>
<form method="post" th:action="@{/test}" >
用户名<input type="text" name="username"><br>
密 码<input type="password" name="password"><br>
<input type="submit">
</form>
<a th:href="@{/login}">前往登录界面</a>
<a th:href="@{/login.html}">前往登录界面</a>
<a th:href="@{/login2(username='xyz',password=12345)}">测试实体类接收参数</a>
<a th:href="@{/test2/abv/40474}">测试路径参数</a>
<a th:href="@{/testForward}">测试转发视图</a>
<a th:href="@{/testRedirect}">测试重定向视图</a><br>
<a th:href="@{/testServletAPI}">测试ServletAPI</a>
<a th:href="@{/testModelAndView}">测试ModelAndView</a>
<a th:href="@{/testModel}">测试Model</a>
<a th:href="@{/testMap}">测试Map</a>
<a th:href="@{/testModelMap}">测试ModelMap</a>
<a th:href="@{/testSession}">测试Session</a>
<a th:href="@{/testApplication}">测试Application</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>成功</title>
</head>
<body>
<h1>success</h1>
<p th:text="${testScope}"></p>
<p th:text="${session.testSessionScope}"></p>
<p th:text="${application.testApplicationScope}"></p>
</body>
</html>
处理静态资源访问不到的问题
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
- 当前工程的web.xml配置的前端控制器DispatcherServlet的url-pattern是/
tomcat的web.xml配置的DefaultServlet的url-pattern也是/
此时,浏览器发送的请求会优先被DispatcherServlet进行处理,但是DispatcherServlet无法处理静态资源
若配置了<mvc:default-servlet-handler />,此时浏览器发送的所有请求都会被DefaultServlet处理
若配置了<mvc:default-servlet-handler />和<mvc:annotation-driven />
浏览器发送的请求会先被DispatcherServlet处理,无法处理在交给DefaultServlet处理
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<context:component-scan base-package="com.itzhh.mvc.controller"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver"
class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean
class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<!-- 配置默认的servlet处理静态资源
当前工程的web.xml配置的前端控制器DispatcherServlet的url-pattern是/
tomcat的web.xml配置的DefaultServlet的url-pattern也是/
此时,浏览器发送的请求会优先被DispatcherServlet进行处理,但是DispatcherServlet无法处理静态资源
若配置了<mvc:default-servlet-handler />,此时浏览器发送的所有请求都会被DefaultServlet处理
若配置了<mvc:default-servlet-handler />和<mvc:annotation-driven />
浏览器发送的请求会先被DispatcherServlet处理,无法处理在交给DefaultServlet处理
-->
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
</beans>
使用@ResponseBody
- 服务器处理ajax请求之后,大多数情况都需要向浏览器响应一个java对象,此时必须将java对象转换为json字符串才可以响应到浏览器。在SpringMVC中,我们可以直接使用@ResponseBody注解实现此功能
所需配置
1、 添加依赖,如何不添加会出现下图中的错误
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.1</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.12.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.12.1</version>
</dependency>
2、添加MVC的注解驱动
<!--开启mvc的注解驱动-->
<mvc:annotation-driven />
3、使用@ResponseBody注解标识控制器方法,在方法中,将需要转换为json字符串并响应到浏览器的java对象作为控制器方法的返回值,此时SpringMVC就可以将此对象直接转换为json字符串并响应到浏览器
package com.itzhh.controller;
import com.itzhh.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
import java.util.Map;
/**
* Author: zhh
* Date: 2023-01-22 23:12
* Description: <描述>
*/
@Controller
public class TestController {
@RequestMapping("/test/show")
@ResponseBody
public String show(){
return "Hello";
}
@RequestMapping("/test/show2")
@ResponseBody
public Map<String, Object> show2(){
Map<String, Object> map = new HashMap();
User user1 = new User(1,"abc","1123","456",1);
User user2 = new User(2,"dcf","1123","456",2);
User user3 = new User(3,"yhb","1123","456",1);
User user4 = new User(4,"okn","1123","456",2);
User user5 = new User(5,"rty","1123","456",1);
map.put("user1",user1);
map.put("user2",user2);
map.put("user3",user3);
map.put("user4",user4);
map.put("user5",user5);
return map;
}
}
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<a th:href="@{login.html}">前往登录界面</a>
<a th:href="@{/test/show}">测试ResponseBody</a>
<a th:href="@{/test/show2}">测试ResponseBody2</a>
</body>
</html>
- 结果图
@RestController注解
- @RestController注解是springMVC提供的一个复合注解,标识在控制器的类上,就相当于为类添加了@Controller注解,并且为其中的每个方法添加了@ResponseBody注解
文件的上传和下载
下载
- ResponseEntity:可以作为控制器方法的返回值,表示响应到浏览器的完整的响应报文
@RequestMapping("/test/down")
public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException {
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取服务器中文件的真实路径
String realPath = servletContext.getRealPath("img");
realPath = realPath + File.separator + "pic1.png";
//创建输入流
InputStream is = new FileInputStream(realPath);
//创建字节数组,is.available()获取输入流所对应文件的字节数
byte[] bytes = new byte[is.available()];
//将流读到字节数组中
is.read(bytes);
//创建HttpHeaders对象设置响应头信息
MultiValueMap<String, String> headers = new HttpHeaders();
//设置要下载方式以及下载文件的名字
headers.add("Content-Disposition", "attachment;filename=pic1.png");
//设置响应状态码
HttpStatus statusCode = HttpStatus.OK;
//创建ResponseEntity对象
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(bytes, headers, statusCode);
//关闭输入流
is.close();
return responseEntity;
}
上传
- 文件上传要求form表单的请求方式必须为post,并且添加属性enctype=“multipart/form-data” SpringMVC中将上传的文件封装到MultipartFile对象中,通过此对象可以获取文件相关信息
步骤
1、添加依赖:
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
2、在SpringMVC的配置文件中添加配置:
<!--必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
3、控制器方法以及form表单上传代码:
@RequestMapping("/test/up")
public String testUp(MultipartFile photo, HttpSession session) throws IOException {
//获取上传的文件的文件名
String fileName = photo.getOriginalFilename();
//获取上传的文件的后缀名
String hzName = fileName.substring(fileName.lastIndexOf("."));
//获取uuid
String uuid = UUID.randomUUID().toString();
//拼接一个新的文件名
fileName = uuid + hzName;
//获取ServletContext对象
ServletContext servletContext = session.getServletContext();
//获取当前工程下photo目录的真实路径
String photoPath = servletContext.getRealPath("photo");
//创建photoPath所对应的File对象
File file = new File(photoPath);
//判断file所对应目录是否存在
if(!file.exists()){
file.mkdir();
}
String finalPath = photoPath + File.separator + fileName;
//上传文件
photo.transferTo(new File(finalPath));
return "success";
}
<form th:action="@{/test/up}" method="post" enctype="multipart/form-data">
头像:<input type="file" name="photo"><br>
<input type="submit" value="上传">
</form>
- 结果
拦截器
SpringMVC中的拦截器有三个抽象方法:
- preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法
- postHandle:控制器方法执行之后执行postHandle()
- afterCompletion:处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()
步骤:
1、写一个类实现HandlerInterceptor接口,重写其中的三个方法,有默认的。
@Component
public class FirstInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("FirstInterceptor---->preHandle");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("FirstInterceptor---->postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("FirstInterceptor---->afterCompletion");
}
}
2、在springmvc.xml中配置:三种配置方式,如何要求不高,可以使用前面两种,要是有需要排除的用第三种
<mvc:interceptors>
<!-- <bean class="com.itzhh.interceptor.FirstInterceptor"/>-->
<!-- <ref bean="firstInterceptor"/>-->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<!-- 配置需要拦截的请求的请求路径,/**表示所有请求-->
<mvc:mapping path="/**"/>
<!-- 配置需要排除拦截的请求的请求路径-->
<mvc:exclude-mapping path="/abc"/>
<!-- 配置拦截器-->
<ref bean="firstInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
3、编写测试controller
@Controller
public class TestController {
@RequestMapping("/test/test1")
public String testInterceptor(){
return "success";
}
}
<a th:href="@{test/test1}">测试拦截器</a>
- 如果重写的preHandle方法返回false,则被拦截,不执行后面的
- 如果为true,则执行,不会拦截
多个拦截器的执行顺序
- 多个拦截器的执行顺序和在SpringMVC的配置文件中配置的顺序有关
preHandle()按照配置的顺序执行,而postHandle()和afterCompletion()按照配置的反序执行
<ref bean="firstInterceptor"/>
<ref bean="secondInterceptor"/>
- 若拦截器中有某个拦截器的preHandle()返回了false
拦截器的preHandle()返回false和它之前的拦截器的preHandle()都会执行
所有的拦截器的postHandle()都不执行
拦截器的preHandle()返回false之前的拦截器的afterCompletion()会执行
异常处理器
基于xml配置异常处理器
- 在springmvc.xml中配置下列bean即可
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<!--
properties的键表示处理器方法执行过程中出现的异常
properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面
-->
<prop key="java.lang.ArithmeticException">error</prop>
</props>
</property>
<!-- exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享-->
<property name="exceptionAttribute" value="ex"></property>
</bean>
- 测试代码
@RequestMapping("/test/test2")
public String test2(){
int a=1/0;
return "success";
}
error.html
<body>
<h1>error</h1>
<p th:text="${ex}"></p>
</body>
- 结果
基于注解配置异常处理器
package com.itzhh.controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
//将当前类标识为异常处理的组件
@ControllerAdvice
public class ExceptionController {
//设置要处理的异常信息
@ExceptionHandler(ArithmeticException.class)
public String handleException(Throwable ex, Model model){
//ex表示控制器方法所出现的异常
model.addAttribute("ex", ex);
return "error";
}
}
注解配置SpringMVC
在Servlet3.0环境中,容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类,如果找到的话就用它来配置Servlet容器。 Spring提供了这个接口的实现,名为SpringServletContainerInitializer,这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。Spring3.2引入了一个便利的WebApplicationInitializer基础实现,名为AbstractAnnotationConfigDispatcherServletInitializer,当我们的类扩展了AbstractAnnotationConfigDispatcherServletInitializer并将其部署到Servlet3.0容器的时候,容器会自动发现它,并用它来配置Servlet上下文。
通过注解配置,我们将不再需要web.xml和springmvc.xml,直接通过创建配置类来实现
- 创建WebInit代替web.xml
package com.itzhh.config;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.filter.HiddenHttpMethodFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
import javax.servlet.Filter;
import javax.swing.*;
/**
* Author: zhh
* Date: 2023-02-06 9:52
* Description: 代替web.xml
*/
public class WebInit extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
//设置一个配置类代替Spring的配置文件
protected Class<?>[] getRootConfigClasses() {
return new Class[]{SpringConfig.class};
}
@Override
//设置一个配置类代替SpringMVC的配置文件
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class};
}
@Override
//设置SpringMVC的前端控制器DispatcherServlet的url-pattern
protected String[] getServletMappings() {
return new String[]{"/"};
}
@Override
//设置当前的过滤器
protected Filter[] getServletFilters() {
//创建编码过滤器
CharacterEncodingFilter characterEncodingFilter=new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
//创建处理请求方式的过滤器
HiddenHttpMethodFilter hiddenHttpMethodFilter=new HiddenHttpMethodFilter();
return new Filter[]{characterEncodingFilter, hiddenHttpMethodFilter};
}
}
- 之前的web.xml,在配置类中一一对应
<?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_4_0.xsd"
version="4.0">
<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>
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<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:springmvc.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>
</web-app>
2.创建SpringConfig代替Spring的配置文件
package com.itzhh.config;
import org.springframework.context.annotation.Configuration;
/**
* Author: zhh
* Date: 2023-02-06 9:52
* Description: 代替Spring的配置文件
*/
//将类标识为配置类
@Configuration
public class SpringConfig {
}
- 创建WebConfig代替SpringMVC的配置文件
之前通过配置文件一共配置了8个,同过注解配置也是,一一对应
package com.itzhh.config;
import com.itzhh.interceptor.FirstInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.view.ThymeleafViewResolver;
import org.thymeleaf.templatemode.TemplateMode;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.ServletContextTemplateResolver;
import java.util.List;
import java.util.Properties;
/**
* Author: zhh
* Date: 2023-02-06 9:52
* Description: 代替SpringMVC的配置文件
* 扫描组件、视图解析器、默认的servlet、mvc的注解驱动
* 视图控制器、文件上传解析器、拦截器、异常解析器
*/
//将类标识为配置类
@Configuration
//扫描组件
@ComponentScan("com.itzhh")
//开启nvc的注解驱动
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
//默认的servlet静态资源
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
//配置视图解析器
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
//@Bean注解可以将标识的方法的返回值作为bean进行管理,bean的id为方法的方法名
@Bean
public CommonsMultipartResolver multipartResolver(){
return new CommonsMultipartResolver();
}
@Override
//配置拦截器
public void addInterceptors(InterceptorRegistry registry) {
FirstInterceptor firstInterceptor=new FirstInterceptor();
registry.addInterceptor(firstInterceptor).addPathPatterns("/**");
}
@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("ex");
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;
}
}
- 之前的springmvc.xml
<?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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 自动扫描包-->
<context:component-scan base-package="com.itzhh.controller"></context:component-scan>
<!-- 配置Thymeleaf视图解析器 -->
<bean id="viewResolver" class="org.thymeleaf.spring5.view.ThymeleafViewResolver">
<property name="order" value="1"/>
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring5.SpringTemplateEngine">
<property name="templateResolver">
<bean class="org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver">
<!-- 视图前缀 -->
<property name="prefix" value="/WEB-INF/templates/"/>
<!-- 视图后缀 -->
<property name="suffix" value=".html"/>
<property name="templateMode" value="HTML5"/>
<property name="characterEncoding" value="UTF-8" />
</bean>
</property>
</bean>
</property>
</bean>
<!--
配置默认的servlet处理静态资源
当前工程的web.xml配置的前端控制器DispatcherServlet的url-pattern是/
tomcat的web.xml配置的DefaultServlet的url-pattern也是/
此时,浏览器发送的请求会优先被DispatcherServlet进行处理,但是DispatcherServlet无法处理静态资源
若配置了<mvc:default-servlet-handler />,此时浏览器发送的所有请求都会被DefaultServlet处理
若配置了<mvc:default-servlet-handler />和<mvc:annotation-driven />
浏览器发送的请求会先被DispatcherServlet处理,无法处理在交给DefaultServlet处理
-->
<mvc:default-servlet-handler />
<!--开启mvc的注解驱动-->
<mvc:annotation-driven />
<!--配置视图控制器-->
<mvc:view-controller path="/" view-name="index"></mvc:view-controller>
<!--文件上传控制器:必须通过文件解析器的解析才能将文件转换为MultipartFile对象-->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
<!-- 拦截器-->
<!-- <mvc:interceptors>-->
<!--<!– <bean class="com.itzhh.interceptor.FirstInterceptor"/>–>-->
<!-- <ref bean="firstInterceptor"/>-->
<!-- <ref bean="secondInterceptor"/>-->
<!-- <mvc:interceptor>-->
<!-- <mvc:mapping path="/**"/>-->
<!--<!– 配置需要拦截的请求的请求路径,/**表示所有请求–>-->
<!-- <mvc:mapping path="/**"/>-->
<!--<!– 配置需要排除拦截的请求的请求路径–>-->
<!-- <mvc:exclude-mapping path="/abc"/>-->
<!--<!– 配置拦截器–>-->
<!-- <ref bean="firstInterceptor" />-->
<!-- </mvc:interceptor>-->
<!-- </mvc:interceptors>-->
<!--异常解析器-->
<!-- <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">-->
<!-- <property name="exceptionMappings">-->
<!-- <props>-->
<!-- <!–-->
<!-- properties的键表示处理器方法执行过程中出现的异常-->
<!-- properties的值表示若出现指定异常时,设置一个新的视图名称,跳转到指定页面-->
<!-- –>-->
<!-- <prop key="java.lang.ArithmeticException">error</prop>-->
<!-- </props>-->
<!-- </property>-->
<!--<!– exceptionAttribute属性设置一个属性名,将出现的异常信息在请求域中进行共享–>-->
<!-- <property name="exceptionAttribute" value="ex"></property>-->
<!-- </bean>-->
</beans>
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SSM_A</artifactId>
<groupId>com.itzhh</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring_mvc_annotation</artifactId>
<packaging>war</packaging>
<dependencies>
<!-- SpringMVC -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.3.1</version>
</dependency>
<!-- 日志 -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<!-- ServletAPI -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- Spring5和Thymeleaf整合包 -->
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
<version>3.0.12.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
</dependencies>
</project>
SpringMVC常用组件
- DispatcherServlet:前端控制器
作用:统一处理请求和响应,整个流程控制的中心,由它调用其它组件处理用户的请求 - HandlerMapping:处理器映射器
作用:根据请求的url、method等信息查找Handler,即控制器方法 - Handler:处理器
作用:在DispatcherServlet的控制下Handler对具体的用户请求进行处理 - HandlerAdapter:处理器适配器
作用:通过HandlerAdapter对处理器(控制器方法)进行执行 - ViewResolver:视图解析器
作用:进行视图解析,得到相应的视图,例如:ThymeleafView、InternalResourceView、RedirectView - View:视图
作用:将模型数据通过页面展示给用户
springmvc运行机制
-
客户端发送请求到达中央控制器DispatcherServlet
-
由中央控制器负责解析整个SpringMVC的运行流程
-
当中央控制器接收到请求之后,会将请求先交给HandlerMapping进行处理
-
HandlerMapping负责解析整个SpringMVC的业务流程,将请求分发给合适的处理器
-
处理完成之后将处理的结果返回给中央控制器
-
中央控制器将处理结果交给HandlerAdapter
-
由HandlerAdapter负责适配不同类型的处理器,找到对应的Handler进行处理
-
Handler负责处理核心业务逻辑并返回响应的视图与模型 将响应结果封装成一个对象,ModelAndView
-
ModelAndView负责处理模型与视图 最终会将ModelAndView交给中央控制器 中央控制器将结果交给ViewResolver
-
ViewResolver负责解析响应结果,将其解析为具体的视图技术 根据解析结果找到View,由View使用具体的视图技术来进行具体的实现
-
最终将处理完成的结果返回给中央控制器 由中央控制器将结果返回给客户端 最终在客户端生成对应的效果