JSR303--异常处理

后端开发过程中,免不了进行异常处理。怎么进行异常处理。如果在业务代码中进行异常处理的话,侵入太大,也不便于后续维护管理。

校验和异常处理相辅相成。校验失败就应该发生异常。此处使用一个JSR303校验规则实现校验,使用spring提供的异常统一处理方式。把异常处理逻辑抽取出来维护。@ControllerAdvice 注解标识位一个异常处理类。@ExceptionHandler注解分类处理异常。

校验方式中,适用不同的场景。可以分组校验,自定义校验。给我们开发中提供了很大的便利。

 

自定义校验

1.编写一个自定义校验注解

2.编写一个自定义的校验器

3.关联注解和校验器,并使用

自定义校验注解:

package com.wang.common.annotation;


import com.wang.common.valid.ListValueConstraintValidator;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * 自定义校验注解
 * @author zhipan.wang
 */
@Documented
/*
 * 指定校验器
 */
@Constraint(
        validatedBy = {ListValueConstraintValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {
    //异常信息定义
    String message() default "{com.wang.common.annotation.ListValue.message}";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    int[] vals() default {};

}

异常信息:ValidationMessages.properties

#传递的状态值不是指定的值!
com.wang.common.annotation.ListValue.message = \u4f20\u9012\u7684\u72b6\u6001\u503c\u4e0d\u662f\u6307\u5b9a\u7684\u503c!

自定义注解检验器

package com.wang.common.valid;

import com.wang.common.annotation.ListValue;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.HashSet;
import java.util.Set;


/**
 * 自定义注解校验器
 * 1.实现ConstraintValidator<注解,类型>
 * @author zhipan
 */
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {
    private Set<Integer> set = new HashSet<>(2);
    @Override
    public void initialize(ListValue constraintAnnotation) {
        for (int val : constraintAnnotation.vals()) {
            set.add(val);
        }
    }

    @Override
    public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
        return set.contains(integer);
    }
}

使用自定义注解@ListValue  

    /**
     * 显示状态[0-不显示;1-显示]
     */
    @NotNull(groups = AddGroup.class)
    @ListValue(vals = {0,1},groups = {AddGroup.class,UpdateGroup.class})
    private Integer showStatus;

分组异常处理

1 利用接口标识需要校验的分组

2 字段添加groups属性标识接收校验的分组 

3 方法注解@Validated({AddGroup.class})

接口编写,用于标识异常处理组

package com.wang.common.valid;

/**
 * 分组校验标志接口,用于标识新增时需要校验
 * @author zhipan.wang
 *
 */
public interface AddGroup {
}

校验注解中group参数指定分组,标识该分组需要校验 

@Null(message = "新增不能传品牌id",groups = AddGroup.class)
	@NotNull(message = "修改必须有品牌id",groups = UpdateGroup.class)

@Validated中指定该方法的分组 

    /**
     * 保存
     */
    @PostMapping("/save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand) {
            brandService.save(brand);
            return R.ok();
    }

 

统一处理异常使用步骤

发送异常时,抛出由ControllerAdvice来统一处理。

1 @ControllerAdvice 异常处理类

2 @ExceptionHandler 注解,处理异常

 

自定义ControllerAdvice 处理异常:

package com.wang.gulimall.product.exception;


import com.wang.common.exception.BizCodeEnums;
import com.wang.common.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;


/**
 * 统一处理异常类
 * @author zhipan.wang
 */
@Slf4j
@RestControllerAdvice(basePackages = "com.wang.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {

    @ExceptionHandler(value = Exception.class)
    public R handleValidException(MethodArgumentNotValidException e){
        log.error("数据校验错误:{},异常类型:{}",e.getMessage(),e.getClass());
        BindingResult bindingResult = e.getBindingResult();
        Map<String,String> map = new HashMap<>();
        bindingResult.getFieldErrors().forEach(item->{
            String defaultMessage = item.getDefaultMessage();
            String field = item.getField();
            map.put(field,defaultMessage);
        });
        return R.error(BizCodeEnums.VALID_EXCEPTION.getCode(),BizCodeEnums.VALID_EXCEPTION.getMsg()).put("data",map);
    }

    @ExceptionHandler(value = Throwable.class)
    public R handleException(Throwable throwable){
        //异常状态码,5位数字
        //前两位位业务场景,后三位表示错误码  10001  10通用  001参数格式异常
        //11 商品 12订单  13 购物车 14 物流
        return R.error(BizCodeEnums.UNKNOWN_EXCEPTION.getCode(),BizCodeEnums.UNKNOWN_EXCEPTION.getMsg());
    }
}
/*
JSR303
 */

异常码枚举类

package com.wang.common.exception;

public enum BizCodeEnums {
    UNKNOWN_EXCEPTION(10000, "系统未知异常"),
    VALID_EXCEPTION(10001, "数据校验异常");

    private int code;
    private String msg;

    BizCodeEnums(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

 

基本异常处理使用步骤

1.Entity添加校验注解

例如@NotBlank  @Min @Patten...

2.接口方法参数标注@Valid

3.BindlingResult 获取校验结果

 

Entity代码:

package com.wang.gulimall.product.entity;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import java.io.Serializable;
import java.util.Date;
import lombok.Data;
import lombok.Value;
import org.hibernate.validator.constraints.URL;

import javax.validation.constraints.*;

/**
 * 品牌
 *
 * @author zhipan.wang
 * @email zhipan_wang@qq.com
 * @date 2020-05-25 18:26:43
 */
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 品牌id
	 */
	@TableId
	private Long brandId;
	/**
	 * 品牌名
	 * 入参校验该字段必须有至少一个字符,message为自定义错误信息
	 */
	@NotEmpty
	@NotBlank(message="品牌名不能为空")
	private String name;
	/**
	 * 品牌logo地址
	 */
	@NotEmpty
	@URL(message = "必须是一个合法的URL地址")
	private String logo;
	/**
	 * 介绍
	 */
	private String descript;
	/**
	 * 显示状态[0-不显示;1-显示]
	 */
	private Integer showStatus;
	/**
	 * 检索首字母
	 */
	@NotEmpty
	@Pattern(regexp = "^[a-zA-Z]$",message="检索字母必须是一个字母")
	private String firstLetter;
	/**
	 * 排序
	 */
	@NotNull
	@Min(value=0,message="排序必须大于0")
	private Integer sort;

}

Controller代码,@Valid使用,@BindlingResult

    @PostMapping("/save")
    public R save(@Valid @RequestBody BrandEntity brand, BindingResult result) {
        if (result.hasErrors()) {
            Map<String, String> map = new HashMap<>();
            //获取错误结果
            result.getFieldErrors().forEach((item) -> {
                //获取错误消息
                String msg = item.getDefaultMessage();
                //获取错误字段
                String field = item.getField();
                map.put(field, msg);
            });
            return R.error(400, "提交的数据不合法!").put("data", map);
        } else {
            brandService.save(brand);
            return R.ok();
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值