日志功能类介绍
项目首页地址:https://blog.csdn.net/weixin_45019350/article/details/108869025
springboot项目自动导入日志的包,日志抽象层使用的是slf4j,日志实现使用的logback
一、首先编写配置文件
在application.yml的文件,写入配置内容
启动工程后我们可以发现工程目录结构下会多一个文件夹叫log这里专门存放日志文件
引入配置文件对SpringBoot中logging日志进行重新定义配置信息
二、编写日志类
1、编写一个日志信息类,我们通常采用的方式是使用spring中的aop(面向切面编程)来实现功能。
2、新建一个包叫aspect,新建一个类叫LogAspect日志类。
3、日志类中我们用注解@Aspect声明该类为一个切面类。
4、我们通过切面类中的前置通知和后置通知来获取相关日志信息。并把获取到的日志信息封装到实体类中。通过日志类对象打印出来。
相关注解介绍:
@Aspect:作用是把当前类标识为一个切面供容器读取
@Pointcut:Pointcut是植入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around:环绕增强,相当于MethodInterceptor
@AfterReturning:后置增强,相当于AfterReturningAdvice,方法正常退出时执行
@Before:标识一个前置增强方法,相当于BeforeAdvice的功能,相似功能的还有
@AfterThrowing:异常抛出增强,相当于ThrowsAdvice @After: final增强,不管是抛出异常或者正常退出都会执行
日志类:
@Aspect
@Component
public class LogAspect {
//获取日志类对象
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//定义切面方法
@Pointcut("execution(* com.ldf.demo.controller.*.*(..))")
public void log(){ }
//定义前置通知
@Before("log()")
public void doBefore(JoinPoint jp){
//通过获取request上下文对象来获取request对象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//获取id地址
String id = request.getRemoteAddr();
//获取url路径
String url = request.getRequestURL().toString();
//通过切面对象获取类名和方法名
String classMethod = jp.getSignature().getDeclaringTypeName() + "." + jp.getSignature().getName();
//获取参数
Object[] args = jp.getArgs();
//封装到实体类对象中,打印成日志
RequestLog log = new RequestLog(id, url, classMethod, args);
logger.info("Request : {}",log);
}
//定义后置通知
@After("log()")
public void doAfter(){
}
//定义后置增强方法,相当于AfterReturningAdvice,方法正常退出时执行
@AfterReturning(returning = "result",pointcut = "log()")
public void doAfterRuturn(Object result) {
logger.info("Result : {}" ,result);
}
//定义日志实体封装类
private class RequestLog{
private String url;
private String ip;
private String classMethod;
private Object[] args;
public RequestLog(String url, String ip, String classMethod, Object[] args) {
this.url = url;
this.ip = ip;
this.classMethod = classMethod;
this.args = args;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getClassMethod() {
return classMethod;
}
public void setClassMethod(String classMethod) {
this.classMethod = classMethod;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
@Override
public String toString() {
return "RequestLog{" +
"url='" + url + '\'' +
", ip='" + ip + '\'' +
", classMethod='" + classMethod + '\'' +
", args=" + Arrays.toString(args) +
'}';
}
}
}
自定义异常类介绍
自定义异常我们可以用注解@ControllerAdvice ,顾名思义,这是一个增强的 Controller。这是 SpringMVC 提供的功能,在 Spring Boot 中可以直接使用使用这个 Controller ,可以实现三个方面的功能:
全局异常处理
全局数据绑定
全局数据预处理
这里我们只做全局异常处理讲解。
一、定义一个异常处理类
在该类中,可以定义多个方法,不同的方法处理不同的异常,例如专门处理空指针的方法、专门处理数组越界的方法…,也可以直接向上面代码一样,在一个方法中处理所有的异常信息。
@ExceptionHandler 注解用来指明异常的处理类型,即如果这里指定为 NullpointerException,则数组越界异常就不会进到这个方法中来。
@ControllerAdvice
public class ControllerException {
//获取日志类
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//定义这是一个异常处理类方法Exception异常都会经过该方法
@ExceptionHandler(Exception.class)
public ModelAndView exceptionHandel(HttpServletRequest request,Exception e) throws Exception {
//错误信息打印成日志
logger.error("Request URL: {} Exception : {}",request.getRequestURL(),e);
//当标识了状态码的时候就不拦截,抛出交给虚拟机处理如:404,500等
if (AnnotationUtils.findAnnotation(e.getClass(), ResponseStatus.class)!=null){
throw e;
}
//定义返回的视图
ModelAndView mv = new ModelAndView();
mv.addObject("url",request.getRequestURL());
mv.addObject("exception",e);
mv.setViewName("error/error");
return mv;
}
}
二、自定义异常类
在Spring MVC中,我们可以通过几种方式设置HttpResponse的状态。
我们可以使用@ResponseStatus标记带有状态码和应返回原因的方法或异常类。在调用标记的处理程序方法时或引发指定的异常时,HTTP状态将设置为使用@ResponseStatus批注定义的状态。
带有@ResponseStatus注解的异常类会被ResponseStatusExceptionResolver 解析。可以实现自定义的一些异常,自定义异常实现方式很简单必须继承异常类实现对应的方法即可。
//没有找到状态码异常
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFountException extends RuntimeException{
public NotFountException() {
super();
}
public NotFountException(String message) {
super(message);
}
public NotFountException(String message, Throwable cause) {
super(message, cause);
}
}
Exception异常我们会交给异常处理类处理,RuntimeException异常我们会把它交给自定义异常类处理。