Spring AOP 日誌管理

首先感謝你們寫的有關AOP的博客,本人蔘考了不少篇博客,走了一點小彎路,因此在此記錄下配置的過程。 一、Mavan的相關依賴java

<!--配置aop切面編程須要引入的包 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.7.4</version>
        </dependency>

二、Spring 的配置文件spring

<!--Aop切面編程的配置-->
    <aop:aspectj-autoproxy proxy-target-class="true" />

三、Struts2 的配置文件數據庫

<!-- Spring AOP -->
    <constant name="struts.objectFactory.spring.autoWire.alwaysRespect" value="true" />

四、日誌實體(省略數據庫的操做)apache

package com.gxuwz.entity;

import javax.persistence.*;
@Entity
@Table(name = "sys_log")
public class SysLog extends BaseEntity{

	private static final long serialVersionUID = -2894437117210657269L;
	
	@Column(name = "log_ip_add")
	private String ipAdd;		// IP地址
	@Column(name = "log_msg")
	private String msg;			// 消息
	@Column(name = "log_method")
	private String method;		// 方法
	@Column(name = "log_clazz")
	private String clazz; 		// 類名
	@Column(name = "log_username")
	private String username;	// 用戶名
	@Column(name = "log_create_date")
	private String createDate;	//建立時間
        // 省略get、set的方法
}

五、自定義AOP的註解編程

package com.gxuwz.annotation;

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)	//註解會在class中存在,運行時可經過反射獲取
@Target(ElementType.METHOD)			//目標是方法
@Documented							//文檔生成時,該註解將被包含在javadoc中,可去掉
public @interface LogMsg
{
    String msg() default "";

}

六、切面session

package com.gxuwz.annotation;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.gxuwz.entity.SysLog;
import com.gxuwz.entity.SysUser;
import com.gxuwz.service.ILogService;
import com.gxuwz.util.DateUtils;
import com.opensymphony.xwork2.ActionContext;

import java.lang.reflect.Method;
import java.util.Map;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Aspect
@Component
public class LogAspect {
	private static final Logger logger = Logger.getLogger(LogAspect.class);
	
	private SysLog log = new SysLog();	// 定義一個日誌對象
	
	@Resource(name = "logService")
	private ILogService logService;

	/**
	 * 定義Pointcut,Pointcut的名稱,此方法不能有返回值,該方法只是一個標示
	 */
	@Pointcut("@annotation(com.gxuwz.annotation.LogMsg)")
	public void controllerAspect() {
		System.out.println("我是一個切入點");
	}

	/**
	 * 前置通知(Before advice) :在某鏈接點(JoinPoint)以前執行的通知,但這個通知不能阻止鏈接點前的執行。
	 * 
	 * @param joinPoint
	 */
	@Before("controllerAspect()")
	public void doBefore(JoinPoint joinPoint) {
		System.out.println("=====LogAspect前置通知開始=====");
		// handleLog(joinPoint, null);
	}

	/**
	 * 後通知(After advice) :當某鏈接點退出的時候執行的通知(不管是正常返回仍是異常退出)。
	 * 
	 * @param joinPoint
	 */
	@AfterReturning(pointcut = "controllerAspect()")
	public void doAfter(JoinPoint joinPoint) {
		System.out.println("=====LogAspect後置通知開始=====");
		handleLog(joinPoint, null);	// 等執行完SQL語句以後再記錄,避免獲取不到Session
	}

	/**
	 * 拋出異常後通知(After throwing advice) : 在方法拋出異常退出時執行的通知。
	 * 
	 * @param joinPoint
	 * @param e
	 */
	@AfterThrowing(value = "controllerAspect()", throwing = "e")
	public void doAfter(JoinPoint joinPoint, Exception e) {
		System.out.println("=====LogAspect異常通知開始=====");
		// handleLog(joinPoint, e);
	}

	/**
	 * 環繞通知(Around advice)
	 * :包圍一個鏈接點的通知,相似Web中Servlet規範中的Filter的doFilter方法。能夠在方法的調用先後完成自定義的行爲
	 * ,也能夠選擇不執行。
	 * 
	 * @param joinPoint
	 */
	@Around("controllerAspect()")
	public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
		System.out.println("=====LogAspect 環繞通知開始=====");
		//handleLog(joinPoint, null);
		Object obj = joinPoint.proceed();
		System.out.println("=====LogAspect 環繞通知結束=====");
		return obj;
	}

	/**
	 * 日誌處理
	 * 
	 * @param joinPoint
	 * @param e
	 */
	private void handleLog(JoinPoint joinPoint, Exception e) {
		try {
			HttpServletRequest request = (HttpServletRequest) ActionContext
					.getContext().get(ServletActionContext.HTTP_REQUEST);
			System.out.println("IP地址:" + request.getRemoteAddr());
			log.setIpAdd(request.getRemoteAddr());
			Map<String, Object> session = (Map<String, Object>) ActionContext
					.getContext().getSession();
			// 讀取session中的用戶
			SysUser user = (SysUser) session.get("user");
			System.out.println("用戶名:" + user.getUserName());
			log.setUsername(user.getUserName());
			System.out.println("時間:"+DateUtils.getCurrentDate());
			log.setCreateDate(DateUtils.getCurrentDate());
			LogMsg logger = giveController(joinPoint);
			if (logger == null) {
				return;
			}
			System.out.println("用戶操做:"+logger.msg());
			log.setMsg(logger.msg());
			String signature = joinPoint.getSignature().toString(); // 獲取目標方法簽名
			String methodName = signature.substring(
					signature.lastIndexOf(".") + 1, signature.indexOf("("));

			//String longTemp = joinPoint.getStaticPart().toLongString();
			String classType = joinPoint.getTarget().getClass().getName();

			Class<?> clazz = Class.forName(classType);

			Method[] methods = clazz.getDeclaredMethods();
			System.out.println("方法名:" + methodName);

			for (Method method : methods) {
				if (method.isAnnotationPresent(LogMsg.class)
						&& method.getName().equals(methodName)) {
					// OpLogger logger = method.getAnnotation(OpLogger.class);
					String clazzName = clazz.getName();
					log.setClazz(clazzName);
					log.setMethod(methodName);
					System.out.println("類名:" + clazzName + ", 方法名:"
							+ methodName);
				}
			}
			
			logService.save(log);	//保存日誌對象

		} catch (Exception exp) {
			logger.error("異常信息:{}", exp);
			exp.printStackTrace();
		}
	}

	/**
	 * 得到註解
	 * 
	 * @param joinPoint
	 * @return
	 * @throws Exception
	 */
	private static LogMsg giveController(JoinPoint joinPoint)
			throws Exception {
		Signature signature = joinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature) signature;
		Method method = methodSignature.getMethod();

		if (method != null) {
			return method.getAnnotation(LogMsg.class);
		}
		return null;
	}

}

七、在Controller的方法上寫註解、例如日誌

/**
 * 用戶控制器
 * @author 小胡  
 * @date 2017年5月28日
 */
public class UserController extends AbstractBaseController{
	@LogMsg(msg = "用戶登錄")
	public String doLogin(){
            ...
        }
}
相關文章
相關標籤/搜索