精华内容
下载资源
问答
  • 对于后端开发而言,前端request请求中的参数校验是一个必不可少的环节。无论传来的参数是id还是email还是其他的参数,我们都要对参数的类型、大小、格式等等做这样或者那样的校验,然后才进行逻辑处理,以确保逻辑...
  • Spring Boot 参数校验

    2019-12-10 15:04:08
    Bean Validation是Java定义的一套基于注解的数据校验规范。这里简单实现了Spring Boot 参数校验,包括自定义注解,分组校验,全局异常处理等
  • 主要介绍了springboot+dubbo+validation 进行rpc参数校验的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 主要介绍了如何在spring-boot中进行参数校验及lombok的使用详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
  • 基于Spring boot + maven,以注解+AOP方式实现的java后端项目接口参数校验框架。迄今为止使用最简单、最容易理解的参数校验方案。博客地址:https://blog.csdn.net/weixin_42686388/article/details/104009771
  • 下面小编就为大家带来一篇java自定义注解实现前后台参数校验的实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 参数校验器和整合Mybatis&MybatisPlus.md
  • 参数校验参数是否为空接口,循环判断多个参数,可以直接使用
  • 统一接口解密封装校验参数测试用例
  • sap发票校验两个常用的用户参数sap发票校验两个常用的用户参数sap发票校验两个常用的用户参数sap发票校验两个常用的用户参数
  • 普通web请求可以通过 javax.validation.constraints package下的注解进行参数校验,那么校验后返回的校验失败的结果怎么友好型提醒呢?通过下面异常拦截处理: package com.oyo.supplier.web; import ...

    普通web请求可以通过 javax.validation.constraints package下的注解进行参数校验,那么校验后返回的校验失败的结果怎么友好型提醒呢?通过下面异常拦截处理:

    package com.oyo.supplier.web;
    
    import com.alibaba.fastjson.JSON;
    import com.google.common.collect.Lists;
    import com.oyo.common.enums.ResponseCode;
    import com.oyo.common.exception.ServiceException;
    import com.oyo.common.response.BaseResponse;
    import com.oyo.supplier.common.enums.CommonEnum;
    import com.oyo.supplier.web.response.ArgumentInvalidResponse;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.validation.FieldError;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    import java.sql.SQLException;
    import java.util.List;
    
    /**
     * @author kermit.liu on 2019/2/22
     */
    @ControllerAdvice
    @ResponseBody
    @Slf4j
    public class DefaultControllerAdvice {
    
        /**
         * 添加全局异常处理流程,根据需要设置需要处理的异常
         *
         * @param request   request
         * @param exception exception
         * @return BaseResponse
         */
        @ExceptionHandler(value = MethodArgumentNotValidException.class)
        public BaseResponse methodArgumentNotValidHandler(HttpServletRequest request, MethodArgumentNotValidException exception) {
            log.warn(request.getRequestURI() + " exception, params = " + JSON.toJSONString(request.getParameterMap()), exception);
            // 按需重新封装需要返回的错误信息
            List<ArgumentInvalidResponse> invalidArguments = Lists.newArrayList();
            // 解析原错误信息,封装后返回,此处返回非法的字段名称,原始值,错误信息
            StringBuilder msg = new StringBuilder();
            msg.append(ResponseCode.ILLEGAL_ARGUMENT.getMsg()).append(": ");
            for (FieldError error : exception.getBindingResult().getFieldErrors()) {
                ArgumentInvalidResponse argumentInvalidResponse = ArgumentInvalidResponse.builder()
                        .field(error.getField())
                        .defaultMessage(error.getDefaultMessage())
                        .rejectedValue(error.getRejectedValue())
                        .build();
                invalidArguments.add(argumentInvalidResponse);
                msg = msg.append(error.getDefaultMessage()).append(";");
            }
            BaseResponse<Object> fail = BaseResponse.fail(ResponseCode.ILLEGAL_ARGUMENT.getCode(), msg.toString());
            fail.setData(JSON.toJSONString(invalidArguments));
            return fail;
        }
    
        @ExceptionHandler(value = SQLException.class)
        public BaseResponse methodSQLHandler(HttpServletRequest request, SQLException exception) {
            log.warn(request.getRequestURI() + " exception, params = " + JSON.toJSONString(request.getParameterMap()), exception);
            BaseResponse<Object> fail = BaseResponse.fail(CommonEnum.RESPONSE.SQL_ERROR.getCode(), CommonEnum.RESPONSE.SQL_ERROR.getDesc());
            fail.setData(JSON.toJSONString(exception.getErrorCode()));
            return fail;
        }
    
        @ExceptionHandler({Exception.class})
        public BaseResponse handException(HttpServletRequest request, Exception e) {
            if (e instanceof ServiceException) {
                log.warn(request.getRequestURI() + " exception, params = " + JSON.toJSONString(request.getParameterMap()), e);
                return BaseResponse.fail(((ServiceException) e).getCode(), ((ServiceException) e).getMsg());
            } else {
                log.error(request.getRequestURI() + " exception, params = " + JSON.toJSONString(request.getParameterMap()), e);
                BaseResponse<Object> fail = BaseResponse.fail(CommonEnum.RESPONSE.SERVER_ERROR.getCode(), CommonEnum.RESPONSE.SERVER_ERROR.getDesc());
                fail.setData(e.getMessage());
                return fail;
            }
        }
    }
    

     

    展开全文
  • Java参数校验

    千次阅读 2019-01-23 16:19:56
    基本步骤 引入pom依赖 ...-- 参数校验 --&amp;amp;gt; &amp;amp;lt;!-- start --&amp;amp;gt; &amp;amp;lt;dependency&amp;amp;gt; &amp;amp;lt;groupId&amp;amp;gt

    基本步骤

    1. 引入pom依赖
    2. 书写需要校验的实体
    3. 书写实体校验工具类
    4. 编写测试代码

    引入pom依赖

            <!-- 参数校验 -->
            <!-- start -->
            <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.0.14.Final</version>
            </dependency>
            <dependency>
                <groupId>org.glassfish</groupId>
                <artifactId>javax.el</artifactId>
                <version>3.0.1-b11</version>
            </dependency>
            <!-- end -->
    

    书写需要校验的实体

    package com.ahut.common.utils;
    
    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotNull;
    
    /**
     * desc : 新增用户请求
     * create_user : cheng
     * create_date : 2019/1/23 11:34
     */
    public class AddUserRequest {
    
        /**
         * 用户名
         */
        @NotNull(message = "用户名不能为空")
        private String userName;
        /**
         * 年龄
         */
        @Min(value = 0, message = "用户年龄最小为0")
        private int age;
    
    
        public String getUserName() {
            return userName;
        }
    
        public void setUserName(String userName) {
            this.userName = userName;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    

    书写实体校验工具类

    package com.ahut.common.utils;
    
    import com.ahut.common.entity.BeanValidateResult;
    import org.apache.commons.collections.CollectionUtils;
    
    import javax.validation.ConstraintViolation;
    import javax.validation.Validation;
    import javax.validation.Validator;
    import javax.validation.ValidatorFactory;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Set;
    import java.util.stream.Collectors;
    
    /**
     * desc : 实体校验工具类
     * create_user : cheng
     * create_date : 2019/1/23 13:54
     */
    public final class BeanValidateUtil {
    
        /**
         * 私有化构造方法
         */
        private BeanValidateUtil() {
        }
    
        /**
         * desc : 校验
         * create_user : cheng
         * create_date : 2019/1/23 13:56
         */
        public static <T> List<BeanValidateResult> validate(T bean) {
            // 校验null
            if (Objects.isNull(bean)) {
                return getNullValidateResultList();
            }
    
            // 获取验证器工厂
            ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
            // 获取验证器
            Validator validator = validatorFactory.getValidator();
            // 执行验证
            Set<ConstraintViolation<T>> validateSet = validator.validate(bean);
            return getValidateResultList(validateSet);
        }
    
        /**
         * desc : 获取校验实体list
         * create_user : cheng
         * create_date : 2019/1/23 14:12
         */
        private static <T> List<BeanValidateResult> getValidateResultList(Set<ConstraintViolation<T>> validateSet) {
            List<BeanValidateResult> validateResultList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(validateSet)) {
                validateResultList = validateSet.stream().map(BeanValidateUtil::convertToBeanValidateResult).collect(Collectors.toList());
            }
            return validateResultList;
        }
    
        /**
         * desc : 转换类型
         * create_user : cheng
         * create_date : 2019/1/23 14:48
         */
        private static <T> BeanValidateResult convertToBeanValidateResult(ConstraintViolation<T> validate) {
            BeanValidateResult validateResult = new BeanValidateResult();
            validateResult.setFieldName(validate.getPropertyPath().toString());
            validateResult.setMessage(validate.getMessage());
            return validateResult;
        }
        /**
         * desc : 获取bean为null时的校验结果
         * create_user : cheng
         * create_date : 2019/1/24 10:39
         */
        private static List<BeanValidateResult> getNullValidateResultList() {
            List<BeanValidateResult> validateResultList = new ArrayList<>();
            BeanValidateResult validateResult = new BeanValidateResult();
            validateResult.setFieldName("validateBean");
            validateResult.setMessage("bean is null");
            validateResultList.add(validateResult);
            return validateResultList;
        }
    
    }
    
    package com.ahut.common.entity;
    
    /**
     * desc : 参数校验结果封装实体
     * create_user : cheng
     * create_date : 2019/1/23 14:45
     */
    public class BeanValidateResult {
    
        private String fieldName;
    
        private String message;
    
        public String getFieldName() {
            return fieldName;
        }
    
        public void setFieldName(String fieldName) {
            this.fieldName = fieldName;
        }
    
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    

    编写测试代码

    package com.ahut.common.utils;
    
    import com.ahut.common.entity.BeanValidateResult;
    import org.junit.Test;
    
    import java.util.List;
    
    /**
     * desc : 测试参数校验
     * create_user : cheng
     * create_date : 2019/1/23 14:21
     */
    public class BeanValidateUtilTest {
    
        /**
         * desc :
         * create_user : cheng
         * create_date : 2019/1/23 14:21
         */
        @Test
        public void testValidate() {
            AddUserRequest request = new AddUserRequest();
            request.setAge(-1);
    
            List<BeanValidateResult> validateResultList = BeanValidateUtil.validate(request);
            for (BeanValidateResult validateResult : validateResultList) {
                System.out.println(validateResult.getFieldName() + " : " + validateResult.getMessage());
            }
        }
    
    }
    

    输出结果

    userName : 用户名不能为空
    age : 用户年龄最小为0
    

    自定义注解

    定义注解

    package com.ahut.common.annotation;
    
    import com.ahut.common.annotation.validate.ListIsNotEmptyValidator;
    
    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * desc : 校验list不为空的注解
     * create_user : cheng
     * create_date : 2019/1/24 16:33
     */
    @Target({ElementType.FIELD, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = ListIsNotEmptyValidator.class)
    public @interface ListIsNotEmpty {
    
        String message() default "{com.ahut.common.annotation.ListIsNotEmpty.message}";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    }
    

    定义注解校验器

    package com.ahut.common.annotation.validate;
    
    import com.ahut.common.annotation.ListIsNotEmpty;
    import org.apache.commons.collections.CollectionUtils;
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    import java.util.List;
    
    /**
     * desc : 验证ListIsNotEmpty注解
     * create_user : cheng
     * create_date : 2019/1/24 16:38
     */
    public class ListIsNotEmptyValidator implements ConstraintValidator<ListIsNotEmpty, List> {
    
        /**
         * desc :
         * create_user : cheng
         * create_date : 2019/1/24 16:49
         */
        @Override
        public boolean isValid(List list, ConstraintValidatorContext constraintValidatorContext) {
            return CollectionUtils.isNotEmpty(list);
        }
    
        /**
         * desc : 初始化
         * create_user : cheng
         * create_date : 2019/1/24 16:49
         */
        @Override
        public void initialize(ListIsNotEmpty constraintAnnotation) {
        }
    
    }
    
    展开全文
  • SpringBoot里参数校验/参数验证

    万次阅读 多人点赞 2019-05-08 13:47:56
    在控制器类的方法里自己写校验逻辑代码当然也可以,只是代码比较丑陋,有点“low”。业界有更好的处理方法,分别阐述如下。 2、PathVariable校验 @GetMapping("/path/{group:[a-zA-Z0-9_]+}/{userid}") @...

    1、前言

    在控制器类的方法里自己写校验逻辑代码当然也可以,只是代码比较丑陋,有点“low”。业界有更好的处理方法,分别阐述如下。

    2、PathVariable校验

    @GetMapping("/path/{group:[a-zA-Z0-9_]+}/{userid}")
    @ResponseBody
    public String path(@PathVariable("group") String group, @PathVariable("userid") Integer userid) {
        return group + ":" + userid;
    }
    

    用法是:路径变量:正则表达式。当请求URI不满足正则表达式时,客户端将收到404错误码。不方便的地方是,不能通过捕获异常的方式,向前端返回统一的、自定义格式的响应参数。

    3、方法参数校验

    @GetMapping("/validate1")
    @ResponseBody
    public String validate1(
            @Size(min = 1,max = 10,message = "姓名长度必须为1到10")@RequestParam("name") String name,
            @Min(value = 10,message = "年龄最小为10")@Max(value = 100,message = "年龄最大为100") @RequestParam("age") Integer age) {
        return "validate1";
    }
    

    如果前端传递的参数不满足规则,则抛出异常。注解Size、Min、Max来自validation-api.jar,更多注解参见相关标准小节。

    4、表单对象/VO对象校验

    当参数是VO时,可以在VO类的属性上添加校验注解。

    public class User {
        @Size(min = 1,max = 10,message = "姓名长度必须为1到10")
        private String name;
    
        @NotEmpty
        private String firstName;
    
        @Min(value = 10,message = "年龄最小为10")@Max(value = 100,message = "年龄最大为100")
        private Integer age;
    
        @Future
        @JSONField(format="yyyy-MM-dd HH:mm:ss")
        private Date birth;
        。。。
    }
    

    其中,Future注解要求必须是相对当前时间来讲“未来的”某个时间。

    @PostMapping("/validate2")
    @ResponseBody
    public User validate2(@Valid @RequestBody User user){
        return user;
    }
    

    5、自定义校验规则

    5.1 自定义注解校验

    需要自定义一个注解类和一个校验类。

    import javax.validation.Constraint;
    import javax.validation.Payload;
    import java.lang.annotation.*;
    
    @Documented
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.PARAMETER,ElementType.FIELD})
    @Constraint(validatedBy = FlagValidatorClass.class)
    public @interface FlagValidator {
        // flag的有效值,多个使用,隔开
        String values();
    
        // flag无效时的提示内容
        String message() default "flag必须是预定义的那几个值,不能随便写";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    }
    
    import javax.validation.ConstraintValidator;
    import javax.validation.ConstraintValidatorContext;
    
    public class FlagValidatorClass implements ConstraintValidator<FlagValidator,Object> {
        /**
         * FlagValidator注解规定的那些有效值
         */
        private String values;
    
        @Override
        public void initialize(FlagValidator flagValidator) {
            this.values = flagValidator.values();
        }
    
        /**
         * 用户输入的值,必须是FlagValidator注解规定的那些值其中之一。
         * 否则,校验不通过。
         * @param value 用户输入的值,如从前端传入的某个值
         */
        @Override
        public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) {
            // 切割获取值
            String[] value_array = values.split(",");
            Boolean isFlag = false;
    
            for (int i = 0; i < value_array.length; i++){
                // 存在一致就跳出循环
                if (value_array[i] .equals(value)){
                    isFlag = true; break;
                }
            }
    
            return isFlag;
        }
    }
    

    使用我们自定义的注解:

    public class User {
        // 前端传入的flag值必须是1或2或3,否则校验失败
        @FlagValidator(values = "1,2,3")
        private String flag ;
        。。。
    }
    

    5.2 分组校验

    import org.hibernate.validator.constraints.Length;
    import javax.validation.constraints.Min;
    import javax.validation.constraints.NotNull;
    
    public class Resume {
        public interface Default {
        }
    
        public interface Update {
        }
    
        @NotNull(message = "id不能为空", groups = Update.class)
        private Long id;
    
        @NotNull(message = "名字不能为空", groups = Default.class)
        @Length(min = 4, max = 10, message = "name 长度必须在 {min} - {max} 之间", groups = Default.class)
        private String name;
    
        @NotNull(message = "年龄不能为空", groups = Default.class)
        @Min(value = 18, message = "年龄不能小于18岁", groups = Default.class)
        private Integer age;
        。。。
    }
    
        /**
         * 使用Defaul分组进行验证
         * @param resume
         * @return
         */
        @PostMapping("/validate5")
        public String addUser(@Validated(value = Resume.Default.class) @RequestBody Resume resume) {
            return "validate5";
        }
    
        /**
         * 使用Default、Update分组进行验证
         * @param resume
         * @return
         */
        @PutMapping("/validate6")
        public String updateUser(@Validated(value = {Resume.Update.class, Resume.Default.class}) @RequestBody Resume resume) {
            return "validate6";
        }
    

    建立了两个分组,名称分别为Default、Update。POST方法提交时使用Defaut分组的校验规则,PUT方法提交时同时使用两个分组规则。

    6、异常拦截器

    通过设置全局异常处理器,统一向前端返回校验失败信息。

    import com.scj.springbootdemo.WebResult;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.CollectionUtils;
    import org.springframework.validation.ObjectError;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.validation.ConstraintViolation;
    import javax.validation.ConstraintViolationException;
    import java.util.List;
    import java.util.Set;
    
    /**
     * 全局异常处理器
     */
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        private Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
    
        /**
         * 用来处理bean validation异常
         * @param ex
         * @return
         */
        @ExceptionHandler(ConstraintViolationException.class)
        @ResponseBody
        public  WebResult resolveConstraintViolationException(ConstraintViolationException ex){
            WebResult errorWebResult = new WebResult(WebResult.FAILED);
            Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
            if(!CollectionUtils.isEmpty(constraintViolations)){
                StringBuilder msgBuilder = new StringBuilder();
                for(ConstraintViolation constraintViolation :constraintViolations){
                    msgBuilder.append(constraintViolation.getMessage()).append(",");
                }
                String errorMessage = msgBuilder.toString();
                if(errorMessage.length()>1){
                    errorMessage = errorMessage.substring(0,errorMessage.length()-1);
                }
                errorWebResult.setInfo(errorMessage);
                return errorWebResult;
            }
            errorWebResult.setInfo(ex.getMessage());
            return errorWebResult;
        }
    
        @ExceptionHandler(MethodArgumentNotValidException.class)
        @ResponseBody
        public WebResult resolveMethodArgumentNotValidException(MethodArgumentNotValidException ex){
            WebResult errorWebResult = new WebResult(WebResult.FAILED);
            List<ObjectError>  objectErrors = ex.getBindingResult().getAllErrors();
            if(!CollectionUtils.isEmpty(objectErrors)) {
                StringBuilder msgBuilder = new StringBuilder();
                for (ObjectError objectError : objectErrors) {
                    msgBuilder.append(objectError.getDefaultMessage()).append(",");
                }
                String errorMessage = msgBuilder.toString();
                if (errorMessage.length() > 1) {
                    errorMessage = errorMessage.substring(0, errorMessage.length() - 1);
                }
                errorWebResult.setInfo(errorMessage);
                return errorWebResult;
            }
            errorWebResult.setInfo(ex.getMessage());
            return errorWebResult;
        }
    }
    
    

    7、相关标准

    JSR 303 是Bean验证的规范 ,Hibernate Validator 是该规范的参考实现,它除了实现规范要求的注解外,还额外实现了一些注解。
    validation-api-1.1.0.jar 包括如下约束注解:

    约束注解说明
    @AssertFalse被注释的元素必须为 false
    @AssertTrue被注释的元素必须为 true
    @DecimalMax(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @DecimalMin(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @Digits (integer, fraction)被注释的元素必须是一个数字,其值必须在可接受的范围内
    @Null被注释的元素必须为 null
    @NotNull被注释的元素必须不为 null
    @Min(value)被注释的元素必须是一个数字,其值必须大于等于指定的最小值
    @Max(value)被注释的元素必须是一个数字,其值必须小于等于指定的最大值
    @Size(max, min)被注释的元素的大小必须在指定的范围内
    @Past被注释的元素必须是一个过去的日期
    @Future被注释的元素必须是一个将来的日期
    @Pattern(value)被注释的元素必须符合指定的正则表达式

    hibernate-validator-5.3.6.jar 包括如下约束注解:

    约束注解说明
    @Email被注释的元素必须是电子邮箱地址
    @Length被注释的字符串的大小必须在指定的范围内
    @NotBlank被注释的字符串的必须非空
    @NotEmpty被注释的字符串、集合、Map、数组必须非空
    @Range被注释的元素必须在合适的范围内
    @SafeHtml被注释的元素必须是安全Html
    @URL被注释的元素必须是有效URL

    8、参数校验原理

    这篇文章 写得比较深入,我没有太理解。

    9、本文源码

    公司不让上传源码到GitHub,可以参加这篇文章

    10、同时校验2个或更多个字段/参数

    常见的场景之一是,查询某信息时要输入开始时间和结束时间。显然,结束时间要≥开始时间。可以在查询VO类上使用自定义注解,下面的例子来自这里。划重点:@ValidAddress使用在类上。

    @ValidAddress
    public class Address {
    
        @NotNull
        @Size(max = 50)
        private String street1;
    
        @Size(max = 50)
        private String street2;
    
        @NotNull
        @Size(max = 10)
        private String zipCode;
    
        @NotNull
        @Size(max = 20)
        private String city;
    
        @Valid
        @NotNull
        private Country country;
    
        // Getters and setters
    }
    
    public class Country {
    
        @NotNull
        @Size(min = 2, max = 2)
        private String iso2;
    
        // Getters and setters
    }
    
    @Documented
    @Target(TYPE)
    @Retention(RUNTIME)
    @Constraint(validatedBy = { MultiCountryAddressValidator.class })
    public @interface ValidAddress {
    
        String message() default "{com.example.validation.ValidAddress.message}";
    
        Class<?>[] groups() default {};
    
        Class<? extends Payload>[] payload() default {};
    }
    
    public class MultiCountryAddressValidator 
           implements ConstraintValidator<ValidAddress, Address> {
    
        public void initialize(ValidAddress constraintAnnotation) {
    
        }
    
        @Override
        public boolean isValid(Address address, 
                               ConstraintValidatorContext constraintValidatorContext) {
    
            Country country = address.getCountry();
            if (country == null || country.getIso2() == null || address.getZipCode() == null) {
                return true;
            }
    
            switch (country.getIso2()) {
                case "FR":
                    return // Check if address.getZipCode() is valid for France
                case "GR":
                    return // Check if address.getZipCode() is valid for Greece
                default:
                    return true;
            }
        }
    }
    
    展开全文
  • SpringBoot使用validation-api实现对枚举类参数校验 前言 之前写了一个博客是关于使用SpringBoot使用validation-api实现参数校验,当时使用的注解都是validation-api自带的注解只能完成对空值、长度等简单的校验,在...

    SpringBoot使用validation-api实现对枚举类参数校验

    前言

    之前写了一个博客是关于使用SpringBoot使用validation-api实现参数校验,当时使用的注解都是validation-api自带的注解只能完成对空值、长度等简单的校验,在我们日常的使用当中会遇到对参数是否在枚举值类的校验,针对这种情况我们怎么来实现呢?

    SpringBoot使用validation-api实现参数校验可参考我的博客:SpringBoot使用validation-api实现参数校验

    正文

    SpringBoot使用validation-api实现对枚举类参数校验

    ValidationApi框架就是用来解决参数校验中代码冗余问题,ValidationApi框架提供一些注解用来帮助我们对请求参数进行校验。

    Maven依赖

    <!--参数校验-->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>
    
    
    <!--提供一些字符串操作-->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.3.2</version>
    </dependency>
    
    
    <!--lombok-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.2</version>
        <optional>true</optional>
    </dependency>
    
    
    <!--knife4j接口-->
    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-spring-boot-starter</artifactId>
        <version>2.0.4</version>
    </dependency>
    

    EnumValidate:用于对枚举校验的接口

    /**
    * 用于实现枚举类的校验
    */
    public interface EnumValidate<T> {
    
        /**
         * 校验枚举值是否存在
         */
        boolean existValidate(T value);
    }
    

    ActionTypeEnumValid:用于对枚举类校验的自定义注解

    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Constraint(validatedBy = {ActionTypeEnumValidator.class})
    @Documented
    public @interface ActionTypeEnumValid {
    
    
        String message() default "";
    
    
        Class<?>[] groups() default {};
    
    
        Class<? extends Payload>[] payload() default {};
    
    
        Class<?>[] target() default {};
    
    
        /**
         * 允许的枚举
         *
         * @return
         */
        Class<? extends Enum<?>> enumClass();
    
    
    }
    

    ActionTypeEnumValidator:枚举校验器

    /**
    * 用于校验ActionTypeEnumValidator
    */
    public class ActionTypeEnumValidator implements ConstraintValidator<ActionTypeEnumValid,String> {
    
    
        private Class<? extends Enum> enumClass;
    
    
        @Override
        public void initialize(ActionTypeEnumValid actionTypeEnumValid) {
            enumClass = actionTypeEnumValid.enumClass();
        }
    
    
        @Override
        public boolean isValid(String value, ConstraintValidatorContext context) {
            if (value == null || "".equals(value)) {
                return true;
            }
    
    
            EnumValidate[] enums = (EnumValidate[]) enumClass.getEnumConstants();
            if(enums ==null || enums.length == 0){
                return false;
            }
    
    
            return enums[0].existValidate(value);
        }
    
    
    }
    

    ActionTypeEnum:枚举类

    @Getter
    public enum ActionTypeEnum implements EnumValidate<String> {
    
    
        ACTION_INVOKR("invoke", "invoke"),
        UNKNOWN_ERROR("no", "no");
    
        /**
         * 状态值
         */
        private String couponType;
    
        /**
         * 状态描述
         */
        private String couponTypeDesc;
    
        ActionTypeEnum(String couponType, String couponTypeDesc) {
            this.couponType = couponType;
            this.couponTypeDesc = couponTypeDesc;
        }
    
    
        public static String getDescByType(String couponType) {
            for (ActionTypeEnum type : ActionTypeEnum.values()) {
                if (type.couponType.equals(couponType) ) {
                    return type.couponTypeDesc;
                }
            }
            return null;
        }
    
        /**
         * 判断是否在枚举类当中
         * @param value
         * @return
         */
        @Override
        public boolean existValidate(String value) {
            if (value == null || "".equals(value)) {
                return false;
            }
            for (ActionTypeEnum testEnum : ActionTypeEnum.values()) {
                if (testEnum.getCouponType().equalsIgnoreCase(value)) {
                    return true;
                }
            }
            return false;
        }
    
        public String getcouponTypeStr() {
            return String.valueOf(this.couponType);
        }
    }
    

    GlobalExceptionHandler:使用SpringMVC提供的异常处理机制,对ValidationApi的异常进行封装

    @RestControllerAdvice
    @Slf4j
    public class GlobalExceptionHandler {
    
        /**
         * 忽略参数异常处理器
         *
         * @param e 忽略参数异常
         * @return Response
         */
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler(MissingServletRequestParameterException.class)
        public ResponseResult parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
            log.error("参数异常", e);
            return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), "请求参数 " + e.getParameterName() + " 不能为空");
        }
    
    
        /**
         * 缺少请求体异常处理器
         *
         * @param e 缺少请求体异常
         * @return Response
         */
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler(HttpMessageNotReadableException.class)
        public ResponseResult parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
            log.error("缺少请求体异常", e);
            return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), "参数体不能为空");
        }
    
    
        /**
         * 参数效验异常处理器
         *
         * @param e 参数验证异常
         * @return ResponseInfo
         */
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public ResponseResult parameterExceptionHandler(MethodArgumentNotValidException e) {
            log.error("参数验证异常", e);
            // 获取异常信息
            BindingResult exceptions = e.getBindingResult();
            // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
            if (exceptions.hasErrors()) {
                List<ObjectError> errors = exceptions.getAllErrors();
                if (!errors.isEmpty()) {
                    // 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
                    FieldError fieldError = (FieldError) errors.get(0);
                    return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), fieldError.getDefaultMessage());
                }
            }
            return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR);
        }
    
    
        /**
         * 自定义参数错误异常处理器
         *
         * @param e 自定义参数
         * @return ResponseInfo
         */
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler({BusinessException.class})
        public ResponseResult paramExceptionHandler(BusinessException e) {
            log.error("业务异常", e);
            // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
            if (!StringUtils.isEmpty(e.getMessage())) {
                return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR.getcouponTypeStr(), e.getMessage());
            }
            return new ResponseResult(CouponTypeEnum.PARAMETER_ERROR);
        }
    
    
        /**
         * 其他异常
         *
         * @param e
         * @return
         */
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        @ExceptionHandler({Exception.class})
        public ResponseResult otherExceptionHandler(Exception e) {
            log.error("其他异常", e);
            // 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
            if (!StringUtils.isEmpty(e.getMessage())) {
                return new ResponseResult(CouponTypeEnum.UNKNOWN_ERROR.getcouponTypeStr(), e.getMessage());
            }
            return new ResponseResult(CouponTypeEnum.UNKNOWN_ERROR);
        }
    }
    

    验证

    请求的封装类

    /**
    * 指令的封装类
    */
    @Getter
    @Setter
    @ToString
    public class CommandPOJO implements Serializable {
        private static final long serialVersionUID = -8497328408069586664L;
    
        //指令
        @NotNull(message = "指令为必填项,不得为空")
        @ActionTypeEnumValid(message = "该指令暂不支持,暂时只支持invoke", enumClass = ActionTypeEnum.class)
        private String action ="invoke";
    
    }
    

    请求接口

    • @Valid 用于开启请求参数校验
    @RestController
    @Slf4j
    @Api(value = "远程调用模块")
    @RequestMapping("/xiyuanrpc")
    public class RPCController {
    
        @PostMapping("/rpcNettybyInvoke")
        @ApiOperation(value = "rpc远程调用")
        @InvokeParameterCheck
        @MethodLogPrint
        public ResponseResult rpcNettybyInvoke(@Valid @RequestBody CommandPOJO pojo) {
            return NettyClientUtil.rpcNetty(pojo);
        }
    
    }
    

    通过Knife4j访问对应接口
    在这里插入图片描述

    源码

    项目源码可从的我的github中获取:github源码地址

    在这里插入图片描述

    展开全文
  • java后台参数校验 一. 单个参数的校验方式 实现原理:@ControllerAdvice,@Validated注解对参数进行校验 实现方式: 1.创建统一的系统常量 package com.hm.middle_service.common; /** * @Author:huangzhimin * ...
  • Spring参数校验--List类型参数校验

    千次阅读 2019-03-06 00:05:27
    1.遇到的问题: 今天开发接口,遇到请求...发现参数校验失效。 // 控制器 @RequestMapping(value = "/saveVideo", method = RequestMethod.POST) @ResponseBody public List&lt;SaveVideoRe...
  • 今天就看到了一段代码,里面判断参数是否为空长度是多少,格式对不对等就是一堆判断,然后代码中就很多判断,或者单独写了判断方法,如果请求类不复用,或者复用但是判断都一样的话可以优先使用请求层校验,或者接口...
  • SpringBoot使用validation-api实现参数校验 前言 我们在开发Java项目的时候,经常需要对参数进行一些必填项、格式、长度等进行校验,如果手写代码对参数校验,每个接口会需要很多低级的代码,这样会降低代码的可读性...
  • 参数校验的多种方式

    千次阅读 2019-09-08 14:31:03
    参数校验的几种方式 如果默认的字段类型和选项不能满足需求,需要再补充校验行为,可以使用以下三种方法: 通过字段中的validators 选项进行校验 validate_<field_name>方法:对<field_name>字段进行...
  • java中优雅的参数校验方法

    万次阅读 多人点赞 2019-09-12 01:52:42
    如何更有“逼格”地在java中写出高大上的参数校验方法?
  • 在 Web 开发中, 我们经常需要校验各种参数,这是一件繁琐又重要的事情,对于很多人来说,在做参数校验的时候,会有以下几种类型的处理方式: 甩锅型 校验太麻烦了,让客户端去负责校验就行了,调用方传错了是调用方...
  • SpringMVC 参数校验

    千次阅读 2021-01-09 21:17:40
    SpringMVC 可以通过使用注解的方式对参数进行校验,省去参数校验的代码 引入依赖 Spring项目需引入 <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-...
  • controller参数校验

    千次阅读 2019-11-14 11:27:30
    使用javax.validation去校验参数,可以避免过多的if判断。 对需要校验的入参类添加注解 public class TestVO { /*** 用户ID*/ @NotNull(message = "用户id不能为空") private Long userId; /** 用户名*/ @...
  • 故事的开始: 前端进行校验,这个概念应该是没有问题的吧?比如:前端输入手机号的、链接的、邮箱地址的,我们是不是web端传入参数的时候,要对用户填入的格式进行校验。...2、“后端进行参数校验,...
  • Gin请求参数校验

    千次阅读 2020-06-10 07:35:26
    gin参数校验使用的是 validator库,因此本文的内容同样适用于使用validator来做参数校验的地方 校验规则 完整的校验规则可参考 https://godoc.org/github.com/go-playground/validator,下面分享常用的校验规则规则...
  • 背景:在java后端项目开发过程中,其实有很多大一部分项目,后端都没有做接口参数校验,或者做了参数校验,但是实现方式都是简单的使用if判断;主要原因在于:API的参数校验目前缺少比较流行的方案、现有方案不适用...
  • koa2参数校验方案

    千次阅读 2020-05-08 20:27:13
    在开发nodejs后端项目时,我们希望最好的结果便是将所有的参数校验部分单独抽离出来放在另外的文件中不和路由模块绑定在一起.将参数校验的逻辑代码封装到一个中间件函数里,如果用户上传的参数不符合
  • 常用参数校验注解: @AssertFalse 所注解的元素必须是Boolean类型,且值为false @AssertTrue 所注解的元素必须是Boolean类型,且值为true @DecimalMax 所注解的元素必须是数字,且值小于等于给定的值 @DecimalMin ...
  • 后端参数校验工具类

    千次阅读 2019-01-11 17:10:37
    后端参数校验工具类 1、应用场景 1、Controller层判断传入参数是否符合规则,不符合规则直接返回错误状态码。 2、其他需要校验参数的地方。 2、工具类 public class CheckUtil { /** * 中文,字母,数字 _ - . ...
  • 【dubbo】参数校验

    千次阅读 2019-03-10 19:46:00
    dubbo的SPI扩展是有关于参数校验的SP扩展,校难的原理其实也是用的拦截器原理。dubbo包有一个 ValidationFilter的拦截器实现。dubbo是有自己的校验器实现的JValidator,如果需要自定义的话,则需要实现 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 404,682
精华内容 161,872
关键字:

参数校验是什么意思

友情链接: miraupit.rar