一,使用aop记录方法调用日志
1)使用注解与aop做方法调用日志,只需要把注解添加在要记录的方法上就可以,不会影响代码结构
2)实现思路 数据库表建立>>配置需要环境>>自定义注解>>定义切点与操作(包含处理逻辑)>>添加注解
二,配置环境
1)在原来的项目pom文件中添加以下aop需要的依赖
<springframework>4.0.5.RELEASE</springframework>
<aspectj>1.8.5</aspectj>
<!-- Spring AOP -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${springframework}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj}</version>
</dependency>
2)springmvc配置
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
<!-- 启动AspectJ支持 只对扫描过的bean有效 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<!-- 指定Sping组件扫描的基本包路径 -->
<context:component-scan base-package="com.bjsxt.portl">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
三,自定义注解
1)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 日志记录
* @author heyuan***
* @date: 2017年11月22日 上午11:41:57
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Log {
String name() default ""; //用于写方法作用
}
四,定义切点与操作
1)
@Aspect
@Component
public class SeriveLogAop
{
@Resource
private OperationLogMapper operationLogMapper;
@Pointcut("@annotation(com.bjsxt.portal.annotation.SeriveLog)")
public void SeriveLogAopqd()
{
System.out.println("---------->切点");
}
@After("SeriveLogAopqd()")
public void Afters(JoinPoint joinPoint)
{
OperationLog operationLog = new OperationLog();
User user = new User();
StringBuffer arg = new StringBuffer();
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; ++i) {
System.out.println("\t==>参数[" + i + "]:\t" + args[i].toString());
arg.append(args[i].toString());
}
Signature signature = joinPoint.getSignature();
String signa = signature.toString();
MethodSignature ms = (MethodSignature)joinPoint.getSignature();
Method method = ms.getMethod();
String name = ((SeriveLog)method.getAnnotation(SeriveLog.class)).name();
String name2 = method.getName();
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
user.setuUsername("无登录人");
String host = request.getRemoteHost();
String username = user.getuUsername();
String time = Time.getTime();
operationLog.setoIp(host);
operationLog.setuUsername(username);
operationLog.setoTime(time);
operationLog.setoMethodname(name2);
operationLog.setoExplain(name);
operationLog.setoFullpath(signa);
operationLog.setoParameter(arg.toString());
this.operationLogMapper.addOperationLogs(operationLog);
}
}
五,在需要记录的方法上添加@Log(name="方法描述")
六,常用知识
注解:
@Before – 目标方法执行前执行 前置通知 JoinPoint joinPoint
@After – 目标方法执行后执行 后置通知
@AfterReturning – 目标方法返回后执行,如果发生异常不执行
@AfterThrowing – 异常时执行 异常通知
@Around – 在执行上面其他操作的同时也执行这个方法 环绕通知 ProceedingJoinPoint pjp 执行方法:pjp.proceed(); 要返回pjp
joinPoint:方法
joinPoint.getKind() // method-execution
joinPoint.getTarget().toString()// 获取连接点所在的目标对象; com.xxx.portal.service.impl.UserServiceImpl@a269a21
joinPoint.getArgs() //获取连接点方法运行时的入参列表;
System.out.println("Args:");
for(int i=0;i<os.length;i++){
System.out.println("\t==>参数["+i+"]:\t"+os[i].toString());
}
joinPoint.getSignature() //获取连接点的方法签名对象;String com.bjsxt.portal.service.impl.UserServiceImpl.getUser(User,HttpServletRequest,HttpSession)
joinPoint.getSourceLocation() // org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$SourceLocationImpl@161b0ee2
joinPoint.getStaticPart() // execution(String com.xxx.portal.service.impl.UserServiceImpl.getUser(User,HttpServletRequest,HttpSession))
MethodSignature ms=(MethodSignature) joinPoint.getSignature();
Method method=ms.getMethod();
method.getAnnotation(Log.class).name();
//method.getAnnotation(Log.class).name() 获取操作名(@log(name="内容"))
method.getName(); //获取当前执行方法名
常用方法:
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
request.getSession();
request.getHost();//获取ip
异常名称: e.getClass().toString()
网络参考资料
@Aspect
@Component
public class LogAop {
ThreadLocal<Long> time=new ThreadLocal<Long>();
ThreadLocal<String> tag=new ThreadLocal<String>();
//切点
@Pointcut("@annotation(com.bjsxt.portal.annotation.Log)")
public void logqd() {
System.out.println("---------->切点");
}
/**
* 在所有标注@Log的地方切入
* @param joinPoint
* 前置通知
*/
@Before("logqd()")
public void beforeExec(JoinPoint joinPoint){
time.set(System.currentTimeMillis());
tag.set(UUID.randomUUID().toString());
info(joinPoint);
MethodSignature ms=(MethodSignature) joinPoint.getSignature();
Method method=ms.getMethod();
//method.getAnnotation(Log.class).name() 获取操作名(@log(name="内容"))
System.out.println(method.getAnnotation(Log.class).name()+"标记"+tag.get());
}
/**
*后置通知
*/
@After("logqd()")
public void afterExec(JoinPoint joinPoint){
MethodSignature ms=(MethodSignature) joinPoint.getSignature();
Method method=ms.getMethod();
System.out.println("标记为"+tag.get()+"的方法"+method.getName()+"运行消耗"+(System.currentTimeMillis()-time.get())+"ms");
}
/**
*环绕通知
*/
@Around("logqd()")
public Object aroundExec(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("前");
Object proceed = pjp.proceed();
System.out.println("后");
return proceed;
}
private void info(JoinPoint joinPoint){
System.out.println("--------------------------------------------------");
System.out.println("King:\t"+joinPoint.getKind());
System.out.println("Target:\t"+joinPoint.getTarget().toString());
Object[] os=joinPoint.getArgs();
System.out.println("Args:");
for(int i=0;i<os.length;i++){
System.out.println("\t==>参数["+i+"]:\t"+os[i].toString());
}
System.out.println("Signature:\t"+joinPoint.getSignature());
System.out.println("SourceLocation:\t"+joinPoint.getSourceLocation());
System.out.println("StaticPart:\t"+joinPoint.getStaticPart());
System.out.println("--------------------------------------------------");
}
}
/**
* 异常通知
*@descript
*@param point
*@version 1.0
*/
@AfterThrowing(pointcut = "controllerAspect()", throwing = "e")
public void doAfterThrowing(JoinPoint point, Throwable e) {
LogFormMap logForm = new LogFormMap();
Map<String, Object> map = null;
String user = null;
String ip = null;
try {
ip = SecurityUtils.getSubject().getSession().getHost();
} catch (Exception ee) {
ip = "无法获取登录用户Ip";
}
try {
map=getControllerMethodDescription(point);
// 登录名
user = SecurityUtils.getSubject().getPrincipal().toString();
if (Common.isEmpty(user)) {
user = "无法获取登录用户信息!";
}
} catch (Exception ee) {
user = "无法获取登录用户信息!";
}
logForm.put("accountName",user);
logForm.put("module",map.get("module"));
logForm.put("methods","<font color=\"red\">执行方法异常:-->"+map.get("methods")+"</font>");
logForm.put("description","<font color=\"red\">执行方法异常:-->"+e+"</font>");
logForm.put("actionTime","0");
logForm.put("userIP",ip);
try {
logMapper.addEntity(logForm);
} catch (Exception e1) {
e1.printStackTrace();
}
}
来源:https://www.cnblogs.com/hi-feng/p/7895925.html