统一异常处理和返回参数封装

统一异常处理类

代码中无论是业务成功或者失败,都需要封装返回对象,目前代码中都是哪里用到就在哪里进行封装,因此我们可以封装返回对象,以下是代码:

@Data
public class Result<T> {

    private String code;

    private String message;

    private T data;

    public Result(T code, T message, T data) {
        this.code = String.valueOf(code);
        this.message = String.valueOf(message);
        this.data = data;
    }

    // 请求成功,指定data
    public static <T> Result<T> success(T data) {
        Result<T> tResult = (Result<T>) new Result<>(ResultEnum.SUCCESS.getCode(), ResultEnum.SUCCESS.getMessage(), data);
        return tResult;
    }

    // 请求成功,指定data和指定message
    public static <T> Result<T> success(String message, T data) {
        Result<T> tResult = (Result<T>) new Result<>(ResultEnum.SUCCESS.getCode(), message, data);
        return tResult;
    }

    // 请求失败
    public static Result<?> failed() {
        return new Result<>(ResultEnum.FAILED.getCode(), ResultEnum.FAILED.getMessage(), null);
    }

    // 请求失败,指定message
    public static Result<?> failed(String message) {
        return new Result<>(ResultEnum.FAILED.getCode(), message, null);
    }

    // 请求失败,指定code和message
    public static Result<?> failed(String code, String message) {
        return new Result<>(code, message, null);
    }
}

返回对象枚举类:

public enum ResultEnum {
    SUCCESS("200", "请求成功"),
    FAILED("500", "请求失败");

    private String code;

    private String message;

    ResultEnum(String code, String message) {
        this.code = code;
        this.message = message;
    }

    public String getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    @Override
    public String toString() {
        String resultMessage = code + ":" + message;
        return resultMessage;
    }
}

统一异常捕获

可以给controller层的方法加上切面来统一处理异常,简化代码中出现的大量try()catch()语句;

@RestControllerAdvice注解(@ControllerAdvice也可以),用来定义controller层的切面,添加@Controller注解的类中的方法执行都会进入该切面,同时我们可以使用@ExceptionHandler来对不同的异常进行捕获和处理,对于捕获的异常,我们可以进行日志记录,并且封装返回对象。

import org.example.mongodemo.domain.Result;
import org.example.mongodemo.domain.ResultEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.client.HttpClientErrorException;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

// 使用@RestControllerAdvice和@ControllerAdvice都是可以的
// @RestControllerAdvice(basePackages = {"org.example.ctrl", "org.example.ctrl", .....}), 指定包路径进行切面,可以指定多个包
// @RestControllerAdvice(basePackageClasses = TestController.class) , 指定Contrller.class进行切面
// @RestControllerAdvice 不带参数默认覆盖所有添加了@Controller注解的类
@RestControllerAdvice
public class MyControllerAdviceHanlder {

    @Autowired
    HttpServletRequest httpServletRequest;

    /**
     * 日志
     */
    private static final Logger logger = LoggerFactory.getLogger(MyControllerAdviceHanlder.class);

    private void logErrorPrint(Exception e){
        // 组装日志内容
        String logInfo = String.format("报错API URL: %S, error = ", httpServletRequest.getRequestURI(), e.getMessage());
        // 打印日志
//        System.out.println(logInfo);
        logger.info(logInfo);
    }

    /**
     * {@code @RequestBody} 参数校验不通过时抛出的异常处理
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException exception) {
        // 打印日志
        logErrorPrint(exception);
        // 组织异常信息,可能存在多个参数校验失败
        BindingResult bindingResult = exception.getBindingResult();
        StringBuilder sb = new StringBuilder("校验参数失败:");
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
       sb.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage()).append(", ");
        }
        return Result.failed(ResultEnum.FAILED.getCode(), sb.toString());
    }

    /**
     * Unchecked类型异常
     * 包括:ArithmeticException,NullPointerException,ClassCastException,IllegalArgumentException,IllegalStateException,ArrayIndexOutOfBoundsException异常
     *
     * @param exception
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    protected Result serviceException(RuntimeException exception) {
        logErrorPrint(exception);
        return Result.failed(exception.getMessage());
    }

    /**
     * 其他异常(checked类型异常)
     *
     * @param exception
     * @return
     */
    @ExceptionHandler({HttpClientErrorException.class, IOException.class, Exception.class})
    protected Result serviceException(Exception exception) {
        logErrorPrint(exception);
        return Result.failed(exception.getMessage());
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值