paulwong

          自定義注釋與操作行為記錄

          自定義注釋就是一個標記,一個信息收集器,如果配合SPRING的AOP使用,可以記錄用戶的操作行為。

          import java.lang.annotation.ElementType;
          import java.lang.annotation.Retention;
          import java.lang.annotation.RetentionPolicy;
          import java.lang.annotation.Target;

          /**
           * 新增的用法:@Audit(behaviour="新增了專題", 
           *            value="#{args[0].colSubject}")
           *
           * 修改的用法:@Audit(behaviour="修改了專題", id="#{args[0].colSubject.id}", 
           *            className="com.paul.program.colsubject.valueobject.ColSubject",
           *            value="#{args[0].colSubject}")
           *
           * 刪除的用法:@Audit(behaviour="刪除了專題", id="#{args[0].colSubject.id}"
           *             className="com.paul.program.colsubject.valueobject.ColSubject")
           *             
           * 
          @author PAUL
           *
           
          */
          @Retention(RetentionPolicy.RUNTIME)
          @Target(ElementType.METHOD)
          public @interface Audit {
              
              String id() default "";
              String className() default "";
              String collectionName() default "";
              String value() default "";
              String behaviour();

          }


          值對象
          AuditData.java
          package com.paul.common.audit;

          import java.io.Serializable;
          import java.util.Date;

          import org.codehaus.jackson.annotate.JsonProperty;
          import org.codehaus.jackson.map.annotate.JsonSerialize;
          import org.springframework.data.annotation.CreatedBy;
          import org.springframework.data.annotation.CreatedDate;
          import org.springframework.data.annotation.Id;
          import org.springframework.data.mongodb.core.mapping.Document;
          import org.springframework.data.mongodb.core.mapping.Field;

          import com.paul.common.util.jackson.CustomJsonDateSerializer;

          @Document(collection = "auditdata")
          public class AuditData implements Serializable{

              private static final long serialVersionUID = -4011585863836336249L;
              
              @Id
              private String id;
              
              @CreatedBy
              @Field("userid")
              @JsonProperty("userid")
              private String userId;
              
              @CreatedDate
              @Field("createdate")
              @JsonProperty("createdate")
              @JsonSerialize(using = CustomJsonDateSerializer.class)
              private Date createDate;
              
              private String behaviour;
              
              @Field("newvalue")
              @JsonProperty("newvalue")
              private String newValue;
              
              @Field("oldvalue")
              @JsonProperty("oldvalue")
              private String oldValue;

              public String getId() {
                  return id;
              }

              public void setId(String id) {
                  this.id = id;
              }

              public String getUserId() {
                  return userId;
              }

              public void setUserId(String userId) {
                  this.userId = userId;
              }

              public Date getCreateDate() {
                  return createDate;
              }

              public void setCreateDate(Date createDate) {
                  this.createDate = createDate;
              }

              public String getBehaviour() {
                  return behaviour;
              }

              public void setBehaviour(String behaviour) {
                  this.behaviour = behaviour;
              }


              public String getNewValue() {
                  return newValue;
              }

              public void setNewValue(String newValue) {
                  this.newValue = newValue;
              }

              public String getOldValue() {
                  return oldValue;
              }

              public void setOldValue(String oldValue) {
                  this.oldValue = oldValue;
              }

              public String toString() {
                  return "AuditData [id=" + id + ", userId=" + userId + ", createDate="
                          + createDate + ", behaviour=" + behaviour + ", newValue="
                          + newValue + ", oldValue=" + oldValue + "]";
              }
              

          }


          RootObject.java
          package com.paul.common.audit;

          public class RootObject {

              private final Object[] args;

              private final Object invokedObject;

              private final Object returned;

              private final Throwable throwned;

              public RootObject(Object invokedObject, Object[] args, Object returned, Throwable throwned) {
                  super();
                  this.invokedObject = invokedObject;
                  this.args = args;
                  this.returned = returned;
                  this.throwned = throwned;
              }

              public Object[] getArgs() {
                  return args;
              }

              public Object getInvokedObject() {
                  return invokedObject;
              }

              public Object getReturned() {
                  return returned;
              }

              public Throwable getThrowned() {
                  return throwned;
              }

          }


          TemplateParserContext.java
          package com.paul.common.audit;

          import org.springframework.expression.ParserContext;

          public class TemplateParserContext implements ParserContext {

              public String getExpressionPrefix() {
                  return "#{";
              }

              public String getExpressionSuffix() {
                  return "}";
              }

              public boolean isTemplate() {
                  return true;
              }
          }


          獲取用戶ID
          package com.paul.common.audit.aware;

          import javax.servlet.http.HttpServletRequest;

          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;
          import org.springframework.data.domain.AuditorAware;
          import org.springframework.stereotype.Component;
          import org.springframework.web.context.request.RequestContextHolder;
          import org.springframework.web.context.request.ServletRequestAttributes;

          import com.paul.common.constant.Constants;
          import com.paul.program.account.valueobject.Account;

          @Component
          public class MyAppAuditor implements AuditorAware<String> {
              
              private static Logger logger = LoggerFactory.getLogger(MyAppAuditor.class);

              // get your user name here
              public String getCurrentAuditor() {
                  
                  String result = "N/A";
                  try {
                      HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                              .getRequestAttributes()).getRequest();
                      Account account = (Account)request.getSession().getAttribute(Constants.USER_INFO);
                      result = account.getLoginName();
                  } catch (Exception e) {
                      logger.error(e.getMessage(), e);
                  }
                  return result;
              }
          }


          切面
          package com.paul.common.audit.interceptor;

          import java.text.SimpleDateFormat;
          import java.util.ArrayList;
          import java.util.Date;
          import java.util.List;
          import java.util.Map;
          import java.util.concurrent.ConcurrentHashMap;
          import java.util.concurrent.TimeUnit;

          import org.apache.commons.lang.builder.ToStringBuilder;
          import org.apache.commons.lang.builder.ToStringStyle;
          import org.aspectj.lang.ProceedingJoinPoint;
          import org.aspectj.lang.annotation.Around;
          import org.aspectj.lang.annotation.Aspect;
          import org.slf4j.Logger;
          import org.slf4j.LoggerFactory;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.data.mongodb.core.MongoTemplate;
          import org.springframework.expression.EvaluationException;
          import org.springframework.expression.Expression;
          import org.springframework.expression.ExpressionParser;
          import org.springframework.expression.ParseException;
          import org.springframework.expression.ParserContext;
          import org.springframework.expression.spel.standard.SpelExpressionParser;
          import org.springframework.stereotype.Component;

          import com.paul.common.audit.AuditData;
          import com.paul.common.audit.AuditDataRequest;
          import com.paul.common.audit.RootObject;
          import com.paul.common.audit.TemplateParserContext;
          import com.paul.common.audit.annotation.Audit;
          import com.paul.common.audit.service.AuditDataService;
          import com.paul.common.util.StringUtils;

          @Component
          @Aspect
          public class AuditAspect {
              
              private static Logger logger = LoggerFactory.getLogger(AuditAspect.class);
              
              @Autowired
              private AuditDataService auditDataService;
              
              @Autowired
              private MongoTemplate mongoTemplate;
              
              private SimpleDateFormat dateFormatPrototype = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

              private Map<String, Expression> expressionCache = new ConcurrentHashMap<String, Expression>();

              private ExpressionParser expressionParser = new SpelExpressionParser();

              private ParserContext parserContext = new TemplateParserContext();
              

              protected static void appendThrowableCauses(Throwable throwable, String separator, StringBuilder toAppendTo) {
                  List<Throwable> alreadyAppendedThrowables = new ArrayList<Throwable>();

                  while (throwable != null) {
                      // append
                      toAppendTo.append(throwable.toString());
                      alreadyAppendedThrowables.add(throwable);

                      // cause
                      Throwable cause = throwable.getCause();
                      if (cause == null || alreadyAppendedThrowables.contains(cause)) {
                          break;
                      } else {
                          throwable = cause;
                          toAppendTo.append(separator);
                      }
                  }
              }
              
              private String getValueByEl(String template, Object invokedObject, Object[] args, Object returned, Throwable throwned)
              {
                  String result = "N/A";
                  if(StringUtils.isBlank(template))
                      return result;
                  try {
                      Expression expression = expressionCache.get(template);
                      if (expression == null) {
                          expression = expressionParser.parseExpression(template, parserContext);
                          expressionCache.put(template, expression);
                      }

                      Object evaluatedMessage = expression.getValue(new RootObject(invokedObject, args, returned, throwned), Object.class);
                      result = evaluatedMessage.toString();
                  } catch (ParseException e) {
                      logger.error(e.getMessage(), e);
                  } catch (EvaluationException e) {
                      logger.error(e.getMessage(), e);
                  }
                  return result;
              }


              protected AuditData buildAuditData(Audit auditAnnotation, Object invokedObject, Object[] args, Object returned, Throwable throwned, long durationInNanos) {
                  
                  AuditData auditData = new AuditData();
                  auditData.setBehaviour(auditAnnotation.behaviour());
                  String id = this.getValueByEl(auditAnnotation.id(), invokedObject, args, returned, throwned);
                  auditData.setOldValue(this.getOldValueToString(id, auditAnnotation.className()));
                  try {
                      String newValue = this.getValueByEl(auditAnnotation.value(), invokedObject, args, returned, throwned);
                      auditData.setNewValue(newValue);

                      StringBuilder msg = new StringBuilder();

                      SimpleDateFormat simpleDateFormat = (SimpleDateFormat) dateFormatPrototype.clone();
                      msg.append(simpleDateFormat.format(new Date()));
          //            auditData.setCreateDate(simpleDateFormat.format(new Date()));

                      msg.append(" ").append(newValue);

                      if (throwned != null) {
                          msg.append(" threw '");
                          appendThrowableCauses(throwned, ", ", msg);
                          msg.append("'");
                      }
                      msg.append(" by ");
                      String user = this.getUser();
                      if (user == null) {
                          user = "anonymous";
                      } 
                      msg.append(" in ") .append(TimeUnit.MILLISECONDS.convert(durationInNanos, TimeUnit.NANOSECONDS)).append(" ms");
                      return auditData;
                  } catch (Exception e) {
                      /*StringBuilder msg = new StringBuilder("Exception evaluating template '" + template + "': ");
                      appendThrowableCauses(e, ", ", msg);
          */
                      return auditData;
                  }
              }
              
              private String getOldValueToString(/*ProceedingJoinPoint proceedingJoinPoint,*/ String id, String className) 
              {
                  String result = "N/A";
                  /*String id = "5385be613d2a47eec07c53d4";
                  try {
                      MethodSignature methodSig = (MethodSignature) proceedingJoinPoint.getSignature();
                      Object target = proceedingJoinPoint.getTarget();
                      Object newValue = proceedingJoinPoint.getArgs()[0];
                      String findMethodName = "findOne";
                      Object oldValue=null;
                      Method findMethod = target.getClass().getDeclaredMethod(findMethodName, (Class<?>[])null);
                      oldValue = findMethod.invoke(target, (Object[]) null);

                  } catch (Exception e) {
                      logger.error(e.getMessage(), e);
                  }
          */
                  if(StringUtils.isBlank(id) || StringUtils.isBlank(className))
                      return result;
                  
                  try {
                      Object object = mongoTemplate.findById(id, Class.forName(className));
                      result = ToStringBuilder.reflectionToString(object,  ToStringStyle.SHORT_PREFIX_STYLE); 
                  } catch (Exception e) {
                      logger.error(e.getMessage(), e);
                  }
                  return result;
              }
              
          //    @Around("execution(* com.paul..**.repository..*(..))")
              @Around("@annotation(auditAnnotation)")
              public Object aroundAdvice(ProceedingJoinPoint proceedingJoinPoint, Audit auditAnnotation) throws Throwable {
                  
                  boolean ok = false;
                  Object o = null;
                  AuditData auditData = null;
                  try 
                  {
                      auditData = buildAuditData(auditAnnotation, proceedingJoinPoint.getThis(), 
                              proceedingJoinPoint.getArgs(), 
                              o, null, 10);
                      o = proceedingJoinPoint.proceed();
                      ok = true;
                      return o;
                  } 
                  finally 
                  {
                      if (ok)
                      {
          //                String value = (MessageFormat.format(auditAnnotation.value(), proceedingJoinPoint.getArgs()));
                          try 
                          {
                              AuditDataRequest auditDataRequest = new AuditDataRequest();
                              auditDataRequest.setAuditData(auditData);
                              auditDataService.addAuditData(auditDataRequest);
                              logger.info(auditData + "");
                          } 
                          catch (Exception e) 
                          {
                              logger.error(e.getMessage(), e);
                          }
                      }    
                  }
              }
              
              private String getUser()
              {
                  return "Paul";
              }
              

          }


          保存至數據庫
          package com.paul.common.audit.service;

          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.data.domain.Page;
          import org.springframework.stereotype.Service;

          import com.paul.common.audit.AuditData;
          import com.paul.common.audit.AuditDataRequest;
          import com.paul.common.audit.annotation.Audit;
          import com.paul.common.audit.repository.AuditDataRepository;
          import com.paul.program.colsubject.valueobject.ColSubjectRequest;

          @Service
          public class AuditDataService {
              
              @Autowired
              private AuditDataRepository auditDataRepository;
              
          //    @Audited(message = "save(#{args[0].name}, #{args[0].email}): #{returned?.id}")
              @Audit(behaviour="修改了審計", id="#{args[0].colSubject.id}", 
                      className="com.paul.program.colsubject.valueobject.ColSubject",
                      value="#{args[0].colSubject}")
              public void saveObject(ColSubjectRequest colSubjectRequest)
              {
                  
              }
              
              @Audit(behaviour="刪除了專題", id="#{args[0]}",
                       className="com.paul.program.subject.valueobject.Subject")
              public void delete(String id) {
              }
              
              @Audit(behaviour="新增了專題", value="#{args[0].colSubject}")
              public void add(ColSubjectRequest colSubjectRequest) {
              }
              
              public AuditData addAuditData(AuditDataRequest auditDataRequest)
              {
                  return auditDataRepository.save(auditDataRequest.getAuditData());
              }
              
              public Page<AuditData> findAll(AuditDataRequest auditDataRequest)
              {
                  Page<AuditData> page = auditDataRepository.findAll(auditDataRequest.getPageable());
                  return page;
              }

          }


          DAO
          package com.paul.common.audit.repository;

          import org.springframework.data.repository.PagingAndSortingRepository;

          import com.paul.common.audit.AuditData;

          /**
           * 審計
           * 
           
          */
          public interface AuditDataRepository extends PagingAndSortingRepository<AuditData, String>{
              
          }

          posted on 2014-07-25 14:56 paulwong 閱讀(1370) 評論(0)  編輯  收藏 所屬分類: SPRING

          主站蜘蛛池模板: 扬州市| 安塞县| 潞城市| 如皋市| 平昌县| 八宿县| 文成县| 柘荣县| 齐齐哈尔市| 云浮市| 琼中| 海口市| 安吉县| 曲麻莱县| 金华市| 临湘市| 甘谷县| 锦州市| 南康市| 沂南县| 禹城市| 大悟县| 平舆县| 金堂县| 田东县| 增城市| 海门市| 酉阳| 岳阳市| 喀喇沁旗| 连山| 都江堰市| 进贤县| 融水| 吴江市| 漳州市| 乌恰县| 鹤岗市| 玉林市| 大港区| 曲沃县|