使用@ControllerAdvice全局异常捕获

 1.目录结构:

2.TestController代码:

import com.microview.zuul.exception.BusinessException;
import com.microview.zuul.vo.requestVo.UserInfo;
import org.springframework.http.HttpStatus;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value = "/testDemo")
public class TestController {

  @RequestMapping(value = "/err", method = RequestMethod.GET)
  public void error() {
    throw new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.value(), "手动抛出异常信息");
  }

  @RequestMapping(value = "/err2", method = RequestMethod.POST)
  public void error2(@Validated @RequestBody UserInfo userInfo) {
    throw new NullPointerException();
  }

  @RequestMapping(value = "/err3", method = RequestMethod.GET)
  public int error3() {
    int a = 10 / 0;
    return a;
  }
}

 

3.BusinessException代码:

import org.springframework.http.HttpStatus;

/**
 * 自定义异常
 */

public class BusinessException extends RuntimeException {

  private int code = HttpStatus.INTERNAL_SERVER_ERROR.value();

  public BusinessException(int code, String message) {
    super(message);
    this.code = code;
  }

  public int getCode() {
    return this.code;
  }
}

 

4.GlobalExceptionHandler代码:

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.microview.zuul.vo.responseVo.ResponseVo;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

/**
 * 全局异常控制类
 */

@ControllerAdvice
public class GlobalExceptionHandler {


  /**
   * 表单验证异常处理,该异常来自于表单验证框架 Hibernate validation,当字段验证未通过时会抛出此异常。
   */
  @ExceptionHandler(BindException.class)
  public ModelAndView methodArgumentNotValidExceptionException(HttpServletRequest request,
                                                               BindException exception,
                                                               HttpServletResponse response) {

    printStackTraceMethod(exception);

    return processExceptionMethod(request,
                                  response,
                                  exception.getClass().getSimpleName(),
                                  HttpStatus.BAD_REQUEST.value(),
                                  exception.getBindingResult().getFieldError().getDefaultMessage());
  }

  /**
   * 业务异常处理,手动抛出的BusinessException异常
   */
  @ExceptionHandler(value = BusinessException.class)
  private ModelAndView errorHandler(HttpServletRequest request, BusinessException exception, HttpServletResponse response) {

    printStackTraceMethod(exception);

    return processExceptionMethod(request, response, exception.getClass().getSimpleName(), exception.getCode(), exception.getMessage());
  }

  /**
   * 程序运行过程中出现的未知异常统一处理
   */
  @ExceptionHandler(value = Exception.class)
  public ModelAndView errorHandler(HttpServletRequest request, Exception exception, HttpServletResponse response) {

    printStackTraceMethod(exception);

    return processExceptionMethod(request, response, exception.getClass().getSimpleName(), HttpStatus.INTERNAL_SERVER_ERROR.value(), "系统繁忙,请稍后再试!");
  }

  /**
   * 处理异常
   */
  private ModelAndView processExceptionMethod(HttpServletRequest request, HttpServletResponse response, String error, int httpCode, String message) {

    ResponseVo responseVo = new ResponseVo(null, httpCode, message);

    return sendExceptionInfoToWebMethod(request, response, responseVo);
  }

  /**
   * 异常输出给调用者
   */
  private ModelAndView sendExceptionInfoToWebMethod(HttpServletRequest request, HttpServletResponse response, ResponseVo responseVo) {

    if (!(request.getHeader("accept").contains("application/json") || (request.getHeader("X-Requested-With") != null &&
                                                                          request.getHeader("X-Requested-With").contains("XMLHttpRequest")
                                                                         )
       )) {

      ModelAndView modelAndView = new ModelAndView("error");
      modelAndView.addObject("exception", responseVo);
      return modelAndView;

    } else {

      response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
      response.setCharacterEncoding("UTF8");
      response.setHeader("Content-Type", "application/json");
      try {
        response.getWriter().write(JSONObject.toJSONString(responseVo, SerializerFeature.WriteMapNullValue));
      } catch (IOException e) {
        e.printStackTrace();
      }
      return null;

    }
  }

  /**
   * 打印异常信息,便于查看异常具体信息
   */
  private void printStackTraceMethod(Exception e) {
    e.printStackTrace();
  }
}

5.UserInfo代码:

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import lombok.Data;



@Data
public class UserInfo {

  @NotNull(message = "年龄不能为空")
  @Max(value = 130, message = "年龄不能超过130岁")
  @Min(value = 0, message = "年龄不能小于0岁")
  private Integer userAge;

  @NotBlank(message = "名字不能为空")
  private String userName;

}

6.ResponseVo代码:

import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;
import java.util.Optional;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.http.HttpStatus;

/**
 * 统一返回给调用者的数据格式
 */

@Data
@AllArgsConstructor
public final class ResponseVo<T> implements Serializable {

  private static final long serialVersionUID = -1472019435018714147L;

  @ApiModelProperty(value = "接口返回数据")
  private T data;

  @ApiModelProperty(value = "接口错误码")
  private Integer code;

  @ApiModelProperty(value = "接口消息")
  private String message;

  /**
   * 调用成功标识
   */
  public static <T> ResponseVo<T> success(T data) {
    return new ResponseVo<>(data, HttpStatus.OK.value(), "请求成功");
  }

  /**
   * 调用成功标识
   */
  public static <T> ResponseVo<T> success() {
    return new ResponseVo<>(null, HttpStatus.OK.value(), "请求成功");
  }

  /**
   * 调用失败标识
   */
  public static <T> ResponseVo<T> fail(int code, String message) {
    return new ResponseVo<>(null, code, Optional.ofNullable(message).orElse("请求失败"));
  }

  /**
   * 调用失败标识
   */
  public static <T> ResponseVo<T> fail(String message) {
    return new ResponseVo<>(null, null, Optional.ofNullable(message).orElse("请求失败"));
  }

  /**
   * 调用失败标识
   */
  public static <T> ResponseVo<T> fail() {
    return new ResponseVo<>(null, null, "系统错误");
  }
}

 

7.error.ftl代码:

<!DOCTYPE html>
<html>
<head>
    <meta name="robots" content="noindex,nofollow" />
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <style>
        h2{
            color: #4288ce;
            font-weight: 400;
            padding: 6px 0;
            margin: 6px 0 0;
            font-size: 18px;
            border-bottom: 1px solid #eee;
        }

        /* Exception Variables */
        .exception-var table{
            width: 100%;
            max-width: 500px;
            margin: 12px 0;
            box-sizing: border-box;
            table-layout:fixed;
            word-wrap:break-word;
        }
        .exception-var table caption{
            text-align: left;
            font-size: 16px;
            font-weight: bold;
            padding: 6px 0;
        }
        .exception-var table caption small{
            font-weight: 300;
            display: inline-block;
            margin-left: 10px;
            color: #ccc;
        }
        .exception-var table tbody{
            font-size: 13px;
            font-family: Consolas,"Liberation Mono",Courier,"微软雅黑";
        }
        .exception-var table td{
            padding: 0 6px;
            vertical-align: top;
            word-break: break-all;
        }
        .exception-var table td:first-child{
            width: 28%;
            font-weight: bold;
            white-space: nowrap;
        }
        .exception-var table td pre{
            margin: 0;
        }
    </style>
</head>
<body>

<div class="exception-var">
    <h2>错误页面</h2>
    <table>
        <tbody>
        <tr>
            <td>错误码</td>
            <td>
                ${(exception.code)!}
            </td>
        </tr>
        <tr>
            <td>响应数据</td>
            <td>
                ${(exception.data)!}
            </td>
        </tr>
        <tr>
            <td>提示信息</td>
            <td>
                ${(exception.message)!}
            </td>
        </tr>
        </tbody>
    </table>
</div>
</body>
</html>

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值