SpringMVC笔记
- 公共AI网站:https://chatgptplus.cn/
- vue3官网:https://cn.vuejs.org/
- SpringBoot官网:https://docs.spring.io/spring-boot/index.html
Ant风格访问
Spring MVC 支持 Ant 风格(Ant-style path matching)主要体现在 URL 路径匹配模式上。这种模式是 Spring Web 框架用来进行 URL 模式匹配的一种方式,借用了 Apache Ant(一个流行的 Java 构建工具)中的路径匹配规则。Ant 风格的路径匹配使得 URL 路径映射更加灵活和方便。
*匹配单一路径层级中的任意字符。**匹配任意多个路径层级。?匹配单个字符。
1. Ant 风格路径匹配规则
Ant 风格的路径匹配规则中有几个特殊字符,分别是 *、** 和 ?,它们具有不同的匹配意义:
(1) *(匹配零个或多个字符)
*可以匹配路径中的任何部分,但只能匹配单一层级中的路径。- 举个例子,
/foo/*可以匹配/foo/bar或/foo/abc,但不能匹配/foo/bar/baz。 - 示例:
/foo/*匹配/foo/bar。/foo/*/bar匹配/foo/abc/bar。
(2) **(匹配零个或多个目录)
**可以匹配多个目录层级,它比*更加强大,能够跨越多个层级。- 示例:
/foo/**/bar匹配/foo/bar、/foo/abc/bar、/foo/abc/def/bar等。/foo/**/bar/**/baz匹配/foo/abc/bar/xyz/baz。
(3) ?(匹配单个字符)
?用于匹配单个字符,不是零个或多个字符。它通常用于精确匹配某些路径中的单个字符。- 示例:
/foo/a?c可以匹配/foo/abc,但不能匹配/foo/abcc。
2. Ant 风格的路径匹配应用
Spring MVC 采用了这种路径匹配方式,使得映射 URL 路径时更加灵活。例如,使用 @RequestMapping 注解来定义控制器方法时,可以利用 Ant 风格的路径匹配规则。
示例 1:@RequestMapping 使用 Ant 风格
java
@Controller
public class MyController {
@RequestMapping("/foo/*") // 匹配路径 /foo/bar 或 /foo/abc
public String handleFoo() {
return "foo";
}
@RequestMapping("/foo/**") // 匹配路径 /foo/bar 或 /foo/abc/xyz
public String handleFooRecursive() {
return "fooRecursive";
}
@RequestMapping("/foo/a?c") // 匹配路径 /foo/abc,但不匹配 /foo/abcc
public String handleSpecificPattern() {
return "specificPattern";
}
}
在这个例子中:
/foo/*只会匹配/foo/bar或/foo/abc等简单路径。/foo/**会匹配/foo/bar、/foo/abc/xyz等多层次路径。/foo/a?c会匹配/foo/abc,但不会匹配/foo/abcc。
示例 2:@RequestMapping 配合请求方法
Spring MVC 还支持在映射中结合请求方法(如 GET、POST)来实现更细粒度的路径匹配:
java
@Controller
@RequestMapping("/foo")
public class FooController {
@RequestMapping(value = "/bar/*", method = RequestMethod.GET) // GET 请求
public String handleBar() {
return "barGET";
}
@RequestMapping(value = "/bar/**", method = RequestMethod.POST) // POST 请求
public String handleBarPost() {
return "barPOST";
}
}
在这个例子中:
/foo/bar/*仅在处理GET请求时匹配。/foo/bar/**仅在处理POST请求时匹配。
3. Ant 风格路径与通配符的结合使用
在实际开发中,Spring MVC 支持 Ant 风格路径的同时,还可以与路径变量、正则表达式等功能结合使用。
示例 1:路径变量 + Ant 风格
java
@RequestMapping("/user/{id}/**") // 匹配多层路径,id 为路径变量
public String handleUser(@PathVariable("id") String userId) {
return "User ID: " + userId;
}
- 这个路径匹配
/user/123/abc/xyz,其中id会捕获为123。
示例 2:正则表达式 + Ant 风格
java
@RequestMapping("/product/{id:\\d+}/**") // 正则匹配数字 id
public String handleProduct(@PathVariable("id") String productId) {
return "Product ID: " + productId;
}
- 这里的路径
/product/{id:\\d+}/**只会匹配数字形式的id,比如/product/123/abc/xyz。
4. 优先级和匹配规则
在使用 Ant 风格路径匹配时,路径匹配的优先级有一定的规则。具体来说,/** 会匹配任何路径,所以它的优先级通常较低,避免与其他精确匹配的路径冲突。
示例:优先级比较
java
@Controller
@RequestMapping("/foo")
public class FooController {
@RequestMapping("/foo/{id}") // 精确匹配路径 /foo/{id}
public String handleFoo(@PathVariable String id) {
return "foo:" + id;
}
@RequestMapping("/foo/**") // 匹配所有以 /foo/ 开头的路径
public String handleFooCatchAll() {
return "catchAll";
}
}
在这个例子中,如果访问 /foo/bar,它会首先匹配 /foo/{id},因为它更精确。
访问控制
请求地址时返回对应的网页文件
@RestController用于返回对象格式的内容,在后面会使用ModelAndView可以返回网页文件@Controller用于返回网页文件
环境要求
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.36</version>
</dependency>
错误页面设置
在这个路径下可以配置错误码要访问的页面,也就是可以自定义页面内容

使用@Controller
返回需要访问的HTML内容页面,最后返回的字符串就是页面,这个页面位于templates目录下
java
@RequestMapping("/use")
@Controller
public class UseController {
// 带参数访问
@RequestMapping(value = "hello", method = RequestMethod.GET, params = {"name"})
public String hello() {
return "hello";
}
@GetMapping("jumpPage")
public String jumpPage() {
return "jumpPage";
}
@GetMapping("index")
public String quick() {
return "user";
}
// 跳转的页面
@GetMapping("toJump")
public String toJump() {
return "redirect:jumpPage";
}
}
如果在使用@Controller需要返回JSON内容,需要在控制器方法上加上@ResponseBody
java
@GetMapping("getJson")
@ResponseBody
public List<String> getJson() {
ArrayList<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
return list;
}
将视图和模型拆开
java
// 将视图和模型拆开
@GetMapping("page/test3")
public String test3(Model model) {
model.addAttribute("test3", "测试3");
return "page/test3";
}
使用@RestController
使用方式1
如果使用@RestController那么返回的就是JSON对象,但是这时候要想返回网页文件,需要使用ModelAndView
java
@RequestMapping("userRest")
@RestController
public class UseRestController {
@GetMapping("page/test")
public ModelAndView test() {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("page/test");
modelAndView.addObject("message", "这是消息内容");
return modelAndView;
}
}
我们引入了thymeleaf所以有以下内容<h4 th:text="'消息:'+ ${message}"></h4>
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>使用RestController返回页面信息</title>
</head>
<body>
<h3>使用RestController返回页面信息</h3>
<h4 th:text="'消息:'+ ${message}"></h4>
</body>
</html>
其中
modelAndView.addObject("message", "这是消息内容");是可选的
使用方式2
在控制器方法上使用ModelAndView
java
@GetMapping("page/test2")
public ModelAndView test2(ModelAndView modelAndView) {
modelAndView.addObject("hello", "你好");
modelAndView.setViewName("page/test2");
return modelAndView;
}
向session共享数据
在 Spring MVC 中,Session 是用于存储用户会话期间的数据的一种机制。每个用户访问的应用程序都将拥有一个唯一的会话。通过 HttpSession,可以在用户的会话中存储一些数据,直到用户关闭浏览器或会话过期。
Spring MVC 提供了多种方式来与 HttpSession 进行交互,下面详细介绍如何通过 HttpSession 向 Session 共享数据。
1. 通过 HttpSession 操作 Session 数据
在 Spring MVC 控制器中,您可以通过 HttpSession 对象来存储和读取会话数据。
示例:将数据添加到 Session
java
@Controller
public class SessionController {
@RequestMapping("/setSessionData")
public String setSessionData(HttpSession session) {
// 将数据存储到 Session 中
session.setAttribute("username", "JohnDoe");
session.setAttribute("age", 30);
return "sessionSet"; // 返回视图名
}
@RequestMapping("/getSessionData")
public String getSessionData(HttpSession session, Model model) {
// 从 Session 中获取数据
String username = (String) session.getAttribute("username");
Integer age = (Integer) session.getAttribute("age");
model.addAttribute("username", username);
model.addAttribute("age", age);
return "sessionData"; // 返回视图名
}
}
URL 请求:
GET /setSessionData会将数据"username": "JohnDoe"和"age": 30存储到 Session 中。GET /getSessionData会从 Session 中获取并显示存储的值。
2. 使用 @SessionAttributes 注解
@SessionAttributes 注解用于将控制器中的某些模型属性放入 Session 中。这种方式比直接操作 HttpSession 更为方便和简洁,特别是当需要共享多个模型属性时。
示例:使用 @SessionAttributes
java
@Controller
@SessionAttributes("user")
public class UserController {
// 在模型中添加用户对象
@RequestMapping("/setUser")
public String setUser(Model model) {
User user = new User("John", 30);
model.addAttribute("user", user);
return "userSet";
}
// 从 Session 中获取用户对象
@RequestMapping("/getUser")
public String getUser(@ModelAttribute("user") User user, Model model) {
model.addAttribute("user", user);
return "userDetails";
}
}
URL 请求:
GET /setUser会将user对象放入 Session 中。GET /getUser会从 Session 中获取user对象。
@SessionAttributes 注解不仅可以放入 Session 中,还可以与 @ModelAttribute 注解结合使用,确保模型数据保持在 Session 中。
3. 使用 @ModelAttribute 注解
@ModelAttribute 注解允许将数据放入模型中,并且在方法调用前通过 Model 传递给视图。如果和 @SessionAttributes 一起使用,它可以将属性直接添加到 HttpSession。
示例:使用 @ModelAttribute 和 @SessionAttributes
java
@Controller
@SessionAttributes("cart")
public class CartController {
// 在模型中创建并存储购物车
@ModelAttribute("cart")
public Cart createCart() {
return new Cart(); // 创建一个空的购物车对象
}
// 添加商品到购物车
@RequestMapping("/addToCart")
public String addToCart(@ModelAttribute("cart") Cart cart, @RequestParam("item") String item) {
cart.addItem(item); // 将商品添加到购物车
return "cartUpdated";
}
// 显示购物车内容
@RequestMapping("/viewCart")
public String viewCart(@ModelAttribute("cart") Cart cart, Model model) {
model.addAttribute("cart", cart);
return "viewCart";
}
}
URL 请求:
GET /addToCart?item=Apple会将Apple添加到cart中。GET /viewCart会显示购物车中的内容。
4. 通过 @RequestParam 或 @PathVariable 获取 Session 数据
如果在请求中需要通过路径变量或请求参数传递数据并存储到 Session 中,可以结合 @RequestParam 或 @PathVariable 来实现。
示例:使用 @RequestParam 存储 Session 数据
java
@Controller
public class SessionController {
@RequestMapping("/setSession/{username}")
public String setSessionData(@PathVariable("username") String username, HttpSession session) {
session.setAttribute("username", username);
return "sessionSet";
}
@RequestMapping("/getSession")
public String getSessionData(HttpSession session, Model model) {
String username = (String) session.getAttribute("username");
model.addAttribute("username", username);
return "sessionData";
}
}
URL 请求:
GET /setSession/JohnDoe会将"username": "JohnDoe"存储到 Session 中。GET /getSession会从 Session 中获取并显示username。
5. 删除 Session 数据
如果希望在某个操作后清除 Session 中的某些数据,可以使用 HttpSession 提供的 removeAttribute 方法。
示例:删除 Session 数据
java
@Controller
public class SessionController {
@RequestMapping("/removeSessionData")
public String removeSessionData(HttpSession session) {
session.removeAttribute("username"); // 删除指定的属性
return "sessionRemoved";
}
}
URL 请求:
GET /removeSessionData会从 Session 中删除"username"属性。
6. Session 过期与清理
默认情况下,Spring MVC 的 HttpSession 会话会在用户关闭浏览器后过期,或者会话超时(默认30分钟)。可以在 web.xml 或应用的配置类中设置会话超时:
示例:设置 Session 超时
xml
<session-config>
<session-timeout>30</session-timeout> <!-- 设置会话超时为30分钟 -->
</session-config>
7. 通过 Spring 配置 Session
通过 Spring 配置文件或 Java 配置类,还可以控制 Session 的相关行为(如会话过期时间、session 的持久化等)。
示例:Java 配置类
java
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SessionInterceptor()).addPathPatterns("/**");
}
}
SessionInterceptor 可以用于监控和管理 Session 数据。
8. 总结
在 Spring MVC 中,向 Session 共享数据主要有以下几种方式:
HttpSession:通过HttpSession对象存储和读取 Session 数据。@SessionAttributes:通过@SessionAttributes注解将模型属性添加到 Session 中。@ModelAttribute:结合@SessionAttributes使用,将模型数据持久化到 Session 中。@RequestParam和@PathVariable:将请求参数或路径变量存储到 Session 中。- Session 过期与清理:可以通过配置控制会话超时,或手动清除 Session 数据。
Spring MVC 提供的 Session 管理机制非常灵活,能够满足各种需求。
向application域共享数据
在 Spring MVC 中,Application 域(也称为 ServletContext )是一个全局范围,用于在整个应用程序中共享数据。不同于 Session 域和 Request 域,Application 域中的数据对整个 Web 应用的所有用户都是可见的,因此适合存储全局共享的配置信息、常量、初始化数据等。
在 Spring MVC 中,我们可以通过 ServletContext 来向 Application 域共享数据,通常使用 setAttribute 和 getAttribute 方法来进行操作。
1. 通过 ServletContext 共享数据
ServletContext 是与整个 Web 应用程序相关联的对象,它允许你在多个请求和多个会话之间共享数据。在 Spring MVC 中,可以通过以下两种方式来访问 ServletContext:
- 直接使用
HttpServletRequest.getSession().getServletContext()获取ServletContext。 - 使用
@Autowired注解注入ServletContext对象。
示例 1:通过 ServletContext 共享数据
1.1 通过 HttpServletRequest 获取 ServletContext
java
@Controller
public class ApplicationController {
@RequestMapping("/setApplicationData")
public String setApplicationData(HttpServletRequest request) {
// 获取 ServletContext
ServletContext servletContext = request.getServletContext();
// 向 Application 域存储数据
servletContext.setAttribute("appName", "SpringMVCApp");
servletContext.setAttribute("version", "1.0.0");
return "applicationDataSet";
}
@RequestMapping("/getApplicationData")
public String getApplicationData(HttpServletRequest request, Model model) {
// 获取 ServletContext
ServletContext servletContext = request.getServletContext();
// 从 Application 域获取数据
String appName = (String) servletContext.getAttribute("appName");
String version = (String) servletContext.getAttribute("version");
model.addAttribute("appName", appName);
model.addAttribute("version", version);
return "applicationData";
}
}
URL 请求:
GET /setApplicationData会向Application域中存储"appName": "SpringMVCApp"和"version": "1.0.0"。GET /getApplicationData会从Application域中读取数据,并返回给视图。
1.2 通过 @Autowired 注入 ServletContext
java
@Controller
public class ApplicationController {
@Autowired
private ServletContext servletContext;
@RequestMapping("/setApplicationData")
public String setApplicationData() {
// 向 Application 域存储数据
servletContext.setAttribute("appName", "SpringMVCApp");
servletContext.setAttribute("version", "1.0.0");
return "applicationDataSet";
}
@RequestMapping("/getApplicationData")
public String getApplicationData(Model model) {
// 从 Application 域获取数据
String appName = (String) servletContext.getAttribute("appName");
String version = (String) servletContext.getAttribute("version");
model.addAttribute("appName", appName);
model.addAttribute("version", version);
return "applicationData";
}
}
在这个例子中,@Autowired 注解会自动将 ServletContext 注入到控制器中。
2. 应用场景
将数据放到 Application 域中通常用于存储以下类型的数据:
- 应用级别的数据:例如应用名称、版本号、初始化配置等,这些数据是全局共享的。
- 常量和初始化信息 :如果有一些需要在多个请求中共享的常量或初始化信息,可以将它们放到
Application域中。 - 数据库连接池或常用资源 :对于一些全局共享的资源(如数据库连接池),可以在
Application域中进行配置并在不同的请求中共享。
3. 注意事项
- 全局共享 :与
Session和Request域不同,Application域中的数据对所有用户和请求都可见。因此,要特别小心在Application域中存储敏感数据,避免泄漏用户个人信息等。 - 生命周期 :
Application域中的数据在整个应用程序生命周期内有效,直到应用服务器重新启动。因此,放入Application域的数据一般是全局的、不会频繁变化的。 - 线程安全 :
Application域的数据是共享的,因此在并发访问时要考虑线程安全问题。如果有多个线程访问同一数据,可能需要进行同步。
4. 清理 Application 域中的数据
如果不再需要某个共享数据,可以使用 removeAttribute 方法从 Application 域中移除该数据。
示例:删除 Application 域中的数据
java
@Controller
public class ApplicationController {
@RequestMapping("/removeApplicationData")
public String removeApplicationData(HttpServletRequest request) {
// 获取 ServletContext
ServletContext servletContext = request.getServletContext();
// 从 Application 域移除数据
servletContext.removeAttribute("appName");
servletContext.removeAttribute("version");
return "applicationDataRemoved";
}
}
URL 请求:
GET /removeApplicationData会从Application域中移除appName和version属性。
5. 使用 @ApplicationScope(Spring 方式)
如果使用 Spring 框架进行开发,也可以使用 Spring 提供的 @ApplicationScope 注解来定义在整个应用范围内共享的 Bean。这种方法通常用于 Spring 组件,而不是直接操作 ServletContext。
示例:使用 @ApplicationScope
java
@Component
@Scope("application")
public class AppConfig {
private String appName = "SpringMVCApp";
public String getAppName() {
return appName;
}
}
在这种情况下,Spring 管理的 Bean 会在应用级别共享,类似于 ServletContext 中存储的数据。
6. 总结
Application域(即ServletContext)用于在整个应用程序范围内共享数据,适合存储全局共享的信息、配置和常量。- 通过
HttpServletRequest.getServletContext()或@Autowired注解可以访问ServletContext并向Application域中共享数据。 - 数据存储在
Application域中可以在整个应用程序生命周期内有效,适用于共享全局性的、无需频繁更新的数据。 - 应谨慎存储敏感数据,并注意线程安全和数据的生命周期。
通过合理地使用 Application 域,你可以实现全局共享的数据管理,并且不需要担心会话或请求的生命周期问题。
重定向和转发使用
在 Spring MVC 中,**重定向(Redirect)和转发(Forward)**是两种常见的请求处理方式,它们分别用于不同的场景。Spring 提供了灵活的 API 来实现这两种请求方式。
1. 转发(Forward)
转发是指服务器将请求转发到另一个资源(如 JSP 页面或另一个控制器方法),并且请求和响应都不会发生改变。即,URL 不会发生变化,客户端仍然看到原始的 URL。
转发的实现
在 Spring MVC 中,可以通过以下两种方式实现转发:
- 使用
RequestDispatcher.forward()方法。 - 使用
ModelAndView中的"forward:"前缀来指定转发的路径。
示例 1:使用 RequestDispatcher 转发
java
@Controller
public class ForwardController {
@RequestMapping("/forwardExample")
public void forward(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 使用 Servlet 的 RequestDispatcher 进行转发
request.getRequestDispatcher("/forwardedPage").forward(request, response);
}
@RequestMapping("/forwardedPage")
public String forwardedPage() {
return "forwardedPage"; // 返回视图
}
}
示例 2:使用 ModelAndView 转发
java
@Controller
public class ForwardController {
@RequestMapping("/forwardExample")
public ModelAndView forwardExample() {
// 使用 ModelAndView 进行转发
return new ModelAndView("forward:/forwardedPage");
}
@RequestMapping("/forwardedPage")
public String forwardedPage() {
return "forwardedPage"; // 返回视图
}
}
解释:
forward:/forwardedPage表示将请求转发到/forwardedPage,且客户端的 URL 不会发生变化。- 在转发的过程中,控制器方法返回的视图会直接被渲染。
转发的特点
- URL 不改变:用户的浏览器地址栏不会发生变化,仍然显示原始的请求路径。
- 共享同一个请求 :请求数据(如请求参数)会被转发到目标资源,可以通过
request对象共享。 - 适用于内部请求:转发是服务端内部的操作,适用于控制器之间的跳转或者从控制器到视图的跳转。
2. 重定向(Redirect)
重定向是指服务器告诉客户端(浏览器)重新发起一个新的请求。重定向会导致浏览器地址栏的 URL 更新为新的地址,因此会导致一次新的 HTTP 请求。
重定向的实现
在 Spring MVC 中,重定向可以通过以下几种方式实现:
- 使用
redirect:前缀返回视图。 - 使用
HttpServletResponse.sendRedirect()方法。
示例 1:使用 redirect: 前缀
java
@Controller
public class RedirectController {
@RequestMapping("/redirectExample")
public String redirectExample() {
// 使用 redirect: 前缀进行重定向
return "redirect:/redirectedPage";
}
@RequestMapping("/redirectedPage")
public String redirectedPage() {
return "redirectedPage"; // 返回视图
}
}
示例 2:使用 HttpServletResponse.sendRedirect()
java
@Controller
public class RedirectController {
@RequestMapping("/redirectExample")
public void redirectExample(HttpServletResponse response) throws IOException {
// 使用 HttpServletResponse.sendRedirect() 进行重定向
response.sendRedirect("/redirectedPage");
}
@RequestMapping("/redirectedPage")
public String redirectedPage() {
return "redirectedPage"; // 返回视图
}
}
解释:
redirect:/redirectedPage会发出一个 HTTP 302 重定向响应,浏览器会发起一次新的请求到/redirectedPage,并更新地址栏的 URL。- 使用
HttpServletResponse.sendRedirect()方法也会发送重定向响应,同样会导致浏览器重新发起新的请求。
重定向的特点
- URL 改变:浏览器的地址栏会更新为重定向的目标 URL。
- 不同的请求:重定向会产生一次新的 HTTP 请求,原请求的参数不会自动携带到新请求中,除非在重定向 URL 中显式传递。
- 适用于跨请求跳转:重定向适合用于不同请求之间的跳转,特别是当需要在多个请求中传递数据时。
3. 重定向与转发的区别
| 特性 | 重定向(Redirect) | 转发(Forward) |
|---|---|---|
| URL 变化 | 浏览器地址栏会更新为新的 URL | 浏览器地址栏不会改变,仍然是原始请求 URL |
| 请求次数 | 会产生两次请求:第一次请求重定向,第二次是新的目标请求 | 只会产生一次请求(内部请求) |
| 数据传递 | 重定向后,数据不能自动传递到新请求中,除非通过 URL 参数传递 | 可以直接传递请求数据,如请求参数和请求属性 |
| 适用场景 | 当需要跨请求或跨控制器传递数据时,或者需要跳转到外部 URL | 当请求处理完成后,内部跳转到另一个视图或资源时 |
| 性能 | 因为需要进行两次请求,所以相比转发略有性能开销 | 因为只需要一次请求,性能开销较小 |
4. 常见使用场景
(1) 重定向的使用场景
-
表单提交后的重定向 :表单数据提交后,为了防止表单重复提交(用户刷新页面时),常常会使用重定向到另一个页面,这种方法叫做 Post/Redirect/Get (PRG) 模式。
例如,用户提交了一个订单数据后,页面显示 "订单已提交",并重定向到订单查看页面。
java@RequestMapping("/submitOrder") public String submitOrder(Order order) { orderService.save(order); // 提交订单后重定向到订单详情页 return "redirect:/orderDetails?orderId=" + order.getId(); } -
外部 URL 重定向:在用户登录后重定向到外部系统或第三方网站。
java@RequestMapping("/redirectToExternalSite") public String redirectToExternal() { // 重定向到外部 URL return "redirect:http://www.example.com"; }
(2) 转发的使用场景
-
内部资源的转发:当需要在同一应用程序内部跳转时(如从控制器到视图),或者从一个控制器跳转到另一个控制器时,可以使用转发。
例如,在处理用户请求后,将其转发到 JSP 页面进行显示:
java@RequestMapping("/showUser") public String showUserDetails(Model model) { User user = userService.getUser(); model.addAttribute("user", user); return "forward:/userDetails.jsp"; // 内部转发到 userDetails.jsp 页面 } -
从一个控制器跳转到另一个控制器:在处理完业务逻辑后,可能需要跳转到另一个控制器来处理某些逻辑。
java@RequestMapping("/processOrder") public String processOrder(Order order) { orderService.process(order); return "forward:/orderConfirmation"; // 内部跳转到订单确认页面 }
5. 总结
- 重定向(Redirect):客户端浏览器会发起一次新的请求,地址栏 URL 会发生变化,适用于需要跨请求跳转或外部跳转的场景。
- 转发(Forward):请求在服务器内部被转发,地址栏 URL 不变,适用于同一请求的内部跳转。
通过合理使用转发和重定向,你可以灵活地控制请求流转和用户体验。
Thymeleaf快速入门
Thymeleaf 是一种现代化的 Java 模板引擎,广泛用于生成 HTML、XML、JavaScript 等内容。它有许多内置的指令和功能,用于渲染动态内容、条件渲染、循环、处理表达式等。以下是 Thymeleaf 中常见的指令和属性的详细介绍:
1. th:text
用于替换元素的文本内容。
html
<span th:text="${message}"></span>
${message}的值会替换span元素的文本。
如果需要格式化日期,需要注意,使用
temporals进行操作
html<td class="text-success" th:text="${#temporals.format(bill.transactionDate,'yyyy-MM-dd HH:mm:ss')}"></td>
2. th:utext
用于替换元素的文本内容,并允许处理 HTML 标签(不会转义 HTML)。
html
<span th:utext="${htmlContent}"></span>
${htmlContent}的内容直接插入,并解析其中的 HTML。
3. th:value
设置表单元素的 value 属性,通常用于输入框或选择框。
html
<input type="text" th:value="${user.name}" />
- 将
${user.name}的值赋给该输入框的value属性。
4. th:each
用于循环遍历集合或数组。
html
<ul>
<li th:each="person : ${people}">
<span th:text="${person.name}"></span>
</li>
</ul>
- 遍历
people集合,输出每个person.name。
5. th:if
用于条件渲染,只有满足条件时才渲染元素。
html
<div th:if="${user.isAdmin}">
<p>Welcome, admin!</p>
</div>
- 如果
user.isAdmin为true,渲染该div。
6. th:unless
与 th:if 相反,只有条件为 false 时才渲染元素。
html
<div th:unless="${user.isAdmin}">
<p>You are not an admin!</p>
</div>
- 如果
user.isAdmin为false,渲染该div。
7. th:attr
用于设置元素的多个属性。
html
<img th:attr="src=${imageUrl}" th:attr="alt=${imageDescription}" />
- 设置
img元素的src和alt属性。
8. th:src / th:href
用于动态设置 src 或 href 属性。
html
<img th:src="@{${imageUrl}}" alt="Image">
<a th:href="@{${linkUrl}}">Click Here</a>
th:src用于设置图片的src属性,th:href用于设置链接的href属性。
9. th:class
动态设置 class 属性,支持条件表达式。
html
<div th:class="${isActive} ? 'active' : 'inactive'">...</div>
- 如果
isActive为true,设置class="active",否则为inactive。
10. th:classappend / th:classprepend
分别在现有的 class 属性上追加或前置新类。
html
<div th:classappend="'newClass'">...</div>
<div th:classprepend="'prefixClass'">...</div>
th:classappend会将新的类追加到现有类的后面。th:classprepend会将新的类添加到现有类的前面。
11. th:id
设置元素的 id 属性。
html
<input type="text" th:id="${elementId}" />
- 设置
input元素的id为${elementId}的值。
12. th:action
设置表单的 action 属性。
html
<form th:action="@{/submitForm}" method="post">
<!-- form fields -->
</form>
- 设置表单的
action为/submitForm。
13. th:style
设置元素的 style 属性。
html
<div th:style="'color: ' + ${color}"></div>
- 动态设置
style属性,${color}的值会成为color样式的值。
14. th:fragment
定义一个可重用的片段,通常在模板中调用。
html
<div th:fragment="userFragment">
<p>Welcome, <span th:text="${user.name}"></span></p>
</div>
- 定义一个
userFragment片段,可以在其他模板中引用。
15. th:replace
替换当前元素,并将一个片段或其他模板插入其中。
html
<div th:replace="~{userFragment}"></div>
th:replace会将userFragment片段的内容插入到当前div中。
16. th:include
将另一个模板的内容插入当前模板中,但不会替换当前元素。
html
<div th:include="~{userFragment}"></div>
- 插入
userFragment的内容,但保留当前div元素。
17. th:with
局部变量声明,用于在模板中定义临时变量。
html
<div th:with="total=${cart.totalPrice}">
<p th:text="'Total price: ' + ${total}"></p>
</div>
th:with用于在当前元素的上下文中定义变量,类似于局部变量。
18. th:block
在模板中定义一个不会渲染任何 HTML 标签的块元素。用于组合多个元素。
html
<th:block th:each="person : ${people}">
<p th:text="${person.name}"></p>
</th:block>
th:block不会渲染任何标签,但可以用来包装多个元素进行条件判断或循环。
19. th:switch / th:case
类似于 Java 中的 switch 语句,用于条件选择。
html
<div th:switch="${status}">
<span th:case="'active'">Active</span>
<span th:case="'inactive'">Inactive</span>
<span th:case="*">Unknown</span>
</div>
- 根据
${status}的值,渲染对应的span元素。
20. th:object
用来为表单元素绑定一个对象。
html
<form th:action="@{/submit}" th:object="${user}">
<input type="text" th:field="*{name}" />
<input type="text" th:field="*{email}" />
<button type="submit">Submit</button>
</form>
th:object绑定整个表单到user对象。th:field用于绑定每个表单字段到对象的属性。
21. th:href / th:src
用于动态设置 URL 值。
html
<a th:href="@{/users/{id}(id=${user.id})}">Profile</a>
<img th:src="@{/images/{imageName}(imageName=${image.name})}" />
- 动态生成 URL,支持路径变量的替换。
22. th:placeholder
设置表单输入框的 placeholder 属性。
html
<input type="text" th:placeholder="${placeholderText}" />
- 设置
input的placeholder为${placeholderText}的值。
总结
Thymeleaf 提供了许多强大的指令来处理模板中的动态内容、条件渲染、迭代和属性绑定。常见的指令包括:
th:text、th:utext:用于设置文本内容。th:each:用于循环遍历。th:if、th:unless:用于条件判断。th:attr、th:id、th:class:用于设置 HTML 属性。th:replace、th:include:用于片段包含。
span>
Inactive
Unknown
```
- 根据
${status}的值,渲染对应的span元素。
20. th:object
用来为表单元素绑定一个对象。
html
<form th:action="@{/submit}" th:object="${user}">
<input type="text" th:field="*{name}" />
<input type="text" th:field="*{email}" />
<button type="submit">Submit</button>
</form>
th:object绑定整个表单到user对象。th:field用于绑定每个表单字段到对象的属性。
21. th:href / th:src
用于动态设置 URL 值。
html
<a th:href="@{/users/{id}(id=${user.id})}">Profile</a>
<img th:src="@{/images/{imageName}(imageName=${image.name})}" />
- 动态生成 URL,支持路径变量的替换。
22. th:placeholder
设置表单输入框的 placeholder 属性。
html
<input type="text" th:placeholder="${placeholderText}" />
- 设置
input的placeholder为${placeholderText}的值。
总结
Thymeleaf 提供了许多强大的指令来处理模板中的动态内容、条件渲染、迭代和属性绑定。常见的指令包括:
th:text、th:utext:用于设置文本内容。th:each:用于循环遍历。th:if、th:unless:用于条件判断。th:attr、th:id、th:class:用于设置 HTML 属性。th:replace、th:include:用于片段包含。th:switch、th:case:用于类似switch的条件语句。