Spring Aop+注釈実現ログ記録

10990 ワード

システム業務操作ログ記録は各システムにとって不可欠な一部ですが、通常はログを記録する必要がある箇所ごとに、ログを追加するサービス方法を呼び出します.これは主に面倒です.この機能はSpring AOPを用いて注釈と結合して実現できます.
1、まず注解類を定義します.
@Target(value = ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
    String module() default "";
    String desc() default "";
}
注解類は2つの属性があり、moduleは操作モジュールであり、descは具体的に記録されたログ情報である.2、切麺類を定義する:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;
/**
 * Created by Administrator on 2017/6/2.
 */
@Aspect
public class LogAspect {
    private final Logger logger = LoggerFactory.getLogger(LogAspect.class);
    private long timeStart;
    @Before(value = "execution(* aop.service..*.*(..))")
    public void doBefore(JoinPoint joinPoint) {
        timeStart = System.currentTimeMillis();
    }
    @After(value = "execution(* aop.service..*.*(..))")
    public void doAfter(JoinPoint joinPoint) {
        long timeEnd = System.currentTimeMillis();
        logger.info("  :" + joinPoint.getTarget().getClass().getSimpleName()+"."+joinPoint.getSignature().getName() + "    。  :" + (timeEnd-timeStart)+"ms.");
        Method proxyMethod = ((MethodSignature)(joinPoint.getSignature())).getMethod();
        try {
            Method sourceMethod = joinPoint.getTarget().getClass().getMethod(proxyMethod.getName(), proxyMethod.getParameterTypes());
            SysLog sysLog = sourceMethod.getAnnotation(SysLog.class);
            if (sysLog != null) {
                String module = sysLog.module();
                String desc = sysLog.desc();
                //           
                /**
                 * 1.  request  
                 * 2.  request  session
                 * 3. session         
                 */
                RequestAttributes ra = RequestContextHolder.getRequestAttributes();
                ServletRequestAttributes sra = (ServletRequestAttributes)ra;
                HttpServletRequest request = sra.getRequest();
                HttpSession session = request.getSession();
                //  session       
                String loginInfo = (String) session.getAttribute("username");
                String username = "admin";
                logger.info(username + " [" + module + "]" + desc);
            }
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }
}
3、springプロファイルの追加:
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean id="aspectEventLog" class="aop.LogAspect" />
4、maven依存:
<dependency>
    <groupId>org.aspectjgroupId>
    <artifactId>aspectjrtartifactId>
    <version>1.8.1version>
dependency>
<dependency>
    <groupId>org.aspectjgroupId>
    <artifactId>aspectjweaverartifactId>
    <version>1.6.12version>
dependency>
<dependency>
    <groupId>junitgroupId>
    <artifactId>junitartifactId>
    <version>4.10version>
dependency>
<dependency>
    <groupId>${spring.groupId}groupId>
    <artifactId>spring-testartifactId>
    <version>${spring.version}version>
dependency>
<dependency>
    <groupId>org.springframeworkgroupId>
    <artifactId>spring-contextartifactId>
    <version>${spring.version}version>
dependency>
5、テストサービス:
@Service
public class TestService {
    @SysLog(module = SysConstant.MODULE_USER_MGR,desc = "    ")
    public void test() {
        System.out.println("   test()  ,username=" + username);
        try {
            Thread.sleep((long) (Math.random()*3000L));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
実行結果:
   test()  
12:39:30,355  INFO main aop.LogAspect:33 -TestService.test    。  :1601ms.
12:39:30,356  INFO main aop.LogAspect:44 - admin [    ]    
最後に説明しますが、このようなことは具体的にはできません.例えば、ある人がユーザーを追加した場合、このようなレベルではできません.上でhttpspervletrequestを手に入れたら、もちろんすべての要求パラメータを得ることができます.より具体的には、各要求に特定のパラメータを運ぶ必要があります.
たとえば、ユーザAAがユーザーBBを追加すると、BBは固定名前のパラメータに入れなければなりません.注をしなくても、モジュール名と具体的なログ情報をrequestに入れて、切断面でrequestから取得するということですが、これはちょっと面倒くさいです.
モジュールに具体的に登録して、IPなどを記録するだけで満足できます.