一、404
404错误进不了SpringMVC异常处理(ExceptionHandlerAdvice),会默认进入SpringBoot异常处理:BasicErrorController
1.自写一个ExceptionController类继承BasicErrorController,重写其两个方法
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
//浏览器直接输入url访问,会进入这里;这里可以返回json数据,也可以跳转到404.html、500.html
}
和
@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
//前端触发访问后端接口,会进入这里,直接返回json数据(code和messageText)
}
public class ExceptionController extends BasicErrorController{
private static final Logger log = LoggerFactory.getLogger("ExceptionController");
@Autowired
private ApplicationContext applicationContext;
private static class HtmlResourceView implements View {
private Resource resource;
HtmlResourceView(Resource resource) {
this.resource = resource;
}
@Override
public String getContentType() {
return MediaType.TEXT_HTML_VALUE;
}
@Override
public void render(Map<String, ?> model, HttpServletRequest request,
HttpServletResponse response) throws Exception {
response.setContentType(getContentType());
FileCopyUtils.copy(this.resource.getInputStream(),
response.getOutputStream());
}
}
public ExceptionController(ErrorAttributes errorAttributes, ErrorProperties errorProperties, List<ErrorViewResolver> errorViewResolvers) {
super(errorAttributes, errorProperties, errorViewResolvers);
}
@Override
@RequestMapping(produces = "text/html")
public ModelAndView errorHtml(HttpServletRequest request,
HttpServletResponse response) {
//浏览器直接输入url访问,会进入这里;这里可以返回json数据,也可以跳转到404.html、500.html
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); //这里会去调用AbstractErrorController的方法
//ModelAndView view = new ModelAndView("error", model); //这里默认的页面必须写error
//1.先去(前缀/resources):/META-INF/resources/error/、/resources/error/、/static/error/、/public/error/,按照顺序找404.html
//2.如果没有则modelAndView = null,就会去找默认的页面:ErrorMvcAutoConfiguration的WhitelabelErrorViewConfiguration()
ModelAndView defView = new ModelAndView(); //自定义跳转到哪里的页面
String location = "classpath:/public/";
String viewName = "static/";
try {
Resource resource = this.applicationContext.getResource(location);
resource = resource.createRelative(viewName + status +".html");
if (resource.exists()) {
defView = new ModelAndView(new HtmlResourceView(resource), model);
}
} catch (Exception ex) {
}
return (modelAndView != null ? modelAndView : defView);
}
@Override
@RequestMapping
@ResponseBody
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
//前端触发访问后端接口,会进入这里,直接返回json数据(code和messageText)
Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
HttpStatus status = getStatus(request);
String message = body.get("message").toString();
Map<String, Object> map = new HashMap<>();
map.put("messageText", message);
map.put("code", status.value() + "");
return new ResponseEntity<>(map, status);
}
}
2.定义完自己的ExceptionController之后,还需要一个配置类:
需定义一个自己的错误控制器:ExceptionControllerConfig,让其先进入自定义异常处理类
@Configuration
@ConditionalOnWebApplication
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@AutoConfigureBefore(WebMvcAutoConfiguration.class)
@EnableConfigurationProperties(ResourceProperties.class)
public class ExceptionControllerConfig {
private final ServerProperties serverProperties;
private final List<ErrorViewResolver> errorViewResolvers;
public ExceptionControllerConfig(ServerProperties serverProperties, ObjectProvider<List<ErrorViewResolver>> errorViewResolversProvider) {
this.serverProperties = serverProperties;
this.errorViewResolvers = errorViewResolversProvider.getIfAvailable();
}
@Bean
public ExceptionController exceptionController(ErrorAttributes errorAttributes) {
return new ExceptionController(errorAttributes, this.serverProperties.getError(), this.errorViewResolvers);
}
}
二、500
1.会先进入ExceptionHandlerAdvice中,把捕获500的方法去掉,
就会进入BasicErrorController中,和404一样
三、我们可以自定义跳转到哪个文件夹,甚至哪个文件名
errorHtml方法中,跳转到404或500页面
具体跳转到哪个文件夹下:
分析源码所得:
1.先去(前缀/resources):/META-INF/resources/error/、/resources/error/、/static/error/、/public/error/,按照顺序找404.html
2.如果没有则modelAndView = null,就会去找默认的页面:ErrorMvcAutoConfiguration的WhitelabelErrorViewConfiguration()