项目总结:JSR303与异常处理


前言

在开发中,常常会遇到抛出异常的情况,异常处理除了输出在日志中,还需要提示给用户。我们希望在抛出异常时输出指定的异常信息。当正常操作时按接口要求返回数据,当非正常流程时要获取异常信息进行记录,并提示给用户。
这里只说明使用流程,具体原理较为粗略

一、JSR303简介

JSR-303 是 JAVA EE 6 中的一项子规范,叫做 Bean Validation,官方参考实现是Hibernate Validator。
Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的实现,除此之外还有一些附加的 constraint。官网

二、规范异常信息

异常处理除了输出在日志中,还需要提示给用户,前端和后端需要作一些约定:

  1. 错误提示信息统一以json格式返回给前端。
  2. 以HTTP状态码决定当前是否出错,非200为操作异常。

代码中统一抛出项目的自定义异常类型,这样可以统一去捕获这一类或几类的异常。
规范了异常类型就可以去获取异常信息。
如果捕获了非项目自定义的异常类型统一向用户提示“执行过程异常,请重试”的错误信息。

三、捕获异常

代码统一用try/catch方式去捕获代码比较臃肿,可以通过SpringMVC提供的控制器增强类统一由一个类去完成异常的捕获
如下图:

在这里插入图片描述


四、数据校验

1.首先添加需要依赖的包:

<dependency>
   <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2.常用注解

约束注解名称约束注解说明
@Null用于验证对象为null
@NotNull用于对象不能为null,无法查检长度为0的字符串
@NotBlank只用于String类型上,不能为null且trim()之后的size>0
@NotEmpty用于集合类、String类不能为null,且size>0。但是带有空格的字符串校验不出来
@Size用于对象(Array,Collection,Map,String)长度是否在给定的范围之内
@Length用于String对象的大小必须在指定的范围内
@Pattern用于String对象是否符合正则表达式的规则
@Email用于String对象是否符合邮箱格式
@Min用于Number和String对象是否大等于指定的值
@Max用于Number和String对象是否小等于指定的值
@AssertTrue用于Boolean对象是否为true
@AssertFalse用于Boolean对象是否为false

@Data
public class AddMeetingDto {

 @NotEmpty(message = "会议名称不能为空")
 @ApiModelProperty(value = "会议名称", required = true)
 private String meetingName;

 @NotEmpty(message = "优先级不能为空")
 @ApiModelProperty(value = "优先级", required = true)
 private Integer prio;


 @NotEmpty(message = "会议类型不能为空")
 @ApiModelProperty(value = "会议类型")
 private String meetingType;


 @ApiModelProperty(value = "会议描述", required = true)
 private String meetingDescription;

 @ApiModelProperty(value = "创建人", required = true)
 private String createPeople;
 @ApiModelProperty(value = "会议室id", required = true)
 private Long roomId;
 @NotEmpty(message = "参与人员不能为空")
 @ApiModelProperty(value = "参与人员", required = true)
 List<ParticipantsDto> participants;
 @NotEmpty(message = "会议时间不为空")
 @ApiModelProperty(value = "会议时间", required = true)
 List<FreeTimeDto> freeTime;
}

   @ApiOperation("新增会议基础信息")
    @PostMapping("/meeting")
    public MeetingBaseInfoDto createMeetingBase(@Valid @RequestBody AddMeetingDto addMeetingDto){
        Long manageId=12334123L;
        MeetingBaseInfoDto meetingBase = meetingInformationService.createMeetingBase(manageId, addMeetingDto);
        return meetingBase;
    }

五、统一异常处理

从 Spring 3.0 - Spring 3.2 版本之间,对 Spring 架构和 SpringMVC 的Controller 的异常捕获提供了相应的异常处理。

  • @ExceptionHandler
    Spring3.0提供的标识在方法上或类上的注解,用来表明方法的处理异常类型。
  • @ControllerAdvice
    Spring3.2提供的新注解,从名字上可以看出大体意思是控制器增强,
    在项目中来增强SpringMVC中的Controller。通常和@ExceptionHandler
    结合使用,来处理SpringMVC的异常信息。
  • @ResponseStatus
    Spring3.0提供的标识在方法上或类上的注解,用状态代码和应返回的原因标记方法或异常类。
    调用处理程序方法时,状态代码将应用于HTTP响应。
    通过上面的两个注解便可实现微服务端全局异常处理,具体代码如下:
    首先添加需要依赖的包:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>

1. 定义一些通用的异常信息

package com.meeting.base.execption;
public enum CommonError {

   UNKOWN_ERROR("执行过程异常,请重试。"),
   PARAMS_ERROR("非法参数"),
   OBJECT_NULL("对象为空"),
   QUERY_NULL("查询结果为空"),
   REQUEST_NULL("请求参数为空");

   private String errMessage;

   public String getErrMessage() {
      return errMessage;
   }

   private CommonError( String errMessage) {
      this.errMessage = errMessage;
   }
}

2. 自定义异常类型

package com.meeting.base.execption;

public class MeetingPlanException extends RuntimeException {
   private String errMessage;
   public MeetingPlanException() {
      super();
   }

   public MeetingPlanException(String errMessage) {
      super(errMessage);
      this.errMessage = errMessage;
   }

   public String getErrMessage() {
      return errMessage;
   }

   public static void cast(CommonError commonError){
       throw new MeetingPlanException(commonError.getErrMessage());
   }
   public static void cast(String errMessage){
       throw new MeetingPlanException(errMessage);
   }
}

3. 响应用户的统一类型

package com.xuecheng.base.execption;

import java.io.Serializable;

/**
 * 错误响应参数包装
 */
public class RestErrorResponse implements Serializable {

    private String errMessage;

    public RestErrorResponse(String errMessage){
        this.errMessage= errMessage;
    }

    public String getErrMessage() {
        return errMessage;
    }

    public void setErrMessage(String errMessage) {
        this.errMessage = errMessage;
    }
}

4、全局异常处理器

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

   @ResponseBody
   @ExceptionHandler(MeetingPlanException.class)
   @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
   public RestErrorResponse customException(MeetingPlanException e) {
      log.error("【系统异常】{}",e.getErrMessage(),e);
      return new RestErrorResponse(e.getErrMessage());

   }

   @ResponseBody
   @ExceptionHandler(Exception.class)
   @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
   public RestErrorResponse exception(Exception e) {

      log.error("【系统异常】{}",e.getMessage(),e);

      return new RestErrorResponse(CommonError.UNKOWN_ERROR.getErrMessage());

   }
}


六、分组校验

我们在做校验的时候,通常会遇到一个实体类的添加和修改,他们的校验规则是不同的,所以分组显得尤为重要。他可以帮助我们少建一个冗余的实体类。

用class类型来表示不同的分组,所以我们定义不同的接口类型(空接口)表示不同的分组,如下:

1. 创建分组接口(不需写任何内容)

public class ValidationGroups {
 public interface Inster{};
 public interface Update{};
 public interface Delete{};

}

2. 在定义校验规则时指定分组

@NotEmpty(groups = {ValidationGroups.Inster.class},message = "添加会议名称不能为空")
 @NotEmpty(groups = {ValidationGroups.Update.class},message = "修改会议名称不能为空")
// @NotEmpty(message = "会议名称不能为空")
 @ApiModelProperty(value = "会议名称", required = true)
 private String name;

3. 在Controller方法中启动校验规则指定要使用的分组名:

    @ApiOperation("新增会议基础信息")
    @PostMapping("/meeting")
    public MeetingBaseInfoDto createMeetingBase(@Validated({ValidationGroups.Inster.class}) @RequestBody AddMeetingDto addMeetingDto){
        Long manageId=12334123L;
        MeetingBaseInfoDto meetingBase = meetingInformationService.createMeetingBase(manageId, addMeetingDto);
        return meetingBase;
    }
}

总结

以上内容满足基本开发没有什么问题!

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值