springboot2.4.2自定义错误页面和客户端json数据完全整合
错误页面定制(在有模板引擎的情况下):
有模板的支持下: 在templates文件夹下 建立 error文件夹
在error文件夹下
404.html
500.html
过滤器:
过滤器的目的是为了获取当前请求出错的URL存入Header出错之后跳转/error可以从response.getHeader(“URL”);获取到出错的请求路径并且返回
package com.baojiaren.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @author ✎ℳ๓₯㎕.倾心❀、
* @create 2021-05-08-20:45
*/
@Component
public class MyFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("初始化过滤器:", filterConfig.getFilterName());
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//对请求进行预处理
logger.info("过滤器开始对请求进行预处理:");
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response= (HttpServletResponse) servletResponse;
// 获取当前请求的URL
StringBuffer url = request.getRequestURL();
//把当前请求的URL存入Header 返回
response.setHeader("URL", url.toString());
//通过 doFilter 方法实现过滤功能
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
logger.info("销毁过滤器");
}
}
工具类
package com.baojiaren.utils;
import org.springframework.http.HttpStatus;
import javax.servlet.http.HttpServletRequest;
/**
* @author ✎ℳ๓₯㎕.倾心❀、
* @create 2021-05-08-0:00
*/
public class HttpStatusUtil {
/**
* 获取请求状态码
* @param request
* @return
*/
public static HttpStatus getStatus (HttpServletRequest request){
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
} else {
try {
return HttpStatus.valueOf(statusCode);
} catch (Exception var4) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
}
}
}
错误消息的定制:
package com.baojiaren.controller;
import com.baojiaren.utils.HttpStatusUtil;
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* 全局异常拦截处理定制错误页面和返回客户端数据
*
* @author ✎ℳ๓₯㎕.倾心❀、
* @create 2021-05-07-22:49
*/
@ControllerAdvice
@Controller
@RequestMapping(value = "/error")
public class MyGlobalExceptionHandler {
@ExceptionHandler(Exception.class)
@RequestMapping(produces = {"text/html"})//返回给浏览器
public Object customException(HttpServletRequest request, HttpServletResponse response, Object o, Exception e) {
ModelAndView model = new ModelAndView();
// 获取请求头判断是浏览器请求还是客户端请求
String head = request.getHeader("User-Agent");
HttpStatus status = HttpStatusUtil.getStatus(request);
// 获取请求出错的URL
String path = response.getHeader("URL");
// 判断是否浏览器发送的请求 浏览器的请求头一般为Mozilla 其他为客户端应用程序
if (head.startsWith("Mozilla")) {
System.out.println("Mozilla============");
//携带错误数据信息到页面
model.addObject("timestamp", new Date());
model.addObject("statusCode", status.value());
model.addObject("error", status.getReasonPhrase());
model.addObject("path", path);
model.addObject("exception", e.getMessage());
int i = status.value() / 100;//判断是4xx还是5xx错误
if (i == 4) {
model.setViewName("error/4xx");//使用自己定制的错误页面
} else if (i == 5) {
model.setViewName("error/5xx");//使用自己定制的错误页面
}
return model;
} else {
// 返回客户端json数据
Map<String, Object> map = new HashMap<>();
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity(status);
} else {
map.put("error", status.getReasonPhrase());
map.put("timestamp", new Date());
map.put("statusCode", status.value());
map.put("path", path);
map.put("exception", e.getMessage());
return new ResponseEntity(map, status);
}
}
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:title="${statusCode}"></title>
</head>
<body>
<h1>
<span th:text="'错误提示:'+${error}"></span> <br>
<span th:text="${#dates.format(timestamp)}"></span> <br>
<span th:text="'状态码:'+${statusCode}"></span> <br>
<span th:text="'请求路径:'+${path}"></span> <br>
<span th:text="'错误提示:'+${error}"></span> <br>
<span th:if="${exception}!=null" th:text="'异常信息:'+${exception}"></span>
</h1>
</body>
</html>
这是为了测试就没有写css和js了
测试方法
package com.baojiaren.controller;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.web.bind.annotation.*;
/**
* @author ✎ℳ๓₯㎕.倾心❀、
* @create 2021-05-07-19:12
*/
@RestController
@RequestMapping("/api")
public class ClearCacheController {
@Caching(
evict = {
@CacheEvict(cacheNames = "emp", allEntries = true),
@CacheEvict(cacheNames = "dep", allEntries = true)
})
@GetMapping("/clearCache")
public String clearCacheAll() {
return "success";
}
// 测试方法
@GetMapping("/show")
public String show() {
int i = 10 / 0;
return "index";
}
}
浏览器测试:
500错误测试
404测试:
应用程序测试:
这里使用的是Postman
404测试
500测试