首先感謝你們寫的有關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(){ ... } }