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>