在SpringBoot項目中這幾個注解你們還用嗎?
環(huán)境:SpringBoot3.3.0
1. 簡介
在SpringBoot應(yīng)用開發(fā)中,傳統(tǒng)的請求屬性處理方式如@ModelAttribute,@SessionAttribute,@RequestAttribute以及RedirectAttributes似乎用的越來越少了,但是在一些特定場景下它們發(fā)揮著不可或缺的作用尤其是當(dāng)涉及到表單提交、會話狀態(tài)管理和重定向?qū)傩詡鬟f時。
- @ModelAttribute:主要用于綁定請求中的數(shù)據(jù)到方法參數(shù)或模型屬性上,常用于處理表單提交,使得復(fù)雜的對象綁定變得簡單直接。它允許你預(yù)處理傳入的數(shù)據(jù),或者初始化一個命令對象供表單使用。
- @SessionAttribute:用于從HttpSession中存取屬性,這對于存儲非敏感的用戶信息或臨時數(shù)據(jù)非常有用,比如用戶設(shè)置或購物車信息。
- @RequestAttribute:處理單一請求上下文,允許你在控制器間通過HttpServletRequest傳遞自定義屬性,適合傳遞那些不需要跨請求持久化的數(shù)據(jù)。
- RedirectAttributes:是在執(zhí)行重定向操作時用來傳遞閃存屬性的利器,這些屬性在重定向后的一次請求中可用,之后自動移除,非常適合于向用戶展示操作成功或失敗的消息,同時保持URL的干凈。
接下來將詳細(xì)接上上面幾個注解及類的使用。
2. 實戰(zhàn)案例
2.1 @ModelAttribute
該注解可用于方法參數(shù)及方法上;
用于方法參數(shù)
@GetMapping("/product/{cateId}/{id}")
public ProductDTO test(@ModelAttribute ProductDTO dto) {
return dto ;
}
圖片
首先,SpringMVC會自動將請求URI中的占位符數(shù)據(jù)綁定到當(dāng)前ProductDTO對象上,這個綁定與@ModelAttribute注解沒有關(guān)系。而這里注解的作用是將當(dāng)前ProductDTO對象綁定到模型數(shù)據(jù)中,接下來如果你使用的thymeleaf則可以直接在頁面中訪問,如下示例:
@GetMapping("/product/{cateId}/{id}")
public String test(@ModelAttribute ProductDTO dto) {
return "modelattribute" ;
}
在頁面中直接訪問ProductDTO;
<div th:if="${productDTO}">
<ul>
<li>cateId: <a th:text="${productDTO.cateId}"></a></li>
<li>id: <a th:text="${productDTO.id}"></a></li>
</ul>
</div>
頁面顯示
圖片
在上面你看到了,默認(rèn)訪問的key是當(dāng)前類型的首字母改為小寫,我們可以通過配置屬性修改默認(rèn)key
public String test(@ModelAttribute("dto") ProductDTO dto)
這樣在頁面中訪問的key將是:dto。
用于方法
@GetMapping("/product/{cateId}/{id}")
public String test() {
return "modelattribute" ;
}
@ModelAttribute("dto")
public ProductDTO dto(ProductDTO dto) {
System.out.println("dto....") ;
return dto ;
}
將注解用于方法上后,當(dāng)前的Controller中的所有接口都會先執(zhí)行該方法將請求中的參數(shù)信息綁定到ProductDTO對象中,最后將該dto綁定到模型數(shù)據(jù)上。通過上面的配置你在頁面上一樣也可以訪問該對象數(shù)據(jù)。
2.2 @SessionAttribute
該注解只能用于方法參數(shù)上。
該注解的作用用于讀取session中的數(shù)據(jù)到當(dāng)前的參數(shù)中,如下示例:
@GetMapping("/user")
@ResponseBody
public User user(@SessionAttribute("user") User user) {
return user ;
}
// 模擬登錄后將User對象存入Session中
@GetMapping("/login")
@ResponseBody
public String login(HttpSession session) {
session.setAttribute("user", new User(666L, "Admin")) ;
return "login success" ;
}
這里會讀取Session中key=user的數(shù)據(jù)到當(dāng)前User對象中,你需要先登錄,然后再訪問/user接口。
如果session中沒有user,那么程序?qū)箦e
圖片
錯誤提示,session對象中沒有user屬性。通過如下方式設(shè)置不是必須的;
public User user(@SessionAttribute(value = "user", required = false) User user)
也可以將參數(shù)設(shè)置為Optional;
public User user(@SessionAttribute("user") Optional<User> user)
通過上面2中方式設(shè)置,在Session中不存在對應(yīng)的屬性時也不會報錯。
注:還有一個@SessionAttributes注解,該注解可以用于類上。
2.3 @RequestAttribute
該注解同樣只能用于方法參數(shù)上。
與 @SessionAttribute 類似,你也可以使用 @RequestAttribute 注解來訪問先前創(chuàng)建的請求屬性(例如,由 Servlet Filter或 HandlerInterceptor 創(chuàng)建的屬性),如下示例:
先定義一個Filter,該Filter作用是向Request中設(shè)置值;
@Component
public class UserFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
request.setAttribute("user", new User(888L, "Guest")) ;
filterChain.doFilter(request, response) ;
}
}
接下來在Controller中通過@RequestAttribute訪問user屬性。
@GetMapping("/user")
@ResponseBody
public User user(@RequestAttribute("user") Optional<User> user) {
return user.orElse(new User()) ;
}
圖片
與@SessionAttribute一樣,參數(shù)可以通過Optional設(shè)置不是必須的。
2.4 RedirectAttributes
當(dāng)頁面通過redirect進(jìn)行跳轉(zhuǎn)時,可以通過該類定義在接口方法參數(shù)中,將數(shù)據(jù)保存到該對象中后,你就可以在調(diào)整到的頁面中使用配置的屬性了,如下示例:
@GetMapping("")
public String index(RedirectAttributes ra) {
// 將你需要的數(shù)據(jù)存入該對象中
ra.addFlashAttribute("message", "hello") ;
// redirect其它頁面
return "redirect:/page/tm" ;
}
@GetMapping("tm")
public String tm(RedirectAttributes ra) {
return "test" ;
}
test.html頁面如下:
<body>
<h1>Test Page</h1>
<div th:if="${message}">
<h2 th:text="${message}" />
</div>
</body>
訪問上面的/page,將redirec到最終的test.html頁面;
圖片
redirect過來后我們可以訪問到配置的數(shù)據(jù)。