一.全局异常处理
1.创建自定义异常BusinessRuntimeException
package com.zm.common.exception;
public class BusinessRuntimeException extends RuntimeException {
private static final long serialVersionUID = 7903308178033567233L;
/**
* 结果码
*/
private String code;
/**
* 结果码描述
*/
private String msg;
/**
* 结果码枚举
*/
private ErrorResultCode resultCode;
public BusinessRuntimeException(ErrorResultCode resultCode) {
super(resultCode.getMsg());
this.code = resultCode.getCode();
this.msg = resultCode.getMsg();
this.resultCode = resultCode;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public ErrorResultCode getResultCode() {
return resultCode;
}
public void setResultCode(ErrorResultCode resultCode) {
this.resultCode = resultCode;
}
}
2.创建全局错误枚举类
package com.zm.common.exception;
public enum ErrorResultCode {
/**
*系统异常
*/
SYSTEM_ERROR("500","系统异常"),
/**
* 参数错误
*/
PARAMETER_ERROR("00000", "参数有误"),
/**
* 不存在该用户
*/
DATA_ABNORMITY("10001", "不存在该用户"),
;
/**
* 结果码
*/
private String code;
/**
* 结果码描述
*/
private String msg;
ErrorResultCode(String code, String msg) {
this.code = code;
this.msg = msg;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
3.创建GlobalExceptionResolver全局处理类
package com.zm.common.exception;
import com.zm.common.util.ApiResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
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.stream.Collectors;
/**
* 全局Controller层异常处理类
*/
/**
* @RestControllerAdvice 和 @ControllerAdvice区别在于@RestControllerAdvice不需要加@ResponseBody
*/
@RestControllerAdvice
public class GlobalExceptionResolver {
private static final Logger LOG = LoggerFactory.getLogger(com.zm.common.exception.GlobalExceptionResolver.class);
/**
* 处理所有不可知异常
* @param e 异常
* @return json结果
*/
@ExceptionHandler(Exception.class)
public ApiResult handleException(Exception e) {
LOG.info(e.getMessage(), e);
e.printStackTrace();
return ApiResult.usuallyError(ErrorResultCode.SYSTEM_ERROR);
}
/**
* 处理所有业务异常
* @param e 业务异常
* @return json结果
*/
@ExceptionHandler(BusinessRuntimeException.class)
public ApiResult handleOpdRuntimeException(BusinessRuntimeException e) {
LOG.info(e.getMessage(), e);
e.printStackTrace();
return ApiResult.usuallyError(e.getResultCode());
}
/**
*@RequestParam上校验失败-> 抛出ConstraintViolationException
*/
@ExceptionHandler(value = ConstraintViolationException.class)
public ApiResult error(ConstraintViolationException e) {
String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining());
return ApiResult.paramError("ConstraintViolationException:"+message);
}
/**
*单独使用@Valid@Validated验证路径中请求实体校验失败后抛出的异常
*/
@ExceptionHandler(BindException.class)
public ApiResult BindExceptionHandler(BindException e) {
String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
return ApiResult.paramError("BindException:"+message);
}
/**
*@RequestBody上校验失败后抛出的异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ApiResult MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining());
return ApiResult.paramError("MethodArgumentNotValidException:"+message);
}
}
3.测试一下
package com.zm.service.impl;
import com.zm.common.exception.BusinessRuntimeException;
import com.zm.common.exception.ErrorResultCode;
import com.zm.dao.UserDao;
import com.zm.entity.User;
import com.zm.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public User selectUserInfoByName(String name) {
User user = userDao.selectUserInfoByName(name);
if(user == null){
throw new BusinessRuntimeException(ErrorResultCode.DATA_ABNORMITY);
}
return user ;
}
}
package com.zm.web.controller;
import com.zm.common.util.ApiResult;
import com.zm.entity.User;
import com.zm.service.UserService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@RestController
public class HelloController {
@Autowired
private UserService userService;
@GetMapping("/Exception")
public String hello() {
User 小明 = userService.selectUserInfoByName("小名");
return 小明.toString();
}
}
4.测试结果捕获业务层异常成功
全局异常和校验参数整合
1.pom.xml导入依赖包
<!-- hibernate校验依赖包-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.0.Final</version>
</dependency>
2.需要的类
package com.zm.common.util;
import com.zm.common.exception.ErrorResultCode;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
@ApiModel
public class ApiResult<T> implements Serializable {
@ApiModelProperty(value = "回调数据")
private T data;
@ApiModelProperty(value = "版本号")
private String vision;
@ApiModelProperty(value = "状态码")
private String code;
@ApiModelProperty(value = "消息提示")
private String msg;
@ApiModelProperty(value = "数据结果集")
public T getData() {
return data;
}
public String getVision() {
return vision;
}
public String getCode() {
return code;
}
public String getMsg() {
return msg;
}
public ApiResult<T> setData(T data) {
this.data = data;
return this;
}
public ApiResult<T> setVision(String vision) {
this.vision = vision;
return this;
}
public ApiResult<T> setCode(String code) {
this.code = code;
return this;
}
public ApiResult<T> setMsg(String msg) {
this.msg = msg;
return this;
}
public static ApiResult successMsg() {
return new ApiResult().setCode("200").setMsg("scuess").setData(null).setVision("1");
}
public static ApiResult successMsg(Object Object) {
return new ApiResult().setCode("200").setMsg("scuess").setData(Object).setVision("1");
}
public static ApiResult usuallyError(ErrorResultCode resultCode) {
ApiResult apiResult = new ApiResult().setCode(resultCode.getCode()).setMsg(resultCode.getMsg());
return apiResult;
}
public static ApiResult paramError(String msg) {
ApiResult apiResult = new ApiResult().setCode(ErrorResultCode.PARAMETER_ERROR.getCode()).setMsg(msg);
return apiResult;
}
}
package com.zm.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel
public class User {
@ApiModelProperty(value = "id")
private Integer id;
@ApiModelProperty(value = "姓名")
@NotBlank(message="姓名不能为空")
private String name;
@ApiModelProperty(value = "年龄")
@NotNull(message="年龄不能为空")
private Integer age;
@ApiModelProperty(value = "爱好")
private String skill;
@ApiModelProperty(value = "评价")
private String evaluate;
@ApiModelProperty(value = "成绩")
private Integer fraction;
}
3.在Controller层的使用
Controller层加上注解@Validated
1.@Valid @RequestBody -> 抛出MethodArgumentNotValidException
2.@Valid -> 抛出BindException
3.@Valid@RequestParam上 -> 抛出ConstraintViolationException
链接: https://www.cnblogs.com/fqybzhangji/p/10384347.html.
package com.zm.web.controller;
import com.zm.common.util.ApiResult;
import com.zm.entity.User;
import com.zm.service.UserService;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
@RestController
@Validated
public class HelloController {
@Autowired
private UserService userService;
@GetMapping("/Exception")
@ApiOperation(value = "全局异常演示" ,httpMethod = "GET")
public String hello() {
User 小明 = userService.selectUserInfoByName("小名");
return 小明.toString();
}
@PostMapping("/MethodArgumentNotValidException")
@ApiOperation(value = "校验异常情况一" ,httpMethod = "POST")
public ApiResult<User> hello(@Valid @RequestBody User userVo) {
System.out.println("请求参数:"+userVo);
return ApiResult.successMsg();
}
@GetMapping("/ConstraintViolationException")
@ApiOperation(value = "校验异常情况二" ,httpMethod = "GET")
public ApiResult<User> hello1(@Valid @NotBlank(message = "姓名不能为空") @RequestParam("name")String name,
@NotNull(message = "年龄不能为空") @RequestParam("age")Integer age) {
System.out.println("请求参数:"+name+","+age);
return ApiResult.successMsg();
}
@PostMapping("/BindException")
@ApiOperation(value = "校验异常情况三" ,httpMethod = "POST")
public ApiResult<User> hello1(@Valid User userVo) {
System.out.println("请求参数:"+userVo);
return ApiResult.successMsg(userVo);
}
}
4.@Validated和@Valid区别
链接: https://blog.csdn.net/qq_27680317/article/details/79970590.
5.Validator提供两种工作模式
Validator提供两种工作模式:
1、validator.normal:普通模式(会校验完所有的属性,然后返回所有的验证失败信息)
2、validator.fail_fast:快速失败返回模式(只要有一个验证失败,则返回异常)
默认的工作模式为快速失败返回模式,一旦发现校验失败项,立即返回。普通模式在测试时期可以使用,可以对全部的校验项进行完整的校验(校验组序列,以及基于校验组序列的其他配置无效),通过修改配置文件中的校验模式,从而实现工作模式的自由切换。开发人员无需关心其中的原理和过程。
配置Validator的工作模式
package com.zm.common.exception;
import org.hibernate.validator.HibernateValidator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
@Configuration
public class ParamValidateConfig {
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
postProcessor.setValidator(validator());
return postProcessor;
}
@Bean
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast( true )
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
}
6.测试结果
@Valid @RequestBody组合下
http://127.0.0.1:8080/MethodArgumentNotValidException
GET请求下@Valid @RequestParam组合
http://127.0.0.1:8080/ConstraintViolationException?name&age
快速返回模式生效,只校验了一个参数立即返回
@Valid 单独校验实体类
http://127.0.0.1:8080/BindException?name=&age=
7.常用注解:
Validation常用注解含义
@Null 限制只能为null
@NotNull 限制必须不为null
@AssertFalse 限制必须为false
@AssertTrue 限制必须为true
@DecimalMax(value) 限制必须为一个不大于指定值的数字
@DecimalMin(value) 限制必须为一个不小于指定值的数字
@Digits(integer,fraction) 限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future 限制必须是一个将来的日期
@Max(value) 限制必须为一个不大于指定值的数字
@Min(value) 限制必须为一个不小于指定值的数字
@Past 限制必须是一个过去的日期
@Pattern(value) 限制必须符合指定的正则表达式
@Size(max,min) 限制字符长度必须在min到max之间
@Past 验证注解的元素值(日期类型)比当前时间早
@NotEmpty 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式
链接: https://www.cnblogs.com/lw5946/p/11574987.html.
8.其他嵌套校验等等参考:
链接: https://my.oschina.net/shadowolf/blog/1934934.
链接: https://docs.jboss.org/hibernate/validator/4.2/reference/zh-CN/html_single/#validator-usingvalidator.
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/133963.html