前言
Spring Boot整合shiro时,在前端传输数据给后端的时候,后端一般要进行数据格式的校验和数据业务的校验;
数据格式的校验:比如手机号11位,如果传输的是12位,而数据库中设置的字段是11位,从而导致无法插入到数据库,报SQL相关的异常,这时候就需要对格式进行校验;
数据业务的校验:比如查询手机号是否重复
我们知道在前端可以进行数据格式的校验,比如【el-form】组件提供了表单验证的功能,只需要通过【rules】属性传入约定的验证规则等实现数据格式的校验,但那是前端做的,在后端中一般会在控制层进行数据的格式校验,在service层进行数据的业务校验,只有格式校验和业务校验都通过之后才会进行数据库操作。下面介绍下格式校验。
数据校验器
其中数据格式校验不通过时用自定义的BusinessException类进行捕捉:
BusinessException异常类的创建与使用
public class ValidatorUtils {
private static Validator validator;
static {
validator = Validation.buildDefaultValidatorFactory().getValidator();
}
/**
* 校验对象
*
* @param object 待校验对象
* @param groups 待校验组
* @throws BusinessException 校验不通过,则报异常
*/
public static void validate(Object object, Class<?>... groups)
throws BusinessException {
/**
* 进行具体的数据校验
*/
Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
// 如果数据校验器校验的结果不为空 说明就存在数据校验不通过
if (constraintViolations != null && !constraintViolations.isEmpty()) {
// 遍历校验不通过的信息
for (ConstraintViolation<Object> objectConstraintViolation : constraintViolations) {
// 校验不通过的原因
String message = objectConstraintViolation.getMessage();
Integer code = Constant.PARAM_CHECKED_ERROR;
throw new BusinessException(message, code );
}
}
}
}
区分新增和修改时不同校验的两个接口
public interface UpdateGroup {}
public interface AddGroup {}
表单实体
@Data
public class SysUserForm {
private Long id;
@NotEmpty(message = "登录名不可以为空", groups = {AddGroup.class, UpdateGroup.class})
@Length(min = 5, max = 15, message = "登录名5~15位字符", groups = {AddGroup.class, UpdateGroup.class})
private String loginName;
//使用默认密码
private String loginPassword;
@NotEmpty(message = "手机号不可以为空", groups = {AddGroup.class, UpdateGroup.class})
@Length(min = 11, max = 11, message = "手机号只能是11位字符", groups = {AddGroup.class, UpdateGroup.class})
private String phone;
@NotEmpty(message = "真实姓名不可以为空", groups = {AddGroup.class, UpdateGroup.class})
private String realname;
@NotEmpty(message = "身份证不可以为空", groups = {AddGroup.class, UpdateGroup.class})
@Length(min = 18, max = 18, message = "身份证只能是18位", groups = {AddGroup.class, UpdateGroup.class})
private String idCard;
@NotNull(message = "性别不可以为空", groups = {AddGroup.class})
@Range(min = 0, max = 1, message = "性别只能是男或者是女")
private Integer sex;
@NotNull(message = "地址不可以为空", groups = {AddGroup.class, UpdateGroup.class})
private String address;
private String img;
}
控制层校验数据格式
service层内容省略
@RestController
@RequestMapping("/sys/user")
public class SysUserController extends BaseController {
@SysLog("更新当前登录的用户信息")
@PostMapping("update")
public Result updateUser(SysUserForm sysUserForm) {
//进行数据格式的校验,然后得到之后的数据。
ValidatorUtils.validate(sysUserForm, UpdateGroup.class);
return sysUserService.updateCurUserInfo(sysUserForm);
}
@SysLog("新增用户")
@PostMapping("add")
public Result addUser(SysUserForm sysUserForm){
//进行数据格式的校验,然后得到之后的数据。
ValidatorUtils.validate(sysUserForm, AddGroup.class);
return sysUserService.addUser(sysUserForm);
}
}
全局异常捕获
当数据格式校验出现问题,用自定义异常抛出的时候,会由下方【全局异常处理器】进行处理,根据实际业务需求可能返回Object对象或者ModelAndView等等。由此可以避免频繁的使用try catch,使代码变得简洁。
@ControllerAdvice
public class GlobalExceptionHandler {
@ResponseBody
@ExceptionHandler
public Object handlerException(Exception exception) {
exception.printStackTrace();
// 判断是否是自己定义的异常信息
if (exception instanceof BusinessException) {
BusinessException bussiException = (BusinessException) exception;
return new Result(bussiException);
}
// shiro
if (exception instanceof ShiroException) {
if (exception instanceof UnknownAccountException) {
return new Result(ResultEnum.USER_USER_PASSWORD_ERROR);
}
if (exception instanceof AuthenticationException) {
return new Result(ResultEnum.USER_NOT_HAVE_PERMISSION_ERROR);
}
}
// 可能发生是其他异常
return new Result(ResultEnum.UN_KNOWN_ERROR);
}
}
|