java 异常验证框架validation,全局异常处理,请求验证
1、依赖
异常验证框架validation<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>${spring-boot.version}</version></dependency>
当鼠标放在依赖上,依赖文字会变蓝
@NotNull@NotNullprivate String content;@Validated:标识参数不能为空public Integer register(@RequestBody @Validated UserRegDTO user) {}
全局接口异常处理:@ControllerAdvice和@ExceptionHandler
//@ControllerAdvice//能捕获异常,但是不能输出给客户端
@RestControllerAdvice//会自动将错误包装成json返回给客户端
package cn.tedu._05weibo.common.ex;/**** 全局异常处理器***/import cn.tedu._05weibo.common.reponse.JsonResult;
import cn.tedu._05weibo.common.reponse.ServiceCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RestControllerAdvice;import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;@Slf4j
//@ControllerAdvice//能捕获异常,但是不能输出给客户端
@RestControllerAdvice//会自动将错误包装成json返回给客户端
public class GlobalExceptionHandler {@ExceptionHandlerpublic JsonResult handMethodArgumentNotValidException(MethodArgumentNotValidException ex){StringBuffer stringBuffer=new StringBuffer();for (FieldError fieldError : ex.getFieldErrors()) {stringBuffer.append(fieldError.getDefaultMessage());}// @NotNull(message = "内容不能为空") 获取错误消息,与之对应System.out.println("全局捕获验证异常:"+stringBuffer);return new JsonResult(ServiceCodeEnum.PARAM_ERROR.getCode(),stringBuffer.toString());}@ExceptionHandlerpublic JsonResult handConstraintViolationException(ConstraintViolationException exception){log.error("捕获非封装异常:"+exception.getMessage());StringBuffer stringBuffer=new StringBuffer();Set<ConstraintViolation<?>> constraintViolations = exception.getConstraintViolations();for (ConstraintViolation<?> constraintViolation : constraintViolations) {stringBuffer.append(constraintViolation.getMessage());}
// 使接口报错和java处理的异常同步return new JsonResult(ServiceCodeEnum.SERVICE_ERROR.getCode(),stringBuffer.toString());}/*** 运行时抛出异常,都不会崩溃,只会在这里处理错误日志* 不会抛出500的异常* */@ExceptionHandlerpublic JsonResult handRuntimeException(RuntimeException exception){log.error("捕获运行时异常:"+exception.getMessage());return new JsonResult(ServiceCodeEnum.SERVICE_ERROR);}/*** 捕获java中异常,不会抛出500的异常** Exception的父类是Throwable* Error的父类也是Throwable* */@ExceptionHandlerpublic JsonResult handThrowable(Throwable throwable){log.error("捕获所有异常:"+throwable.getMessage());return new JsonResult(ServiceCodeEnum.SERVICE_ERROR);}
}
JsonResult
package cn.tedu._05weibo.common.reponse;import lombok.AccessLevel;
import lombok.Data;
import lombok.experimental.FieldDefaults;/*** 统一接口返回数据* */
//统一接口返回数据@Data
@FieldDefaults(level = AccessLevel.PRIVATE)
public class JsonResult {Integer code;String msg;
// 相应数据Object data;public JsonResult() {}public JsonResult(ServiceCodeEnum serviceCodeEnum){this.code=serviceCodeEnum.getCode();this.msg=serviceCodeEnum.getMsg();}public JsonResult(Integer code,String msg){this.code=code;this.msg=msg;}public JsonResult(ServiceCodeEnum serviceCodeEnum, Object data){this.code=serviceCodeEnum.getCode();this.msg=serviceCodeEnum.getMsg();this.data=data;}public JsonResult test(){return new JsonResult(ServiceCodeEnum.SUCCESS);}
}
ServiceCodeEnum
@Getter//生成get方法
@AllArgsConstructor//构造参数
public enum ServiceCodeEnum {// 构造方法SUCCESS(1,"OK"),PARAM_ERROR(2,"参数错误"),SERVICE_ERROR(3,"网络错误,请检查你的网络"),USER_NAME_OR_PASSWORD_ERROR_CODE(300,"用户名或密码错误"),NO_LOGIN(200,"未登录");private Integer code;private String msg;
}
ValidationConfig
@Configuration
public class ValidationConfig {// 设置全局异常,是快速失败,默认为true
// 为false时,会收集所有错误@Beanpublic javax.validation.Validator validator() {return Validation.byProvider(HibernateValidator.class).configure().failFast(false).buildValidatorFactory().getValidator();}
}
@NotNull(message = "内容不能为空"):判断字符串,是否为null ,tag:null
@NotEmpty //什么都没有字符串
即能验证字符串是否为null,也能验证字符串为空,例:"content": null、"content": ""
@NotBlank//空白:“ ”
@NotBlank = @NotNull + @NotEmpty,且也可以验证:"content": " "
@Size(min=2,max = 6,message = "标签长度为2-6")
@Range(min = 2,max = 6,message = "大小在2-6之内")
"".substring(0,10);这句会报错,但是,因为有运行时异常处理,就不会报错
/*** 运行时抛出异常,都不会崩溃,只会在这里处理错误日志* */@ExceptionHandlerpublic JsonResult handRuntimeException(RuntimeException exception){log.error("捕获运行时异常:"+exception.getMessage());return new JsonResult(ServiceCodeEnum.SERVICE_ERROR);}
自定义内部状态码
错误码:10300-10399
订单模块:10100-10199
支付模块10500-10599
@Validated 表示为验证对象
package cn.tedu._05weibo.controller;import cn.tedu._05weibo.mapper.UserMapper;
import cn.tedu._05weibo.pojo.dto.UserLoginDTO;
import cn.tedu._05weibo.pojo.dto.UserRegDTO;
import cn.tedu._05weibo.pojo.entity.User;
import cn.tedu._05weibo.pojo.vo.UserVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpSession;
import java.util.Date;@Slf4j
@RestController
@RequestMapping(value = "/v1/users")
@Api(tags = "用户相关接口")
public class UserController {@Autowired UserMapper userMapper;
// 注册@PostMapping(value = "reg")@ApiOperation("注册功能")public Integer register(@RequestBody @Validated UserRegDTO user) {// soutpSystem.out.println("UserController.register:"+user);UserVo userVo = userMapper.selectByUsername(user.getUsername());if(userVo!=null) {return 2;}User u = new User();BeanUtils.copyProperties(user,u);u.setCreated(new Date());userMapper.insertUser(u);return 1;}// HttpSession:做会话@PostMapping(value = "login")public int login(@RequestBody UserLoginDTO user, HttpSession session) {UserVo userVo = userMapper.selectByUsername(user.getUsername());System.out.println("user = " + user);log.info("myMethod方法被执行");log.debug("");if(userVo==null) {return 3;}if(!userVo.getPassword().equals(user.getPassword())) {return 2;}session.setAttribute("user", userVo);return 1;}@GetMapping(value = "currentUser")public UserVo currentUser(HttpSession session){UserVo userVo = (UserVo) session.getAttribute("user");return userVo;}@GetMapping(value = "logout")public void logout(HttpSession session){session.removeAttribute("user");System.out.println("退出成功" );}
}