1. 异常页配置
1.1 对于404和500错误
SpringBoot会自动拦截这两个异常,去resources–> templates --> error下找404.html和500.html
1.2 自定义异常页
需要自定义拦截器,根据自定义错误跳转到相应的错误页面
① 自定义拦截器,使用@ControllerAdvice + @ExceptionHandler 进行全局的 Controller 层异常处理
@ControllerAdvice 注解,用于拦截全局的Controller的异常,跳转到error页面
package com.javaer.blog.handler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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
public class ControllerExceptionHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(Exception.class)
public ModelAndView exceptionHander(HttpServletRequest httpServletRequest, Exception e){
logger.error("Request URL: {}, Exception: {}", httpServletRequest.getRequestURI(), e);
ModelAndView mv = new ModelAndView();
mv.addObject("url",httpServletRequest.getRequestURI());
mv.addObject("exception",e);
mv.setViewName("error/error");
return mv;
}
}
② 自定义NotFoundException异常,状态码标记为找不到
注意,在第一步拦截了所有的异常,我们需要对异常进行判断,不处理已经标明了状态码的异常,把标明了状态码的异常交个springBoot本身来处理
package com.javaer.blog.handler;
@ControllerAdvice
public class ControllerExceptionHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(Exception.class)
public ModelAndView exceptionHander(HttpServletRequest httpServletRequest, Exception e) throws Exception {
logger.error("Request URL: {}, Exception: {}", httpServletRequest.getRequestURI(), e);
if(AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class)!=null){
throw e;
}
ModelAndView mv = new ModelAndView();
mv.addObject("url",httpServletRequest.getRequestURI());
mv.addObject("exception",e);
mv.setViewName("error/error");
return mv;
}
}
再自定义NotFoundException,状态码为找不到
package com.javaer.blog.Exception;
@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);
}
}
使用
package com.javaer.blog.web;
@Controller
public class indexController {
@RequestMapping("/")
public String index(){
String blog = null;
if(blog == null){
throw new NotFoundException("博客不存在");
}
return "index";
}
}
2. 日志处理
希望在日志记录
① 请求的url
② 访问者ip
③ 调用的方法
④ 参数
⑤ 返回内容
做法:
不用在每个controller里面进行内容记录,而是使用aop来针对切面的前后来处理
package com.javaer.blog.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Aspect
@Component
public class LogAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private class ReqeustLog {
private String url;
private String ip;
private String classMethod;
private Object[] args;
public ReqeustLog(String url, String ip, String classMethod, Object[] args) {
this.url = url;
this.ip = ip;
this.classMethod = classMethod;
this.args = args;
}
@Override
public String toString() {
return "ReqeustLog{" + "url='" + url + '\'' + ", ip='" + ip + '\'' + ", classMethod='" + classMethod + '\'' + ", args=" + Arrays.toString(args) + '}';
}
}
//定义一个切面,针对web下的所有类的所有方法
@Pointcut("execution(* com.javaer.blog.web.*.*(..))")
public void log(){
}
//切面之前
@Before("log()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String classMethod = joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName();
ReqeustLog reqeustLog = new ReqeustLog(request.getRequestURL().toString(), request.getRemoteAddr(), classMethod, joinPoint.getArgs());
logger.info("Rquest ----- {}", reqeustLog);
}
//切面之后
@After("log()")
public void doAfter(){
}
//返回之后
@AfterReturning(returning = "result",pointcut = "log()")
public void doAfterReturn(Object result){
logger.info("Return ------ {}",result );
}
}