方法一:Spring Boot 将所有的错误默认映射到/error, 实现AbstractErrorController.
代码如下
@Controller
public class ErrorController extends AbstractErrorController {
private static final String ERROR_PATH = "/error";
Log log = LogFactory.getLog(ErrorController.class);
@Autowired
ObjectMapper objectMapper;
public ErrorController() {
super(new DefaultErrorAttributes());
}
@RequestMapping(ERROR_PATH)
public ModelAndView getErrorPath(HttpServletRequest request, HttpServletResponse response) {
Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
request, false));
Throwable cause = getCause(request);
int status = (Integer) model.get("status");
//错误信息
String message = (String) model.get("message");
//友好提示
String errorMessage = getErrorMessage(cause);
//请求地址
String requestPath = (String) model.get("path");
//后台打印日志信息方方便查错
log.info(status + ":" + message, cause);
log.info("requestPath" + ":" + requestPath);
log.info(message, cause);
response.setStatus(status);
if (isJsonRequest(request)) {
Result result = new Result();
result.setCode(status);
result.setMsg(message);
writeJson(response, result);
return null;
} else {
ModelAndView view = new ModelAndView("/error.html");
view.addAllObjects(model);
view.addObject("status", status);
view.addObject("errorMessage", errorMessage);
view.addObject("cause", cause);
return view;
}
}
/**
* 判断客户端发起的是页面渲染请求还是Json 请求
*
* @param request
* @return
*/
protected boolean isJsonRequest(HttpServletRequest request) {
String requestUri = request.getRequestURI();
if (requestUri.endsWith(".json")) {
return true;
} else {
return (request.getHeader("accept").contains("application/json") || (request.getHeader("X-Requested-With") != null
&& request.getHeader("X-Requested-With").contains("XMLHttpRequest")));
}
}
protected void writeJson(HttpServletResponse response, Object error) {
response.setContentType("application/json;charset=utf-8");
try {
response.getWriter().write(objectMapper.writeValueAsString(error));
} catch (IOException e) {
}
}
/**
* 获取自定义异常信息
*
* @param ex
* @return
*/
protected String getErrorMessage(Throwable ex) {
if (ex instanceof MyException) {
return ex.getMessage();
}
return "服务器错误,请联系管理员";
}
/**
* 获取应用系统的异常信息
*
* @param request
* @return
*/
protected Throwable getCause(HttpServletRequest request) {
Throwable error = (Throwable) request.getAttribute("javax.servlet.error.exception");
if (error != null) {
while (error instanceof ServletException && error.getCause() != null) {
error = error.getCause();
}
}
return error;
}
@Override
public String getErrorPath() {
return null;
}
}
方法二:使用注解@ControllerAdvice
编写一个全局异常处理的类,这个类里面可以分门别类处理各种异常,可以对每一种异常提供一种自定义页面,使用户体验更加友好。
代码如下:
@ControllerAdvice
public class GlobalExceptionHandler {
private static final String ERROR_PATH = "/error";
Log log = LogFactory.getLog(ErrorController.class);
@Autowired
ObjectMapper objectMapper;
@ExceptionHandler(value = Exception.class)
public ModelAndView defaultErrorHandler(HttpServletRequest request, HttpServletResponse response,
Exception e) throws Exception {
log.info("GlobalExceptionHandler");
if (isJsonRequest(request)) {
Result result = new Result();
result.setMsg(e.getMessage());
writeJson(response, result);
return null;
} else {
ModelAndView view = new ModelAndView("/error.html");
view.addObject("errorMessage", e.getMessage());
view.addObject("cause", e);
return view;
}
}
方法三:添加自定义错误页面
1)html静态页面:在resources/public/error/ 下定义 如添加404页面: resources/public/error/404.html页面,中文注意页面编码
2)模板引擎页面:在templates/error/下定义 如添加5xx页面: templates/error/5xx.ftl