SpringMVC支持使用 【JSR303】 方式进行校验 1、springboot默认导第三方的校验框架hibernate-validator
使用JSR303的三大步 1)、给需要校验数据的javaBean上标注校验注解; 2)、告诉SpringBoot,这个需要校验;@Valid springmvc进入方法之前,确定参数值的时候就会进行校验,如果校验出错,直接返回错误,不执行controller代码 3)、如何感知校验成功还是失败; 只需要给开启了校验的javaBean参数后面,紧跟一个BindingResult对象就可以获取到校验结果; 只要有BindingResult,即使校验错了,方法也会执行。我们需要手动处理
统一的异常处理:
Controller:
代码语言:javascript复制 @ApiOperation(value = "用户注册")
@PostMapping(value = "/register")
public Object register(@Valid @RequestBody UmsAdminParam umsAdminParam, BindingResult result) {
Admin admin = null;
//TODO 完成注册功能
// int errorCount = result.getErrorCount();
// if(errorCount>0){
// List<FieldError> fieldErrors = result.getFieldErrors();
// fieldErrors.forEach((fieldError)->{
// String field = fieldError.getField();
// log.debug("属性:{},传来的值是:{},校验出错。出错的提示消息:{}",
// field,fieldError.getRejectedValue(),fieldError.getDefaultMessage());
// });
//
//
// return new CommonResult().validateFailed(result);
// }else {
//
// }
log.debug("需要注册的用户详情:{}",umsAdminParam);
int i = 10/0;
return new CommonResult().success(admin);
}
利用aop完成统一的数据校验
代码语言:javascript复制import com.xiepanpan.gmall.to.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
/**
* 切面如何编写
* 1、导入切面场景
* <dependency>
* <groupId>org.springframework.boot</groupId>
* <artifactId>spring-boot-starter-aop</artifactId>
* </dependency>
* 2、编写切面
* 1)、@Aspect
* 2)、切入点表达式
*
*
* 3)、通知
* 前置通知:方法执行之前触发
* 后置通知:方法执行之后触发
* 返回通知:方法正常返回之后触发
* 异常通知:方法出现异常触发
*
* 正常执行: 前置通知==>返回通知==>后置通知
* 异常执行: 前置通知==>异常通知==>后置通知
*
* 环绕通知:4合1;拦截方法的执行
*
*/
//利用aop完成统一的数据校验,数据校验出错就返回给前端错误提示
@Slf4j
@Aspect
@Component
public class DataVaildAspect {
/**
* 目标方法的异常,一般都需要再次抛出去。让别人感知
* @param point
* @return
* @throws Throwable
*/
@Around("execution(* com.xiepanpan.gmall.admin..*Controller.*(..))")
public Object validAround(ProceedingJoinPoint point) throws Throwable {
Object proceed = null;
log.debug("校验切面介入工作....");
Object[] args = point.getArgs();
for (Object obj:args){
if(obj instanceof BindingResult){
BindingResult r = (BindingResult) obj;
if(r.getErrorCount()>0){
//框架自动校验检测到错了
return new CommonResult().validateFailed(r);
};
}
}
//就是我们反射的 method.invoke();
proceed = point.proceed(point.getArgs());
log.debug("校验切面将目标方法已经放行....{}",proceed);
return proceed;
}
}
全局拦截器:
代码语言:javascript复制import com.xiepanpan.gmall.to.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 统一处理所有异常,给前端返回500的json
*
* 当我们编写环绕通知的时候,目标方法出现的异常一定要再次跑出去
*/
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = {ArithmeticException.class})
public Object handlerException(Exception exception){
log.error("系统全局异常感知,信息:{}",exception.getStackTrace());
return new CommonResult().validateFailed("数学没学好");
}
@ExceptionHandler(value = {NullPointerException.class})
public Object handlerException02(Exception exception){
log.error("系统出现异常感知,信息:{}",exception.getMessage());
return new CommonResult().validateFailed("空指针了...");
}
}
JavaBean:
代码语言:javascript复制import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotEmpty;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Null;
import javax.validation.constraints.Pattern;
/**
* 用户登录参数
* Created by xiepanpan 4/26.
*/
@ToString
@Getter
@Setter
public class UmsAdminParam {
/**
* 能使用的校验注解
* 1)、Hibernate org.hibernate.validator.constraints 里面的所有
* 2)、JSR303规范规定的都可;
* javax.validation.constraints
* @Pattern(regexp = "")
*/
@Length(min = 6,max = 18,message = "用户名长度必须是6-18位")
@ApiModelProperty(value = "用户名", required = true)
private String username;
@ApiModelProperty(value = "密码", required = true)
private String password;
@NotEmpty
@ApiModelProperty(value = "用户头像")
private String icon;
@Email(message = "邮箱格式不正确,哈哈哈")
@ApiModelProperty(value = "邮箱")
private String email;
//使用负责正则进行校验
@Null //必须是不传的
@ApiModelProperty(value = "用户昵称")
private String nickName;
@ApiModelProperty(value = "备注")
private String note;
}
通用返回对象CommonResult 类:
代码语言:javascript复制import com.alibaba.fastjson.JSON;
import org.springframework.validation.BindingResult;
/**
* 通用返回对象
*/
public class CommonResult {
//操作成功
public static final int SUCCESS = 200;
//操作失败
public static final int FAILED = 500;
//参数校验失败
public static final int VALIDATE_FAILED = 404;
//未认证
public static final int UNAUTHORIZED = 401;
//未授权
public static final int FORBIDDEN = 403;
private int code;
private String message;
private Object data;
/**
* 普通成功返回
*
* @param data 获取的数据
*/
public CommonResult success(Object data) {
this.code = SUCCESS;
this.message = "操作成功";
this.data = data;
return this;
}
/**
* 普通失败提示信息
*/
public CommonResult failed() {
this.code = FAILED;
this.message = "操作失败";
return this;
}
/**
* 参数验证失败使用
*
* @param message 错误信息
*/
public CommonResult validateFailed(String message) {
this.code = VALIDATE_FAILED;
this.message = message;
return this;
}
/**
* 未登录时使用
*
* @param message 错误信息
*/
public CommonResult unauthorized(String message) {
this.code = UNAUTHORIZED;
this.message = "暂未登录或token已经过期";
this.data = message;
return this;
}
/**
* 未授权时使用
*
* @param message 错误信息
*/
public CommonResult forbidden(String message) {
this.code = FORBIDDEN;
this.message = "没有相关权限";
this.data = message;
return this;
}
/**
* 参数验证失败使用
* @param result 错误信息
*/
public CommonResult validateFailed(BindingResult result) {
validateFailed(result.getFieldError().getDefaultMessage());
return this;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
}