• JSR303数据校验方法


            使用JSR303做后台数据校验是有效确保非法数据绕过前端提交数据,必须确保数据的有效性和准确性。方法步骤如下:

            一、引入依赖

    1. <dependency>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-validation</artifactId>
    4. <version>2.6.6</version>
    5. </dependency>

     二、在实体类上加入注解

    1.@NotNull:不能为null,但可以为empty (“”,”“,”“)

    2.@NotEmpty:不能为null,而且长度必须大于0 (”“,”“)

    3.@NotBlank:只能作用在String上,不能为null,而且调用trim()后,长度必须大于0

    1. /**
    2. * 品牌名
    3. */
    4. @NotBlank(message = "品牌名不能为空")
    5. private String name;
    6. /**
    7. * 品牌logo地址
    8. */
    9. @NotBlank(message = "品牌logo不能为空")
    10. @URL(message = "品牌logo必须是合格的http地址")
    11. private String logo;
    12. /**
    13. * 介绍
    14. */
    15. @NotBlank(message = "品牌介绍不能为空")
    16. private String descript;
    17. /**
    18. * 显示状态[0-不显示;1-显示]
    19. */
    20. private Integer showStatus;
    21. /**
    22. * 检索首字母
    23. */
    24. @NotBlank(message = "检索首字母不能为空")
    25. @Pattern(regexp = "/^[a-zA-Z]$/", message = "检索首字母必须是英文字母")
    26. private String firstLetter;
    27. /**
    28. * 排序
    29. */
    30. @NotNull
    31. @Min(value = 0, message = "排序必须大于等于0")
    32. private Integer sort;

    三、后台 controller 中验证提交的信息

    提交参数中加入@Valid注解,并通过BindingResult收集验证错误信息。

    1. public R save(@Valid @RequestBody BrandEntity brand, BindingResult result){
    2. if(result.hasErrors()){
    3. Map<String, String> map = new HashMap<>();
    4. result.getFieldErrors().forEach(item -> {
    5. // 获取验证不通过字段名
    6. String field = item.getField();
    7. // 获取验证不通过字段信息
    8. String message = item.getDefaultMessage();
    9. map.put(field, message);
    10. });
    11. return R.error(400, "提交数据不合法").put("data", map);
    12. }else{
    13. brandService.save(brand);
    14. return R.ok();
    15. }
    16. }

    四、通过postman绕过前端测试

     五、为了方便在每个controller中使用校验方法,通过AOP切面将校验异常及其他异常整合成一个类。

    1. /**
    2. * 集中处理 controller中的异常
    3. */
    4. @Slf4j
    5. @RestControllerAdvice(basePackages = "com.javahorse.gmall.product.controller")
    6. public class gmallExceptionControllerAdvice {
    7. /**
    8. * 处理验证异常
    9. * @param e
    10. * @return
    11. */
    12. @ExceptionHandler(value = MethodArgumentNotValidException.class)
    13. public R handValidException(MethodArgumentNotValidException e) {
    14. log.error("数据校验异常:{},异常类型:{}", e.getMessage(), e.getClass());
    15. BindingResult bindingResult = e.getBindingResult();
    16. Map<String, String> errorMap = new HashMap<>();
    17. bindingResult.getFieldErrors().forEach(item -> {
    18. // 获取验证不通过字段名
    19. String field = item.getField();
    20. // 获取验证不通过字段信息
    21. String message = item.getDefaultMessage();
    22. errorMap.put(field, message);
    23. });
    24. return R.error(BizCodeEnum.VAILD_EXCEPTION.getCode(), BizCodeEnum.VAILD_EXCEPTION.getMsg()).put("data", errorMap);
    25. }
    26. /**
    27. * 处理不能精确匹配的其他异常
    28. * @param throwable
    29. * @return
    30. */
    31. @ExceptionHandler(value = Throwable.class)
    32. public R handValidException(Throwable throwable) {
    33. return R.error(BizCodeEnum.UNKNOW_EXCEPTION.getCode(), BizCodeEnum.UNKNOW_EXCEPTION.getMsg());
    34. }
    35. }

    六、设置通用的错误代码及信息枚举类

    1. /**
    2. * @desc: 通用错误代码及信息类
    3. */
    4. public enum BizCodeEnum {
    5. UNKNOW_EXCEPTION(10000, "系统未知异常"),
    6. VAILD_EXCEPTION(10001,"数据校验异常");
    7. private int code;
    8. private String msg;
    9. BizCodeEnum(int code, String msg) {
    10. this.code = code;
    11. this.msg = msg;
    12. }
    13. public int getCode() {
    14. return code;
    15. }
    16. public String getMsg() {
    17. return msg;
    18. }
    19. }

    七、修改原先的controller,由于通过AOP切面方式校验,所以不需要在controller中 BindingResult,只需要@Valid 注解就可以通过切面类捕获抛出的异常来达到校验的结果,代码修改如下:

    1. @RequestMapping("/save")
    2. public R save(@Valid @RequestBody BrandEntity brand){
    3. brandService.save(brand);
    4. return R.ok();
    5. }

    八、测试

     msg和code已经变成切面类定义的错误信息了。

  • 相关阅读:
    软考高级-系统架构师-案例分析-数据库真题考点汇总
    Nvidia Jetson/Orin +FPGA+AI大算力边缘计算盒子:潍柴雷沃智慧农业无人驾驶
    如何选择合适的数据库管理工具?Navicat Or DBeaver
    Java面试题:细数ThreadLocal大坑,内存泄露本可避免
    Seata-Saga模式简介与三种模式对比
    Flink Table API & SQL
    C#,动态规划(DP)模拟退火(Simulated Annealing)算法与源代码
    电脑照片尺寸如何调整成自己想要的
    C++之模板
    JavaScript 什么是三元表达式?
  • 原文地址:https://blog.csdn.net/Tiger_Paul/article/details/125536284