Java使用validation攔截非法提交的數(shù)據(jù)的方法實現(xiàn)
注意:本文使用的是Springboot 2.x版本,如果使用其他版本會略有差異,本文僅作拋轉(zhuǎn)引義,開發(fā)時需結(jié)合自己項目的實際情況來定。
一.引入依賴
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
二.提交數(shù)據(jù)的實體類添加驗證規(guī)則的注解
需根據(jù)屬性的類型和業(yè)務(wù)規(guī)則添加相應(yīng)的注解
import lombok.Data; import org.hibernate.validator.constraints.URL; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; /** * @author: * @Desc: * @create: 2025-04-14 10:32 **/ @Data public class StoreDeviceDTO { @NotNull(message = "storeId不能為空") private Long storeId; @NotBlank(message = "設(shè)備名稱不能為空") private String deviceName; @NotBlank(message = "設(shè)備圖片不能為空") @URL(message = "設(shè)備圖片必須是一個合法的URL地址") private String deviceImage; }
三.在控制器方法上添加@Valid注解
@PostMapping("/addApply") public AjaxResult add(@Valid @RequestBody StoreApplyDTO storeApplyDTO) { storeApplyService.saveStoreApply(storeApplyDTO); return AjaxResult.success(); }
如果傳的集合類型的數(shù)據(jù),則比較特殊,需要在控制器類名上加上@Validated注解,同時方法中也要加上上@Validated注解,正確的使用方式如下:
@RestController @Validated public class StoreDeviceController { @Autowired private IStoreDeviceService storeDevicesService; @PostMapping("/saveDevices") public AjaxResult saveDevices(@RequestBody @Validated List<@Valid StoreDeviceDTO> deviceDTOList) { storeDevicesService.saveDevices(deviceDTOList); return AjaxResult.success(); } }
其中@Valid和@Validated引用的包為:
import org.springframework.validation.annotation.Validated; import javax.validation.Valid;
為了給前端返回時是可讀性強(qiáng)的文字說明,而不是一堆英文說明,需要在全局異常處理類中添加如下代碼:
@RestControllerAdvice public class GlobalExceptionHandler { /** * 自定義驗證異常 */ @ExceptionHandler(MethodArgumentNotValidException.class) public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { //log.error(e.getMessage(), e); String message = e.getBindingResult().getFieldError().getDefaultMessage(); return AjaxResult.error(message); } }
第一個返回示例:
{ "msg": "門店id不能為空", "code": 500 }
第二個返回示例(可進(jìn)一步優(yōu)化):
{ "msg": "saveDevices.deviceDTOList[0].deviceName: 設(shè)備名稱不能為空, saveDevices.deviceDTOList[0].deviceImage: 設(shè)備圖片必須是一個合法的URL地址", "code": 500 }
拓展:分組校驗
很多時候,有新增和修改操作,需進(jìn)行不同的驗證,比如新增時無需帶id,而修改時必須帶id,此時可通過分組檢驗,以實現(xiàn)區(qū)別對接。下面是實現(xiàn)的過程:
1.創(chuàng)建新建和修改的分組interface
//新增 public interface AddGroup { } //修改 public interface UpdateGroup { }
2.請求體添加分組注解
import com.bbc.validate.group.AddGroup; import com.bbc.validate.group.UpdateGroup; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.*; import java.util.List; /** * @author: * @Desc: * @create: 2025-03-22 14:34 **/ @Data @ApiModel(description = "認(rèn)證項目請求體") public class CertificateDTO { @ApiModelProperty("申請認(rèn)證ID") @NotNull(message = "申請認(rèn)證ID不能為空",groups ={UpdateGroup.class}) private Long id; @NotNull(message = "storeId不能為空",groups ={AddGroup.class,UpdateGroup.class}) private Long storeId; @NotBlank(message = "認(rèn)證項目不能為空",groups ={AddGroup.class,UpdateGroup.class}) @ApiModelProperty("認(rèn)證項目") private String project; @NotNull(message = "請上傳證書材料", groups = {AddGroup.class}) @Size(min = 1, max = 9, message = "請上傳1-9張證書材料圖片", groups = {AddGroup.class, UpdateGroup.class}) @ApiModelProperty("認(rèn)證項目材料圖片(1-9張)") private List<String> certificateMaterials; @Size(max = 200, message = "認(rèn)證說明最多200個字符") @ApiModelProperty("認(rèn)證說明/備注(最多200字)") private String instructions; }
3.controller中的方法添加了分組
@ApiOperation("新增認(rèn)證管理") @Log(title = "認(rèn)證管理", businessType = BusinessType.INSERT) @PostMapping("/saveProject") @RepeatSubmit(interval = 5000, message = "不允許重復(fù)提交,請稍候再試") public AjaxResult add(@Validated(AddGroup.class) @RequestBody CertificateDTO certificateDTO) { certificateService.saveCertificateProject(certificateDTO); return AjaxResult.success(); } /** * 修改認(rèn)證管理 */ @ApiOperation("修改認(rèn)證管理") @Log(title = "認(rèn)證管理", businessType = BusinessType.UPDATE) @PutMapping("/editProject") public AjaxResult edit(@Validated(UpdateGroup.class) @RequestBody CertificateDTO certicateDTO) { certificateService.updateCertificateProject(certicateDTO); return AjaxResult.success(); }
避坑指南:
如果DTO類某個屬性添加了分組校驗,但Controller方法未指定校驗分組,會導(dǎo)致分組校驗失效,沒有添加分組注解的基礎(chǔ)校驗仍然有效。
情況說明:
1. 默認(rèn)行為
- 未指定分組:當(dāng)Controller方法沒有使用
@Validated
指定分組時,只會校驗沒有分組的約束注解 - 有分組注解:帶有
groups
屬性的校驗注解將被跳過(因為沒有添加@Validated注解
)
2. 示例分析
public class CertificateDTO { @NotEmpty(message = "證書材料不能為空", groups = {AddGroup.class}) // 有分組 private List<String> certificateMaterials; @Size(max = 200) // 無分組 private String instructions; }
在Controller中:
@PostMapping public void save(@RequestBody @Valid StoreCertificateDTO dto) { // 只會校驗instructions字段 // certificateMaterials不會被校驗,因為未指定AddGroup分組 }
3. 解決方案
方案1:在Controller類上添加@Validated注解
@RestController @Validated(AddGroup.class) // 指定默認(rèn)分組 public class CertificateController { @PostMapping public void save(@RequestBody @Valid CertificateDTO dto) { // 現(xiàn)在會校驗AddGroup分組和沒有分組的約束 } }
方案2:在方法參數(shù)上指定分組
@PostMapping public void save(@RequestBody @Validated(AddGroup.class) StoreCertificateDTO dto) { // 明確指定校驗分組 }
方案3:混合使用(推薦)
@RestController @Validated // 類級別啟用校驗 public class CertificateController { @PostMapping("/add") public void add(@RequestBody @Validated(AddGroup.class) StoreCertificateDTO dto) { // 添加操作使用AddGroup分組 } @PostMapping("/update") public void update(@RequestBody @Validated(UpdateGroup.class) StoreCertificateDTO dto) { // 更新操作使用UpdateGroup分組 } }
4. 重要注意事項
@Valid
vs @Validated
:
@Valid
(JSR-303)不支持分組@Validated
(Spring擴(kuò)展)支持分組
默認(rèn)校驗:
- 沒有分組的約束注解總是會被校驗
- 有分組的約束只在指定對應(yīng)分組時才會校驗
繼承關(guān)系:
- 分組可以繼承,父接口的分組會被子接口繼承
分組雖好,使用不當(dāng)可能會得不到預(yù)期的結(jié)果,那么什么情況下要分組,什么情況下不分組呢:
5. 使用建議
- 明確指定分組:重要的業(yè)務(wù)校驗都應(yīng)該明確指定分組
- 分層設(shè)計:
- 基礎(chǔ)校驗(非空、格式等)可以不分組
- 業(yè)務(wù)規(guī)則校驗使用分組
- 文檔注釋:在代碼中注明各分組的用途
- 測試覆蓋:編寫測試驗證分組校驗是否按預(yù)期工作
到此這篇關(guān)于Java使用validation攔截非法提交的數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Java使用validation攔截非法提交內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Springboot項目javax.validation使用方法詳解
- java validation 后臺參數(shù)驗證的使用詳解
- java使用Validation進(jìn)行數(shù)據(jù)校驗的方式總結(jié)
- JAVA中通過Hibernate-Validation進(jìn)行參數(shù)驗證
- JAVA中的字段校驗(validation)
- 使用javax.validation.constraints對請求體進(jìn)行統(tǒng)一校驗
- Java參數(shù)校驗中validation和validator的區(qū)別詳解
- Java Validation Api實現(xiàn)原理解析
- Java Validation Api如何實現(xiàn)自定義注解
- Javax Validation自定義注解進(jìn)行身份證號校驗
相關(guān)文章
springmvc處理模型數(shù)據(jù)ModelAndView過程詳解
這篇文章主要介紹了springmvc處理模型數(shù)據(jù)ModelAndView過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-01-01Java Spring 中的監(jiān)聽器Listener詳解與實戰(zhàn)教程
Spring 提供了多種監(jiān)聽器機(jī)制,可以用于監(jiān)聽?wèi)?yīng)用生命周期、會話生命周期和請求處理過程中的事件,這篇文章主要介紹了Java Spring 之監(jiān)聽器(Listener)詳解與實戰(zhàn),需要的朋友可以參考下2025-06-06