開源項目地址: github開源鏈接
使用AOP切入的方式記錄操作日志,本代碼主要采用枚舉作為記錄方式,具體代碼如下.
首先先定義先關枚舉:
- /**
- * 枚舉公共接口
- * @author LeiYong
- *
- */
- public interface EnumSuper {
- /**
- * 獲取值
- * @return
- */
- public String getValue();
- /**
- * 獲取描述信息
- * @return
- */
- public String getDiscription();
- }
- public enum LogOperateEnum implements EnumSuper{
- Select("0","查詢"),Save("1","新增"),Update("2","修改"),Delete("3","刪除");
- private String value;
- private String discription;
-
- LogOperateEnum(String value, String discription) {
- this.value = value;
- this.discription = discription;
- }
-
- @Override
- public String getValue() {
- return value;
- }
-
- @Override
- public String getDiscription() {
- return discription;
- }
-
-
- }
- public enum LogEnum implements EnumSuper{
- Sys("系統(tǒng)",""),
- Activity("活動",""),
- Shop("商城",""),
- Usr("用戶",""),
- Scd("預約","")
- ;
- private String value;
- private String discription;
-
- LogEnum(String value, String discription) {
- this.value = value;
- this.discription = discription;
- }
-
- @Override
- public String getValue() {
- return value;
- }
-
- @Override
- public String getDiscription() {
- return discription;
- }
-
-
- }
接下來定義注解Logger
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- @Documented
- public @interface Logger {
- /**
- * 操作類型 0-查詢 1-新增 2-修改 3-刪除
- * @return
- */
- LogOperateEnum type();
- /**
- * 所屬模塊
- * @return
- */
- LogEnum model();
- /**
- * 業(yè)務主鍵
- * @return
- */
- String title() default "#pk";
- }
最后LoggerAspect切面類
此處keyGenerate為主鍵生成,參考另一篇博文,使用redis生成數(shù)據(jù)庫主鍵自增
使用redis生成數(shù)據(jù)庫主鍵自增
- package com.cykj.base.core.aop;
-
- import java.lang.reflect.Method;
- import java.util.Date;
-
- import javax.servlet.http.HttpServletRequest;
-
- import org.apache.commons.lang3.StringUtils;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
-
- import com.cykj.base.common.annotation.Logger;
- import com.cykj.base.common.system.SystemConfig;
- import com.cykj.base.common.system.properties.AdminPropertiesConfig;
- import com.cykj.base.common.util.PropertiesCacheUtil;
- import com.cykj.base.common.util.StringUtil;
- import com.cykj.base.core.model.log.LogOperater;
- import com.cykj.base.core.model.sys.SysUser;
- import com.cykj.base.core.model.usr.UsrUser;
- import com.cykj.base.core.model.usr.UsrUserSlave;
- import com.cykj.base.core.provide.log.LogOperaterService;
- import com.cykj.base.core.util.AopUtil;
- import com.cykj.base.core.util.WebUtils;
-
- /**
- * 操作日志
- * @author LeiYong
- *
- */
- @Aspect
- @Component
- public class LoggerAspect {
-
- @Autowired
- private LogOperaterService logOperaterService;
- @Pointcut("@annotation(com.cykj.base.common.annotation.Logger)")
- private void loggerMethod(){}//定義一個切入點,此處Logger為Logger類全路徑
- /**
- * 記錄操作日志
- *
- * @param jp
- * @return
- * @throws Throwable
- */
- @Around("loggerMethod()")
- public Object logger(ProceedingJoinPoint jp) throws Throwable {
-
- Object result = null;
- Boolean logEnable = SystemConfig.LOG_ENABLE;
- result = AopUtil.executeJoinPointMethod(jp, jp.getArgs());
- if (logEnable&&result!=null) {
- LogOperater lo = null;
- SysUser su = getLoginSysUser();
- if (su!=null) {
- lo = getLogBySysUser(su, jp);
- }else {
- UsrUserSlave uu = getLoginUsrUser();
- lo = getLogByUsrUser(uu, jp);
- }
- if (lo!=null) {
- logOperaterService.insertSelective(lo);
- }
- }
- return result;
- }
-
- /**
- * 記錄系統(tǒng)用戶操作日志
- * @param user
- * @param jp
- * @return
- */
- private LogOperater getLogBySysUser(SysUser user,ProceedingJoinPoint jp){
- LogOperater logOperater = getLogger(jp);
- if (logOperater!=null) {
- logOperater.setCreateBy(user.getPk());
- logOperater.setFrom("0");
- logOperater.setOrgPk(user.getOrgPk());
- }
- return logOperater;
- }
- /**
- * 記錄微信用戶操作日志
- * @param user
- * @param jp
- * @return
- */
- private LogOperater getLogByUsrUser(UsrUser user,ProceedingJoinPoint jp){
- LogOperater logOperater = getLogger(jp);
- if (logOperater!=null) {
- logOperater.setCreateBy(user.getPk());
- logOperater.setFrom("1");
- // logOperater.setOrgPk(user.getOrgPk());
- }
- return logOperater;
- }
-
- private LogOperater getLogger(ProceedingJoinPoint jp){
- //獲取切入點方法及參數(shù)
- Method method = AopUtil.getMethod(jp);
- Logger t = AopUtil.getMethodAnnotation(method, Logger.class);
- try {
- Boolean flag = PropertiesCacheUtil.loadProjectProperties(AdminPropertiesConfig.LOGGER_CONFIG).getBoolean(t.type().toString());
- //未配置或true都記錄日志,僅為false時不記錄
- if (flag!=null&&!flag) {
- return null;
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- String[] paramNames = AopUtil.getMethodParamNames(method);
- String pk = AopUtil.parseKeyByParam(t.title(),paramNames, jp.getArgs());
- //主鍵,機構pk,創(chuàng)建人,創(chuàng)建時間,操作類型,模塊,處理方法,主鍵,操作內容
- //自增長主鍵
- LogOperater logOperater = new LogOperater();
- logOperater.setCreateTime(new Date());
- logOperater.setType(t.type().getValue());
- logOperater.setModel(t.model().getValue());
- logOperater.setFunc(t.model().getDiscription());
- logOperater.setMethod(method.getName());
- if (StringUtils.isNotBlank(pk)) {
- int index = pk.indexOf(",");
- if (index<0) {
- logOperater.setTitle(pk);
- }else{
- logOperater.setTitle(StringUtil.subString(pk, 0, index));
- int count = StringUtils.countMatches(pk, ",");
- String content = SystemConfig.LOG_CONTENT_LENGTH>pk.length()?pk:StringUtil.subString(pk, 0, SystemConfig.LOG_CONTENT_LENGTH)+"...";
- logOperater.setContent(count+"筆:"+content);
- }
- }
- return logOperater;
- }
- /**
- * 獲取系統(tǒng)登錄用戶
- * @return
- */
- private SysUser getLoginSysUser(){
- HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
- return WebUtils.getLoginUser(request);
- }
- /**
- * 獲取微信登錄用戶(未實現(xiàn))
- * @return
- */
- private UsrUserSlave getLoginUsrUser(){
- return null;
- }
-
- }
再在spring的xml中配置掃描到LoggerAspect所在package目錄,大功告成
使用起來也非常方便,在需要加操作日志的方法上加個注解就OK了,如此則記錄為系統(tǒng)模塊,執(zhí)行查詢,主鍵為參數(shù)pk(此處使用springSpel表達式解析)
- @Logger(model=LogEnum.Sys,type=LogOperateEnum.Select,title="#pk")
- public Json get(String orgPk,String pk) {}
最后附上AOPUtil代碼
- package com.cykj.base.core.util;
-
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Method;
-
- import org.apache.commons.lang3.StringUtils;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
- import org.springframework.expression.ExpressionParser;
- import org.springframework.expression.spel.standard.SpelExpressionParser;
- import org.springframework.expression.spel.support.StandardEvaluationContext;
-
- public class AopUtil {
- private static ExpressionParser parser;
- /**
- * 獲取被攔截方法對象
- *
- * MethodSignature.getMethod() 獲取的是頂層接口或者父類的方法對象 而緩存的注解在實現(xiàn)類的方法上
- * 所以應該使用反射獲取當前對象的方法對象
- */
- public static Method getMethod(ProceedingJoinPoint pjp) {
- // 獲取參數(shù)的類型
- Class<?>[] parameterTypes = ((MethodSignature)pjp.getSignature()).getMethod().getParameterTypes();
- //此方法當參數(shù)傳遞null時會報錯,故而改為采用上述方式
- // Object[] args = pjp.getArgs();
- // Class[] argTypes = new Class[pjp.getArgs().length];
- // for (int i = 0; i < args.length; i++) {
- // if (args[i]!=null) {
- // argTypes[i] = args[i].getClass();
- // }
- // }
- Method method = null;
- try {
- method = pjp.getTarget().getClass().getMethod(pjp.getSignature().getName(), parameterTypes);
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (SecurityException e) {
- e.printStackTrace();
- }
- return method;
- }
- /**
- * 通過spring spel解析參數(shù)獲取redis緩存key
- *
- * @param keys
- * 緩存keys
- * @param paramNames
- * 參數(shù)名
- * @param args
- * 參數(shù)列表
- * @return
- */
- public static String parseKeyByParam(String keys, String[] paramNames, Object[] args) {
- if (StringUtils.isBlank(keys)) {
- return "";
- }
- ExpressionParser parser = getParser();
- StandardEvaluationContext context = new StandardEvaluationContext();
- // 把方法參數(shù)放入SPEL上下文中
- for (int i = 0; i < paramNames.length; i++) {
- context.setVariable(paramNames[i], args[i]);
- }
- // 獲取參數(shù)key
- StringBuffer sb = new StringBuffer();
- // for (int i = 0; i < keys.length; i++) {
- sb.append(parser.parseExpression(keys).getValue(context, String.class));
- // }
- return sb.toString();
- }
-
- /**
- * 獲取參數(shù)名列表
- *
- * @param method
- * @return
- */
- public static String[] getMethodParamNames(Method method) {
- // 獲取被攔截方法參數(shù)名列表(使用Spring支持類庫)
- LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
- String[] paraNameArr = u.getParameterNames(method);
- return paraNameArr;
- }
-
- /**
- * 獲取緩存主鍵
- * @param jp
- * @param clazz
- * @return
- * @throws SecurityException
- * @throws NoSuchFieldException
- */
- // public static <T extends Annotation> String[] getCachedKey(T t,String[] paramNames, Class<T> clazz) throws NoSuchFieldException, SecurityException {
- //// Method method = getMethod(jp);
- //// T t = getMethodAnnotation(method, clazz);
- // // String fieldKey = null;
- // // if (cache.isParam()) {
- // String fieldKey = parseKeyByParam(ReflectionUtil.getField(t.getClass().getField("cachekey"), t).toString(), paramNames, jp.getArgs());
- // // }
- // return fieldKey.split(",");
- // }
-
- /**
- * 獲取方法注解
- * @param method
- * @param clazz 注解類型
- * @return
- */
- public static <T extends Annotation> T getMethodAnnotation(Method method,Class<T> clazz){
- T t = method.getAnnotation(clazz);
- return t;
- }
- /**
- * 獲取redis緩存key通過集合參數(shù)
- *
- * @param keys
- * 緩存keys
- * @param params
- * 參數(shù)名
- * @param returnObj
- * 參數(shù)列表
- * @return
- */
- private String parseKeyByReturn(String keys, Object returnObj) {
- ExpressionParser parser = getParser();
- StandardEvaluationContext context = new StandardEvaluationContext();
- // 把方法參數(shù)放入SPEL上下文中
- context.setVariable("obj", returnObj);
- // 獲取參數(shù)key
- StringBuffer sb = new StringBuffer();
- sb.append(parser.parseExpression(keys).getValue(context, String.class));
- return sb.toString();
- }
- /**
- * 使用SPEL進行key的解析
- *
- * @return
- */
- public synchronized static ExpressionParser getParser() {
- if (parser == null) {
- parser = new SpelExpressionParser();
- }
- return parser;
- }
- /**
- * 執(zhí)行切入點方法
- * @param jp
- * @param params 方法參數(shù)
- * @return
- */
- public static Object executeJoinPointMethod(ProceedingJoinPoint jp,Object[] params){
- Object obj = null;
- try {
- if (params==null||params.length==0) {
- obj = jp.proceed();
- }else{
- obj = jp.proceed(params);
- }
- } catch (Throwable e) {
- e.printStackTrace();
- }
- return obj;
- }
- }
本站僅提供存儲服務,所有內容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內容,請
點擊舉報。