在发生异常的时候,如果是Filter 中的异常,使用@ControllerAdvice 中gen @ExceptionHandler 捕获异常是捕获不到的,所以spring boot 默认提供了另一种方式来解决
下面是在出现异常的时候,出现的错误的页面提示信息
在显示的时候,可能返回json 数据,可以根据实际的情况 ,返回html页面或者是 json 类型的数据
在spring boot 中错误默认是由BasicErrorController 类来处理的,该类中核心的两个方法,下面展示
@RequestMapping(produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView errorHtml(HttpServletRequest request,
HttpServletResponse response) {
HttpStatus status = getStatus(request);
Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes(
request, isIncludeStackTrace(request, MediaType.TEXT_HTML)));
response.setStatus(status.value());
ModelAndView modelAndView = resolveErrorView(request, response, status, model);
return (modelAndView != null) ? modelAndView : new ModelAndView("error", model);
}
@RequestMapping
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
return new ResponseEntity<>(body, status);
}
其中 getErrorAttributes 方法使用来获取错误信息的,错误信息包含五个信息 timestamp status error path message
其中 errorHtml 返回的是 具体的页面的数据,而 error 返回的是字符串的数据
在errorHtml 方法中, 通过resolver.resolveErrorView 来获取 ModelAndView 视图,如果没有获取到view ,则返回null
如果返回的是空,则会默认找error页面
但是在 resolverErrorView 方法中 还是调用的 resolver.resolveErrorView 来获取 ModelAndView
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status,
Map<String, Object> model) {
ModelAndView modelAndView = resolve(String.valueOf(status.value()), model);
if (modelAndView == null && SERIES_VIEWS.containsKey(status.series())) {
modelAndView = resolve(SERIES_VIEWS.get(status.series()), model);
}
return modelAndView;
}
用于获取 ModelAndView
会默认寻找 4xx 5xx 的页面
可以发现,获取获取所有的静态资源路径,并且返回,如果没有发现视图的名称,则会返回上面显示的信息
上面的配置,只能完成页面的显示,但是不能对 json 的数据,进行处理(不能对 timestamp status error path message操作)
对Json 数据进行处理(DefaultErrorAttribute)
/**
* 用于设置 自己的错误信息内容
*/
@Component
public class MyErrorAttribute extends DefaultErrorAttributes {
@Override
public Map<String, Object> getErrorAttributes(WebRequest webRequest, boolean includeStackTrace) {
// map 中有 timestamp status error path message 信息,可進行修改
Map<String, Object> map = super.getErrorAttributes(webRequest, includeStackTrace);
map.put("message","出错了");
map.remove("error");
return map;
}
}
对视图进行处理(ErrorViewResovler)
/**
* 用于操作 返回 视图名称
*/
@Component
public class MyErrorResolver implements ErrorViewResolver {
/**
* @param request
* @param status 状态
* @param model 表示的是默认的异常数据的五条数据,可以对数据进行修改
* @return
*/
@Override
public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
ModelAndView view = new ModelAndView("errorPage");
view.addObject("custommsg","出错啦");
view.addObject(model);
view.setStatus(status);
return view;
}
}
但是如果只对数据,进行操作,建议还是使用 DefaultErrorAttribute
对json 数据和 视图都进行操作(BasicErrorController)
在ErrorMvcAutoConfiguration 类中 有BasicErrorController
表示在生成BasicErrorController 的Bean 的时候, 需要加载ErrorController 类才可以
在使用的时候我们使用BasicErrorController ,因为该类已经实现了很多的方法。
@Component
public class MyErrorContoller extends BasicErrorController {
@Autowired
public MyErrorContoller(ErrorAttributes errorAttributes, ServerProperties serverProperties, List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes, serverProperties.getError(), errorViewResolvers);
}
@Override
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
HttpStatus status = getStatus(request);
// 获取异常中的五个数据
Map<String, Object> map = getErrorAttributes(
request, isIncludeStackTrace(request, MediaType.TEXT_HTML));
ModelAndView view = new ModelAndView("errapge");
view.addObject("message", "自定义异常类view 操作");
response.setStatus(status.value());
view.addObject(map);
return view;
}
@Override
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
Map<String, Object> body = getErrorAttributes(request,
isIncludeStackTrace(request, MediaType.ALL));
body.put("message", "自定义异常类 json 处理");
HttpStatus status = getStatus(request);
return new ResponseEntity<>(body, status);
}
}