一、JSR 303
1.1 JSR 303介紹
? ?JSR 303,它是Java EE(現(xiàn)在稱為Jakarta EE)規(guī)范中的一部分。JSR 303定義了一種用于驗證Java對象的標準規(guī)范,也稱為Bean驗證。
? ? ? ? Bean驗證是一種用于驗證對象屬性的框架,它可以確保對象符合特定的規(guī)則和約束。這些規(guī)則可以包括字段的非空性、長度限制、格式驗證等。通過使用Bean驗證,開發(fā)人員可以在應(yīng)用程序中輕松地定義和應(yīng)用驗證規(guī)則,以確保數(shù)據(jù)的完整性和一致性。
?
1.2 為什么要使用JSR-303
? ? ? ? 當我們開發(fā)應(yīng)用程序時,經(jīng)常需要對用戶輸入的數(shù)據(jù)進行驗證,以確保數(shù)據(jù)的有效性和一致性。例如,我們可能需要驗證用戶注冊表單中的用戶名是否符合要求、密碼是否足夠強壯、電子郵件地址是否有效等等。
? ? ? ? 在學這個之前我們都是通過前端進行驗證的,如果說前端代碼校驗沒寫好又或者是對于會一點編程的人來說,可以直接繞過前端發(fā)請求(通過類似Postman這樣的測試工具進行非常數(shù)據(jù)請求),把一些錯誤的參數(shù)傳過來,這樣是不安全的。
所以我們一般都是前端做一套校驗,后端再做一套校驗,這樣安全性就能夠大大得到提升了。
?
總的來說,使用JSR 303可以讓數(shù)據(jù)驗證過程更加簡單、直觀和可靠。它可以幫助我們減少重復的驗證代碼,提高代碼的可讀性和可維護性,減少錯誤和漏洞的出現(xiàn),并提高開發(fā)效率。因此,JSR 303是一個有用的工具,可以在開發(fā)過程中幫助我們更好地處理數(shù)據(jù)驗證的需求。???????
1.3、常用注解
- @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ī)則
- @Email?? ?用于String對象是否符合郵箱格式
- @Min?? ?用于Number和String對象是否大等于指定的值
- @Max?? ?用于Number和String對象是否小等于指定的值
- @AssertTrue?? ?用于Boolean對象是否為true
- @AssertFalse?? ?用于Boolean對象是否為false
?
1.4 使用示例?
1.4.1 導入JSR303依賴
<!-- 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>
1.4.2?配置校驗規(guī)則
package com.liwen.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data//相當于set get toString方法
@AllArgsConstructor //有參構(gòu)造器
@NoArgsConstructor //無參構(gòu)造器
public class User {
@NotNull(message = "用戶編號不能為空")
private Long id;
@NotBlank(message = "用戶名不能為空")
private String name;
@NotBlank(message = "賬號不能為空")
private String loginname;
@Length(min = 6, max = 15, message = "用戶名長度是6-15位")
private String pwd;
//權(quán)限
private Long rid;
}
1.4.3 編寫方法校驗
????????使用@Validated
注解對User
對象進行服務(wù)端校驗。User
對象需要使用JSR 303注解進行屬性驗證規(guī)則的定義。
//給數(shù)據(jù)添加服務(wù)端校驗
@RequestMapping("/valiAdd")
public String valiAdd(@Validated User user, BindingResult result, HttpServletRequest req) {
//如果服務(wù)端驗證不通過,有錯誤 boolean
if (result.hasErrors()) {
//得到所有錯誤
List<FieldError> fieldErrors = result.getFieldErrors();
//創(chuàng)建集合保存錯誤信息,用戶傳輸?shù)角岸诉M行顯示
Map<String, Object> map = new HashMap<>();
//迭代錯誤
for (FieldError fieldError : fieldErrors) {
//將多個屬性的驗證失敗信息輸送到控制臺
System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
//保存錯誤信息
map.put(fieldError.getField(), fieldError.getDefaultMessage());
}
//將集合保存到域?qū)ο? req.setAttribute("errorMap", map);
} else {
//如果校驗沒有錯誤則進行增加
this.userBiz.insertSelective(user);
//返回到主頁
return "redirect:list";
}
//校驗錯誤繼續(xù)在本界面
return "user/edit";
}
?1.4.4 編寫前端
通過span標簽形式將后端保存的錯誤信息輸出在頁面。?
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用戶編輯、新增公共頁面</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/${empty u ? 'users/valiAdd' : 'users/edit'}" method="post">
用戶id:<input type="text" name="id" value="${u.id }"><span style="color: red">${errorMap.id}</span><br>
用戶名:<input type="text" name="name" value="${u.name }"><span style="color: red">${errorMap.naem}</span><br>
賬號:<input type="text" name="loginname" value="${u.loginname }"><span style="color: red">${errorMap.loginname}</span><br>
密碼:<input type="text" name="pwd" value="${u.pwd }"><span style="color: red">${errorMap.pwd}</span><br>
權(quán)限:<input type="text" name="rid" value="${u.rid }"><span style="color: red">${errorMap.rid}</span><br>
<input type="submit">
</form>
</body>
</html>
?
1.5 @Validated與@Valid區(qū)別
@Validated:
-
Spring提供的
-
支持分組校驗
-
可以用在類型、方法和方法參數(shù)上。但是不能用在成員屬性(字段)上
-
由于無法加在成員屬性(字段)上,所以無法單獨完成級聯(lián)校驗,需要配合@Valid
@Valid:
-
JDK提供的(標準JSR-303規(guī)范)
-
不支持分組校驗
-
可以用在方法、構(gòu)造函數(shù)、方法參數(shù)和成員屬性(字段)上
-
可以加在成員屬性(字段)上,能夠獨自完成級聯(lián)校驗
?
二、攔截器(interceptor)
?2.1 什么是攔截器 ?
? SpringMVC的處理器攔截器,類似于Servlet開發(fā)中的過濾器Filter,用于對處理器進行預處理和后處理還有請求攔截和過濾。依賴于web框架,在實現(xiàn)上基于Java的反射機制,屬于面向切面編程(AOP)的一種運用。由于攔截器是基于web框架的調(diào)用,因此可以使用Spring的依賴注入(DI)進行一些業(yè)務(wù)操作,同時一個攔截器實例在一個 controller生命周期之內(nèi)可以多次調(diào)用。
攔截器主要用于實現(xiàn)以下功能:
- 預處理操作:攔截器可以在請求被處理之前進行一些預處理操作,例如參數(shù)校驗、權(quán)限驗證、請求日志記錄等。這樣可以在進入具體的請求處理邏輯之前,對請求進行一些統(tǒng)一的處理。
- 后處理操作:攔截器可以在請求處理完成后進行一些后處理操作,例如統(tǒng)一的異常處理、結(jié)果封裝、響應(yīng)日志記錄等。這樣可以在請求處理完成后,對響應(yīng)進行一些統(tǒng)一的處理。
- 請求攔截和過濾:攔截器可以對請求進行攔截和過濾,根據(jù)一定的條件判斷是否允許請求繼續(xù)處理。例如,可以根據(jù)用戶的權(quán)限進行攔截,如果用戶沒有權(quán)限訪問某個資源,可以直接攔截請求并返回相應(yīng)的錯誤信息。
?
? ?例如在Java的Spring框架中,可以通過實現(xiàn)HandlerInterceptor接口來創(chuàng)建自定義的攔截器。在Spring中,攔截器可以通過配置來指定攔截的路徑和順序,以及是否攔截子路徑等。
? ? ? ? 攔截器的執(zhí)行順序一般是根據(jù)配置的順序來確定的,可以通過配置來控制攔截器的執(zhí)行順序。在請求處理過程中,攔截器會按照配置的順序依次執(zhí)行,每個攔截器都可以對請求進行攔截、處理和修改。?
??????總之,攔截器是一種在請求處理過程中對請求進行攔截和處理的組件,可以用于實現(xiàn)一些預處理、后處理、請求攔截和過濾等功能。它提供了一種靈活的機制,可以對請求進行統(tǒng)一的處理和控制。
2.2?攔截器與過濾器的區(qū)別???
什么是過濾器(Filter):
? ? ? ? 依賴于servlet容器。在實現(xiàn)上基于函數(shù)回調(diào),可以對幾乎所有請求進行過濾,但是缺點是一個過濾器實例只能在容器初始化時調(diào)用一次。使用過濾器的目的是用來做一些過濾操作,比如:在過濾器中修改字符編碼;在過濾器中修改HttpServletRequest的一些參數(shù),包括:過濾低俗文字、危險字符等。
-
過濾器(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處理的請求
2.3 攔截器的應(yīng)用場景及作用
- 權(quán)限驗證:攔截器可以用于驗證用戶的權(quán)限,例如檢查用戶是否登錄、是否具有訪問某個資源的權(quán)限等。通過攔截請求并進行權(quán)限驗證,可以保護系統(tǒng)的安全性和數(shù)據(jù)的完整性。
- 日志記錄:攔截器可以用于記錄請求和響應(yīng)的日志信息,包括請求的URL、請求參數(shù)、處理時間、響應(yīng)結(jié)果等。通過記錄日志,可以方便地進行系統(tǒng)的監(jiān)控、故障排查和性能優(yōu)化。
- 參數(shù)預處理:攔截器可以對請求參數(shù)進行預處理,例如對參數(shù)進行驗證、轉(zhuǎn)換、修正等操作。這樣可以確保請求參數(shù)的有效性和一致性,減少錯誤和異常的發(fā)生。
- 異常處理:攔截器可以用于統(tǒng)一處理請求過程中出現(xiàn)的異常。通過攔截異常并進行統(tǒng)一的處理,可以提供友好的錯誤提示頁面或返回特定的錯誤信息,提高系統(tǒng)的容錯性和用戶體驗。
- 緩存控制:攔截器可以用于控制緩存的使用,例如根據(jù)請求的URL、參數(shù)等條件判斷是否使用緩存,以及緩存的過期時間等。通過攔截請求并進行緩存控制,可以提高系統(tǒng)的性能和響應(yīng)速度。
- 請求重定向:攔截器可以根據(jù)一定的條件對請求進行重定向,將請求轉(zhuǎn)發(fā)到其他的URL或處理器進行處理。通過攔截請求并進行重定向,可以實現(xiàn)請求的轉(zhuǎn)發(fā)、路由和流程控制。
- 統(tǒng)一處理:攔截器可以用于實現(xiàn)一些統(tǒng)一的處理邏輯,例如對請求進行統(tǒng)一的編碼轉(zhuǎn)換、字符集設(shè)置、響應(yīng)頭設(shè)置等。通過攔截請求并進行統(tǒng)一處理,可以提高系統(tǒng)的一致性和可維護性。
? ? ? ? 攔截器在Web開發(fā)中的應(yīng)用非常廣泛,它可以對請求進行攔截、處理和修改,實現(xiàn)權(quán)限驗證、日志記錄、參數(shù)預處理、異常處理、緩存控制、請求重定向和統(tǒng)一處理等功能。通過使用攔截器,可以提高系統(tǒng)的安全性、穩(wěn)定性、性能和可維護性。
?
2.4 快速入門
2.4.1 創(chuàng)建攔截器
package com.liwen.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*
1. 定義攔截器類,實現(xiàn)HandlerInterceptor接口
2. 注意當前類必須受Spring容器控制
*/
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...");
}
}
2.4.2 配置攔截器
在spring-mvc.xml中配置:
<!--配置攔截器-->
<mvc:interceptors>
<bean class="com.liwen.interceptor.OneInterceptor"></bean>
</mvc:interceptors>
2.4.3?運行測試
啟動項目,打開瀏覽器訪問請求地址,測試攔截器你會發(fā)現(xiàn)他們運行順序是
preHandle --> postHandle --> afterCompletion
2.5 攔截器工作流程
- 當有攔截器后,請求會先進入preHandle方法,
- ? 如果方法返回true,則放行繼續(xù)執(zhí)行后面的handle[controller的方法]和后面的方法
- ? 如果返回false,則直接跳過后面方法的執(zhí)行。
?
?preHandle:用于對攔截到的請求進行預處理,方法接收布爾(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 | 異常對象 |
2.6 攔截器鏈
在spring-mvc.xml中配置多個攔截器文章來源:http://www.zghlxwxcb.cn/news/detail-732896.html
<!--2) 多攔截器(攔截器鏈)-->
<mvc:interceptors>
<mvc:interceptor>
<!--攔截所有-->
<mvc:mapping path="/**"/>
<bean class="com.liwen.interceptor.OneInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<!--攔截users下的controller-->
<mvc:mapping path="/users/**"/>
<bean class="com.liwen.interceptor.TwoInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
?運行測試:走了兩個攔截器,如果運行的是?http://localhost:8080/file/list?將不會執(zhí)行Two...攔截器。文章來源地址http://www.zghlxwxcb.cn/news/detail-732896.html
到了這里,關(guān)于【SpringMVC】JSR 303與攔截器注解使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!