SpringMVC中的JSR303與攔截器的使用方法
一,JSR303的概念
JSR303是Java中的一個標準,用于驗證和校驗JavaBean對象的屬性的合法性。它提供了一組用于定義驗證規(guī)則的注解,如@NotNull、@Min、@Max等。在Spring MVC中,可以使用JSR303注解對請求參數(shù)進行校驗。
1.2 為什么要使用JSR303?(更加理解)
前端不是已經(jīng)校驗過數(shù)據(jù)了嗎?為什么我們還要做校驗?zāi)?,直接用不就好了?草率了,假如說前端代碼校驗沒寫好又或者是對于會一點編程的人來說,直接繞過前端發(fā)請求(通過類似Postman這樣的測試工具進行非常數(shù)據(jù)請求),把一些錯誤的參數(shù)傳過來,你后端代碼不就危險了嘛
所以我們一般都是前端一套校驗,后端在一套校驗,這樣安全性就能夠大大得到提升了。
1.3 常用的注解
在上面JSR303的概念中也指到了一些注解,以下是注解的詳細概述
注解 | 說明 |
---|---|
@Null | 用于驗證對象為null |
@NotNull | 用于對象不能為null,無法查檢長度為0的字符串 |
@NotBlank | 只用于String類型上,不能為null且trim()之后的size>0 |
@NotEmpty | 用于集合類、String類不能為null,且size>0。但是帶有空格的字符串校驗不出來 |
@Size | 用于對象(Array,Collection,Map,String)長度是否在給定的范圍之內(nèi) |
@Length | 用于String對象的大小必須在指定的范圍內(nèi) |
@Pattern | 用于String對象是否符合正則表達式的規(guī)則 |
用于String對象是否符合郵箱格式 | |
@Min | 用于Number和String對象是否大等于指定的值 |
@Max | 用于Number和String對象是否小等于指定的值 |
@AssertTrue | 用于Boolean對象是否為true |
@AssertFalse | 用于Boolean對象是否為false |
1.4 @Validated與@Valid區(qū)別
@Validated:
Spring提供的
支持分組校驗
可以用在類型、方法和方法參數(shù)上。但是不能用在成員屬性(字段)上
由于無法加在成員屬性(字段)上,所以無法單獨完成級聯(lián)校驗,需要配合@Valid
@Valid:
JDK提供的(標準JSR-303規(guī)范)
不支持分組校驗
可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(字段)上
可以加在成員屬性(字段)上,能夠獨自完成級聯(lián)校驗
二,JSR303使用
2.1 導(dǎo)入pom.xml依賴
<!-- JSR303 --> <hibernate.validator.version>6.0.7.Final</hibernate.validator.version> <!-- JSR303 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>${hibernate.validator.version}</version> </dependency>
2.2 配置校驗規(guī)則
package com.Bingzy.model; import lombok.ToString; import org.hibernate.validator.constraints.NotBlank; @ToString public class Tbook { @ToString public class Clazz { @NotNull(message = "書籍編號不能為空") protected Integer bid; @NotBlank(message = "書籍名不能為空") protected String bname; @NotBlank(message = "書籍價格不能為空") protected Float price; public Clazz(String bid, String bname, Float price) { this.bid = bid; this.bname = bname; this.price = price; } public String getBid() { return bid; } public void setBid(String bid) { this.bid = bid; } public String getBname() { return bname; } public void setBname(String bname) { this.bname = bname; } public Float getPrice() { return price; } public void setPrice(Float price) { this.price = price; } @Override public String toString() { return "Clazz{" + "bid='" + bid + '\'' + ", bname='" + bname + '\'' + ", price=" + price + '}'; } } }
2.3 入門案例
在請求處理方法中,使用@Validated或@Valid注解要驗證的對象,并根據(jù)BindingResult判斷校驗是否通過。
// 給數(shù)據(jù)添加服務(wù)端校驗 @RequestMapping("/valiAdd") public String valiAdd(@Validated Tbook tbook, BindingResult result, HttpServletRequest req){ // 如果服務(wù)端驗證不通過,有錯誤 if(result.hasErrors()){ // 服務(wù)端驗證了實體類的多個屬性,多個屬性都沒有驗證通過 List<FieldError> fieldErrors = result.getFieldErrors(); Map<String,Object> map = new HashMap<>(); for (FieldError fieldError : fieldErrors) { // 將多個屬性的驗證失敗信息輸送到控制臺 System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage()); map.put(fieldError.getField(),fieldError.getDefaultMessage()); } req.setAttribute("errorMap",map); }else { this.tbookBiz.insertSelective(tbook); return "redirect:list"; } return "book/edit"; }
edit.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>博客的編輯界面</title> </head> <body> <center> 編輯界面 <form action="${pageContext.request.contextPath }/${empty b ? 'book/valiAdd' : 'book/edit'}" method="post"><br> 書籍id:<input type="text" name="bid" value="${b.bid }"><span style="color: red">${errorMap.bid}</span><br> 書籍名稱:<input type="text" name="bname" value="${b.bname }"><span style="color: red">${errorMap.bname}</span><br> 書籍價格:<input type="text" name="price" value="${b.price }"><span style="color: red">${errorMap.price}</span><br> <input type="submit"> </form> </center> </body> </html>
運行結(jié)果:
點擊新增或修改,進入頁面后點擊提交顯示相對應(yīng)的提示語句
三,攔截器
3.1 什么是攔截器?
Spring MVC攔截器是Spring框架中的一個組件,用于攔截請求并在請求處理之前或之后執(zhí)行一些額外的操作。它可以用于實現(xiàn)一些通用的、與業(yè)務(wù)無關(guān)的功能,如日志記錄、權(quán)限驗證、異常處理、跨域請求處理等。
攔截器在請求到達DispatcherServlet之后,但在具體的Controller方法執(zhí)行之前,提供了一個攔截點,可以對請求進行處理和干預(yù)。攔截器可以攔截請求、響應(yīng)或會話的各個階段,并在每個階段執(zhí)行預(yù)定義的操作。
3.2 什么是過濾器
依賴于servlet容器。在實現(xiàn)上基于函數(shù)回調(diào),可以對幾乎所有請求進行過濾,但是缺點是一個過濾器實例只能在容器初始化時調(diào)用一次。使用過濾器的目的是用來做一些過濾操作,比如:在過濾器中修改字符編碼;在過濾器中修改HttpServletRequest的一些參數(shù),包括:過濾低俗文字、危險字符等
3.3 攔截器與過濾器的區(qū)別?
過濾器(filter)
1.filter屬于Servlet技術(shù),只要是web工程都可以使用
2.filter主要由于對所有請求過濾
3.filter的執(zhí)行時機早于Interceptor
攔截器(interceptor)
1.interceptor屬于SpringMVC技術(shù),必須要有SpringMVC環(huán)境才可以使用
2.interceptor通常由于對處理器Controller進行攔截
3.interceptor只能攔截dispatcherServlet處理的請求
3.4 應(yīng)用場景
日志記錄:記錄請求信息的日志,以便進行信息監(jiān)控、信息統(tǒng)計、計算PV(Page View)等。
權(quán)限檢查:如登錄檢測,進入處理器檢測是否登錄,如果沒有直接返回到登錄頁面;
性能監(jiān)控:有時候系統(tǒng)在某段時間莫名其妙的慢,可以通過攔截器在進入處理器之前記錄開始時間,在處理完后記錄結(jié)束時間,從而得到該請求的處理時間(如果有反向代理,如apache可以自動記錄);
通用行為:讀取cookie得到用戶信息并將用戶對象放入請求,從而方便后續(xù)流程使用,還有如提取Locale、Theme信息等,只要是多個Controller中的處理方法都需要的,我們就可以使用攔截器實現(xiàn)
四,攔截器快速入門
定義一個包并創(chuàng)建OneInterceptor類
攔截器(interceptor):
package com.Bingzy.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class OneInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【OneInterceptor】:preHandle..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("【OneInterceptor】:postHandle..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("【OneInterceptor】:afterCompletion..."); } }
spring-mvc.xml配置自定義攔截器
<mvc:interceptors> <bean class="com.Bingzy.interceptor.OneInterceptor"></bean> </mvc:interceptors>
在攔截器(interceptor)中的preHandle()方法中的返回值為true未攔截的情況:
在攔截器(interceptor)中的preHandle()方法中的返回值為false攔截的情況:
注意:攔截器會根據(jù)preHandle()方法返回值進行攔截判斷,返回了一個true
值。這個返回值表示該攔截器已經(jīng)處理了當前的請求,并且可以繼續(xù)向下傳遞請求。如果返回false
,則表示該攔截器不處理當前請求,請求將被終止
4.1 攔截器原理圖
preHandle:用于對攔截到的請求進行預(yù)處理,方法接收布爾(true,false)類型的返回值,返回true:放行,false:不放行。
執(zhí)行時機:在處理器方法執(zhí)行前執(zhí)行
方法參數(shù)
參數(shù) 說明 request 請求對象 response 響應(yīng)對象 handler 攔截到的方法處理 postHandle:用于對攔截到的請求進行后處理,可以在方法中對模型數(shù)據(jù)和視圖進行修改
執(zhí)行時機:在處理器的方法執(zhí)行后,視圖渲染之前
方法參數(shù)
參數(shù) 說明 request 請求對象 response 響應(yīng)對象 handler 攔截到的處理器方法 ModelAndView 處理器方法返回的模型和視圖對象,可以在方法中修改模型和視圖 afterCompletion:用于在整個流程完成之后進行最后的處理,如果請求流程中有異常,可以在方法中獲取對象
執(zhí)行時機:視圖渲染完成后(整個流程結(jié)束之后)
方法參數(shù)
參數(shù) 說明 request 請求參數(shù) response 響應(yīng)對象 handler 攔截到的處理器方法 ex 異常對象
4.2 攔截器鏈
如果多個攔截器能夠?qū)ο嗤恼埱筮M行攔截,則多個攔截器會形成一個攔截器鏈,主要理解攔截器鏈中各個攔截器的執(zhí)行順序。攔截器鏈中多個攔截器的執(zhí)行順序,根攔截器的配置順序有關(guān),先配置的先執(zhí)行
攔截器(interceptor)
package com.Bingzy.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class TwoInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【TwoInterceptor】:preHandle..."); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("【TwoInterceptor】:postHandle..."); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("【TwoInterceptor】:afterCompletion..."); } }
spring-mvc.xml配置自定義攔截器
<mvc:interceptors> <!--2) 多攔截器(攔截器鏈)--> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.Bingzy.interceptor.OneInterceptor"/> </mvc:interceptor> <mvc:interceptor> <mvc:mapping path="/book/**"/> <bean class="com.Bingzy.interceptor.TwoInterceptor"/> </mvc:interceptor> </mvc:interceptors>
運行展示:
五,用戶登錄權(quán)限案例
登入攔截器(interceptor):
package com.Bingzy.interceptor; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("【implements】:preHandle..."); StringBuffer url = request.getRequestURL(); if (url.indexOf("/login") > 0 || url.indexOf("/logout") > 0){ // 如果是 登錄、退出 中的一種 return true; } // 代表不是登錄,也不是退出 // 除了登錄、退出,其他操作都需要判斷是否 session 登錄成功過 String bname = (String) request.getSession().getAttribute("bname"); if (bname == null || "".equals(bname)){ response.sendRedirect("/page/book/login"); return false; } return true; } }
spring-mvc.xml配置自定義登入攔截器
<mvc:interceptors> <bean class="com.Bingzy.interceptor.LoginInterceptor"></bean> </mvc:interceptors>
Controller層(web):
package com.Bingzy.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @Controller public class LoginController { @RequestMapping("/login") public String login(HttpServletRequest req){ String bname = req.getParameter("bname"); HttpSession session = req.getSession(); if ("zs".equals(bname)){ session.setAttribute("bname",bname); } return "redirect:/book/list"; } @RequestMapping("/logout") public String logout(HttpServletRequest req){ req.getSession().invalidate(); return "redirect:/book/list"; } }
login.jsp:
簡單的測試布局,可自行布局
測試結(jié)果:
總結(jié):
如果用戶發(fā)送URL中的后綴包含"/login"或"/logout",則表示當前請求是登錄或退出操作,直接返回true表示繼續(xù)處理請求,后端進行判斷“uname”是否為“zs”,如果不是zs則域?qū)ο蟛粫4妫瑥亩綌r截器判斷域?qū)ο鬄榭談t會重定向到登良頁面,如果不為空就執(zhí)行后端返回的字符串到視圖解析器解析跳轉(zhuǎn)指定頁面
到此這篇關(guān)于SpringMVC中的JSR303與攔截器的使用方法的文章就介紹到這了,更多相關(guān)SpringMVC JSR303與攔截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot集成JSR303參數(shù)校驗的方法實現(xiàn)
- Spring Boot利用JSR303實現(xiàn)參數(shù)驗證的方法實例
- SpringBoot結(jié)合JSR303對前端數(shù)據(jù)進行校驗的示例代碼
- SpringBoot使用jsr303校驗的實現(xiàn)
- Spring中使用JSR303請求約束判空的實現(xiàn)
- SpringBoot后端進行數(shù)據(jù)校驗JSR303的使用詳解
- springboot接口參數(shù)校驗JSR303的實現(xiàn)
- springboot整合JSR303參數(shù)校驗與全局異常處理的方法
- springboot整合JSR303校驗功能實現(xiàn)代碼
相關(guān)文章
深入理解Java class文件格式_動力節(jié)點Java學(xué)院整理
對于理解JVM和深入理解Java語言, 學(xué)習(xí)并了解class文件的格式都是必須要掌握的功課2017-06-06java使用bitmap實現(xiàn)可回收自增id的示例
本文主要介紹了java使用bitmap實現(xiàn)可回收自增id的示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10Springboot攔截器如何獲取@RequestBody參數(shù)
這篇文章主要介紹了Springboot攔截器如何獲取@RequestBody參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06

SpringBoot+mybatis實現(xiàn)多數(shù)據(jù)源支持操作

java 反射getClass .class 的使用方法示例

Spring實戰(zhàn)之@Autowire注解用法詳解

Spring Boot集成Spring Cloud Security進行安全增強的方法