异常处理
在平时访问页面时,可能会因为各种问题导致无法访问,如果页面出现白页,对于访问用户并不友好,那么是否可以将页面访问错误时,提高页面可读性呢?
答案是肯定的。我们可以先定制一个error,404,500三个html文件,然后在后端handler包下新建ControllerExceptionHandler类
@ControllerAdvice
public class ControllerExceptionHandler {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler
public ModelAndView exceptionHander(HttpServletRequest request, Exception e) throws Exception {
logger.error("Request URL: {}, Exception: {}",request.getRequestURI(),e.getMessage());
if(AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null){
throw e;
}
ModelAndView mv = new ModelAndView();
mv.addObject("url",request.getRequestURI());
mv.addObject("exception",e.getMessage());
mv.setViewName("error/error");
return mv;
}
}
注意这里的引用
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ControllerAdvice,是Spring3.2提供的新注解,它是一个Controller增强器,可对controller中被 @RequestMapping注解的方法加一些逻辑处理。最常用的就是异常处理。
if(AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class) != null){
throw e;
}
在已有状态码下,会根据错误状态码进行后续操作
@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);
}
}
这里是先继承一个RuntimeException,再加上@ResponseStatus(HttpStatus.NOT_FOUND),表明这是一个404状态码。当博客为空时,跳转至404界面。
日志处理
1.日志记录内容
请求url
访问者ip
调用方法classMethod
参数args
返回内容
2.日志记录类
@Aspect
@Component
public class LogAspect {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//@Pointcut表明这是一个切面,execution()里规定这个切面拦截哪些内容 *(..)任何参数的所有方法
@Pointcut("execution(* com.lh.web.*.*(..))")
public void log(){
}
@Before("log()")
public void doBefore(){
logger.info("----before-----");
}
@After("log()")
public void doAfter(){
logger.info("----after-----");
}
//记录返回内容
//returning = "res" 返回的是什么东西
@AfterReturning(returning = "res",pointcut = "log()")
public void doAfterReturn(Object res){
logger.info("返回结果:{}" ,res);
}
}
切面注解需要加上@Aspect @Component
在controller里进行测试
启动结果
当要想获得自己想要记录的东西时,在日志记录类中定义一个内部类
对代码进行扩充
//url和ip须通过http获取
//类名和方法名通过JoinPoint获取
@Before("log()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String url = request.getRequestURI();
String ip = request.getRemoteAddr();
//getDeclaringTypeName()类名 getName()方法名
String classMethod = joinPoint.getSignature().getDeclaringTypeName() +
"." + joinPoint.getSignature().getName();
//拿请求参数
Object[] args = joinPoint.getArgs();
RequestLog requestLog = new RequestLog(url,ip,classMethod,args);
logger.info("----before-----"+"请求内容:{}",requestLog);
}
启动后输入
得到结果
如果输入localhost,则会出现
ip=0:0:0:0:0:0:0:1
知识小结
JoinPoint
JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象.
常用api
方法名 | 功能 |
---|---|
Signature getSignature(); | 获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 |
joinPoint.getSignature().getDeclaringTypeName() | 获取类名 |
joinPoint.getSignature().getName() | 获取方法名 |
Object[] getArgs(); | 获取传入目标方法的参数对象 |
Object getTarget(); | 获取被代理的对象 |
Object getThis(); | 获取代理对象 |
url和ip须通过http获取
在一个方法里面如果想获取请求信息,需要从请求上下文获取request,或者在参数列表使用HttpServletRequest request
步骤
- 在方法中获取请求上下文
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
- 获取请求request
HttpServletRequest request = attributes.getRequest();
- 获取参数
String url = request.getRequestURI();
String ip = request.getRemoteAddr();