| <?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"> |
| <modelVersion>4.0.0</modelVersion> |
| |
| <groupId>com.powernode</groupId> |
| <artifactId>SpringMVC</artifactId> |
| <packaging>pom</packaging> |
| <version>1.0-SNAPSHOT</version> |
| <modules> |
| <module>springMVC-001</module> |
| <module>springmvc-hellomvc</module> |
| <module>springmvc-002</module> |
| <module>springMVC-003</module> |
| </modules> |
| |
| <properties> |
| <maven.compiler.source>17</maven.compiler.source> |
| <maven.compiler.target>17</maven.compiler.target> |
| </properties> |
| |
| <dependencies> |
| <dependency> |
| <groupId>org.springframework</groupId> |
| <artifactId>spring-webmvc</artifactId> |
| <version>6.1.7</version> |
| </dependency> |
| |
| <dependency> |
| <groupId>org.thymeleaf</groupId> |
| <artifactId>thymeleaf-spring6</artifactId> |
| <version>3.1.2.RELEASE</version> |
| </dependency> |
| |
| <dependency> |
| <groupId>jakarta.servlet</groupId> |
| <artifactId>jakarta.servlet-api</artifactId> |
| <version>6.1.0</version> |
| |
| <scope>provided</scope> |
| </dependency> |
| |
| |
| |
| |
| |
| |
| |
| <dependency> |
| <groupId>ch.qos.logback</groupId> |
| <artifactId>logback-classic</artifactId> |
| <version>1.5.3</version> |
| </dependency> |
| |
| </dependencies> |
| |
| </project> |
- 新建maven模块springmvc-002
在springmvc-002模块中的pom.xml中新增打包方式为war
| <?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>SpringMVC</artifactId> |
| <groupId>com.powernode</groupId> |
| <version>1.0-SNAPSHOT</version> |
| </parent> |
| <modelVersion>4.0.0</modelVersion> |
| |
| <artifactId>springmvc-002</artifactId> |
| <packaging>war</packaging> |
| |
| <properties> |
| <maven.compiler.source>17</maven.compiler.source> |
| <maven.compiler.target>17</maven.compiler.target> |
| </properties> |
| |
| </project> |
- 在springmvc-002模块上右击,新增框架支持,如图所示:

- 补充:从Java EE 8开始,Servlet API的维护权转交给了Eclipse Foundation的Jakarta EE社区。因此,在最新的Jakarta EE版本中,Servlet API的包名已经从javax.servlet更改为了jakarta.servlet。这意味着jakarta.servlet-api是Servlet API在Jakarta EE 9(以及后续版本)中的新命名形式。
- 添加完web框架后会自动生成web目录,如图所示

- 编辑web.xml文件
| <?xml version="1.0" encoding="UTF-8"?> |
| <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" |
| version="5.0"> |
| |
| |
| <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>0</load-on-startup> |
| </servlet> |
| |
| <servlet-mapping> |
| <servlet-name>springmvc</servlet-name> |
| <url-pattern>/</url-pattern> |
| </servlet-mapping> |
| </web-app> |
| <?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.powernode.springmvc.controller"/> |
| |
| |
| |
| <bean id="viewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"> |
| |
| <property name="characterEncoding" value="utf-8"/> |
| |
| <property name="order" value="1"/> |
| <property name="templateEngine"> |
| <bean class="org.thymeleaf.spring6.SpringTemplateEngine"> |
| <property name="templateResolver"> |
| <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"> |
| |
| <property name="prefix" value="/WEB-INF/templates/"/> |
| |
| <property name="suffix" value=".html"/> |
| |
| <property name="templateMode" value="HTML"/> |
| |
| <property name="characterEncoding" value="utf-8"/> |
| </bean> |
| </property> |
| </bean> |
| </property> |
| </bean> |
| |
| </beans> |
- 在com.powernode.springmvc.controller新增IndexController类
| package com.powernode.springmvc.controller; |
| |
| import org.springframework.stereotype.Controller; |
| import org.springframework.web.bind.annotation.RequestMapping; |
| |
| @Controller |
| public class IndexController { |
| @RequestMapping("/") |
| public String index(){ |
| return "index"; |
| } |
| |
| @RequestMapping("/first") |
| public String first(){ |
| System.out.println("业务逻辑"); |
| return "first"; |
| } |
| } |
- 在WEB-INF目录下新增templates目录,并在此目录下新增firstm.html文件和index.html
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>Title</title> |
| </head> |
| <body> |
| <h1>First HTML PAGE</h1> |
| </body> |
| </html> |
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>首页</title> |
| </head> |
| <body> |
| <h1>首页</h1> |
| <a th:href="@{/first}">First Spring MVC Code!</a> |
| </body> |
| </html> |
- 启动tomcat10,访问http://localhost:8080/ 效果图

单击First Spring MVC Code!后打开下图

获取请求数据的几种方法
- 使用原生的Servlet API进行获取
- 补充: Servlet接口是Java Servlet API中的一个核心接口,它定义了Servlet的生命周期方法以及用于处理HTTP请求和响应的方法。一个Servlet是运行在Web服务器或Servlet容器(如Apache Tomcat、Jetty等)中的Java程序,用于扩展服务器的功能。
Servlet接口中定义的主要方法有:
init(ServletConfig config): 当Servlet被加载到容器中时调用,用于初始化Servlet。
service(ServletRequest req, ServletResponse res): 这是Servlet处理请求的主要方法,但通常我们不直接实现它,而是重写doGet()、doPost()等特定HTTP方法的方法。
destroy(): 当Servlet不再需要时(例如,服务器关闭或重新加载Servlet时)调用,用于释放资源。
ServletRequest接口代表客户端发送的HTTP请求。它定义了一系列方法来获取请求信息,如请求头、请求参数、请求方法、请求路径等。
- 在SpringMVC当中,一个Controller类中的方法参数上如果有HttpServletRequest,SpringMVC会自动将当前请求对象传递给这个参数,因此我们可以通过这个参数来获取请求提交的数据。测试一下。
- 前端准备注册页面register.html
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>用户注册</title> |
| </head> |
| <body> |
| |
| <form th:action="@{/user/reg}" method="post"> |
| 用户名: <input type="text" name="username"><br> |
| 密码: <input type="password" name="password"><br> |
| 性别: |
| 男<input type="radio" name="sex" value="1"> |
| 女<input type="radio" name="sex" value="0"> |
| <br> |
| 兴趣: |
| 抽烟<input type="checkbox" name="interest" value="smoke"> |
| 喝酒<input type="checkbox" name="interest" value="drink"> |
| 烫头:<input type="checkbox" name="interest" value="perm"> |
| <br> |
| 简介: |
| <textarea cols="60" rows="10" name="intro"></textarea> |
| <br> |
| <input type="submit" value="注册"/> |
| </form> |
| </body> |
| </html> |
| |
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>ok</title> |
| </head> |
| <body> |
| <h1>Test OK!</h1> |
| </body> |
| </html> |
- 准备Controller类,UserController
| package com.powernode.springmvc.controller; |
| |
| import jakarta.servlet.http.HttpServletRequest; |
| import jakarta.servlet.http.HttpServletResponse; |
| import jakarta.servlet.http.HttpSession; |
| import org.springframework.stereotype.Controller; |
| import org.springframework.web.bind.annotation.RequestMapping; |
| import org.springframework.web.bind.annotation.RequestMethod; |
| import org.springframework.web.bind.annotation.RequestParam; |
| |
| import java.util.Arrays; |
| |
| @Controller |
| public class UserController { |
| @RequestMapping("/") |
| public String toRegister(){ |
| return "register"; |
| } |
| |
| /*第一种方法原生的Servlet API*/ |
| /*@RequestMapping(value = "/user/reg",method = {RequestMethod.POST}) |
| public String register(HttpServletRequest request, HttpServletResponse response, HttpSession session){ |
| |
| //获取请求提交的数据 |
| String username = request.getParameter("username"); |
| String password = request.getParameter("password"); |
| String sex = request.getParameter("sex"); |
| String[] interest = request.getParameterValues("interest"); |
| String intro = request.getParameter("intro"); |
| |
| System.out.println(username); |
| System.out.println(password); |
| System.out.println(sex); |
| System.out.println(Arrays.toString(interest)); |
| System.out.println(intro); |
| return "ok"; |
| }*/ |
| |
| /*第二种方法:通过注解@RequestParam*/ |
| /*@RequestMapping(value = "/user/reg",method = {RequestMethod.POST}) |
| public String register( |
| @RequestParam("username") |
| String username, //变量名可以自定义 |
| @RequestParam("password") |
| String password, |
| @RequestParam(value = "sex",defaultValue = "1") |
| Integer sex, |
| @RequestParam("interest") |
| String[] interest, |
| @RequestParam("intro") |
| String intro){ |
| System.out.println(username); |
| System.out.println(password); |
| System.out.println(sex); |
| System.out.println(Arrays.toString(interest)); |
| System.out.println(intro); |
| return "ok"; |
| }*/ |
| |
| |
| /*第三种方法(不常用):如果方法形参的名字和提交数据时的name相同,则 @RequestParam 可以省略。*/ |
| /*@RequestMapping(value = "/user/reg",method = {RequestMethod.POST}) |
| public String register( |
| String username, //此处变量名如果写错,那么前端提交后值为null |
| String password, |
| Integer sex, |
| String[] interest, |
| String intro){ |
| System.out.println(username); |
| System.out.println(password); |
| System.out.println(sex); |
| System.out.println(Arrays.toString(interest)); |
| System.out.println(intro); |
| return "ok"; |
| }*/ |
| |
| /*第四种方法:POJO类/JavaBean接收请求参数,当提交的数据非常多时,方法的形参个数会非常多,这不是很好的设计。在SpringMVC中也可以使用POJO类来接收请求参数。要求POJO类的属性名必须和请求参数的参数名保持一致*/ |
| @RequestMapping(value = "/user/reg",method = {RequestMethod.POST}) |
| public String register(User user, |
| @RequestHeader(value = "Referer", required = false,defaultValue ="" ) |
| String referer){ |
| System.out.println(user); |
| System.out.println(referer); |
| return "ok"; |
| } |
| } |
其中@RequestHeader是将请求头信息中的Referer映射到形参referer上,前端提交后后台能看到Referer对应的值.
POJO类如下:
| package com.powernode.springmvc.pojo; |
| |
| import java.util.Arrays; |
| |
| public class User { |
| private Long id; |
| private String username; |
| private String password; |
| private Integer sex; |
| private String[] interest; |
| private String intro; |
| private String age; |
| |
| |
| |
| |
| public User(Long id, String username, String password, Integer sex, String[] interest, String intro, String age) { |
| this.id = id; |
| this.username = username; |
| this.password = password; |
| this.sex = sex; |
| this.interest = interest; |
| this.intro = intro; |
| this.age = age; |
| } |
| |
| public Long getId() { |
| return id; |
| } |
| |
| public void setId(Long id) { |
| this.id = id; |
| } |
| |
| public String getUsername() { |
| return username; |
| } |
| |
| public void setUsername(String username) { |
| this.username = username; |
| } |
| |
| public String getPassword() { |
| return password; |
| } |
| |
| public String getAge() { |
| return age; |
| } |
| |
| public void setAge(String age) { |
| this.age = age; |
| } |
| |
| public void setPassword(String password) { |
| this.password = password; |
| } |
| |
| public Integer getSex() { |
| return sex; |
| } |
| |
| public void setSex(Integer sex) { |
| this.sex = sex; |
| } |
| |
| public String[] getInterest() { |
| return interest; |
| } |
| |
| public void setInterest(String[] interest) { |
| this.interest = interest; |
| } |
| |
| public String getIntro() { |
| return intro; |
| } |
| |
| public void setIntro(String intro) { |
| this.intro = intro; |
| } |
| |
| @Override |
| public String toString() { |
| return "User{" + |
| "id=" + id + |
| ", username='" + username + '\'' + |
| ", password='" + password + '\'' + |
| ", sex=" + sex + |
| ", interest=" + Arrays.toString(interest) + |
| ", intro='" + intro + '\'' + |
| ", age='" + age + '\'' + |
| '}'; |
| } |
| } |
| |
第三种方法有一个前提:如果你采用的是Spring6+版本,需要在该模块的pom.xml文件中指定编译参数'-parameter',配置如下:
| <build> |
| <plugins> |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-compiler-plugin</artifactId> |
| <version>3.1</version> |
| <configuration> |
| <source>17</source> |
| <target>17</target> |
| <compilerArgs> |
| <arg>-parameters</arg> |
| </compilerArgs> |
| </configuration> |
| </plugin> |
| </plugins> |
| </build> |
分别测试以上方法,启动tomcat,在浏览器打开效果图:

输入选项后能够跳转到ok页面,可以通过浏览器F12查看提交的表单数据,也可以在idea控制台看到所填的值

如果前端有cookie,后端可以通过@CookieValue获取前端提交的cookie,比如id(此处的id是测试在前端提前生成好的),通过Get方式获得.
| @GetMapping(value = {"/user/reg"}) |
| public String register(User user, |
| @RequestHeader(value = "Referer", required = false,defaultValue ="" ) |
| String referer, |
| @CookieValue(value = "id",required = false,defaultValue = "") |
| String id){ |
| System.out.println(user); |
| System.out.println(referer); |
| System.out.println("客户端提交过来的CookieID值"+id); |
| return "ok"; |
| } |
---
2024年7月5日
request域对象
接口名:HttpServletRequest
简称:request
request对象代表了一次请求。一次请求一个request。
使用请求域的业务场景:在A资源中通过转发的方式跳转到B资源,因为是转发,因此从A到B是一次请求,如果想让A资源和B资源共享同一个数据,可以将数据存储到request域中。
- 在上面的父项目中创建模块springmvc-005,刷新新模块中的pom.xml,引用父项目中依赖.
- 添加web支持.spring6中添加web依赖


- 编写web.xml
| <?xml version="1.0" encoding="UTF-8"?> |
| <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" |
| version="5.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> |
| |
| |
| <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-servlet.xml</param-value> |
| </init-param> |
| </servlet> |
| |
| <servlet-mapping> |
| <servlet-name>springmvc</servlet-name> |
| <url-pattern>/</url-pattern> |
| </servlet-mapping> |
| </web-app> |
- 创建IndexController
| package com.powernode.springmvc.controller; |
| |
| import org.springframework.stereotype.Controller; |
| import org.springframework.web.bind.annotation.RequestMapping; |
| |
| @Controller |
| public class IndexController { |
| @RequestMapping("/") |
| public String index(){ |
| return "index"; |
| } |
| } |
- 创建spring配置文件并编辑
| <?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.powernode.springmvc.controller"/> |
| |
| |
| <bean id="viewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"> |
| |
| <property name="characterEncoding" value="utf-8"/> |
| |
| <property name="order" value="1"/> |
| <property name="templateEngine"> |
| <bean class="org.thymeleaf.spring6.SpringTemplateEngine"> |
| <property name="templateResolver"> |
| <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"> |
| |
| <property name="prefix" value="/WEB-INF/templates/"/> |
| |
| <property name="suffix" value=".html"/> |
| |
| <property name="templateMode" value="HTML"/> |
| |
| <property name="characterEncoding" value="utf-8"/> |
| </bean> |
| </property> |
| </bean> |
| </property> |
| </bean> |
| |
| </beans> |
- 编写index.html,都测试完成后写的文档,所以index.html页面后后面测试的内容.
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>Title</title> |
| </head> |
| <body> |
| <h1>测试三个域对象</h1> |
| <h2>测试request域对象</h2> |
| <a th:href="@{/testServletAPI}">测试在SpringMVC当中使用原生Servlet API,完成request域共享</a><br> |
| <h2>测试Model接口</h2> |
| <a th:href="@{/testModel}">测试在SpringMVC当中使用Model接口,完成request域共享</a><br> |
| <h2>测试Map接口</h2> |
| <a th:href="@{/testMap}">测试在SpringMVC当中使用Map接口,完成request域共享</a><br> |
| <h2>测试ModelMap接口</h2> |
| <a th:href="@{/testModelMap}">测试在SpringMVC当中使用ModelMap接口,完成request域共享</a><br> |
| <h2>测试ModelAndView</h2> |
| <a th:href="@{/testModelAndView}">测试在SpringMVC当中使用ModelAndView类,完成request域共享</a><br> |
| </body> |
| </html> |
- 创建转发成功访问的ok.html
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>ok</title> |
| </head> |
| <body> |
| <div th:text="${testRequestScope}"></div> |
| </body> |
| </html> |

- 在SpringMVC中,在request域中共享数据有以下几种方式:
- 使用原生HttpServletRequestAPI方式。
- 使用Model接口。
- 使用Map接口。
- 使用ModelMap类。
- 使用ModelAndView类。
| package com.powernode.springmvc.controller; |
| |
| import jakarta.servlet.http.HttpServletRequest; |
| import org.springframework.stereotype.Controller; |
| import org.springframework.ui.Model; |
| import org.springframework.ui.ModelMap; |
| import org.springframework.web.bind.annotation.GetMapping; |
| import org.springframework.web.bind.annotation.RequestMapping; |
| import org.springframework.web.servlet.ModelAndView; |
| |
| import java.util.Map; |
| |
| @Controller |
| public class RequestScopeTestController { |
| @RequestMapping("/testServletAPI") |
| public String testServletAPI(HttpServletRequest request){ |
| |
| request.setAttribute("testRequestScope","在SpringMVC中使用原生ServletAPI完成request域数据共享"); |
| return "ok"; |
| } |
| |
| |
| @RequestMapping("/testModel") |
| public String testModel(Model model){ |
| |
| model.addAttribute("testRequestScope","在SpringMVC中使用Model接口完成request域数据共享"); |
| System.out.println(model); |
| System.out.println(model.getClass().getName()); |
| return "ok"; |
| } |
| |
| @RequestMapping("/testMap") |
| public String testMap(Map<String,Object> map){ |
| |
| map.put("testRequestScope","在SpringMVC中使用Map接口完成request域数据共享"); |
| System.out.println(map); |
| System.out.println(map.getClass().getName()); |
| |
| return "ok"; |
| } |
| |
| @GetMapping("/testModelMap") |
| public String testMap(ModelMap modelMap){ |
| |
| modelMap.addAttribute("testRequestScope","在SpringMVC中使用ModelMap接口完成request域数据共享"); |
| System.out.println(modelMap); |
| System.out.println(modelMap.getClass().getName()); |
| |
| return "ok"; |
| } |
| |
| @RequestMapping("/testModelAndView") |
| public ModelAndView testModelAndView(){ |
| |
| ModelAndView modelAndView = new ModelAndView(); |
| |
| modelAndView.addObject("testRequestScope","在SpringMVC中使用ModelAndView接口完成request域数据共享"); |
| |
| modelAndView.setViewName("ok"); |
| System.out.println("获取ModelAndView类名称"+modelAndView.getClass().getName()); |
| return modelAndView; |
| } |
| } |
- 通过测试无论是Model、Map还是ModelMap,底层实例化的对象都是:BindingAwareModelMap


-
内部实现类:BindingAwareModelMap 是 Spring MVC 内部用于实现 Model、ModelMap 接口和 Map<String, Object> 的具体类。
-
数据传递:在 Spring MVC 中,控制器方法可以通过参数接收 Model、ModelMap 或 Map 类型的对象,并向其中添加数据。这些数据最终会通过 BindingAwareModelMap 实例进行管理和传递,最终到达视图层。
-
请求域绑定:BindingAwareModelMap 中的数据默认会绑定到 HTTP 请求的作用域(request scope)中,使得视图层可以方便地访问这些数据。
-
不要直接使用:尽管 BindingAwareModelMap 提供了许多功能,但开发者通常不需要(也不应该)直接在代码中创建或操作 BindingAwareModelMap 的实例。相反,应该通过 Model、ModelMap 或 Map 接口来与模型数据进行交互。
-
作用域:默认情况下,BindingAwareModelMap 中的数据会绑定到 HTTP 请求的作用域中。这意味着这些数据只在当前请求的生命周期内有效。如果需要跨多个请求共享数据,可以考虑使用其他作用域(如 session scope)或数据存储机制(如数据库)。
- 但是在SpringMVC框架中为了更好的体现MVC架构模式,提供了一个类:ModelAndView。这个类的实例封装了Model和View。也就是说这个类既封装业务处理之后的数据,也体现了跳转到哪个视图。使用它也可以完成request域数据共享。需要注意:
- 方法的返回值类型不是String,而是ModelAndView对象。
- ModelAndView不是出现在方法的参数位置,而是在方法体中new的。
- 需要调用addObject向域中存储数据。
- 需要调用setViewName设置视图的名字。
- 在Spring MVC中,ModelAndView 是用于将模型数据和视图名称封装在一起的一个类。ModelAndView 本身并不直接使用 BindingAwareModelMap,但确实使用了一个模型映射(Model Map)来存储模型数据。
BindingAwareModelMap 是Spring MVC内部使用的一个类,它扩展了 ModelMap(后者又扩展了 LinkedHashMap),并添加了一些额外的功能,主要是与数据绑定相关的
在 ModelAndView 的上下文中,你通常不会直接看到 BindingAwareModelMap 的使用,因为 ModelAndView 提供了 addObject、addAllObjects 等方法来向模型中添加数据,这些方法会委托给其内部的模型映射(通常是 ModelMap 的一个实例,但不一定是 BindingAwareModelMap)。
但是,在某些情况下,Spring MVC内部可能会使用 BindingAwareModelMap 来处理与数据绑定相关的场景。例如,在处理带有表单提交的请求时,如果使用了 @ModelAttribute 注解,并且表单验证失败,Spring MVC可能会使用 BindingAwareModelMap 来存储表单数据以及验证错误。
总的来说,虽然 ModelAndView 不直接使用 BindingAwareModelMap,但Spring MVC在处理与数据绑定相关的场景时可能会使用它。在大多数情况下,你不需要直接关注这一点,只需要使用 ModelAndView 来封装你的模型数据和视图名称即可。
session域对象
在SpringMVC中使用session域共享数据,实现方式有多种,其中比较常见的两种方式:
- 使用原生HttpSession API
- 使用SessionAttributes注解
- 在上面基础上创建SessionScopeController类,分别包括原生的和SessionAttributes注解
| package com.powernode.springmvc.controller; |
| |
| import jakarta.servlet.http.HttpServletRequest; |
| import jakarta.servlet.http.HttpServletResponse; |
| import jakarta.servlet.http.HttpSession; |
| import org.springframework.stereotype.Controller; |
| import org.springframework.ui.ModelMap; |
| import org.springframework.web.bind.annotation.RequestMapping; |
| import org.springframework.web.bind.annotation.SessionAttributes; |
| |
| @Controller |
| @SessionAttributes(value = {"X","Y"}) |
| public class SessionScopeController { |
| @RequestMapping("/testSessionServletAPI") |
| public String testServletAPI(HttpServletRequest request, HttpServletResponse response, HttpSession session){ |
| |
| |
| session.setAttribute("testSessionScope","测试在SpringMVC当中使用原生HttpSessionAPI,完成request域共享"); |
| |
| return "ok"; |
| } |
| |
| @RequestMapping("/testSessionAttribute") |
| public String testSessionAttribute(ModelMap modelMap){ |
| |
| |
| modelMap.addAttribute("X","我是X"); |
| modelMap.addAttribute("Y","我是Y"); |
| return "ok"; |
| } |
| } |
| 注意:@SessionAttributes注解使用在Controller类上。标注了当key是 x 或者 y 时,数据将被存储到会话session中。如果没有 SessionAttributes注解,默认存储到request域中。 |
| <h2>测试session域对象</h2> |
| <a th:href="@{/testSessionServletAPI}">测试在SpringMVC当中使用HttpSession接口,完成session域共享</a><br> |
| <a th:href="@{/testSessionAttribute}">测试在SpringMVC当中使用@SessionAttributes注解,完成session域共享</a><br> |
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>ok</title> |
| </head> |
| <body> |
| <div th:text="${testRequestScope}"></div> |
| <div th:text="${session.testSessionScope}"> |
| </div> |
| <p th:text="${session.X}"></p> |
| <p th:text="${session.Y}"></p> |
| </body> |
| </html> |
RESTFul编程风格
RESTFul是WEB服务接口的一种设计风格。
RESTFul定义了一组约束条件和规范,可以让WEB服务接口更加简洁、易于理解、易于扩展、安全可靠。
REST对请求方式的约束是这样的:
● 查询必须发送GET请求
● 新增必须发送POST请求
● 修改必须发送PUT请求
● 删除必须发送DELETE请求
REST对URL的约束是这样的:
● 传统的URL:get请求,/springmvc/getUserById?id=1
● REST风格的URL:get请求,/springmvc/user/1
● 传统的URL:get请求,/springmvc/deleteUserById?id=1
● REST风格的URL:delete请求, /springmvc/user/1
传统的 URL 与 RESTful URL 的区别是传统的 URL 是基于方法名进行资源访问和操作,而 RESTful URL 是基于资源的结构和状态进行操作的。下面是一张表格,展示两者之间的具体区别:

- 模拟get请求
- 在父模块下创建springmvc-006模块,新增web框架支持
- web.xml
| <?xml version="1.0" encoding="UTF-8"?> |
| <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" |
| xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd" |
| version="5.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>dispatcherServlet</servlet-name> |
| <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> |
| <init-param> |
| <param-name>contextConfigLocation</param-name> |
| <param-value>classpath:dispatcherServlet-servlet.xml</param-value> |
| </init-param> |
| </servlet> |
| <servlet-mapping> |
| <servlet-name>dispatcherServlet</servlet-name> |
| <url-pattern>/</url-pattern> |
| </servlet-mapping> |
| </web-app> |
- resources目录下dispatcher-servlet.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.powernode.springmvc.controller"/> |
| |
| |
| <bean id="viewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"> |
| |
| <property name="characterEncoding" value="utf-8"/> |
| |
| <property name="order" value="1"/> |
| <property name="templateEngine"> |
| <bean class="org.thymeleaf.spring6.SpringTemplateEngine"> |
| <property name="templateResolver"> |
| <bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"> |
| |
| <property name="prefix" value="/WEB-INF/templates/"/> |
| |
| <property name="suffix" value=".html"/> |
| |
| <property name="templateMode" value="HTML"/> |
| |
| <property name="characterEncoding" value="utf-8"/> |
| </bean> |
| </property> |
| </bean> |
| </property> |
| </bean> |
| |
| |
| <mvc:annotation-driven/> |
| |
| |
| <mvc:view-controller path="/" view-name="index"/> |
| |
| </beans> |
| @Controller |
| public class UserController { |
| @RequestMapping(value = "/user",method = RequestMethod.GET) |
| public ModelAndView modelAndView(){ |
| ModelAndView modelAndView = new ModelAndView(); |
| System.out.println("正在查询用户所有信息"); |
| modelAndView.setViewName("ok"); |
| return modelAndView; |
| } |
| @RequestMapping(value = "/user/{id}",method = RequestMethod.GET) |
| public String getById(@PathVariable(value = "id")String id){ |
| System.out.println("正在根据用户id查询用户信息...用户id是"+id); |
| return "ok"; |
| } |
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>首页</title> |
| </head> |
| <body> |
| <h1>测试RESTFul编程风格</h1> |
| <hr> |
| |
| <a th:href="@{/user}">查看用户列表</a><br> |
| |
| <a th:href="@{/user/110}">查询id是1的用户信息</a><br> |
| |
| |
| <form th:action="@{/user}" method="post"> |
| 用户名:<input type="text" name="username"><br> |
| 密码:<input type="password" name="password"><br> |
| 年龄:<input type="text" name="age"><br> |
| <input type="submit" name="保存"> |
| </form> |
| |
| |
| <form th:action="@{/user}" method="post"> |
| |
| <input type="hidden" name="_method" value="put"> |
| |
| 用户名:<input type="text" name="username"><br> |
| 密码:<input type="password" name="password"><br> |
| 年龄:<input type="text" name="age"><br> |
| <input type="submit" name="修改"> |
| </form> |
| |
| |
| <a th:href="@{/user/120}" onclick="dele(event)">删除用户id为120的用户信息</a> |
| <form id="deleForm" method="post"> |
| <input type="hidden" name="_method" value="delete"> |
| </form> |
| |
| <script> |
| function dele(event){ |
| |
| let deleForm = document.getElementById("deleForm"); |
| |
| deleForm.action = event.target.href; |
| |
| deleForm.onsubmit(); |
| |
| event.preventDefault(); |
| } |
| </script> |
| </body> |
| </html> |
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>ok</title> |
| </head> |
| <body> |
| <h1>OK!</h1> |
| </body> |
| </html> |
- 启动tomcat10测试


测试:查询id是1的用户信息

- 模拟post请求
| @RequestMapping(value = "/user",method = RequestMethod.POST) |
| public String save(User user){ |
| System.out.println("正在保存用户信息"); |
| System.out.println(user); |
| return "ok"; |
| } |
| package com.powernode.springmvc.bean; |
| |
| public class User { |
| private String username; |
| private String password; |
| private Integer age; |
| |
| public User(String username, String password, Integer age) { |
| this.username = username; |
| this.password = password; |
| this.age = age; |
| } |
| |
| public User() { |
| } |
| |
| 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 Integer getAge() { |
| return age; |
| } |
| |
| public void setAge(Integer age) { |
| this.age = age; |
| } |
| |
| @Override |
| public String toString() { |
| return "User{" + |
| "username='" + username + '\'' + |
| ", password='" + password + '\'' + |
| ", age=" + age + |
| '}'; |
| } |
| } |
- 启动tomcat测试


后台控制台输出信息:
正在保存用户信息
User
- 模拟PUT请求
对于PUT请求,前提是一个POST请求。然后在发送POST请求的时候,提交这样的数据:_method=PUT,最后在web.xml文件配置SpringMVC提供的过滤器:HiddenHttpMethodFilter
| @RequestMapping(value = "/user",method = RequestMethod.PUT) |
| public String modify(User user){ |
| System.out.println("正在修改用户信息: "+ user); |
| return "ok"; |
| } |
- 配置过滤器,前面已经在dispatcherServlet-servlet.xml中写了

- index.html页面的配置

- 启动tomat测试


- idea控制台输出:
正在修改用户信息: User
- 模拟delete请求
| @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE) |
| public String del(@PathVariable("id") String id){ |
| System.out.println("正在删除用户"); |
| return "ok"; |
| } |
- @ResponseBody注解
@ResponseBody 是 Spring MVC 中的一个注解,可以直接将控制器(Controller)的方法返回的对象自动转换为字符串,并写入到 HTTP 响应(HttpServletResponse)的 body 中。这样,前端就可以直接接收到这些数据
| @Controller |
| public class AjaxController { |
| |
| |
| |
| |
| |
| |
| |
| @GetMapping("/ajax") |
| @ResponseBody |
| public String ajax(){ |
| return "hello ajx,My name is SpringMVC"; |
| } |
| } |
@ResponseBody注解等同于原生的

| package com.powernode.springmvc.bean; |
| |
| public class User { |
| private Long id; |
| private String name; |
| private String password; |
| |
| public User(Long id, String name, String password) { |
| this.id = id; |
| this.name = name; |
| this.password = password; |
| } |
| |
| public User() { |
| } |
| |
| public Long getId() { |
| return id; |
| } |
| |
| public void setId(Long id) { |
| this.id = id; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public String getPassword() { |
| return password; |
| } |
| |
| public void setPassword(String password) { |
| this.password = password; |
| } |
| |
| @Override |
| public String toString() { |
| return "User{" + |
| "id=" + id + |
| ", name='" + name + '\'' + |
| ", password='" + password + '\'' + |
| '}'; |
| } |
| } |
修改AjaxController类
| @RequestMapping(value = "/ajax", method = RequestMethod.GET) |
| @ResponseBody |
| public User ajax(){ |
| User user = new User(1122L, "张三", "123"); |
| return user; |
| } |
前端Vue3+axios+Thymeleaf代码:
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>首页</title> |
| |
| |
| <script src="https://cdn.jsdelivr.net/npm/vue@3.x/dist/vue.global.js"></script> |
| |
| |
| <script th:src="@{https://cdn.staticfile.org/axios/0.27.2/axios.min.js}"></script> |
| </head> |
| <body> |
| <h1>发送Vue3+axios+Thymeleaf+springmvc发送Ajax请求</h1> |
| <hr> |
| <div id="app"> |
| <button @click="getMessage">获取消息</button> |
| <h1>{{message}}</h1> |
| </div> |
| |
| <script th:inline="javascript"> |
| Vue.createApp({ |
| data(){ |
| return{ |
| message: '' |
| } |
| }, |
| methods: { |
| |
| async getMessage(){ |
| |
| let response = await axios.get('/ajax') |
| |
| this.message = response.data |
| } |
| } |
| }).mount("#app") |
| </script> |
| </body> |
| </html> |
启动tomcat,前端通过访问/ajax,产生的效果:

补充:
MappingJackson2HttpMessageConverter是Spring框架中的一个HTTP消息转换器,主要用于在Java对象和JSON之间进行转换。
MappingJackson2HttpMessageConverter依赖于Jackson库来实现Java对象与JSON之间的序列化和反序列化。
jackson-databind是Jackson库的核心包之一,它提供了数据绑定的功能,即在Java对象和JSON之间进行转换。
所以pom.xml需要导入jackson-databind包
| |
| <dependency> |
| <groupId>com.fasterxml.jackson.core</groupId> |
| <artifactId>jackson-databind</artifactId> |
| <version>2.17.0</version> |
| </dependency> |
@RestController
在类上添加@RestController 等于 类上添加@Controller + 在每个返回数据的方法上添加@ResponseBody,因为 在类上添加@RestController 默认所有方法都带有 @ResponseBody
@RequestBody
这个注解的作用是直接将请求体传递给Java程序,在Java程序中可以直接使用一个String类型的变量接收这个请求体的内容。
- 将前端页面中的form表单提交后后台转成java对象测试:
编写User类
| package com.powernode.springmvc.bean; |
| |
| public class User { |
| private Long id; |
| private String name; |
| private String password; |
| |
| public User(Long id, String name, String password) { |
| this.id = id; |
| this.name = name; |
| this.password = password; |
| } |
| |
| public User() { |
| } |
| |
| public Long getId() { |
| return id; |
| } |
| |
| public void setId(Long id) { |
| this.id = id; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| public void setName(String name) { |
| this.name = name; |
| } |
| |
| public String getPassword() { |
| return password; |
| } |
| |
| public void setPassword(String password) { |
| this.password = password; |
| } |
| |
| @Override |
| public String toString() { |
| return "User{" + |
| "id=" + id + |
| ", name='" + name + '\'' + |
| ", password='" + password + '\'' + |
| '}'; |
| } |
| } |
编写RequestBodyController类
| package com.powernode.springmvc.controller; |
| |
| import com.powernode.springmvc.bean.User; |
| import org.springframework.stereotype.Controller; |
| import org.springframework.web.bind.annotation.*; |
| |
| |
| @RestController |
| public class RequestBodyController { |
| @PostMapping("/save") |
| public String save(@RequestBody String requestBodyStr){ |
| System.out.println(requestBodyStr); |
| return "ok"; |
| } |
| |
| |
| |
| |
| |
| |
上面的两个方法都可以获取index.html页面中提交的表单信息
| <form th:action="@{/save}" method="post"> |
| 用户名:<input type="text" name="name"/> |
| 密码:<input type="password" name="password"> |
| <input type="submit" value="保存"/> |
| </form> |
通过@RequestBody注解获取的格式是name=alice&password=222222222
,Springmvc使用FormHttpMessageConverter消息转换器,将请求体转换成user对象。
通过pojo类的方法获取的格式时User{id=null, name='江疏影', password='222222222'}
- 在请求体中提交的是一个JSON格式的字符串,这个JSON字符串传递给Spring MVC之后,将JSON字符串转换成POJO对象。
在index.html页面新增测试代码
| <!DOCTYPE html> |
| <html xmlns:th="http://www.thymeleaf.org"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>首页</title> |
| |
| |
| <script src="https://cdn.jsdelivr.net/npm/vue@3.x/dist/vue.global.js"></script> |
| |
| |
| <script th:src="@{https://cdn.staticfile.org/axios/0.27.2/axios.min.js}"></script> |
| </head> |
| <body> |
| <h1>发送Vue3+axios+Thymeleaf+springmvc发送Ajax请求</h1> |
| <hr> |
| <form th:action="@{/save}" method="post"> |
| 用户名:<input type="text" name="name"/> |
| 密码:<input type="password" name="password"> |
| <input type="submit" value="保存"/> |
| </form> |
| |
| |
| <div id="app"> |
| <button @click="getMessage">获取消息</button> |
| <h1>{{message}}</h1> |
| </div> |
| |
| <script th:inline="javascript"> |
| Vue.createApp({ |
| data(){ |
| return{ |
| message: '' |
| } |
| }, |
| methods: { |
| |
| async getMessage(){ |
| |
| let response = await axios.get('/ajax') |
| |
| this.message = response.data |
| } |
| } |
| }).mount("#app") |
| </script> |
| |
| <div id="app1"> |
| <button @click="getMessage">提交post</button> |
| <h1>{{message1}}</h1> |
| </div> |
| |
| |
| <script th:inline="javascript"> |
| let jsonObj = {"name" : "zhangsan","password":"123456"} |
| Vue.createApp({ |
| data1(){ |
| return{ |
| message: '' |
| } |
| }, |
| methods: { |
| |
| async getMessage(){ |
| |
| let response = await axios.post('/save2',JSON.stringify(jsonObj),{ |
| headers : { |
| "Content-Type": "application/json" |
| } |
| }) |
| |
| this.message1 = response.data1 |
| } |
| } |
| }).mount("#app1") |
| </script> |
| </body> |
| </html> |
| ON.stringify(jsonObj),{ |
| headers : { |
| "Content-Type": "application/json" |
| } |
| }) |
| //将返回的数据交给message |
| this.message1 = response.data1 |
| } |
| } |
| }).mount("#app1") |
| </script> |
在RequestBodyController中新增
| |
| @PostMapping(value = "/save2") |
| public String saveUser(@RequestBody User user){ |
| System.out.println(user); |
| return "ok"; |
| } |
重启tomcat,打开浏览器测试,点击"提交post"

idea后台控制台显示User{id=null, name='zhangsan', password='123456'}
,该用户信息是在index.html提交定义好的,如图所示:

RequestEntity类
RequestEntity 是 Spring Framework 的 org.springframework.http.RequestEntity 类,它用于表示一个带有请求头、请求体和 URL 的 HTTP 请求。RequestEntity 通常在发送 HTTP 请求时使用
获取index.html中的post请求信息

在RequestBodyController类中新增
| @PostMapping(value = "/save2") |
| public String saveUser(RequestEntity<User> requestEntity) { |
| |
| HttpMethod method = requestEntity.getMethod(); |
| System.out.println(method); |
| |
| URI url = requestEntity.getUrl(); |
| System.out.println(url); |
| |
| HttpHeaders headers = requestEntity.getHeaders(); |
| System.out.println("请求头"+headers); |
| |
| MediaType contentType = headers.getContentType(); |
| System.out.println("请求头中的内容信息"+contentType); |
| |
| User body = requestEntity.getBody(); |
| System.out.println(body); |
| return "ok"; |
| } |
重启tomcat,启动浏览器,点击"提交post",在ideal后台控制中心获取请求的信息,如图所示:


ResponseEntity类
ResponseEntity不是注解,是一个类。用该类的实例可以封装响应协议,包括:状态行、响应头、响应体。也就是说:如果你想定制属于自己的响应协议,可以使用该类。
假如我要完成这样一个需求:前端提交一个id,后端根据id进行查询,如果返回null,请在前端显示404错误。如果返回不是null,则输出返回的user。
| <a th:href="@{/user/2}">查找id=1的用户信息</a> |
| package com.powernode.springmvc.controller; |
| |
| import com.powernode.springmvc.bean.User; |
| import com.powernode.springmvc.service.UserService; |
| import org.springframework.beans.factory.annotation.Autowired; |
| import org.springframework.http.HttpStatus; |
| import org.springframework.http.ResponseEntity; |
| 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; |
| |
| @Controller |
| public class UserController { |
| @Autowired |
| private UserService userService; |
| |
| @RequestMapping(value = "/user/{id}",method = RequestMethod.GET) |
| public ResponseEntity<User> getById(@PathVariable("id") Long id){ |
| User user = userService.getById(id); |
| if (user == null){ |
| return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); |
| }else{ |
| return ResponseEntity.ok(user); |
| } |
| } |
| } |
| package com.powernode.springmvc.service; |
| |
| import com.powernode.springmvc.bean.User; |
| import org.springframework.stereotype.Service; |
| |
| @Service |
| public class UserService { |
| public User getById(Long id){ |
| if (id == 1){ |
| return new User(111L,"zhangsan","123"); |
| } |
| return null; |
| } |
| } |
重启tomcat,浏览器点击"查找id=1的用户信息"

跳转结果

如果浏览器地址手动更改访问为http://localhost:8080/user/2

拦截器
- 拦截器基本配置
第一种方式:在spring配置文件中配置
配置测试拦截器Interceptor1
| package com.powernode.springmvc.interceptors; |
| |
| import jakarta.servlet.http.HttpServletRequest; |
| import jakarta.servlet.http.HttpServletResponse; |
| import org.springframework.stereotype.Component; |
| import org.springframework.web.servlet.HandlerInterceptor; |
| import org.springframework.web.servlet.ModelAndView; |
| |
| @Component |
| public class Interceptor1 implements HandlerInterceptor { |
| @Override |
| public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
| System.out.println("Interceptor1's preHandlehaha"); |
| return true; |
| |
| } |
| |
| @Override |
| public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { |
| |
| System.out.println("Interceptor1's postHandle"); |
| } |
| |
| @Override |
| public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { |
| HandlerInterceptor.super.afterCompletion(request, response, handler, ex); |
| System.out.println("Interceptor1's afterCompletion"); |
| } |
| } |
- 在dispatcherServlet-servlet.xml中添加
| <mvc:interceptors> |
| <bean class="com.powernode.springmvc.interceptors.Interceptor1"/> |
| </mvc:interceptors> |
第二种方法,使用注解配置
| <mvc:interceptors> |
| |
| <ref bean="interceptor1"/> |
| </mvc:interceptors> |
第二种方式的前提:
● 前提1:包扫描

● 前提2:使用 @Component 注解进行标注

2. 自定义拦截路径
| <mvc:interceptor> |
| |
| <mvc:mapping path="/**"/> |
| |
| <mvc:exclude-mapping path="/ok"/> |
| |
| <ref bean="interceptor1"/> |
| </mvc:interceptor> |
| </mvc:interceptors> |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器
· 面试官:你是如何进行SQL调优的?