建立淘宝客网站,响应式网站设计思路,有没有专门做线下活动的网站,要如何做才能拥有自己的网站呢在设计接口时我们通常需要对接口中的非法参数做校验#xff0c;以降低在程序运行时因为一些非法参数而导致程序发生异常的风险#xff0c;例如登录的时候需要校验用户名密码是否为空#xff0c;创建用户的时候需要校验邮件、手机号码格式是否准确。如果在代码中对接口参数一…在设计接口时我们通常需要对接口中的非法参数做校验以降低在程序运行时因为一些非法参数而导致程序发生异常的风险例如登录的时候需要校验用户名密码是否为空创建用户的时候需要校验邮件、手机号码格式是否准确。如果在代码中对接口参数一个个硬编码校验的话就太繁琐了代码可读性极差。这时不妨试试Validator框架。
原生的依赖是validation-api而hibernate-validator是对validation-api的增强hibernate-validator框架已经集成在spring-boot-starter-web中。
dependencygroupIdorg.hibernate/groupIdartifactIdhibernate-validator/artifactIdversion5.2.0.Final/version
/dependency
但从springboot-2.3开始校验包被独立成了一个starter组件所以需要引入validation和web而springboot-2.3之前的版本只需要引入web依赖就可以了。
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactId
/dependency
部分常见注解如下
注解功能AssertFalse可以为null,如果不为null的话必须为falseAssertTrue可以为null,如果不为null的话必须为trueDecimalMax设置不能超过最大值DecimalMin设置不能超过最小值Digits设置必须是数字且数字整数的位数和小数的位数必须在指定范围内Future日期必须在当前日期的未来Past日期必须在当前日期的过去Max最大不得超过此最大值Min最大不得小于此最小值NotNull不能为null可以是空Null必须为nullPattern必须满足指定的正则表达式Size集合、数组、map等的size()值必须在指定范围内Email必须是email格式Length长度必须在指定范围内NotBlank字符串不能为null,字符串trim()后也不能等于“”NotEmpty不能为null集合、数组、map等size()不能为0字符串trim()后可以等于“”Range值必须在指定范围内URL必须是一个URL
一、基础注解使用
注解简单演示类
import lombok.Data;
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;Data
public class UserVo {Length(min 4, max 12, message 账号长度必须位于4到10之间)private String userCode;NotBlank(message 用户名不能为空)private String userName;Email(message 邮箱格式有误)private String email;Pattern(regexp ^1[3456789]\\d{9}$, message 手机号格式错误)private String phone;/*** 0普通用户VIP会员用户2超级VIP用户*/Pattern(regexp [012], message 用户类型有误请输入0普通用户VIP会员用户2超级VIP用户)private String type;
}在全局异常处理里面加上对参数校验异常的拦截 ExceptionHandler(value {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})public ResponseVo validatedExceptionHandler(Exception e) {log.error(参数校验异常原因是{}, e);if (e instanceof MethodArgumentNotValidException) {//BeanValidation exceptionMethodArgumentNotValidException ex (MethodArgumentNotValidException) e;return ResponseVo.error(ResponseEnum.BODY_NOT_MATCH.getResultCode(),ex.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(; )));} else if (e instanceof ConstraintViolationException) {//BeanValidation GET simple paramConstraintViolationException ex (ConstraintViolationException) e;return ResponseVo.error(ResponseEnum.BODY_NOT_MATCH.getResultCode(),ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining(; )));} else if (e instanceof BindException) {//BeanValidation GET object paramBindException ex (BindException) e;return ResponseVo.error(ResponseEnum.BODY_NOT_MATCH.getResultCode(),ex.getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(; )));}return ResponseVo.error(ResponseEnum.BODY_NOT_MATCH.getResultCode(), ResponseEnum.BODY_NOT_MATCH.getResultMsg());} 定义参数校验的controller
import com.yx.light.element.mybatis.vo.UserVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.validation.constraints.Email;RestController
RequestMapping(value /valid)
Validated
Slf4j
public class ValidController {/*** 单参数校验单参数需要在controller上加上Validated配合使用* param email* return*/PostMapping(value /oneParam, produces application/json; charsetUTF-8)public String oneParam(Email(message 邮箱格式有误) String email) {log.info(校验邮箱为{}, email);return 邮箱校验成功;}/*** body类型校验* param vo* return*/PostMapping(value /bodyParam, produces application/json; charsetUTF-8)public String bodyParam(Validated RequestBody UserVo vo) {log.info(校验body为{}, vo);return body校验成功;}/*** 表单参数校验* param vo* return*/PostMapping(value /formParam, produces application/json; charsetUTF-8)public String formParam(Validated UserVo vo) {log.info(校验表单为{}, vo);return 表单校验成功;}
}
oneParam接口 bodyParam接口 formParam接口 二、自定义参数校验
当然你也可以自定义参数校验出现有些复杂的逻辑基本注解是没办法兼容的需要我们自己去实现自动校验。
自定义校验注解
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;Documented
Retention(RUNTIME)
Target({FIELD, METHOD, PARAMETER, TYPE})
Constraint(validatedBy UserValidation.UniqueUserValidator.class)
public interface UniqueUser {String message() default 用户编码、手机号码、邮箱不允许与现存用户重复;Class?[] groups() default {};Class? extends Payload[] payload() default {};
} 想让自定义验证注解生效需要实现ConstraintValidator接口。接口的第一个参数是 自定义注解类型第二个参数是 被注解字段的类。
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
import java.util.function.Predicate;Slf4j
public class UserValidationT extends Annotation implements ConstraintValidatorT, UserVo {protected PredicateUserVo predicate c - true;Overridepublic boolean isValid(UserVo user, ConstraintValidatorContext constraintValidatorContext) {return predicate.test(user);}/*** 校验用户是否唯一* 即判断数据库是否存在当前新用户的信息如用户编码手机邮箱*/public static class UniqueUserValidator extends UserValidationUniqueUser {Overridepublic void initialize(UniqueUser uniqueUser) {predicate c - !existsUser(c.getUserCode(), c.getEmail(), c.getPhone());}private boolean existsUser(String userCode, String email, String phone) {//TODO 写一个数据库查询判断是否存在相同的用户省略...return true;}}
}
在controller中添加测试接口
PostMapping(value /addUser, produces application/json; charsetUTF-8)
public String addUser(UniqueUser Validated RequestBody UserVo vo) {log.info(校验body为{}, vo);return 新增成功;
}
addUser接口 三、分组校验
如果你的一个实体中的字段某一些是新增的时候必传某一些修改时又不用传那么对于不用传的字段肯定不需要校验的这时候如果我们共用一个实体作为多个接口参数那肯定存在兼容问题此时你就可以考虑将参数分组判断。
定义一个分组接口ValidGroup让其继承javax.validation.groups.Default再在分组接口中定义出多个不同的操作类型CreateUpdateQueryDelete。
import javax.validation.groups.Default;public interface ValidGroup extends Default {interface Crud extends ValidGroup {interface Create extends Crud {}interface Update extends Crud {}interface Query extends Crud {}interface Delete extends Crud {}}
}
稍微修改一下原来的vo给他们加上分组参数groups
import com.yx.light.element.mybatis.validation.ValidGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Length;import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;Data
public class UserVo {Length(min 4, max 12, message 账号长度必须位于4到10之间, groups ValidGroup.Crud.Update.class)private String userCode;NotBlank(message 用户名不能为空, groups ValidGroup.Crud.Create.class)private String userName;Email(message 邮箱格式有误)private String email;Pattern(regexp ^1[3456789]\\d{9}$, message 手机号格式错误)private String phone;/*** 0普通用户VIP会员用户2超级VIP用户*/Pattern(regexp [012], message 用户类型有误请输入0普通用户VIP会员用户2超级VIP用户)private String type;
}在controller中添加如下方法这里我们通过value属性给addUserV2()和updateUser()方法分别指定Create和Update分组。
PostMapping(value /addUserV2, produces application/json; charsetUTF-8)
public String addUserV2(Validated(value ValidGroup.Crud.Create.class) RequestBody UserVo vo) {log.info(校验body为{}, vo);return 新增成功;
}PostMapping(value /updateUser, produces application/json; charsetUTF-8)
public String updateUser(Validated(value ValidGroup.Crud.Update.class) RequestBody UserVo vo) {log.info(校验body为{}, vo);return 更新成功;
}addUserV2接口 updateUser接口