第二期:深入理解 Spring Web MVC [特殊字符](核心注解 + 进阶开发)

前言:

欢迎来到 Spring Web MVC 深入学习 的第二期!在第一期中,我们介绍了 Spring Web MVC 的基础知识,学习了如何 搭建开发环境、配置 Spring MVC、编写第一个应用,并初步了解了 控制器、视图解析、请求处理流程 等核心概念。

本期将带你深入探讨 Spring Web MVC 中的核心注解,帮助你更灵活、高效地构建 Web 应用。除了基础注解外,我们还将介绍一些 进阶开发技巧,包括 异常处理、数据绑定、会话管理、拦截器使用等,让你更好地掌握 Spring MVC 的精髓。

通过本期的学习,你将能够:

  • 理解和使用 Spring Web MVC 核心注解,提升开发效率;

  • 处理复杂请求、绑定参数、定制视图渲染

  • 使用拦截器、异常处理和会话管理,提升应用的稳定性与可维护性。

💡 无论你是初学者还是有一定经验的开发者,第二期的内容都会帮助你更好地理解 Spring Web MVC,让你在 Web 开发的道路上走得更远。准备好迎接更深入的学习了吗?让我们开始吧!🚀


1  详细解析 Spring MVC 注解 🔍

在 Spring Web MVC 中,注解驱动的开发方式极大提高了开发效率,简化了配置过程。掌握这些注解的使用,可以让你在开发中更轻松地处理 HTTP 请求、数据绑定、异常处理等功能。

本节将深入解析 Spring MVC 核心注解 的使用,帮助你更好地理解它们背后的原理,并学会如何高效地在实际开发中应用。我们将重点讨论以下内容:

  • @Controller vs @RestController

  • @RequestMapping 的高级用法

  • @PathVariable vs @RequestParam

  • @ModelAttribute 数据绑定原理

  • @ResponseBodyHttpMessageConverter 解析机制


📌 1.1 @Controller vs @RestController

🔹 @Controller

  • 作用@Controller 是 Spring MVC 中 标识控制器类 的核心注解,用来处理 HTTP 请求并返回视图。

  • 返回值:默认情况下,@Controller 方法的返回值会被视为 视图名,需要通过 视图解析器(如 InternalResourceViewResolver)进行解析,最终返回给用户。

  • 示例

@Controller
public class HelloController {@RequestMapping("/hello")public String sayHello(Model model) {model.addAttribute("message", "Hello, Spring MVC!");return "hello";  // 返回视图名}
}

这里返回的是 "hello" 视图名,Spring 会根据配置的 ViewResolver 渲染 hello.jsp 页面。


🔹 @RestController

  • 作用@RestController@Controller 的一个扩展,结合了 @Controller@ResponseBody。当你不需要渲染视图,只需要返回 数据(通常是 JSON 或 XML)时,可以使用 @RestController

  • 返回值@RestController 方法的返回值会直接作为 HTTP 响应体 进行处理,不经过视图解析。

  • 示例

@RestController
@RequestMapping("/api")
public class ApiController {@GetMapping("/message")public String getMessage() {return "Hello, RESTful World!";}
}

访问 /api/message 会直接返回 "Hello, RESTful World!",而不是返回视图。

📌 总结

  • 使用 @Controller 时,返回值是视图名。

  • 使用 @RestController 时,返回值直接作为 HTTP 响应体,通常是 JSON 数据。


📌 1.2 @RequestMapping 的高级用法🔍

@RequestMapping 是 Spring Web MVC 中最核心的注解之一,用于映射 HTTP 请求到指定的控制器方法。它提供了非常强大的功能,能够处理多种 HTTP 请求方式(GET、POST、PUT、DELETE 等),并且支持路径参数、请求头、请求参数等多种条件的匹配。

在 Spring 4.3 及之后的版本中,@RequestMapping 的功能得到了增强,许多更简洁和具体的注解(如 @GetMapping@PostMapping 等)被引入,但 @RequestMapping 仍然是功能最强大的请求映射注解,它可以完成更多复杂的请求映射需求。

本节将深入探讨 @RequestMapping高级用法,帮助你更好地理解其强大功能。


📌 1.2.1 @RequestMapping 的常见用法

🔹 基本用法
@RequestMapping("/home")
public String home() {return "home";  // 返回视图名
}

@RequestMapping("/home")/home URL 映射到 home() 方法,当请求访问 /home 时,返回对应的视图。

🔹 支持 HTTP 方法的指定

通过 method 属性,@RequestMapping 可以指定特定的 HTTP 请求方法(如 GET、POST、PUT、DELETE)。

@RequestMapping(value = "/create", method = RequestMethod.POST)
public String create() {return "create";
}

该方法仅会响应 POST 请求。


📌 1.2.2  @RequestMapping 的路径匹配

🔹 传递路径变量(Path Variables)

Spring MVC 支持在 URL 中传递变量,并通过 @PathVariable 注解获取它们。

@RequestMapping("/user/{id}")
public String getUser(@PathVariable("id") int id) {return "User ID: " + id;
}
  • 访问 /user/123,方法中的 id 会被绑定为 123

🔹 使用正则表达式进行路径匹配

@RequestMapping 支持在路径中使用 正则表达式 来进行更精确的匹配。

@RequestMapping(value = "/product/{id:\\d+}", method = RequestMethod.GET)
public String getProduct(@PathVariable("id") int id) {return "Product ID: " + id;
}
  • 这个例子会匹配 /product/123,但不会匹配 /product/abc,因为 id 必须是数字。

🔹 路径中的多个占位符

如果 URL 中有多个变量,可以在路径中指定多个占位符。

@RequestMapping("/order/{orderId}/item/{itemId}")
public String getItem(@PathVariable("orderId") int orderId, @PathVariable("itemId") int itemId) {return "Order ID: " + orderId + ", Item ID: " + itemId;
}
  • 访问 /order/100/item/200 时,orderId100itemId200


📌 1.2.3  @RequestMapping 的请求参数匹配

🔹 传递查询参数(Request Parameters)

@RequestMapping 支持通过 @RequestParam 注解来匹配 URL 查询参数。

@RequestMapping("/search")
public String search(@RequestParam("keyword") String keyword) {return "Searching for: " + keyword;
}
  • 访问 /search?keyword=Springkeyword 会被绑定为 "Spring"

🔹 通过 params 属性指定请求参数

你可以使用 params 属性来指定 必须包含的请求参数,只有当请求中包含这些参数时,映射才会生效。

@RequestMapping(value = "/search", params = "keyword", method = RequestMethod.GET)
public String search(@RequestParam("keyword") String keyword) {return "Searching for: " + keyword;
}
  • 只有访问 /search?keyword=Spring,此方法才会被调用。没有 keyword 参数的请求将不会匹配。

🔹 请求头匹配(Headers)

你还可以根据 HTTP 请求头中的内容来进行条件匹配,使用 headers 属性来指定匹配的请求头。

@RequestMapping(value = "/search", headers = "key=abc", method = RequestMethod.GET)
public String search() {return "Search with header key=abc";
}
  • 只有当请求头中包含 key=abc 时,方法才会被调用。


📌 1.2.4 @RequestMapping 的跨版本支持

🔹 处理不同版本的请求

可以通过 producesconsumes 属性来定义请求的 支持格式,例如支持不同的内容类型(application/json, application/xml 等)。

@RequestMapping(value = "/user", method = RequestMethod.GET, produces = "application/json")
public User getUser() {return new User(1, "John Doe");
}
  • 这个方法仅会在请求头 Acceptapplication/json 时被调用,并且返回 JSON 格式的数据。

🔹 consumes 用于处理请求体的类型

consumes 属性用于指定 请求体的内容类型,适用于 POST 或 PUT 请求。

@RequestMapping(value = "/add", method = RequestMethod.POST, consumes = "application/x-www-form-urlencoded")
public String addUser(@RequestParam("name") String name, @RequestParam("age") int age) {return "User added: " + name + ", Age: " + age;
}
  • 这个方法仅会处理请求体为 application/x-www-form-urlencoded 类型的请求。


📌 1.2.5 @RequestMapping 的方法参数

🔹 @RequestBody

通过 @RequestBody 注解,Spring 会将 HTTP 请求的 请求体内容 自动转换为 Java 对象。

@RequestMapping(value = "/user", method = RequestMethod.POST)
public String createUser(@RequestBody User user) {return "User created: " + user.getName();
}
  • 通过 @RequestBody,Spring 会根据请求的 Content-Type(如 application/json)将请求体解析为 User 对象。


📌 1.2.6 @RequestMapping 的返回值处理

🔹 返回视图名

当方法返回字符串时,Spring 会将其视为视图名,交由视图解析器处理。

@RequestMapping("/home")
public String home() {return "home";  // 返回视图名
}
🔹 返回数据(JSON/XML)

当方法返回数据(如对象)时,Spring 会根据返回值的类型自动转换数据格式(通常是 JSON 或 XML)。这依赖于 @ResponseBody@RestController

@RequestMapping(value = "/user", method = RequestMethod.GET)
@ResponseBody
public User getUser() {return new User(1, "John Doe");
}
  • 返回的 User 对象会被自动转换为 JSON 格式,并作为 HTTP 响应返回。


📌 总结:@RequestMapping 高级用法

功能说明
路径变量使用 {} 指定路径中的变量,通过 @PathVariable 注解获取路径参数。
正则表达式匹配通过正则表达式对路径进行匹配,增强路径的灵活性。
查询参数通过 @RequestParam 获取 URL 查询参数,支持参数条件匹配。
请求头匹配使用 headers 属性,指定请求头必须满足的条件。
支持内容类型通过 producesconsumes 属性指定支持的请求和响应格式。
请求体处理使用 @RequestBody 解析请求体为 Java 对象。
返回值转换方法返回值可以是视图名或直接返回数据,支持自动转换为 JSON 或 XML。

通过掌握 @RequestMapping 的高级用法,你可以在 Spring MVC 中实现更加灵活、细粒度的请求映射,提高开发的效率和可维护性。


📌 1.3 @PathVariable vs @RequestParam🔍

@PathVariable@RequestParam 是 Spring MVC 中两个非常常用的注解,它们都用于提取 HTTP 请求中的数据,但它们的使用场景和处理方式有所不同。理解这两个注解的区别和适用场景对于编写清晰、高效的代码非常重要。


📌 1.3.1 @PathVariable

🔹 作用

@PathVariable 用于从 URL 路径 中提取变量,常用于 RESTful 风格的 API 中。它通常与 路径模板(例如 /users/{id})一起使用,用来提取路径中的动态部分。

🔹 使用场景

  • RESTful URL@PathVariable 更符合 REST 风格的 URL 设计,在 URL 中表达资源的身份(如 /users/{id})或层级结构(如 /orders/{orderId}/items/{itemId})。

  • 路径中的变量:适用于传递 资源标识符资源类别层次结构信息 的情况。

🔹 示例
@RestController
public class UserController {@GetMapping("/user/{id}")public String getUser(@PathVariable("id") int id) {return "User ID: " + id;}
}
  • URL 示例/user/123

    • @PathVariable("id") 会绑定到 URL 中的 123

🔹 关键特点
  • URL 中的动态数据@PathVariable 用于提取 URL 中的动态部分,路径中通常包含占位符(如 {id})。

  • 多用于 RESTful 风格 API:在 RESTful API 设计中,路径变量用于标识资源和资源的子集。


📌 1.3.2  @RequestParam

🔹 作用

@RequestParam 用于从 URL 查询参数表单数据 中提取数据,通常用于处理 用户提交的数据查询参数。它非常适合处理 GET 请求中的查询字符串或表单提交的参数。

🔹 使用场景
  • 查询参数:适用于处理来自 URL 查询字符串的数据(如 /search?name=John&age=30)。

  • 表单数据:适用于处理表单提交的数据(如 POST 请求中的表单内容)。

🔹 示例
@RestController
public class SearchController {@GetMapping("/search")public String search(@RequestParam("name") String name, @RequestParam("age") int age) {return "Searching for: " + name + ", Age: " + age;}
}
  • URL 示例/search?name=John&age=30

    • @RequestParam("name") 会绑定到查询参数 name=John@RequestParam("age") 会绑定到查询参数 age=30

🔹 关键特点
  • 查询字符串和表单数据@RequestParam 用于获取 URL 查询字符串中的数据(如 ?key=value)或 POST 请求中的表单参数。

  • 用于提交的参数:常用于获取用户在表单中提交的数据或查询字符串中的参数。


📌 1.3.3 @PathVariable@RequestParam 的区别

🔹 1. 语义和使用场景
  • @PathVariable:通常用于提取 路径中的动态部分,表示 资源的标识符资源的层级结构,更加符合 RESTful 风格的 URL 设计。例如,/users/{id} 中的 {id} 用于表示用户的唯一标识符。

  • @RequestParam:用于提取 查询参数表单数据,通常用于搜索、过滤、分页等场景。例如,/search?name=John&age=30 中的 nameage 就是查询参数。

🔹 2. 位置
  • @PathVariable:提取的是 URL 路径中的数据,通常通过 {} 占位符在路径中定义。

  • @RequestParam:提取的是 查询字符串表单提交的数据,通常是 ?key=value 的形式。

🔹 3. 数据传递方式
  • @PathVariable:数据是通过 URL 路径直接传递的,因此 URL 本身即表示了资源的身份或层级关系。

  • @RequestParam:数据是通过 查询字符串表单提交 传递的,通常用于过滤、排序、分页等操作。

🔹 4. 是否为必选项
  • @PathVariable:路径变量通常是 必选 的,因为它是 URL 路径的一部分。

  • @RequestParam:查询参数和表单数据可以设置为 可选,使用 required=false 可以使参数为可选。

🔹 5. 示例对比
// @PathVariable 示例
@GetMapping("/user/{id}")
public String getUser(@PathVariable("id") int id) {return "User ID: " + id;
}// @RequestParam 示例
@GetMapping("/search")
public String search(@RequestParam("name") String name, @RequestParam("age") int age) {return "Searching for: " + name + ", Age: " + age;
}
  • 访问方式

    • /user/123 会匹配 @PathVariable,提取 id123

    • /search?name=John&age=30 会匹配 @RequestParam,提取 nameJohnage30


📌 1.3.4 @PathVariable vs @RequestParam 使用场景对比

特性@PathVariable@RequestParam
传递数据的方式通过 URL 路径通过 URL 查询参数或表单提交
主要用途标识资源的标识符、层级结构,RESTful 风格提交表单数据、查询、过滤、分页
常见场景获取单个资源、子资源的标识符获取查询条件、表单提交的数据
是否必填通常是必填的,作为路径的一部分可以设置为可选,适合查询参数
是否用于表示资源的标识符是,用于标识资源或其子集否,通常用于传递参数、查询条件等

📌 1.3.5 总结

@PathVariable

  • 适用于提取 URL 路径中的 动态部分,例如 RESTful API 中的资源标识符、层级结构。

  • 用于资源标识符或层次结构的表示,符合 REST 风格的 URL 设计。

@RequestParam

  • 适用于提取 查询参数表单提交数据,通常用于获取用户输入的条件、过滤器、分页参数等。

  • 用于查询条件、表单数据的提取,支持可选参数。

掌握 @PathVariable@RequestParam 的区别和使用场景,你将能够在设计和实现 Web API 时,准确地选择合适的注解,使得 API 路径更加清晰,代码结构更加简洁明了。


📌 1.4  @ModelAttribute 数据绑定原理🔍

 

在 Spring MVC 中,@ModelAttribute 是一个非常强大的注解,通常用于将 HTTP 请求中的数据自动绑定到 Java 对象的字段中。它的应用非常广泛,可以帮助我们减少大量的手动数据绑定代码,并提高代码的可读性和可维护性。

📌 1.4.1 @ModelAttribute 的基本作用

@ModelAttribute 的核心作用是 数据绑定,它使得请求参数(如查询参数、表单数据等)能够自动与 Java 对象进行映射。可以用它来:

  • 自动将 HTTP 请求中的 参数 绑定到方法参数或类的属性上。

  • 在控制器方法执行前,给模型对象添加属性。

通过使用 @ModelAttribute,Spring MVC 可以根据请求参数自动填充 Java 对象中的字段,从而简化了开发流程。


📌 1.4.2 @ModelAttribute 用法解析

🔹 方法参数绑定

@ModelAttribute 最常见的用途之一是将 HTTP 请求中的数据绑定到方法的参数中。Spring 会根据请求中的参数名与方法参数名进行匹配,并将匹配的数据自动绑定到 Java 对象。

示例 1:绑定表单数据到对象

假设有一个表单,用户输入了他们的姓名和年龄,你可以使用 @ModelAttribute 将这些数据自动绑定到 Java 对象上。

public class User {private String name;private int age;// getters and setters
}@Controller
public class UserController {@RequestMapping("/submit")public String submitForm(@ModelAttribute User user) {// 自动绑定表单数据到 user 对象return "User name: " + user.getName() + ", Age: " + user.getAge();}
}
  • 表单数据<form action="/submit" method="post"> <input name="name" /> <input name="age" /> </form>

  • 当表单提交时,Spring 会将请求中的 nameage 参数绑定到 User 对象上,调用 submitForm() 方法时,user 对象会自动填充这些值。

请求 URL 示例/submit?name=John&age=30
  • @ModelAttribute User user 会将 name=Johnage=30 绑定到 user 对象的 nameage 属性上。

🔹 @ModelAttribute 与表单绑定

@ModelAttribute 特别适用于表单提交的数据绑定。当一个 HTML 表单的 input 标签的 name 属性与 Java 对象的字段名匹配时,Spring 会自动将表单数据绑定到 Java 对象上。


📌 1.4.3 @ModelAttribute 的数据绑定原理🔍

Spring MVC 使用 数据绑定 的机制将 HTTP 请求中的数据(如 URL 查询参数、表单数据等)与 Java 对象的字段进行匹配。这个过程涉及以下几个关键步骤:

🔹 1. 请求参数提取

Spring MVC 会首先从 HTTP 请求中提取参数。这些参数可能来自于:

  • URL 查询字符串(/search?name=John&age=30

  • 表单提交的数据(<input name="name">John</input>

  • 请求体(例如 JSON 或 XML 格式的数据)

🔹 2. 字段匹配

Spring 使用反射技术,通过请求参数名与 Java 对象的字段名进行匹配。通常,Spring 会按以下规则进行绑定:

  • 请求参数的名称与 Java 对象字段名匹配(区分大小写)。

  • 如果字段是基本类型或其包装类型,Spring 会尝试将字符串数据转换为相应类型(如 String 转换为 int)。

示例
public class User {private String name;private int age;// getters and setters
}
  • 如果请求参数是 name=Johnage=30,Spring 会将 name 绑定到 User 对象的 name 字段,age 绑定到 age 字段。

🔹 3. 转换器(Type Converters)

如果数据类型不匹配,Spring 会尝试使用 类型转换器(如 String 转换为 intDate)来进行转换。例如,如果请求中的参数是 "30" 字符串,但 Java 对象的字段是 int 类型,Spring 会自动将其转换。

Spring 提供了多种常用的类型转换器,像 StringToDateConverterStringToIntegerConverter 等。开发者也可以根据需要自定义类型转换器。


📌 1.4.4 @ModelAttribute 绑定的高级特性

🔹 1. 自动填充模型

@ModelAttribute 可以在控制器方法执行前,自动将模型对象添加到 ModelModelMap 中。它不仅可以用于方法参数,还可以用于方法级别的注解,自动填充全局数据。

示例 2:全局模型属性绑定

@Controller
public class UserController {@ModelAttribute("user")public User createUser() {// 在所有处理请求的方法中共享的 user 对象return new User();}@RequestMapping("/show")public String showUser(@ModelAttribute("user") User user) {// 这里可以使用已绑定的 user 对象return "showUser";}
}
  • @ModelAttribute("user") 中定义的方法返回的 User 对象,将在每次请求时自动添加到模型中。

  • 即使 showUser() 方法没有明确声明 User 参数,@ModelAttribute("user") 也会确保 User 对象被注入到 Model 中。

🔹 2. 数据验证

在数据绑定过程中,Spring 还可以进行 数据验证。可以结合 @Valid@Validated 注解来实现对绑定数据的验证。

示例 3:数据验证

public class User {@NotEmpty(message = "Name cannot be empty")private String name;@Min(value = 18, message = "Age must be at least 18")private int age;// getters and setters
}@Controller
public class UserController {@RequestMapping("/submit")public String submitForm(@ModelAttribute @Valid User user, BindingResult result) {if (result.hasErrors()) {return "error";}return "success";}
}
  • @Valid 注解会触发对 User 对象的验证,如果验证失败,BindingResult 会包含验证错误的信息。


📌1.4. 5 @ModelAttribute 的优缺点

🔹 优点
  • 简化数据绑定@ModelAttribute 自动将请求数据绑定到 Java 对象,减少了手动提取和转换数据的工作量。

  • 适用于表单处理:特别适合表单提交和查询参数的绑定,开发者不需要手动将每个表单字段赋值给 Java 对象。

  • 验证支持:可以结合 Spring 的验证机制,自动验证表单数据的合法性。

🔹 缺点
  • 灵活性较低:由于自动绑定的特性,有时可能不符合开发者对数据绑定过程的精细控制需求。

  • 潜在的绑定问题:如果请求参数名与 Java 对象的字段名不匹配,可能导致数据绑定失败或错误。


📌 1.4.6 总结

特性@ModelAttribute 数据绑定
数据来源主要从 URL 查询参数、表单提交数据中提取数据。
适用场景适合表单提交、查询参数绑定,以及在控制器方法前后进行模型数据的填充。
绑定机制通过字段名匹配进行数据绑定,支持类型转换(如 String -> int)。
验证支持可结合 @Valid@Validated 进行数据验证,捕获绑定错误。

通过掌握 @ModelAttribute 的数据绑定原理,你可以在 Spring MVC 中更加高效、简洁地处理请求参数的绑定,提升开发体验和代码质量。


📌 1.5. @ResponseBodyHttpMessageConverter 解析机制 🔍

在 Spring Web MVC 中,@ResponseBody 和 ``HttpMessageConverter` 是处理响应数据的两个重要组件。理解它们的工作原理能够帮助你更好地开发 RESTful API 或其他需要数据转换和响应定制化的应用。

📌 1.5.1. @ResponseBody 的作用

@ResponseBody 是一个用于将 Java 方法的返回值直接写入 HTTP 响应体 的注解。通常与控制器方法配合使用,表示返回的对象不需要通过视图解析器(如 JSP)渲染,而是直接作为响应的内容返回给客户端。

🔹 使用场景

  • RESTful API:返回 JSON 或 XML 数据给客户端。

  • 动态生成内容:返回非 HTML 的数据,如图片、文件下载内容等。

示例 1:@ResponseBody 基本用法

@RestController
public class UserController {@GetMapping("/user/{id}")@ResponseBodypublic User getUser(@PathVariable("id") int id) {return new User(id, "John Doe", 30);}
}
  • 当客户端访问 /user/1 时,getUser() 方法会返回一个 User 对象。@ResponseBody 会将该对象转换成响应内容(默认情况下是 JSON 格式),并直接返回给客户端。

🔹 关键点

  • @ResponseBody 用于控制方法的返回值直接写入 HTTP 响应体。

  • 它与传统的视图解析方式(如 JSP)不同,适用于 RESTful 风格的服务。


📌1.5. 2. HttpMessageConverter 解析机制

HttpMessageConverter 是 Spring 中的一个接口,用于将 Java 对象转换为 HTTP 请求/响应的内容,或者将 HTTP 请求/响应的内容转换为 Java 对象。它的作用是 在控制器方法和客户端之间进行数据的序列化和反序列化,支持 JSON、XML、字符串等格式的数据转换。

🔹 主要功能
  1. 从请求体中读取数据并转换为 Java 对象(反序列化)。

  2. 将 Java 对象转换为响应体中的数据(序列化)。

Spring 提供了多个默认的 HttpMessageConverter 实现,最常用的包括:

  • MappingJackson2HttpMessageConverter:用于 JSON 和 Java 对象之间的转换。

  • Jaxb2RootElementHttpMessageConverter:用于 XML 和 Java 对象之间的转换。

  • StringHttpMessageConverter:用于 String 和 HTTP 内容之间的转换。

示例 2:HttpMessageConverter 的工作机制

假设你有一个控制器方法返回一个 User 对象,并且你在类路径中包含了 Jackson 库。

@RestController
public class UserController {@GetMapping("/user/{id}")public User getUser(@PathVariable("id") int id) {return new User(id, "John Doe", 30);}
}
  • User 类:

public class User {private int id;private String name;private int age;// getters and setters
}
  • 当访问 /user/1 时,Spring 会通过 HttpMessageConverterUser 对象转换为 JSON 格式:

    • 如果请求的 Accept 头部为 application/json,Spring 会选择合适的 HttpMessageConverter(如 MappingJackson2HttpMessageConverter),将 User 对象序列化成 JSON。

    • User 对象会被转换为如下的 JSON:

      {"id": 1,"name": "John Doe","age": 30
      }
      
🔹 3. HttpMessageConverter 的工作过程
1. 请求解析(反序列化)

当客户端发送一个请求到 Spring MVC 时,Spring 会查看请求头中的 Content-Type,并根据该类型选择合适的 HttpMessageConverter 将请求体中的数据转换为 Java 对象。例如,客户端发送一个 JSON 请求,Spring 会使用 MappingJackson2HttpMessageConverter 将 JSON 转换为 Java 对象。

2. 响应处理(序列化)

当控制器方法返回一个 Java 对象时,Spring 会根据响应头中的 Accept 来选择合适的 HttpMessageConverter 将 Java 对象转换为所需的格式。比如,如果客户端希望接受 JSON 格式的响应,Spring 会选择 MappingJackson2HttpMessageConverter 来将 Java 对象转换为 JSON 格式。


📌 1.5.4. @ResponseBodyHttpMessageConverter 的关系

@ResponseBodyHttpMessageConverter 密切配合,@ResponseBody 使得 Spring MVC 自动处理返回值的序列化,而 HttpMessageConverter 实现了具体的序列化和反序列化逻辑。

  • @ResponseBody 告诉 Spring 方法的返回值应该直接写入 HTTP 响应体中,而不是通过视图解析。

  • HttpMessageConverter 负责将 Java 对象转换为响应格式(如 JSON、XML 等),以及将请求中的内容转换为 Java 对象。

🔹 流程说明
  1. 控制器方法执行后:

    • 如果方法使用了 @ResponseBody,Spring 会使用合适的 HttpMessageConverter 将返回的 Java 对象转换为合适的响应格式(JSON、XML 或其他)。

    • 例如,如果返回的是一个 Java 对象 User,且请求头中 Accept: application/json,Spring 会使用 MappingJackson2HttpMessageConverter 将该对象转换为 JSON 格式的响应体。

  2. 请求到达控制器:

    • 如果请求包含数据(如 POST 请求),Spring 会使用 HttpMessageConverter 从请求体中解析数据并转换为相应的 Java 对象。例如,如果请求是 application/json 格式,Spring 会使用 MappingJackson2HttpMessageConverter 将 JSON 转换为 Java 对象。


📌 1.5.5. 自定义 HttpMessageConverter

在某些情况下,你可能需要定制或扩展 HttpMessageConverter,例如,支持新的数据格式或自定义序列化规则。

🔹 示例:注册自定义的 HttpMessageConverter

你可以通过 WebMvcConfigurer 来注册一个自定义的 HttpMessageConverter

@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void extendMessageConverters(List<HttpMessageConverter<?>> converters) {// 自定义 JSON 转换器converters.add(new MyCustomHttpMessageConverter());}
}

在上面的示例中,我们可以自定义 MyCustomHttpMessageConverter,来处理特定格式的数据转换。


📌 1.5.6. 总结

特性@ResponseBodyHttpMessageConverter
主要作用将控制器方法的返回值直接写入 HTTP 响应体,避免视图解析负责序列化和反序列化,处理 Java 对象和 HTTP 请求/响应之间的转换
工作机制返回的对象通过 HttpMessageConverter 转换为指定格式根据请求或响应的 Content-Type/Accept 使用合适的转换器
常见用法用于 RESTful API,返回 JSON、XML 等数据处理请求体中的数据反序列化为 Java 对象,或将 Java 对象序列化为响应内容
默认实现自动与 HttpMessageConverter 配合工作提供多个实现,如 MappingJackson2HttpMessageConverterJaxb2HttpMessageConverter

通过理解 @ResponseBodyHttpMessageConverter 的工作机制,你可以更好地开发和调试 Web 应用,特别是 RESTful API,确保数据的正确序列化与反序列化过程。


总结

注解作用
@Controller处理 HTTP 请求并返回视图
@RestController处理 HTTP 请求并直接返回数据(通常为 JSON)
@RequestMapping映射 HTTP 请求路径与控制器方法
@PathVariable获取 URL 路径中的变量
@RequestParam获取 URL 查询参数或表单数据
@ModelAttribute将请求参数绑定到方法的对象上
@ResponseBody将方法的返回值作为响应体返回

通过对这些注解的深入理解,你将能够在 Spring MVC 中更加灵活地处理不同类型的请求,提高开发效率并简化代码结构。


2. 数据绑定与表单处理 📋

在 Spring MVC 中,处理表单数据的过程涉及到 数据绑定表单处理。Spring MVC 提供了强大的数据绑定功能,可以轻松地将 HTTP 请求中的表单数据绑定到 Java 对象中,减少了大量手动提取参数的工作。与此同时,Spring MVC 还支持对数据进行验证和处理校验错误。

📌 2.1. Spring MVC 如何接收表单数据

Spring MVC 通过 数据绑定 机制将 HTTP 请求中的表单数据绑定到 Java 对象。表单提交时,Spring 会自动将请求的参数(通常是表单字段)与 Java 对象的属性进行匹配,并将表单数据填充到对象的字段中。

🔹 表单提交的基本流程

  1. HTML 表单: 表单是用户输入数据的地方,表单中的 input 元素的 name 属性必须与 Java 对象的属性名一致。Spring MVC 会根据这些 name 属性自动将表单数据绑定到 Java 对象中。

    <form action="/submit" method="POST"><input type="text" name="name" /><input type="number" name="age" /><button type="submit">Submit</button>
    </form>
    
  2. 控制器接收表单数据: 控制器方法接收 HTTP 请求并通过 @ModelAttribute 或方法参数直接将表单数据绑定到 Java 对象。

    @Controller
    public class UserController {@RequestMapping(value = "/submit", method = RequestMethod.POST)public String submitForm(@ModelAttribute User user) {// 自动绑定 name 和 age 到 User 对象System.out.println(user.getName());return "success";}
    }
    
  3. Spring MVC 数据绑定

    • 请求参数名(如 nameage)会自动映射到 Java 对象的属性(如 nameage)。

    • Spring 使用反射技术将表单数据绑定到对象上。


📌 2.2  @ModelAttribute 绑定表单数据

@ModelAttribute 是 Spring MVC 中一个非常常用的注解,它用于 将请求中的表单数据绑定到 Java 对象。使用 @ModelAttribute 注解可以自动将表单数据填充到控制器方法的参数中。

🔹 @ModelAttribute 的工作机制

  • @ModelAttribute 会根据 HTTP 请求中的参数名与 Java 对象的属性名进行匹配,并将表单数据填充到 Java 对象中。

  • 绑定过程是基于 字段名匹配,所以表单中的 name 属性的名称必须与 Java 对象的属性名一致。

示例:表单绑定到 Java 对象
public class User {private String name;private int age;// getters and setters
}@Controller
public class UserController {@RequestMapping(value = "/submit", method = RequestMethod.POST)public String submitForm(@ModelAttribute User user) {// 这里的 user 对象会自动绑定表单提交的数据System.out.println("Name: " + user.getName());System.out.println("Age: " + user.getAge());return "success";}
}
  • HTML 表单:

    <form action="/submit" method="POST"><input type="text" name="name" /><input type="number" name="age" /><button type="submit">Submit</button>
    </form>
    
  • 当用户填写表单并提交时,Spring MVC 会自动将表单数据绑定到 User 对象中的 nameage 属性。

表单提交:

请求:/submit?name=John&age=30

  • Spring 会自动创建 User 对象,并将 name="John"age="30" 绑定到该对象上。


📌 2.3. BindingResult 处理数据校验错误

在实际开发中,我们通常需要对表单数据进行 验证,以确保用户输入的数据是有效的。Spring MVC 提供了 BindingResult 来处理表单数据的校验和错误处理。

🔹 BindingResult 的作用

BindingResult 是一个 校验结果容器,用于存储表单数据绑定过程中的错误。它会跟随 @ModelAttribute 使用,并在验证过程中收集错误信息。

🔹 如何使用 BindingResult

  • BindingResult 必须紧随 @ModelAttribute 的参数之后声明。

  • 当绑定过程出现校验错误时,BindingResult 会存储这些错误,控制器方法可以通过 BindingResult 来判断是否存在错误。

示例 1:数据验证和错误处理
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;public class User {@NotEmpty(message = "Name cannot be empty")private String name;@Min(value = 18, message = "Age must be at least 18")private int age;// getters and setters
}@Controller
public class UserController {@RequestMapping(value = "/submit", method = RequestMethod.POST)public String submitForm(@ModelAttribute @Valid User user, BindingResult result) {if (result.hasErrors()) {// 如果有错误,返回错误页面return "error";}// 没有错误,继续处理数据return "success";}
}
  • HTML 表单:

    <form action="/submit" method="POST"><input type="text" name="name" /><input type="number" name="age" /><button type="submit">Submit</button>
    </form>
    
  • @Valid 注解用于触发 User 类的验证规则。如果用户输入无效数据(如 age 小于 18 或 name 为空),Spring 会将验证错误信息放入 BindingResult 中。

验证逻辑:
  1. submitForm() 被调用时,Spring 会首先对 User 对象进行验证(使用 @Valid 注解)。

  2. 如果验证失败,BindingResult 会包含错误信息,控制器可以根据 BindingResult.hasErrors() 判断是否存在错误。

  3. 如果没有错误,表单数据会被成功提交。

🔹 BindingResult 错误信息的展示

你可以在 JSP 页面中显示验证错误的信息,以便用户查看哪些字段需要修正。

<form action="/submit" method="POST"><input type="text" name="name" /><input type="number" name="age" /><button type="submit">Submit</button>
</form><c:if test="${not empty errors}"><ul><c:forEach var="error" items="${errors}"><li>${error.defaultMessage}</li></c:forEach></ul>
</c:if>
  • errorsBindingResult 中存储的错误信息,它包含所有验证失败的消息。


📌 2.4. 总结:Spring MVC 表单处理和数据绑定

特性描述
数据绑定Spring MVC 自动将表单数据绑定到 Java 对象的字段中。
@ModelAttribute 作用用于将请求中的表单数据绑定到 Java 对象,减少手动提取参数的代码。
BindingResult用于处理表单数据绑定过程中的校验错误,确保数据符合验证规则。
@Valid 和验证BindingResult 一起使用,可以对表单数据进行验证,确保输入有效。
错误处理BindingResult 存储验证错误信息,控制器根据错误决定如何处理数据。

通过 @ModelAttributeBindingResult 和数据验证机制,Spring MVC 提供了非常强大的表单处理功能,使得开发者可以更高效、更灵活地处理表单数据的绑定和校验。


3. Spring MVC 数据校验 🛠️

在 Spring MVC 中,数据校验是确保用户提交数据的有效性和一致性的关键步骤。Spring 提供了灵活的机制来验证表单数据,这有助于确保应用的稳定性和安全性。数据校验不仅可以用于表单输入,还可以用于 RESTful API 中的请求体验证。

📌 3.1. @Valid@Validated 的区别

@Valid@Validated 都是用于触发数据验证的注解,它们的作用非常相似,但有一些细微的区别。它们都用于触发对模型对象的校验,确保数据符合预期的约束。

🔹 @Valid
  • @Valid 是 Java 的标准注解,属于 JSR 303/JSR 380 规范的一部分。

  • 它用于触发 默认的校验规则,并且只能应用于 单个对象。如果对象内有嵌套对象,@Valid 会对子对象进行递归校验。

  • @Valid 可以用于控制器方法的参数上,或者用于字段的校验(如 @Valid User user)。

🔹 @Validated
  • @Validated 是 Spring 特有的注解,作用与 @Valid 类似,但它支持更 灵活的分组校验

  • 分组校验 使得你可以针对不同的使用场景,对同一个模型对象进行不同的校验规则。

  • @Validated 可以指定校验组(通过 groups 属性),适用于不同场景下的校验,比如新增、修改时的校验规则不同。

区别总结:
特性@Valid@Validated
标准支持JSR 303/JSR 380 规范Spring 框架特有的注解
校验分组支持不支持分组校验支持分组校验(通过 groups 属性)
应用范围只能应用于单个对象支持应用于单个对象和字段,并支持分组
子对象校验支持对子对象进行递归校验支持对子对象进行递归校验
示例:使用 @Valid@Validated
  • @Valid 用法:

    @Controller
    public class UserController {@PostMapping("/register")public String register(@ModelAttribute @Valid User user, BindingResult result) {if (result.hasErrors()) {return "registerForm";  // 返回错误的表单页面}return "success";}
    }
    
  • @Validated 用法:

    @Controller
    public class UserController {@PostMapping("/register")public String register(@ModelAttribute @Validated(User.Create.class) User user, BindingResult result) {if (result.hasErrors()) {return "registerForm";  // 返回错误的表单页面}return "success";}
    }
    
  • User 类:

    public class User {@NotEmpty(message = "Name is required", groups = User.Create.class)private String name;@Min(value = 18, message = "Age must be at least 18", groups = { User.Create.class, User.Update.class })private int age;// getters and setters
    }public interface User {interface Create {}interface Update {}
    }
    

在上面的代码中,@Validated(User.Create.class) 表示只对 User.Create 分组进行校验,这种方式可以根据不同场景(如注册、新增或更新)应用不同的校验规则。


📌 3.2. 自定义校验注解

Spring 提供了内置的验证注解(如 @NotNull, @Min, @Size 等),但在某些情况下,你可能需要根据业务需求进行自定义校验。Spring 允许你创建自定义的校验注解,并与自定义校验逻辑配合使用。

🔹 创建自定义校验注解
  1. 定义注解: 首先,你需要定义一个自定义注解,并且标注为 @Constraint,指明它是一个约束注解。

  2. 实现校验逻辑: 创建一个 ConstraintValidator 类来处理具体的校验逻辑。

步骤 1:定义自定义校验注解
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = AgeValidator.class)  // 指定校验逻辑的实现类
public @interface ValidAge {String message() default "Age must be between 18 and 99";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};
}
步骤 2:实现校验逻辑
public class AgeValidator implements ConstraintValidator<ValidAge, Integer> {@Overridepublic void initialize(ValidAge constraintAnnotation) {// 初始化逻辑,通常可以忽略}@Overridepublic boolean isValid(Integer age, ConstraintValidatorContext context) {// 检查 age 是否在合法范围内return age >= 18 && age <= 99;}
}
步骤 3:应用自定义校验注解
public class User {@NotEmpty(message = "Name is required")private String name;@ValidAge(message = "Invalid age!")private int age;// getters and setters
}
步骤 4:触发校验
@PostMapping("/register")
public String register(@ModelAttribute @Valid User user, BindingResult result) {if (result.hasErrors()) {return "registerForm";}return "success";
}

在这个示例中,@ValidAge 校验注解用于验证 age 字段的合法性。如果 age 不在 18 到 99 的范围内,校验会失败,并返回错误信息 "Invalid age!"


📌 3.3 结合 JSR 303 进行参数校验

JSR 303 是 Java Bean 验证的标准规范,Spring MVC 完全集成了 JSR 303/JSR 380(Bean Validation 1.0 和 2.0)。使用 JSR 303 校验注解,能够简化输入验证的过程,并提供统一的校验机制。

🔹 常用的 JSR 303 校验注解
  • @NotNull:字段不能为 null

  • @NotEmpty:字符串不能为空。

  • @Size(min = 2, max = 10):限制字符串长度。

  • @Min(value):字段值不能小于指定值。

  • @Max(value):字段值不能大于指定值。

  • @Email:必须是有效的电子邮件地址。

结合 JSR 303 进行校验:
public class User {@NotEmpty(message = "Name cannot be empty")private String name;@Min(value = 18, message = "Age must be at least 18")private int age;@Email(message = "Invalid email format")private String email;// getters and setters
}

通过在 User 类中使用 JSR 303 提供的注解,Spring 会自动验证表单数据的有效性。

在控制器方法中触发验证:
@PostMapping("/register")
public String register(@ModelAttribute @Valid User user, BindingResult result) {if (result.hasErrors()) {return "registerForm";  // 有错误,返回表单页面}return "success";  // 没有错误,处理业务逻辑
}

如果用户提交的数据违反了校验规则,Spring 会将错误信息收集到 BindingResult 中,并返回给用户显示。


📌 3.4. 总结:Spring MVC 数据校验

特性@Valid@Validated
注解来源Java Bean Validation(JSR 303/JSR 380)Spring 框架特有的注解
校验分组不支持分组校验支持分组校验(通过 groups 属性)
触发校验的方式用于触发默认校验支持指定校验分组,并触发不同校验规则
支持自定义校验通过自定义注解和实现 ConstraintValidator通过自定义注解和实现 ConstraintValidator

Spring MVC 提供的 @Valid@Validated 注解是进行数据校验的基础工具,并

且你可以自定义校验规则来满足特定业务需求。结合 JSR 303 规范的校验注解,使得整个校验机制更加规范、简洁,并且可以灵活扩展。


4. 视图解析与模板引擎 🎨

在 Spring MVC 中,视图解析是控制器与用户界面之间的桥梁。Spring MVC 支持多种视图技术,包括 JSP、Thymeleaf 和 FreeMarker。每种视图技术都有其优缺点,并适用于不同的场景。在这一章节中,我们将深入了解 视图解析器模板引擎,并探讨如何结合这些技术来渲染动态页面。

📌 4.1. InternalResourceViewResolverThymeleafViewResolver

Spring MVC 通过 视图解析器 来将控制器返回的逻辑视图名称解析成实际的视图实现(如 JSP、HTML)。视图解析器的配置方式对应用的可维护性和性能有重要影响。

🔹 InternalResourceViewResolver

InternalResourceViewResolver 是 Spring MVC 中最常用的视图解析器之一,它主要用于 JSP 文件的解析。其主要职责是根据控制器返回的视图名称,解析成实际的 JSP 文件路径。

  • 工作机制InternalResourceViewResolver 会根据配置的前缀(prefix)和后缀(suffix)来构建最终的视图路径。

  • 用途:通常用于渲染 JSP 页面。

配置 InternalResourceViewResolver
@Configuration
public class WebConfig implements WebMvcConfigurer {@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();viewResolver.setPrefix("/WEB-INF/views/"); // 配置JSP文件所在目录viewResolver.setSuffix(".jsp");  // 配置JSP文件后缀registry.viewResolver(viewResolver);  // 注册视图解析器}
}
  • 视图名称解析:如果控制器返回视图名称 "home"InternalResourceViewResolver 会尝试解析成 /WEB-INF/views/home.jsp 这个文件。

🔹 ThymeleafViewResolver

ThymeleafViewResolver 是 Spring MVC 中专门用于渲染 Thymeleaf 模板的视图解析器。Thymeleaf 是一个现代化的模板引擎,支持自然模板,可以与 HTML 文件无缝集成,适用于构建动态网页。

  • 工作机制ThymeleafViewResolver 会根据控制器返回的视图名称,使用配置的模板引擎(Thymeleaf)来渲染视图。

  • 用途:用于渲染 Thymeleaf 模板。

配置 ThymeleafViewResolver
@Configuration
public class WebConfig implements WebMvcConfigurer {@Beanpublic SpringTemplateEngine templateEngine() {SpringTemplateEngine templateEngine = new SpringTemplateEngine();templateEngine.setTemplateResolver(templateResolver());return templateEngine;}@Beanpublic TemplateResolver templateResolver() {ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();templateResolver.setPrefix("/WEB-INF/templates/");  // 配置模板文件所在目录templateResolver.setSuffix(".html");  // 配置模板文件后缀templateResolver.setTemplateMode("HTML");  // 配置模板的类型return templateResolver;}@Overridepublic void configureViewResolvers(ViewResolverRegistry registry) {ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();viewResolver.setTemplateEngine(templateEngine());  // 设置Thymeleaf模板引擎registry.viewResolver(viewResolver);}
}
  • 视图名称解析:如果控制器返回 "home"ThymeleafViewResolver 会尝试解析成 /WEB-INF/templates/home.html 文件,并使用 Thymeleaf 渲染该模板。


📌 4.2. 使用 Thymeleaf 渲染页面

Thymeleaf 是 Spring 推荐的模板引擎,广泛应用于现代 web 开发中。它支持 HTML 模板,可以直接在浏览器中查看渲染后的页面,便于前后端开发协作。Thymeleaf 的最大特点是支持 自然模板,即你可以在浏览器中看到模板渲染前的 HTML 内容。

🔹 Thymeleaf 的基本语法
  • 表达式:Thymeleaf 使用 ${} 来处理表达式。例如, ${user.name} 用于渲染 user 对象的 name 属性。

  • 条件判断:使用 th:ifth:unless 进行条件判断。

  • 循环:使用 th:each 进行列表的循环渲染。

基本的 Thymeleaf 模板示例

假设控制器返回一个 User 对象,它包含 nameage 属性。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><title>User Info</title>
</head>
<body><h1>User Details</h1><p>Name: <span th:text="${user.name}"></span></p><p>Age: <span th:text="${user.age}"></span></p>
</body>
</html>
控制器示例
@Controller
public class UserController {@RequestMapping("/user")public String getUser(Model model) {User user = new User("John", 30);model.addAttribute("user", user);return "user";  // 视图名称为 "user",对应于 /WEB-INF/templates/user.html}
}
  • 在这个例子中,Thymeleaf 模板渲染时会将 user.nameuser.age 渲染成具体的内容。


📌 4.3. 结合前端模板(JSP、Thymeleaf、FreeMarker)

在 Spring MVC 中,可以根据项目的需求选择不同的模板引擎。每种模板引擎有其特点,开发者可以根据项目的具体需求进行选择。

🔹 JSP(JavaServer Pages)
  • 使用场景:JSP 是传统的 Java Web 开发中的视图技术,适用于需要与 Java EE 技术栈紧密集成的项目。

  • 优缺点

    • 优点:与 Java 技术栈高度集成。

    • 缺点:JSP 的语法较为复杂,并且对现代前端技术的支持较弱,无法灵活应对复杂的动态内容。

🔹 Thymeleaf
  • 使用场景:Thymeleaf 是现代的模板引擎,适用于 Spring Boot 和 Spring MVC 项目,尤其适合前后端分离的项目。

  • 优缺点

    • 优点:自然模板,支持动态生成 HTML 页面,易于与前端开发协作。

    • 缺点:需要额外配置,且模板渲染速度相对较慢(相比于 JSP)。

🔹 FreeMarker
  • 使用场景:FreeMarker 是一种非常灵活的模板引擎,广泛应用于 Java 项目中。它非常适合需要与 Java 后端进行复杂数据交互的应用。

  • 优缺点

    • 优点:非常强大的模板功能,适用于多种复杂场景。

    • 缺点:模板语法相对复杂,需要一定的学习成本。


📌 4.4. 总结:视图解析与模板引擎的选择

特性JSPThymeleafFreeMarker
集成性与 Java EE 紧密集成与 Spring MVC / Spring Boot 紧密集成适合需要复杂数据处理的场景
模板语法基于 HTML 和 Java 代码混合自然模板,支持 HTML 编辑器渲染灵活强大,语法复杂
学习曲线容易上手简单,适合现代 web 开发需要一定的学习成本
性能性能较好,适合小型应用性能较慢,但易于使用性能与复杂性之间的折衷
适用场景传统的 Java Web 开发现代 Web 开发,前后端分离复杂报表或大数据展示

在实际项目中,选择合适的模板引擎取决于项目需求、团队的技术栈以及项目的复杂度。Spring MVC 提供了丰富的视图解析器支持,允许你根据项目需要选择合适的渲染机制。


结语

在这一期中,我们深入探讨了 Spring Web MVC 的核心注解及其背后的原理,并学习了如何利用这些注解进行更高效的开发。通过对 @Controller@RestController@RequestMapping@PathVariable 等核心注解的详细解析,我们理解了 Spring MVC 如何简化开发、提高可维护性以及如何通过注解驱动的方式实现更加简洁、优雅的代码。

同时,我们还学习了如何处理数据绑定、表单提交和数据校验,以及如何配置和使用不同的视图解析器(如 JSP 和 Thymeleaf)。这些都是 Spring Web MVC 开发中不可或缺的部分,掌握它们能够帮助开发者更高效地构建功能强大、用户友好的 web 应用。

回顾要点:
  1. Spring Web MVC 核心注解:我们详细解析了 @Controller@RestController,并探讨了 @RequestMapping 等注解的高级用法,了解了如何将它们与 URI、HTTP 方法、请求参数等关联。

  2. 数据绑定与表单处理:通过 @ModelAttributeBindingResult,我们学习了如何将表单数据绑定到 Java 对象,以及如何进行数据校验。

  3. 视图解析与模板引擎:深入了解了视图解析器的工作原理,特别是 InternalResourceViewResolverThymeleafViewResolver,并学习了如何通过 Thymeleaf 渲染动态页面。

  4. 进阶开发技巧:我们还探索了如何更灵活地使用 Spring MVC 进行开发,特别是在数据校验、视图渲染和前端模板选择等方面。

展望:

Spring Web MVC 作为企业级应用开发的核心框架之一,其广泛应用于多种开发场景中。掌握了核心注解、数据绑定与校验、视图解析等基本概念后,你将能够高效地构建功能丰富的 web 应用。在接下来的章节中,我们将继续深入探讨更复杂的开发场景,如安全性处理、RESTful 风格的 API 开发、异步请求等内容,帮助你进一步提升 Spring Web MVC 的开发能力。

无论你是初学者,还是有一定基础的开发者,通过对 Spring Web MVC 的深入理解,你将能够更自如地应对开发中的各种挑战,构建出更加高效、灵活的应用系统。

期待在下一期中与大家继续深入探讨更多的 Spring Web MVC 高级特性和实战技巧!🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75517.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文读懂数据仓库:从概念到技术落地

数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合&#xff0c;用于支持管理决策。以下是关于数据仓库的详细介绍&#xff1a; 一、特点 面向主题&#xff1a;数据仓库围绕特定主题组织数据&#xff0c;如客户、产品、销售等&#xff0c;而不是像传统数…

JavaScript学习18-css操作和事件处理程序(html/DOM0/DOM2)

一、css操作 第一种&#xff1a;容易出错 第二种&#xff1a;有效避免错误 第三种&#xff1a; 二、事件处理程序 1.HTML事件 2.DOM0级事件处理 3.DOM2级事件处理

npm设置代理和取消代理

设置代理 具体代理端口要根据自己的来 npm config set proxy http://127.0.0.1:7890 npm config set https-proxy http://127.0.0.1:7890取消代理 npm config delete proxy npm config delete https-proxy查看代理 npm config get proxy # 应返回 null npm config get…

从零开始训练Codebook:基于ViT的图像重建实践

完整代码在文末&#xff0c;可以一键运行。 1. 核心原理 Codebook是一种离散表征学习方法&#xff0c;其核心思想是将连续特征空间映射到离散的码本空间。我们的实现方案包含三个关键组件&#xff1a; 1.1 ViT编码器 class ViTEncoder(nn.Module):def __init__(self, codebo…

大数据笔试题_第一阶段配套笔试题02

已知一个字符类型的日期&#xff1a;2022-01-20&#xff0c;请用SQL显示出此日期对应的下个月的月份&#xff0c;结果要求为Number类型&#xff08;202201&#xff09;。 参考答案 sql SELECT to_date(2022-01-20, yyyy-mm-dd) a1,add_months(to_date(2022-01-20, yyyy-mm-d…

C++实现对象单例模式

在 C 中实现单例模式有多种方法&#xff0c;以下是线程安全的现代 C 实现方式&#xff08;推荐 C11 及以上版本&#xff09;&#xff1a; 1. Meyers’ Singleton&#xff08;推荐&#xff09; class Singleton { public:// 删除拷贝构造和赋值运算符Singleton(const Singleto…

企业常用Linux服务搭建

1.需要两台centos 7服务器&#xff0c;一台部署DNS服务器&#xff0c;另一台部署ftp和Samba服务器。 2. 部署DNS 服务器​ #!/bin/bash# 更新系统 echo "更新系统..." sudo yum update -y# 安装 BIND 和相关工具 echo "安装 BIND 和相关工具..." sudo y…

UE5Actor模块源码深度剖析:从核心架构到实践应用

UE5 Actor模块源码深度剖析:从核心架构到实践应用 a. UE5 Actor模块架构概述 在UE5引擎中,Actor扮演着至关重要的角色,它是整个游戏世界中各类可交互对象的基础抽象。从本质上来说,所有能够被放置到关卡中的对象都属于Actor的范畴,像摄像机、静态网格体以及玩家起始位置…

DreamDiffusion代码学习及复现

论文解读在这里 File path | Description /pretrains ┣ &#x1f4c2; models ┃ ┗ &#x1f4dc; config.yaml ┃ ┗ &#x1f4dc; v1-5-pruned.ckpt┣ &#x1f4c2; generation ┃ ┗ &#x1f4dc; checkpoint_best.pth ┣ &#x1f4c2; eeg_pretain ┃ ┗ …

用Python实现TCP代理

依旧是Python黑帽子这本书 先附上代码&#xff0c;我在原书代码上加了注释&#xff0c;更好理解 import sys import socket import threading#生成可打印字符映射 HEX_FILTER.join([(len(repr(chr(i)))3) and chr(i) or . for i in range(256)])#接收bytes或string类型的输入…

Pyinstaller 打包flask_socketio为exe程序后出现:ValueError: Invalid async_mode specified

Pyinstaller 打包flask_socketio为exe程序后出现&#xff1a;ValueError: Invalid async_mode specified 一、详细描述问题描述 Traceback (most recent call last): File "app_3.py", line 22, in <module> File "flask_socketio\__init__.py"…

django REST framework(DRF)教程

Django DRF API Django 基本使用Django DRF序列化器Django DRF视图Django DRF常用功能Django 基本使用 前后端分离开发模式认识RestFulAPI回顾Django开发模式Django REST Framework初探前后端分离开发模式 前后端分离前:前端页面看到的效果都是由后端控制,即后端渲染HTML页面…

【Linux】Orin NX + Ubuntu22.04配置国内源

1、获取源 清华源 arm 系统的源,可以在如下地址获取到 https://mirror.tuna.tsinghua.edu.cn/help/ubuntu-ports/ 选择HTTPS,否则可能报错: 明文签署文件不可用,结果为‘NOSPLIT’(您的网络需要认证吗?)查看Orin NX系统版本 选择jammy的源 2、更新源 1)备份原配…

【含文档+PPT+源码】基于微信小程序的社交摄影约拍平台的设计与实现

项目介绍 本课程演示的是一款基于微信小程序的社交摄影约拍平台的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本套系…

JDBC常用的接口

一、什么是JDBC JDBC是Java语言连接数据库的接口规范。 二、JDBC的体系 1、Java官方提供一个操作数据库的抽象接口 抽象接口有很多的接口和抽象类。 例如&#xff1a;Driver、Connection、Statement。 2、各个数据库厂商提供各自的Java实现类 需要各自实现具体的细节。 例如&am…

容器适配器-stack栈

C标准库不只是包含了顺序容器&#xff0c;还包含一些为满足特殊需求而设计的容器&#xff0c;它们提供简单的接口。 这些容器可被归类为容器适配器(container adapter)&#xff0c;它们是改造别的标准顺序容器&#xff0c;使之满足特殊需求的新容器。 适配器:也称配置器,把一…

[250403] HuggingFace 新增检查模型与电脑兼容性的功能 | Firefox 发布137.0 支持标签组

目录 Hugging Face 让寻找兼容的 AI 模型变得更容易Firefox 137 版本更新摘要 Hugging Face 让寻找兼容的 AI 模型变得更容易 Hugging Face 是一个流行的在线平台&#xff0c;用于访问开源人工智能 (AI) 工具和模型。该平台推出了一项有用的新功能&#xff0c;允许个人轻松检查…

.NET 创建MCP使用大模型对话二:调用远程MCP服务

在上一篇文章.NET 创建MCP使用大模型对话-CSDN博客中&#xff0c;我们简述了如何使用mcp client使用StdIo模式调用本地mcp server。本次实例将会展示如何使用mcp client模式调用远程mcp server。 一&#xff1a;创建mcp server 我们创建一个天气服务。 新建WebApi项目&#x…

Redis 中 Set(例如标签) 和 ZSet(例如排行榜) 的详细对比,涵盖定义、特性、命令、适用场景及总结表格

以下是 Redis 中 Set 和 ZSet 的详细对比&#xff0c;涵盖定义、特性、命令、适用场景及总结表格&#xff1a; 1. 核心定义 数据类型SetZSet&#xff08;Sorted Set&#xff09;定义无序的、唯一的字符串集合&#xff0c;元素不重复。有序的、唯一的字符串集合&#xff0c;每个…

解决Spring参数解析异常:Name for argument of type XXX not specified

前言 在开发 Spring Boot 应用时&#xff0c;我们常遇到类似 java.lang.IllegalArgumentException: Name for argument not specified 的报错。这类问题通常与方法参数名称的解析机制相关&#xff0c;尤其在使用 RequestParam、PathVariable 等注解时更为常见。 一、问题现象与…