当系统发生异常时,自动跳转到我们自己定义的异常页面(404,500等)。完整测试demo
后端:spring boot
前端:Thymeleaf(简单使用)
404.html:
404
404
500.html:
500
500
首页index.html:
首页
首页
IndexController.java:
package com.beishanyao.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class IndexController {
@GetMapping("/")
public String index(){
//以下一行系统会抛出异常,因为不能除以0
int i = 10/0;
return "index";
}
}
在浏览器中输入:http://127.0.0.1:8081/ 显示如下表明500错误已被我们拦截。
故意输错地址为:http://127.0.0.1:8081/a 显示如下表明404错误被我们拦截。
error.html:
错误
错误
ControllerExceptionHandler.java:
package com.beishanyao.hander;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
* ControllerAdvice: 会拦截有【@Controller】标注的类
* @author beishanyao
*/
@ControllerAdvice
@Slf4j
public class ControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView exceptionHandler(HttpServletRequest request,Exception e){
log.error("Request URL : {}, Exception : {}",request.getRequestURL(),e);
ModelAndView mv = new ModelAndView();
mv.addObject("url",request.getRequestURL());
mv.addObject("exception",e);
//返回到 templates 下的 error/error 页面
mv.setViewName("error/error");
return mv;
}
}
注意注解 @Slf4j 为 Lombok 处理日志的注解,Lombok可以大大提高开发效率且简单好用,可以了解下。
在浏览器中输入:http://127.0.0.1:8081/ 显示如下表示拦截成功
同时,服务端会报如下错误:
我们可以把前端代码稍作修改,让错误显示到前端页面,这样的好处是报错之后不用跑到服务器上看错误日志了:
error.html:
错误
错误
访问:http://127.0.0.1:8080/ 显示如下
右键,查看源代码,发现错误日志打印出来了:
NotFoundException.java:
package com.beishanyao;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {
public NotFoundException() {
}
public NotFoundException(String message) {
super(message);
}
public NotFoundException(String message, Throwable cause) {
super(message, cause);
}
}
ControllerExceptionHandler.java:
package com.beishanyao.hander;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
/**
* ControllerAdvice: 会拦截有【@Controller】标注的类
* @author beishanyao
* @date 2020/1/10
*/
@ControllerAdvice
@Slf4j
public class ControllerExceptionHandler {
@ExceptionHandler(Exception.class)
public ModelAndView exceptionHandler(HttpServletRequest request,Exception e) throws Exception {
log.error("Request URL : {}, Exception : {}",request.getRequestURL(),e);
/**
* if模块
* 标注了 ResponseStatus 状态的异常,不在此处统一处理,直接抛出异常,让 springboot 本身处理
*/
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null) {
throw e;
}
ModelAndView mv = new ModelAndView();
mv.addObject("url",request.getRequestURL());
mv.addObject("exception",e);
//返回到 templates 下的 error/error 页面
mv.setViewName("error/error");
return mv;
}
}
在浏览器中输入:http://127.0.0.1:8081/ 显示如下表示拦截成功