zoukankan      html  css  js  c++  java
  • JSR-303规范对请求参数校验,以及异常统一处理

    1.引入依赖,版本需要对应:其中javax.validation是定义规范的一些接口,而实现由hibernate-validator实现

          <dependency>
               <groupId>javax.validation</groupId>
               <artifactId>validation-api</artifactId>
               <version>2.0.1.Final</version>
            </dependency>
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>6.1.7.Final</version>
            </dependency>

    2.创建一个请求对象:

    public class OrderRequest {
    
        private Long id;
        @NotBlank(message ="名称不能为空" )
        private String name;
        @Pattern(regexp = "http://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?",message = "url路径不对")
        private String url;
        @Email(regexp="/+d/",message = "邮件格式不对")
        private String email;
        @DecimalMax("20")
        @DecimalMin("10")
        private BigDecimal amount;
    }

    3.contoller实现:

       @RequestMapping("/order")
        @ResponseBody
        public Map<String, String> testValid(@Valid @RequestBody OrderRequest orderRequest, BindingResult bindingResult){
            boolean hasFieldErrors = bindingResult.hasFieldErrors();
            Map<String, String> map = new HashMap<>();
    
            if(hasFieldErrors){
                for (FieldError fieldError : bindingResult.getFieldErrors()) {
                    String field = fieldError.getField();
                    String defaultMessage = fieldError.getDefaultMessage();
                    map.put(field,defaultMessage);
                }
                map.put("errorCode","400");
                return map;
            }
            map.put("errorCode","200");
            return map;
        }

    4.postman调用:

     问题1:当所给的注解都满足不了需求的时候,如何自定义注解:需求:校验姓名是否带有gogo,参考注解:

     参考上面NotBlank注解,定义一个Checkgogo注解:

    @Documented
    @Constraint(validatedBy = { })
    @Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
    @Retention(RUNTIME)
    public @interface CheckGogo {
        String message() default "{com.yang.xiao.hui.thymeleaf.controller.CheckGogo.message}";
    
        Class<?>[] groups() default { };
    
        Class<? extends Payload>[] payload() default { };
        String value();
    }

    我们需要定义一个使得该注解生效的类,点击@Constraint注解,看看需要一个怎么样的类:

     

     实现如下:

    public class MyGogoConstraintValidator implements ConstraintValidator<CheckGogo,String> {
    
        private String needIncludeValue;
        @Override
        public void initialize(CheckGogo constraintAnnotation) {
            needIncludeValue = constraintAnnotation.value(); //参数需要包含的字符
        }
    
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            
            return value.indexOf(needIncludeValue)!=-1 //校验参数是否包含该字符
        }
    }

    在注解上加上该实现类:

     配置默认信息:在resources文件夹下新增:ValidationMessages.properties

     测试:

    postMan调用:

     自定义提示语:

     

     问题2:有些字段,我们在修改时希望不为空,在新增时希望为空,如编号,如何处理? 这里就要用到分组了,先定义2个空接口:

    //新增分组
    public interface AddCheck {
    
    } 
    
    //修改分组
    public interface UpdateCheck {
    }

    在校验字段时加上分组字段:

     修改controller:

     

     测试:

     问题3:上面所讲,校验失败后,每个controller都要自己处理校验失败的异常,如何统一校验:

    定义一个异常处理类:

        

    @RestControllerAdvice(basePackages="com.yang.xiao.hui.thymeleaf.controller")
    public class CommonExceptionProcessController {
    
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public Map errorHandler(MethodArgumentNotValidException ex) { //处理参数校验异常
            Map map = new HashMap();
            BindingResult bindingResult = ex.getBindingResult();
            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                map.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
    
            map.put("code", 400);
    
            return map;
        }
    
        @ExceptionHandler(value = Throwable.class)
        public Map errorHandler(Throwable ex) {
            Map map = new HashMap();
            map.put("code", 500);
            map.put("message", "服务挂了");
    
            return map;
        }
    
    }

    修改controller:

     @RequestMapping("/order")
        @ResponseBody
        public BigDecimal testValid(@Validated(UpdateCheck.class) @RequestBody OrderRequest orderRequest){ //这里不用再单独处理bindResult了,只管业务代码即可
    
            return   new BigDecimal("20");
        }

    postMan调用:

    
    
    
  • 相关阅读:
    正则中[A-z]与[A-Za-z]的区别
    .Net Core 缓存方式(二)DistributedSqlServerCache实现(2)
    .Net Core 缓存方式(二)分布式缓存及MemoryDistributedCache 实现(1)
    anaconda安装后spyder打不开的解决方法
    Pandas
    CrawlSpider、分布式、增量式
    Scrapy之数据解析与数据持久化存储
    封装axios库
    vue全国省市选择vue组件
    html+jq实现全国省的单选,弹框输入input
  • 原文地址:https://www.cnblogs.com/yangxiaohui227/p/14237447.html
Copyright © 2011-2022 走看看