spring里面的日志是怎么运作的,想记录日志需要什么配置
:使用Spring AOP对action做日志管理
? 如果是想拦截action对action做日志管理,基本和上面差不多,但是要注意。以下几点
首先还是要写一个普通类,不过此类中的方法需要传入参数。 比如
??? package chen.hui.log
??? import org.aspectj.lang.JoinPoint;
???? public classs MyLog{
?????? //在类里面写方法,方法名诗可以任意的。此处我用标准的before和after来表示
//此处的JoinPoint类可以获取,action所有的相关配置信息和request等内置对象。
????? public void before(JoinPoint joinpoint){
??????? joinpoint.getArgs();//此方法返回的是一个数组,数组中包括request以及ActionCofig等类对象
??????? System.out.println("被拦截方法差物调用之前调用此方法,输出此语句");
??????}
????? public void after(JoinPoint joinpoint){
? System.out.println("被拦截方法调用之后调用此方法,输出此语句");
??????}
??? }
?????其次我们在写一个action类作为被拦截类(Spring的AOP就是拦截这个类里面的方法)
???? package chen.hui.log
???? public class LoginAction{//此类中方法可以写任意多个。我只写一个
? public void test(){
??????? Sytem.out.println("测试类的test方法被调用");
??}
?????}
???? 最后进行配置文件的编写。在Spring的配置文件中我们需要进行几句话的配置
??????? bean id="testLog" class="chen.hui.log.MyLog"/bean?!--将日志类注入到bean中。--
?????
aop:config
? ???aop:aspect id="b" ref="testLog"!--调用日志类--
??? aop:pointcut id="log" expression="execution(* chen.hui.log.*.*(..))"/!--配置在log包下所有的类在调用之前都会被拦截--
????aop:before pointcut-ref="log" method="before"/!--在log包下面所有的类的所有方法被调用之前都调用MyLog中的before方法--
????aop:after pointcut-ref="log" method="after"/!--在log包下面所有的类的所有方法被调用之前都调用MyLog中的after方法--
????/aop:aspect
???
??????? ?/aop:config
?
??????? 除了参数外其他地方基本和普通类相似。
?????? 需要注意的是:普通类可以监控单一的类,而action在配置文件中只能到包名而不能到action的类名。不然会报错。就是说如果要记录日志就要记录所有的action而不能记录清余其中一个,这是我答庆滚试了好久得出的结果。如果有高手知道怎么记录单一的action或者有朋友有任何问题可以留下联系方式,大家相互交流,共同进步。
?
springboot 动态日志管理(actuator)
引入依赖
配置文件添加
management.endpoints.web.exposure.include= loggers
之后访问
即可看或搭到每个文件的日志级别
查看配梁某个目录的日志级别
]( {目录名}
可以配置指定目录的衫卖拿日志级别
post请求修改指定目录日志级别:
{目录名}
请求提
再次查看此目录的日志级别发现已被修改
]( {目录名}
如何用Spring进行日志管理
可以用spring aop 进行日志管理,下面是我博客中的内容,项目中也是这么用,只是复杂度更高:
第一步:导包,可以参考:spring4 项目搭建
还需要添加AspectJ(java中最流行的aop框架):
dependency
groupIdorg.springframework/groupId
artifactIdspring-aspects/artifactId
version4.2.2.RELEASE/version
/dependency
第二步:配置bean文件
配置aop可以通过注解,也可以通过配置文件,项目中建议有配置文件,这样便于修改。我先讲解注解方法
配置自动扫描和AspectJ框架
!-- 配置自动扫描的aop包 --
context:component-scan base-package="com.spring.aop"/
!-- 配置 AspectJ --
aop:aspectj-autoproxy/aop:aspectj-autoproxy
如果aop显示不出来就先xml头文件中导入(我相信大家会导入的,就不多说了)
xmlns:aop=""
第三步渣团:业务代码,模拟用户的操作
业务代码AopService
package com.spring.aop;
import org.springframework.stereotype.Service;
@Service
public class AopService {
// 用户登入
public void login(){
System.out.println("登入成功");
}
// 用户退出
public void loginOut(){
System.out.println("用户退出系统");
}
// 用户操作
public void writeABlog(){
System.out.println("用户编写博客");
} 粗型
// 用户操作
public void deleteABlog(){
System.out.println("用户删除博客");
}
}
切面代码:
package com.spring.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LogAspect {
@After("execution(public void com.spring.aop.AopService.*(..))")
public void afterMethod(JoinPoint joinPoint) {
String opreate = joinPoint.getSignature().getName();
System.out.println("ITDragon opreate " + opreate);
} 岩梁猜
}
测试类:
package com.spring.aop;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AopTest {
private ApplicationContext ctx = null;
{
ctx = new ClassPathXmlApplicationContext("beans.xml");
}
@Test
public void aopTest(){
AopService aopService = (AopService) ctx.getBean("aopService");
aopService.login();
aopService.writeABlog();
aopService.deleteABlog();
aopService.loginOut();
}
}
测试结果:
登入成功
ITDragon opreate login
用户编写博客
ITDragon opreate writeABlog
用户删除博客
ITDragon opreate deleteABlog
用户退出系统
ITDragon opreate loginOut
@Before: 前置通知, 在方法执行之前执行
@After: 后置通知, 在方法执行之后执行
@AfterRunning: 返回通知, 在方法返回结果之后执行,方法必须有返回值。需要添加returning = "result",其中result就是返回结构,
@AfterReturning(pointcut="execution(public void com.spring.aop.AopService.*(..))",returning="result")
@AfterThrowing: 异常通知, 在方法抛出异常之后,有异常的时候才执行
@AfterThrowing(pointcut="execution(public void com.spring.aop.AopService.*(..))",throwing="e")
@Around: 环绕通知, 围绕着方法执行
@Component:标识该类受spring管理
@Aspect: 标识该类是一个切面
execution(public void com.spring.aop.AopService.*(..)) : 切入点签名表达式,用*号表示所有,也可以指定,括号内两点表示多个变量,也可以指定,还可以用 , || , !;以每个execution为一个单位
JoinPoint:连接点,该参数可以访问到更多的数据,还有很多方法可以自己试试。
@Order(n): 切面执行的优先级,n值越小,越优先执行
还有重用切面,等知识我就不过多描述了,毕竟是入门,讲一些常用的就可以了。
使用xml配置文件
package com.spring.aop;
import org.aspectj.lang.JoinPoint;
public class LogAspect {
public String afterMethod(JoinPoint joinPoint) {
String opreate = joinPoint.getSignature().getName();
System.out.println("ITDragon opreate " + opreate);
return "";
}
}
配置文件:
!-- 扫描切面类 --
bean class="com.spring.aop.LogAspect" id="logAspect"/bean
!-- aop配置 --
aop:config
!-- 切点 --
aop:pointcut expression="execution(public void com.spring.aop.AopService.*(..))" id="aop"/
!-- 切面 : ref 的值是 切面类的id--
aop:aspect id="aspect" ref="logAspect"
!-- 前置方法 : pointcut-ref 的值是 切点的id --
aop:before method="afterMethod" pointcut-ref="aop"/
/aop:aspect
/aop:config
还是一样的测试方法,其结果为:
ITDragon opreate login
登入成功
ITDragon opreate writeABlog
用户编写博客
ITDragon opreate deleteABlog
用户删除博客
ITDragon opreate loginOut
用户退出系统
在需要打印日志的地方添加切入点即可。切入点函数名尽量见名知意。这样切面函数才能通用。
SpringMvc + AOP Aspect 日志管理AOP执行两次,如何只让AOP执行一次
您好,这样的:这个还真没有 好像 , 你自己写一个吧! 就不判断methodName直接判断Method 这个对象。
切面的优先级
为项目增加一个新的切面类,负责验证功能,则需要指定切面执行的顺序。即切面的优先级。具体方法是给切面类增加@Order注解,并指定具体的数字,值越小优先级越高
1 package com.yl.spring.aop;
2
3 import java.util.Arrays;
4
5 import org.aspectj.lang.JoinPoint;
6 import org.aspectj.lang.annotation.Aspect;
7 import org.aspectj.lang.annotation.Before;
8 import org.springframework.core.annotation.Order;
9 import org.springframework.stereotype.Component;
10
11 /**
12 * 可以使用@Order注解指定切面的优先级,蔽雹值岩改越小优先级越高
13 * @author yul
14 *
15 */
16 @Order(2)
17 @Component
18 @Aspect
19 public class ValidationAspect {
20
21 @Before("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
22 public void vlidateArgs(JoinPoint joinPoint) {
23 System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));
24 }
25 }
切点表达式的重用:
在LoggingAspect类中,切点的表达式可以先定义,在使用。
1 package com.yl.spring.aop;
2
3 import java.util.Arrays;
4
5 import org.aspectj.lang.JoinPoint;
6 import org.aspectj.lang.ProceedingJoinPoint;
7 import org.aspectj.lang.annotation.After;
8 import org.aspectj.lang.annotation.AfterReturning;
9 import org.aspectj.lang.annotation.AfterThrowing;
10 import org.aspectj.lang.annotation.Around;
11 import org.aspectj.lang.annotation.Aspect;
12 import org.aspectj.lang.annotation.Before;
13 import org.aspectj.lang.annotation.Pointcut;
14 import org.springframework.core.annotation.Order;
15 import org.springframework.stereotype.Component;
16 @Order(1)
17 @Component
18 @Aspect
19 public class LoggingAspect {
20
21 /**
22 * 定义一个方法,用于声明切入点表达式。一般的,该方法中再不宏枣帆需要添加其他的代码
23 * 使用@Pointcut 来声明切入点表达式
24 * 后面的其他通知直接使用方法名直接引用方法名即可
25 */
26 @Pointcut("execution(public int com.yl.spring.aop.ArithmeticCalculator.*(..))")
27 public void declareJoinPointExpression() {
28
29 }
30
31 /**
32 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法开始之前执行一段代码
33 */
34 @Before("declareJoinPointExpression()")
35 public void beforeMethod(JoinPoint joinPoint) {
36 String methodName = joinPoint.getSignature().getName();
37 Object[] args = joinPoint.getArgs();
38 System.out.println("The method " + methodName + " begins with " + Arrays.asList(args));
39 }
40
41 /**
42 * 在com.yl.spring.aop.ArithmeticCalculator接口的每一个实现类的每一个方法执行之后执行一段代码
43 * 无论该方法是否出现异常
44 */
45 @After("declareJoinPointExpression()")
46 public void afterMethod(JoinPoint joinPoint) {
47 String methodName = joinPoint.getSignature().getName();
48 Object[] args = joinPoint.getArgs();
49 System.out.println("The method " + methodName + " ends with " + Arrays.asList(args));
50 }
51
52 /**
53 * 方法正常结束后执行的代码
54 * 返回通知是可以访问到方法的返回值的
55 */
56 @AfterReturning(value="declareJoinPointExpression()", returning="result")
57 public void afterReturning(JoinPoint joinPoint, Object result) {
58 String methodName = joinPoint.getSignature().getName();
59 System.out.println("The method " + methodName + " return with " + result);
60 }
61
62 /**
63 * 在方法出现异常时会执行的代码
64 * 可以访问到异常对象,可以指定在出现特定异常时在执行通知代码
65 */
66 @AfterThrowing(value="declareJoinPointExpression()", throwing="ex")
67 public void afterThrowing(JoinPoint joinPoint, Exception ex) {
68 String methodName = joinPoint.getSignature().getName();
69 System.out.println("The method " + methodName + " occurs exception: " + ex);
70 }
71
72 /**
73 * 环绕通知需要携带ProceedingJoinPoint类型的参数
74 * 环绕通知类似于动态代理的全过程:ProceedingJoinPoint类型的参数可以决定是否执行目标方法。
75 * 而且环绕通知必须有返回值,返回值即为目标方法的返回值
76 */
77 @Around("declareJoinPointExpression()")
78 public Object aroundMethod(ProceedingJoinPoint pjd) {
79 Object result = null;
80 String methodName = pjd.getSignature().getName();
81 //执行目标方法
82 try {
83 //前置通知
84 System.out.println("The method " + methodName + " begins with " + Arrays.asList(pjd.getArgs()));
85 result = pjd.proceed();
86 //返回通知
87 System.out.println("The method " + methodName + " ends with " + Arrays.asList(pjd.getArgs()));
88 } catch (Throwable e) {
89 //异常通知
90 System.out.println("The method " + methodName + " occurs expection : " + e);
91 throw new RuntimeException(e);
92 }
93 //后置通知
94 System.out.println("The method " + methodName + " ends");
95 return result;
96 }
97
98 }
当处于不同的类,甚至不同的包时,可以使用包名.类名.方法名
具体代码如下:
1 package com.yl.spring.aop;
2
3 import java.util.Arrays;
4
5 import org.aspectj.lang.JoinPoint;
6 import org.aspectj.lang.annotation.Aspect;
7 import org.aspectj.lang.annotation.Before;
8 import org.springframework.core.annotation.Order;
9 import org.springframework.stereotype.Component;
10
11 /**
12 * 可以使用@Order注解指定切面的优先级,值越小优先级越高
13 * @author yul
14 *
15 */
16 @Order(2)
17 @Component
18 @Aspect
19 public class ValidationAspect {
20
21 @Before("com.yl.spring.aop.LoggingAspect.declareJoinPointExpression()")
22 public void vlidateArgs(JoinPoint joinPoint) {
23 System.out.println("validate: " + Arrays.asList(joinPoint.getArgs()));
24 }
25 }
还木有评论哦,快来抢沙发吧~