简介
springboot的大部分错误,都可以抛出异常,然后全局用@ControllerAdvice
注解的类捕获,然后自定义错误页面。但是404页面通常是不抛异常的,如果要自定义404错误页面,通常只有两种方法:
- 通过
spring.mvc.throw-exception-if-no-handler-found=true
、spring.web.resources.add-mappings=false
配置,让springboot遇到404的时候,抛出异常,这样就可以全局捕获了。优点是方便,代码简单。缺点就是一旦你启用了spring.web.resources.add-mappings=false
,你resources/static/
等目录下的静态文件就访问不了了。所以这个方法适合只做API接口的springboot项目。 - 自己实现
/error
。优点是自由度高,缺点是略微入侵了一点springboot,部分代码理解起来比较累。
下面演示这两种方法的代码:
方法一
- 把
spring.mvc.throw-exception-if-no-handler-found=true
、spring.web.resources.add-mappings=false
加到你的application.properties配置文件中。 - 全局捕获404异常,然后根据请求类型是HTML还是JSON来返回不同的错误页面。代码如下:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(NoHandlerFoundException.class)
public String noFindErr(HttpServletRequest request, HttpServletResponse response, Exception exception, Model model) {
if(model==null){
//api请求,返回JSON等错误信息
String res = "json错误信息";
try {
response.setHeader("Content-Type", "application/json;charset=UTF-8");
OutputStream outputStream = response.getOutputStream();
outputStream.write(res.getBytes());
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}else{
//模板引擎页面,返回一个404网页
model.addAttribute("errorMsg","页面不存在");
return "404";
}
}
}
方法二
继承springboot的ErrorController
,然后覆盖原有/error
页面的逻辑。代码如下:
@Controller
@RequestMapping({"${server.error.path:${error.path:/error}}"})
public class ErrorPageController implements ErrorController {
@RequestMapping(
produces = {"text/html"}
)
public String errorHtmlPage(HttpServletRequest request, HttpServletResponse response, Model model) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == 404) {
//请求类型是HTML,返回thymeleaf 404页面模板
return "404";
}
//其他错误,返回自定义的其他错误模板
return "error";
}
@RequestMapping
@ResponseBody
public void errorJsonPage(HttpServletRequest request, HttpServletResponse response, Model model) {
if (response.getStatus() == 404) {
//是404错误,返回404 JSON
return "this is 404 err json"
} else {
//其他错误,返回自定义的JSON
return "this is other err json"
}
}
}
上面的代码中,第一个method是处理HTML请求(需要返回一个HTML网页)的,第二个method是处理HTML之外的请求的,最常见的就是各种JSON API(返回结果是一个JSON字符串)。
总结
如果你的springboot项目使用了类似thymeleaf之类的模板引擎,并且有返回HTML网页的场景,那么强烈推荐使用第二种办法。如果你的springboot项目只是单纯的作为API Server来使用,那么方法一扩展性更好。