当前位置: 首页 > news >正文

框架--SpringMVC

第 1 章 SpringMVC 基础

1.1 MVC 模型

**MVC 全称 Model View Controller,是一种设计创建 Web 应用程序的模式。**这三个单词分别代表 Web 应用程序的三个部分:

  • Model(模型):指数据模型,用于存储数据以及处理用户请求的业务逻辑。在 Web 应用中,JavaBean 对象、业务模型等都属于 Model。
    举例:电商网站中,Product类(存储商品 ID、名称、价格)和ProductService类(处理商品查询、新增逻辑)都属于 Model。

  • View(视图):用于展示模型中的数据,一般为 JSP 或 HTML 文件。
    举例:电商网站的商品详情页(productDetail.jsp),通过 JSP 标签展示Product对象的名称、价格等数据。

  • Controller(控制器):是应用程序中处理用户交互的部分,接收视图提出的请求,将数据交给模型处理,并将处理后的结果交给视图显示。
    举例:电商网站的ProductController,接收用户 “查询商品详情” 的请求(如/product/1),调用ProductService查询 ID 为 1 的商品,再将商品数据传递给productDetail.jsp展示。

MVC 交互流程:浏览器发起请求(如点击 “查看商品”)→ Controller 接收请求 → 调用 Model 处理业务(查询商品数据)→ Model 返回处理结果(商品信息)→ Controller 将结果传递给 View → View 渲染数据并展示给用户。

1.2 SpringMVC 简介

SpringMVC 是一个基于 MVC 模式的轻量级 Web 框架,是 Spring 框架的一个模块,可与 Spring 直接整合使用(无需额外配置复杂依赖)。它的核心优势是替代 Servlet 技术,通过一套注解(如@Controller@RequestMapping),让一个简单的 Java 类成为处理请求的控制器,而无须实现任何接口。

举例:
传统 Servlet 需要继承HttpServlet并重写doGet/doPost方法,而 SpringMVC 中只需在类上加@Controller,方法上加@RequestMapping("/hello"),即可处理/hello路径的请求,代码更简洁。

SpringMVC 的核心特性:

  • 注解驱动:通过注解快速绑定请求路径与控制器方法。
  • 自动参数封装:无需手动调用request.getParameter(),可直接将请求参数封装为 Java 对象。
  • 灵活的视图支持:支持 JSP、Thymeleaf、Freemarker 等多种视图技术。
  • 与 Spring 生态无缝整合:可直接使用 Spring 的 IOC 容器、事务管理等功能。

第 2 章 SpringMVC 入门案例

本节通过 Maven 创建 Web 项目,实现一个简单的 SpringMVC 请求处理(访问指定路径打印日志),步骤如下:

2.1 创建 Maven Web 项目

用 IDEA 创建 Maven 项目,选择 “maven-archetype-webapp” 骨架,补齐包结构(src/main/javasrc/main/resources)。
引入核心依赖(Spring 核心、SpringWeb、SpringMVC、Servlet、JSP)和 Tomcat 插件,配置如下:

<dependencies><!-- Spring核心模块 --><dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.12.RELEASE</version></dependency><!-- SpringWeb模块 --><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>5.2.12.RELEASE</version></dependency><!-- SpringMVC模块 --><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>5.2.12.RELEASE</version></dependency><!-- Servlet --><dependency><groupId>javax.servlet</groupId><artifactId>servlet-api</artifactId><version>2.5</version><scope>provided</scope> <!-- 服务器已提供,打包时不包含 --></dependency><!-- JSP --><dependency><groupId>javax.servlet.jsp</groupId><artifactId>jsp-api</artifactId><version>2.0</version><scope>provided</scope></dependency>
</dependencies><build><plugins><!-- Tomcat插件(用于启动项目) --><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.1</version><configuration><port>8080</port> <!-- 项目启动端口 --><path>/</path> <!-- 项目上下文路径(根路径) --><uriEncoding>UTF-8</uriEncoding> <!-- 解决URL中文乱码 --></configuration></plugin></plugins>
</build>

2.2 配置前端控制器(web.xml)

SpringMVC 的核心是DispatcherServlet(前端控制器),它是所有请求的入口,负责协调其他组件。在web.xml中配置如下:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="3.1"><display-name>SpringMVC-Demo</display-name><!-- SpringMVC前端控制器(本质是Servlet) --><servlet><servlet-name>dispatcherServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 配置SpringMVC核心配置文件路径 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc.xml</param-value></init-param><!-- 容器启动时加载(优先级1,确保启动顺序) --><load-on-startup>1</load-on-startup></servlet><!-- 映射所有请求到前端控制器 --><servlet-mapping><servlet-name>dispatcherServlet</servlet-name><url-pattern>/</url-pattern> <!-- 匹配所有请求(除JSP外) --></servlet-mapping>
</web-app>

2.3 编写 SpringMVC 核心配置文件(springmvc.xml)

该文件用于配置组件扫描、注解支持等,与 Spring 配置文件语法一致:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 1. 扫描控制器所在包(如com.itbaizhan.controller) --><context:component-scan base-package="com.itbaizhan"/><!-- 2. 开启SpringMVC注解支持(如@RequestMapping、@Controller) --><mvc:annotation-driven/></beans>

2.4 编写控制器(Controller)

通过@Controller注解标记一个 Java 类为控制器,通过@RequestMapping绑定请求路径:

package com.itbaizhan.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller // 标记为控制器,交给Spring管理
public class MyController1 {// 绑定请求路径:访问http://localhost:8080/c1/hello1会触发该方法@RequestMapping("/c1/hello1")public void helloMVC() {System.out.println("Hello SpringMVC!"); // 控制台打印日志}}

2.5 启动项目并测试

  1. 执行 Maven 命令tomcat7:run启动项目;
  2. 浏览器访问http://localhost:8080/c1/hello1
  3. 查看 IDEA 控制台,会输出 Hello SpringMVC!,说明请求处理成功。

第 3 章 SpringMVC 执行流程与核心组件

3.1 执行流程(附详细拆解)

SpringMVC 的执行流程是前端控制器(DispatcherServlet)协调其他组件完成请求处理的过程,具体步骤如下(结合 “访问 /c1/hello1” 案例):

  • 浏览器发送 HTTP 请求:用户访问 http://localhost:8080/c1/hello1,请求被 DispatcherServlet 接收;
  • DispatcherServlet 找 HandlerMappingHandlerMapping(处理器映射器)根据请求路径 /c1/hello1,找到对应的控制器方法(MyController1 的 helloMVC 方法),返回 “方法执行链”;
  • DispatcherServlet 找 HandlerAdapterHandlerAdapter(处理器适配器)根据方法类型(无返回值、参数为空),找到能执行该方法的适配器;
  • 执行控制器方法:适配器调用 MyController1 的 helloMVC 方法,执行业务逻辑(打印日志);
  • 返回处理结果:控制器方法无返回值,默认返回 “路径名 + 后缀” 的视图(如 /c1/hello1.jsp,若不存在会报 404,后续章节会讲视图解析器);
  • 视图渲染与响应:若存在视图,ViewResolver(视图解析器)解析视图路径,View(视图)渲染数据后,通过 DispatcherServlet 返回 HTTP 响应给浏览器。

流程示意图
浏览器 → DispatcherServlet(前端控制器)→ HandlerMapping(找方法)→ HandlerAdapter(执行方法)→ Controller(业务逻辑)→ ModelAndView(结果)→ ViewResolver(解析视图)→ View(渲染)→ 浏览器

3.2 核心组件说明

组件名称作用
DispatcherServlet前端控制器,接收所有请求,协调 HandlerMapping、HandlerAdapter 等组件,是 SpringMVC 的 “入口”
HandlerMapping处理器映射器,根据请求路径匹配对应的控制器方法(如 /c1/hello1 匹配 helloMVC 方法)。
HandlerAdapter处理器适配器,根据控制器方法的参数、返回值类型,选择合适的方式执行方法(适配不同方法签名)。
ViewResolver视图解析器,将逻辑视图名(如 “hello”)解析为实际视图路径(如 /WEB-INF/jsp/hello.jsp)。
View视图,负责渲染模型数据(如 JSP 通过 EL 表达式展示 Model 中的数据)。

以下是复现的完整内容,严格保留原始结构和格式,仅按规范调整标题层级和重点标注:

第 4 章 SpringMVC 参数获取

SpringMVC 支持多种参数获取方式,无需手动调用request.getParameter(),比 Servlet 更简洁。

4.1 封装为简单数据类型

直接在控制器方法参数中声明与请求参数名一致的变量,SpringMVC 会自动封装。

示例 1:获取单个/多个简单参数

package com.itbaizhan.controller;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;@Controller
public class ParamController {// 请求路径:http://localhost:8080/c1/param1?username=张三&age=20@RequestMapping("/c1/param1")public void simpleParam(String username, int age) {System.out.println("用户名:" + username); // 输出“张三”System.out.println("年龄:" + age);       // 输出“20”}
}

规则:请求参数名(如username)必须与方法参数名(String username)一致,支持 Stringintdouble 等简单类型。


4.2 封装为对象类型

若请求参数较多(如用户注册:姓名、年龄、性别),可直接封装为 Java 对象(如Student),SpringMVC 会根据 “请求参数名 = 对象属性名” 自动赋值。

示例 2:封装单个对象
定义实体类(Student)

package com.itbaizhan.model;import lombok.Getter;
import lombok.Setter;
import lombok.ToString;@Getter
@Setter
@ToString
public class Student {private int id;private String name;private String sex;// 省略getter/setter/toString(可通过Lombok注解自动生成)
}

控制器方法

// 请求路径:http://localhost:8080/c1/param2?id=1&name=张三&sex=男
@RequestMapping("/c1/param2")
public void objParam(Student student) {System.out.println(student); // 输出“Student(id=1, name=张三, sex=男)”
}

示例 3:封装关联对象(如 Student 包含 Address)
定义关联对象(Address)

package com.itbaizhan.model;import lombok.Getter;
import lombok.Setter;
import lombok.ToString;@Getter
@Setter
@ToString
public class Address {private String info;    // 地址详情(如“北京市海淀区”)private String postcode;// 邮编(如“100086”)
}

修改 Student 类

public class Student {private int id;private String name;private String sex;private Address address; // 关联Address对象// getter/setter/toString
}

控制器方法与请求路径

// 请求路径:http://localhost:8080/c1/param3?id=1&name=张三&sex=男&address.info=北京市海淀区&address.postcode=100086
@RequestMapping("/c1/param3")
public void objParam2(Student student) {System.out.println(student); // 输出“Student(id=1, name=张三, sex=男, address=Address(info=北京市海淀区, postcode=100086))”
}

4.3 封装为集合类型

SpringMVC 支持将参数封装为ListMap,但需注意:简单类型 List 需加@RequestParam,对象类型集合需封装到含集合属性的对象中。

示例 4:封装简单类型 List(如多选框数据)

// 请求路径:http://localhost:8080/c1/param4?users=张三&users=李四(多个users参数)
@RequestMapping("/c1/param4")
// 简单类型List必须加@RequestParam,否则SpringMVC无法识别
public void listParam(@RequestParam List<String> users) {System.out.println(users); // 输出“[张三, 李四]”
}// 也支持数组类型(无需@RequestParam)
@RequestMapping("/c1/param5")
public void listParam2(String[] users) {System.out.println(users[0]); // 输出“张三”System.out.println(users[1]); // 输出“李四”
}

示例 5:封装对象类型 List(如批量新增学生)
定义含 List 属性的对象(StudentList)

package com.itbaizhan.model;import lombok.Getter;
import lombok.Setter;
import java.util.List;@Getter
@Setter
public class StudentList {private List<Student> students; // 存储多个Student对象的List
}

控制器方法与请求路径

// 请求路径:http://localhost:8080/c1/param6?students[0].id=1&students[0].name=张三&students[1].id=2&students[1].name=李四
@RequestMapping("/c1/param6")
public void listParam3(StudentList studentList) {System.out.println(studentList.getStudents()); // 输出“[Student(id=1, name=张三), Student(id=2, name=李四)]”
}

示例 6:封装 Map 集合
定义含 Map 属性的对象(StudentMap)

package com.itbaizhan.model;import lombok.Getter;
import lombok.Setter;
import java.util.Map;@Getter
@Setter
public class StudentMap {// Map的key为自定义标识(如“student1”),value为Student对象private Map<String, Student> studentMap;
}

控制器方法与请求路径

// 请求路径:http://localhost:8080/c1/param7?studentMap['student1'].id=1&studentMap['student1'].name=张三&studentMap['student2'].id=2&studentMap['student2'].name=李四
@RequestMapping("/c1/param7")
public void mapParam(StudentMap studentMap) {System.out.println(studentMap.getStudentMap()); // 输出“{student1=Student(id=1, name=张三), student2=Student(id=2, name=李四)}”
}

SpringMVC 支持直接在方法参数中声明 Servlet 原生对象(如HttpServletRequestHttpServletResponseHttpSession),无需手动创建

4.4 使用 Servlet 原生对象获取参数

SpringMVC 支持直接在方法参数中声明 Servlet 原生对象(如 HttpServletRequest、HttpServletResponse、HttpSession),无需手动创建:

// 请求路径:http://localhost:8080/c1/param8?name=张三
@RequestMapping("/c1/param8")
public void servletParam(HttpServletRequest request, HttpServletResponse response, HttpSession session) {// 1. 用HttpServletRequest获取请求参数String name = request.getParameter("name");System.out.println("姓名:" + name); // 输出“张三”// 2. 用HttpServletResponse设置响应编码response.setCharacterEncoding("UTF-8");// 3. 用HttpSession存储数据session.setAttribute("username", name);System.out.println("SessionID:" + session.getId()); // 输出Session唯一标识
}

注意:SpringMVC 提供了更简洁的参数获取方式(如对象封装),建议优先使用 SpringMVC 方式,避免与 Servlet 容器紧耦合。

4.5 自定义参数类型转换器

SpringMVC 默认支持 "字符串转简单类型"(如 String→int),但对特殊类型(如 Date)无法自动转换(因日期格式多样,如 2025-01-01、2025/01/01),需自定义转换器。

示例:自定义 Date 类型转换器

定义转换器类,实现 Converter<S, T> 接口(S 为转换前类型,T 为转换后类型):

package com.itbaizhan.converter;import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;// 实现String→Date的转换
public class DateConverter implements Converter<String, Date> {@Overridepublic Date convert(String source) { // source:请求中的日期字符串(如“2025-01-01”)SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // 定义日期格式try {return sdf.parse(source); // 转换为Date对象} catch (ParseException e) {e.printStackTrace();return null; // 转换失败返回null}}
}

在 springmvc.xml 中注册转换器:

<!-- 1. 配置转换器工厂 -->
<bean id="converterFactory" class="org.springframework.context.support.ConversionServiceFactoryBean"><property name="converters"><set><!-- 注册自定义Date转换器 --><bean class="com.itbaizhan.converter.DateConverter"/></set></property>
</bean><!-- 2. 让SpringMVC使用自定义转换器 -->
<mvc:annotation-driven conversion-service="converterFactory"/>

控制器方法测试:

// 请求路径:http://localhost:8080/c1/param9?birthday=2025-01-01
@RequestMapping("/c1/param9")
public void dateParam(Date birthday) {System.out.println("生日:" + birthday); // 输出"生日:Wed Jan 01 00:00:00 CST 2025"
}

4.6 解决中文乱码(编码过滤器)

Tomcat 8+ 可自动处理 GET 请求的中文乱码,但 POST 请求仍会乱码。SpringMVC 提供了 CharacterEncodingFilter 过滤器,可在 web.xml 中配置解决:

<!-- 编码过滤器(必须放在所有过滤器最上方) -->
<filter><filter-name>encFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><!-- 设置编码格式为UTF-8 --><init-param><param-name>encoding</param-name><param-value>utf-8</param-value></init-param>
</filter><!-- 映射所有请求 -->
<filter-mapping><filter-name>encFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

第 5 章 SpringMVC 处理响应

SpringMVC 的响应包括 "视图跳转" 和 "数据传递",核心是通过视图解析器和模型(Model)实现。

5.1 配置视图解析器(ViewResolver)

SpringMVC 默认的视图解析器是 InternalResourceViewResolver,用于解析 JSP 视图。通过配置 "前缀" 和 "后缀",可简化视图路径编写。

示例:配置 JSP 视图解析器

在 springmvc.xml 中添加如下配置:

<!-- 视图解析器:解析JSP视图 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp/"/> <!-- 视图前缀(JSP文件所在目录) --><property name="suffix" value=".jsp"/>          <!-- 视图后缀(文件扩展名) -->
</bean>

规则:控制器返回的逻辑视图名(如 "hello")会被解析为 "前缀 + 逻辑视图名 + 后缀",即 /WEB-INF/jsp/hello.jsp。

5.2 控制器方法的返回值类型

控制器方法的返回值决定了视图跳转的方式,支持 void、String、ModelAndView 三种类型。

5.2.1 返回值为 void(默认跳转)

返回 void 时,SpringMVC 会默认跳转到 "前缀 + 方法请求路径 + 后缀" 的视图:

// 请求路径:http://localhost:8080/helloMVC
@RequestMapping("/helloMVC")
public void helloMVC() {System.out.println("Hello SpringMVC!");
}

跳转逻辑:结合视图解析器配置(prefix=/WEB-INF/jsp/,suffix=.jsp),会跳转到 /WEB-INF/jsp/helloMVC.jsp。

返回 String 时,SpringMVC 会跳转到 "前缀 + 返回值 + 后缀" 的视图,灵活性更高:

返回值为 String(指定视图)

在 SpringMVC 中,控制器方法返回 String 类型时,框架会根据视图解析器的配置跳转到对应的视图页面。默认逻辑视图名会拼接前缀和后缀,例如返回 "helloMVC" 会解析为 /WEB-INF/jsp/helloMVC.jsp

特殊用法是通过 forward:redirect: 前缀实现请求转发或重定向:

@RequestMapping("/c2/hello1")
public String helloMVC1() {return "helloMVC"; // 逻辑视图名
}
  • forward:/c2/hello2:服务器内部转发,地址栏不变。
  • redirect:/c2/hello2:客户端重定向,地址栏变化。

返回值为 ModelAndView(带数据跳转)

ModelAndView 对象允许同时设置视图和数据,数据默认存入 request 域:

@RequestMapping("/c2/hello2")
public ModelAndView useMAV() {ModelAndView mav = new ModelAndView();mav.addObject("username", "百战程序员"); // 数据存入request域mav.setViewName("baizhan"); // 视图名return mav;
}

JSP 中通过 EL 表达式获取数据:

<h1>你好!${requestScope.username}</h1>

需确保 web.xml 使用 Servlet 3.1 以支持 EL 表达式。

向不同作用域传递数据

向 request 域传递数据
  • HttpServletRequest:直接操作 request 对象。
  • Model/ModelMap/Map:框架自动注入参数,数据存入 request 域。
@RequestMapping("/c2/hello4")
public String setRequest(Model model) {model.addAttribute("username", "尚学堂");return "baizhan";
}
向 session 域传递数据

通过 HttpSession 对象设置数据:

@RequestMapping("/c2/hello6")
public String setSession(HttpSession session) {session.setAttribute("address", "北京");return "baizhan";
}
向 context 域传递数据

需通过 HttpSession 获取 ServletContext

@RequestMapping("/c2/hello7")
public String setContext(HttpSession session) {ServletContext context = session.getServletContext();context.setAttribute("age", 10);return "baizhan";
}

请求转发与重定向

方式特点适用场景
请求转发(forward)服务器内部跳转,地址栏不变,共享 request 域数据。同一模块内跳转(如提交表单后显示结果)。
重定向(redirect)客户端重新发起请求,地址栏变化,不共享 request 域数据,可跳转外部路径。跨模块跳转(如登录后跳首页)。

原生实现方式:

@RequestMapping("/c2/hello8")
public void myForward1(HttpServletRequest request, HttpServletResponse response) throws Exception {// 请求转发request.getRequestDispatcher("/c2/hello9").forward(request, response);// 或重定向response.sendRedirect("/c2/hello9");
}

第 6 章 SpringMVC 常用注解

6.1 @Controller:标记控制器

在 SpringMVC 中,使用 @Controller 标注控制器类,将其交给 Spring 容器管理。该注解通常位于类上方,并可与 @RequestMapping 结合使用定义请求路径。

@Controller // 标记为控制器  
@RequestMapping("/c3") // 类级别的请求路径(父路径)  
public class MyController3 {  // 方法级别的请求路径:完整路径为/c3/annotation1  @RequestMapping("/annotation1")  public String annotation1() {  return "baizhan";  }  
}  

6.2 @RequestMapping:绑定请求路径

@RequestMapping 为控制器类或方法绑定请求路径,支持指定请求方式、参数、请求头等。可作用于类上方(父路径)或方法上方(子路径)。

核心属性

  • value/path:请求路径(如 /annotation1)。
  • method:指定请求方式(如 RequestMethod.GETRequestMethod.POST)。
  • params:规定必须携带的请求参数(如 params = {"age"})。
  • headers:规定必须包含的请求头(如 headers = {"User-Agent"})。
@Controller  
@RequestMapping("/c3") // 父路径:/c3  
public class MyController3 {  @RequestMapping(  path = "/annotation1",  method = {RequestMethod.GET, RequestMethod.POST},  params = {"age"},  headers = {"User-Agent"}  )  public String annotation1(String username) {  System.out.println(username);  return "baizhan";  }  
}  

6.3 @RequestParam:获取请求参数

@RequestParam 手动指定请求参数名与方法参数名的映射,支持设置默认值和是否必传。位于方法参数前。

核心属性

  • name/value:请求参数名(如 name = "username")。
  • defaultValue:参数默认值。
  • required:是否必传(默认 true)。
@RequestMapping("/annotation2")  
public String annotation2(  @RequestParam(name = "username", defaultValue = "sxt", required = false) String name  
) {  System.out.println(name); // 若未传参数,输出“sxt”;若传参数,输出“张三”  return "baizhan";  
}  

6.4 @RequestHeader 与 @CookieValue:获取请求头与 Cookie

6.4.1 @RequestHeader:获取请求头数据

用于获取 HTTP 请求头中的数据(如 User-AgentContent-Type)。

6.4.2 @CookieValue:获取 Cookie 数据

用于获取浏览器 Cookie 中的数据(如 JSESSIONID)。

@RequestMapping("/annotation3")  
public String annotation3(  @RequestHeader("User-Agent") String userAgent,  @CookieValue("JSESSIONID") String jSessionId  
) {  System.out.println("浏览器标识:" + userAgent);  System.out.println("SessionID:" + jSessionId);  return "baizhan";  
}  

6.5 @SessionAttributes:将 Model 数据存入 Session

@SessionAttributes 将 Model 中的指定 key 的数据自动存入 Session 域,位于类上方。

@Controller  
@RequestMapping("/c4")  
@SessionAttributes("name") // 将Model中key为name的数据存入Session  
public class MyController4 {  @RequestMapping("/t1")  public String t1(Model model) {  model.addAttribute("name", "北京尚学堂"); // Model→Request+Session  return "baizhan";  }  @RequestMapping("/t2")  public String t2(HttpSession session) {  String name = (String) session.getAttribute("name");  System.out.println(name); // 输出“北京尚学堂”  return "baizhan";  }  
}  

6.6 @ModelAttribute:前置方法与数据绑定

@ModelAttribute 有两种用法:

  1. 标记前置方法:该方法会在控制器其他方法执行前自动执行。
  2. 从 Model 中获取数据:解决参数不从请求中获取,而从 Model 中获取的场景。

示例 1:前置方法

@Controller  
@RequestMapping("/c5")  
public class MyController5 {  @ModelAttribute  public void before() {  System.out.println("前置方法执行"); // 先输出  }  @RequestMapping("/t1")  public String t1() {  System.out.println("t1方法执行"); // 后输出  return "baizhan";  }  
}  

示例 2:从 Model 中获取数据

@Controller  
@RequestMapping("/c6")  
public class MyController6 {  @ModelAttribute  public void before(Model model) {  model.addAttribute("name", "尚学堂");  }  @RequestMapping("/t1")  public String t1(@ModelAttribute("name") String name) {  System.out.println(name); // 输出“尚学堂”  return "baizhan";  }  
}  

第7章 SpringMVC RESTful风格支持

RESTful是一种URL设计范式,将数据视为“资源”,通过URL路径标识资源(如学生),并通过HTTP请求方式(GET、POST、PUT、DELETE)区分操作类型。这种设计使API更简洁、语义化,易于扩展和维护。

7.1 RESTful风格简介

RESTful的核心规则:

  • URL仅标识资源:不包含操作名称(如findByIddelete),而是通过路径表示资源本身(如/student/30表示ID=30的学生)。
  • 请求方式区分操作
    • GET:查询资源(如获取学生信息)。
    • POST:新增资源(如添加新学生)。
    • PUT:修改资源(如更新学生数据)。
    • DELETE:删除资源(如移除学生)。
  • 优势:结构清晰、符合HTTP协议语义、减少URL冗余、支持跨平台调用。

传统URL与RESTful URL对比

操作传统URL示例RESTful URL示例请求方式
查询学生(ID=30)http://localhost:8080/student/findById?id=30http://localhost:8080/student/30GET
删除学生(ID=30)http://localhost:8080/student/deleteById?id=30http://localhost:8080/student/30DELETE
新增学生http://localhost:8080/student/addhttp://localhost:8080/studentPOST
修改学生(ID=30)http://localhost:8080/student/updateById?id=30http://localhost:8080/student/30PUT

7.2 用Postman发送RESTful请求

浏览器默认仅支持GET和POST请求,DELETE和PUT请求需借助工具(如Postman)发送。步骤如下:

  1. 下载并打开Postman:从官网安装Postman应用。
  2. 创建请求集合:例如,新建名为“SpringMVC-RESTful”的集合。
  3. 配置请求
    • 选择请求方式(GET、POST、DELETE或PUT)。
    • 输入URL(如http://localhost:8080/student/30)。
    • 如需传递参数(如新增学生时),在“Body”标签中选择:
      • form-data:用于表单数据(键值对)。
      • x-www-form-urlencoded:用于URL编码参数。
    • 添加参数(如name=张三&age=20)。
  4. 发送请求:点击“Send”按钮,查看响应结果(状态码、响应体等)。

7.3 @PathVariable:获取URL路径参数

在RESTful风格中,URL路径包含占位符(如/student/{id}),@PathVariable注解用于从路径中提取这些参数值。它位于方法参数前,核心属性为value(指定占位符名称;若参数名与占位符一致,可省略)。

示例:RESTful风格控制器

@Controller
@RequestMapping("/student") // 父路径:/student
public class StudentController {// 1. 查询学生(GET /student/30)@RequestMapping(value = "/{id}", method = RequestMethod.GET)public String findStudentById(@PathVariable("id") int id) {System.out.println("查询ID为" + id + "的学生");return "baizhan";}// 2. 删除学生(DELETE /student/30)@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)public String deleteStudent(@PathVariable int id) { // 占位符与参数名一致,省略valueSystem.out.println("删除ID为" + id + "的学生");return "baizhan";}// 3. 新增学生(POST /student)@RequestMapping(method = RequestMethod.POST)public String addStudent(Student student) {System.out.println("新增学生:" + student);return "baizhan";}// 4. 修改学生(PUT /student/30)@RequestMapping(value = "/{id}", method = RequestMethod.PUT)public String updateStudent(@PathVariable int id, Student student) {System.out.println("修改ID为" + id + "的学生:" + student);return "baizhan";}
}

关键点

  • @PathVariable将URL中的{id}绑定到方法参数id
  • 方法需指定method属性以匹配HTTP请求方式。

7.4 简化请求方式注解

SpringMVC提供了专用注解(@GetMapping@PostMapping@PutMapping@DeleteMapping),简化@RequestMapping的配置,使代码更简洁。

示例:简化后的控制器

@Controller
@RequestMapping("/student")
public class StudentController {// 等价于@RequestMapping(value = "/{id}", method = RequestMethod.GET)@GetMapping("/{id}")public String findStudentById(@PathVariable int id) {System.out.println("查询ID为" + id + "的学生");return "baizhan";}// 等价于@RequestMapping(value = "/{id}", method = RequestMethod.DELETE)@DeleteMapping("/{id}")public String deleteStudent(@PathVariable int id) {System.out.println("删除ID为" + id + "的学生");return "baizhan";}// 等价于@RequestMapping(method = RequestMethod.POST)@PostMappingpublic String addStudent(Student student) {System.out.println("新增学生:" + student);return "baizhan";}// 等价于@RequestMapping(value = "/{id}", method = RequestMethod.PUT)@PutMapping("/{id}")public String updateStudent(@PathVariable int id, Student student) {System.out.println("修改ID为" + id + "的学生:" + student);return "baizhan";}
}

优势:减少冗余代码,提高可读性。

7.5 HiddenHttpMethodFilter:支持浏览器发送DELETE/PUT请求

浏览器表单仅支持GET和POST请求。SpringMVC的HiddenHttpMethodFilter过滤器允许将POST请求“伪装”为DELETE或PUT请求。实现步骤如下:

步骤1:在web.xml中配置过滤器

<!-- 支持DELETE/PUT请求的过滤器 -->
<filter><filter-name>httpMethodFilter</filter-name><filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping><filter-name>httpMethodFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

步骤2:编写表单(伪装请求) 表单需满足:

  • 提交方式为method="post"
  • 添加隐藏域_method,值为DELETEPUT。 示例表单(用于删除学生):
<form action="/student/30" method="post"><input type="hidden" name="_method" value="DELETE"><input type="submit" value="删除学生">
</form>

原理:过滤器读取_method参数,将POST请求转换为指定HTTP方式。

总结

  • RESTful核心:通过URL路径标识资源,HTTP方式定义操作,使用@PathVariable获取路径参数。
  • 工具支持:Postman用于发送全类型请求;HiddenHttpMethodFilter扩展浏览器能力。
  • 简化开发:利用@GetMapping等注解减少配置。
  • 参数获取:SpringMVC自动封装简单参数,提升开发效率。 如果您有具体问题(如代码调试或扩展案例),请提供更多细节,我将进一步协助!
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>RESTful表单</title>
</head>
<body><!-- 1. 伪装DELETE请求(删除ID=1的学生) --><form action="/student/1" method="post"><input type="hidden" name="_method" value="DELETE"><input type="submit" value="删除学生"></form><!-- 2. 伪装PUT请求(修改ID=1的学生) --><form action="/student/1" method="post"><input type="hidden" name="_method" value="PUT"><input type="text" name="name" value="张三"><input type="submit" value="修改学生"></form>
</body>
</html>

第 8 章 SpringMVC JSON 数据交互

SpringMVC 支持 JSON 格式的数据交互(如前后端分离架构),核心注解为 @ResponseBody@RequestBody

8.1 @ResponseBody:返回 JSON 数据

作用:将控制器方法的返回值(如 Java 对象)转换为 JSON 格式,直接写入 HTTP 响应体,不经过视图解析器(无需跳转视图)。
位置:方法上方或方法返回值前。

示例 1:返回 JSON 格式结果
引入 Jackson 依赖(SpringMVC 默认使用 Jackson 转换 JSON):

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

定义结果实体类(封装响应数据):

package com.itbaizhan.model;import lombok.Getter;
import lombok.Setter;
import lombok.ToString;@Getter
@Setter
@ToString
public class Result {private boolean flag;    // 请求是否成功(true=成功,false=失败)private String message; // 提示信息// 构造方法public Result(boolean flag, String message) {this.flag = flag;this.message = message;}
}

控制器方法(返回 JSON):

@Controller
@RequestMapping("/c8")
public class MyController8 {// 新增学生,返回JSON结果@PostMapping("/addStudent")@ResponseBody // 将Result对象转为JSONpublic Result addStudent(String name, String sex) {System.out.println("新增学生:" + name + ",性别:" + sex);// 返回JSON:{"flag":true,"message":"添加学生成功!"}return new Result(true, "添加学生成功!");}
}

前端发送 Ajax 请求(JSP 示例):

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Ajax请求</title><!-- 引入jQuery --><script src="/js/jquery-2.1.1.min.js"></script><script>$(function () {$("#btn").click(function () {// 获取表单数据var name = $("#name").val();var sex = $("#sex").val();// 发送Ajax请求$.get("/c8/addStudent", {"name": name, "sex": sex}, function (data) {console.log(data); // 打印JSON结果:{flag: true, message: "添加学生成功!"}});});});</script>
</head>
<body>姓名:<input id="name"/><br/>性别:<input id="sex"/><br/><input type="button" value="提交" id="btn"/>
</body>
</html>

8.2 @RestController:简化 JSON 返回

作用:组合 @Controller@ResponseBody,标记在类上方,表示该类所有方法的返回值都会自动转为 JSON(无需每个方法加 @ResponseBody)。

@RestController // 等价于@Controller + @ResponseBody
@RequestMapping("/c8")
public class MyController8 {// 无需加@ResponseBody,返回值自动转为JSON@PostMapping("/addStudent")public Result addStudent(String name, String sex) {System.out.println("新增学生:" + name + ",性别:" + sex);return new Result(true, "添加学生成功!");}
}

8.3 @RequestBody:接收 JSON 格式参数

作用:将 HTTP 请求体中的 JSON 格式参数转换为 Java 对象(如 Student)。
位置:方法参数前。

示例 2:接收 JSON 参数并返回 JSON 结果
前端发送 JSON 格式的 Ajax 请求:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Ajax请求(JSON参数)</title><script src="/js/jquery-2.1.1.min.js"></script><script>$(function () {$("#btn").click(function () {// 1. 构造JSON数据var param = JSON.stringify({"name": $("#name").val(),"sex": $("#sex").val()});// 2. 发送Ajax请求(Content-Type为application/json)$.ajax({url: "/c8/addStudent2",type: "post",contentType: "application/json", // 声明请求体为JSONdata: param,success: function (data) {console.log(data); // 打印JSON响应}});});});</script>
</head>
<body>姓名:<input id="name"/><br/>性别:<input id="sex"/><br/><input type="button" value="提交" id="btn"/>
</body>
</html>

控制器方法(接收 JSON 参数):

@RestController
@RequestMapping("/c8")
public class MyController8 {// 用@RequestBody将JSON参数转为Student对象@PostMapping("/addStudent2")public Result addStudent2(@RequestBody Student student) {System.out.println("新增学生:" + student); // 输出Student对象return new Result(true, "添加学生成功!");}
}

8.4 放行静态资源

SpringMVC 提供了多种方式配置静态资源映射,确保前端资源能被正确加载。每种方法都适用于不同场景,且在实际项目中可灵活选择或组合使用。

  1. 方案 1:配置默认资源检查器(对应选项 A)

    • 在 SpringMVC 配置文件(如 springmvc.xml)中添加 <mvc:default-servlet-handler/>
    • 作用:让 SpringMVC 将静态资源请求委托给 Web 服务器(如 Tomcat)的默认 Servlet 处理。
    • 优点:简单快捷,无需指定具体路径。
    • 示例配置:
      <!-- 放行静态资源(JS、CSS、图片等) -->
      <mvc:default-servlet-handler/>
      
    • 此方案等同于选项 A 的“配置静态资源筛查器”(术语“筛查器”可能为笔误,实际应为“检查器”或“处理器”)。
  2. 方案 2:配置静态资源映射器(对应选项 B)

    • springmvc.xml 中使用 <mvc:resources/> 标签,为特定路径映射静态资源目录。
    • 作用:精确控制静态资源的访问路径和存储位置。
    • 优点:性能高效,可直接从指定目录加载资源。
    • 示例配置:
      <!-- 配置静态资源映射:/js/**路径映射到/webapp/js/目录 -->
      <mvc:resources mapping="/js/**" location="/js/"/>
      <mvc:resources mapping="/css/**" location="/css/"/>
      <mvc:resources mapping="/img/**" location="/img/"/>
      
    • 此方案直接对应选项 B 的“配置静态资源映射器”。
  3. 方案 3:配置默认 Servlet 处理静态资源(对应选项 C)

    • web.xml 中配置 Web 服务器(如 Tomcat)的默认 Servlet,指定其处理特定文件类型的请求。
    • 作用:绕过 SpringMVC,让服务器直接处理静态资源。
    • 优点:兼容性强,适用于所有 Servlet 容器。
    • 示例配置:
      <!-- 让默认Servlet处理JS、CSS、图片 -->
      <servlet-mapping><servlet-name>default</servlet-name><url-pattern>*.js</url-pattern>
      </servlet-mapping>
      <servlet-mapping><servlet-name>default</servlet-name><url-pattern>*.css</url-pattern>
      </servlet-mapping>
      <servlet-mapping><servlet-name>default</servlet-name><url-pattern>*.jpg</url-pattern>
      </servlet-mapping>
      

http://www.dtcms.com/a/482896.html

相关文章:

  • 做外贸网站注意wordpress 附件下载插件
  • 微波人体传感器技术深度解析:从多普勒效应到工程落地
  • 定长内存池 思考实现过程 C++ 附源码
  • 风电场站AGC/AVC系统方案|风力发电AGC/AVC系统方案|风电场站一次调频系统方案|风力发电一次调频系统产品方案概述
  • sward,一款超级轻量且简洁的知识管理工具
  • 类似京东的购物网站开发价格课程设计代做网站推荐
  • 网站开发毕业设计开题报告手机怎么安装网站程序
  • python调用远程服务器的ollama embedding模型
  • 手机电子商务网站建设怎么做网站排名优化
  • SQL入门:行列转换实战-从基础到高级
  • 科大讯飞【免费】的开源模型实现录音转写与角色判定
  • 上海专业建设网站制作微信群推广
  • 景区网站建设原则做网站需要每年都缴费吗
  • 推广一下自己刚撸的 IDEA 插件—Bean Copy 助手
  • 线粒体靶向压电催化剂调控焦亡与胞葬作用以增强骨肉瘤免疫原性死亡
  • Vue 3 + TypeScript 开发的视频直播页面组件
  • 【开题答辩实录分享】以《智能体育训练助手的设计与实现》为例进行答辩实录分享
  • Vue + Element Plus 手动注册 v-loading 指令
  • docker elasticsearch端口映射解决端口冲突问题
  • SD:在一个 Ubuntu 系统安装 stable diffusion ComfyUI
  • 如何使用命令修改conda虚拟环境目录
  • 学习随笔-ES6和ES5的区别
  • 文件上传阿里云OSS以及本地图片服务器搭建
  • 企业网站建设需注意什么商务网站管理与建设
  • 威县做网站哪儿好个人网站建设的背景
  • Excel导出报Can not find ‘Converter‘ support class Map.
  • Linux osq_lock
  • SSM共享汽车管理系统300fw(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
  • Docker安装部署FileBrowser
  • 基于单片机频率周期脉宽测量系统Proteus仿真(含全部资料)