JAVA共通ログ記録方法の実現

9104 ワード

前言:
以前はfilter層で直接にhttp ServerletRequestをフィルタしてログ処理を要求しましたが、その後は再びget Writer()の時にalready been call異常を報告します。調べてみたら、元の流れの形式は一回しか読み取れませんでした。食べ物のようです。食べたらなくなります。だからfilterとinteceptorではrequestの流れを取ることでログを記録することはできません。
そこでやはり共通の方法を使うつもりです。controller層aopでログを記録します。
Aopを使って操作ログを記録します。
ステップ1:Aopを追加

/**
 *       Handler
 * @author Mingchenchen
 *
 */
public class LogAopHandler {
  @Autowired
  private AuditLogDao auditLogDao;

  /**
   * controller        
   *      aop:around                          
   * @throws Throwable 
   */
  public Object doSaveLog(ProceedingJoinPoint joinPoint) throws Throwable { 
    MethodSignature method = (MethodSignature) joinPoint.getSignature();
    String methodName = method.getName();
    Object[] objects = joinPoint.getArgs();
    String requestBody = null;
    if (objects!=null && objects.length>0) {
      for (Object object : objects) {
        if (object == null) {
          requestBody = null;//POST           XXX
        }else if (object instanceof String) {
          requestBody = (String) object;//               
        }else {
          requestBody = JSONObject.toJSONString(object);
        }
      }
    }

    //   POST     
    boolean isNeedSaveLog = false;
    //     getAnnotationByType  JAVA8   ,        ,        
    RequestMapping annotation = method.getMethod().getAnnotation(RequestMapping.class);
    for (RequestMethod requestMethod : annotation.method()) {
      if (requestMethod==RequestMethod.POST) {
        isNeedSaveLog = true;
      }
    }

    JSONObject requestBodyJson = null;
    try {
      requestBodyJson = JSONObject.parseObject(requestBody);
    } catch (Exception e) {
      //do nothing  POST    body
    }
    HttpServletRequest request = RequestContextUtil.getRequestByCurrentContext();
    String userName = RequestContextUtil.getUserNameByCurrentContext();
    if (StringUtil.isEmpty(userName)) {
      try {
        userName = DmsCache.get(requestBodyJson.getString("userName")).getName();
      } catch (Exception e) {
        userName = RequestContextUtil.getAsynUserInfoByAutoDeploy().getName();
      }
    }

    //  request           
    //  around        result             
    Object result = joinPoint.proceed(objects);
    try {
      JSONObject resultJson = JSONObject.parseObject(result.toString());
      if (isNeedSaveLog) {//   POST        
        LogTypeEnum logTypeEnum = LogTypeEnum.getDesByMethodName(methodName);
        if (logTypeEnum != null) {
          AuditLogEntity auditLogEntity = new AuditLogEntity();
          auditLogEntity.setUuid(StringUtil.createRandomUuid());
          auditLogEntity.setOperator(userName);
          auditLogEntity.setRequestIp(request.getRemoteAddr());
          auditLogEntity.setRequestUrl(request.getRequestURI().replace("/cloud-master", ""));
          auditLogEntity.setEventType(logTypeEnum.getKey());
          auditLogEntity.setEventDesc(logTypeEnum.getDescription());
          auditLogEntity.setRequest(requestBody);
          int isSuccess = "200".equals(resultJson.getString("code")) ? 1 : 0;
          auditLogEntity.setSuccessFlag(isSuccess);
          auditLogEntity.setResponse(result.toString());
          auditLogEntity.setCreateTime(new Date());
          auditLogDao.insert(auditLogEntity);
        }
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  } 
}

ステップ2:springのxmlに声明を出す

  <!--        -->
  <bean id="operationLogAop" class="com.ming.learn.core.aop.LogAopHandler"/>
   <aop:config>
    <aop:aspect id="logAOP" ref="operationLogAop">
     <aop:pointcut id="target" expression="execution(* com.ming.learn..*Controller.*(..))"/>
     <aop:around method="doSaveLog" pointcut-ref="target"/>
    </aop:aspect>
   </aop:config>

これでコアステップが完成し、残りは自分で組み立てて記録するものです。
ステップ3:Dao、Entity、Mapperを書く

import java.util.Date;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 *     
 * @author Mingchenchen
 *
 */
@Table(name="audit_log")
public class AuditLogEntity {
  @Id
  private String uuid;

  @Column(name="event_type")
  private String eventType;//    

  @Column(name="event_desc")
  private String eventDesc;//      

  @Column(name="operator")
  private String operator;//   

  @Column(name="request_ip")
  private String requestIp;//     

  @Column(name="request_url")
  private String requestUrl;//    

  @Column(name="request")
  private String request;//  body

  @Column(name="response")
  private String response;//     

  @Column(name="create_time")
  private Date createTime;

  public String getUuid() {
    return uuid;
  }

  public void setUuid(String uuid) {
    this.uuid = uuid;
  }

  public String getEventType() {
    return eventType;
  }

  public void setEventType(String eventType) {
    this.eventType = eventType;
  }

  public String getEventDesc() {
    return eventDesc;
  }

  public void setEventDesc(String eventDesc) {
    this.eventDesc = eventDesc;
  }

  public String getOperator() {
    return operator;
  }

  public void setOperator(String operator) {
    this.operator = operator;
  }

  public String getRequestIp() {
    return requestIp;
  }

  public void setRequestIp(String requestIp) {
    this.requestIp = requestIp;
  }

  public String getRequestUrl() {
    return requestUrl;
  }

  public void setRequestUrl(String requestUrl) {
    this.requestUrl = requestUrl;
  }

  public String getRequest() {
    return request;
  }

  public void setRequest(String request) {
    this.request = request;
  }

  public String getResponse() {
    return response;
  }

  public void setResponse(String response) {
    this.response = response;
  }

  public Date getCreateTime() {
    return createTime;
  }

  public void setCreateTime(Date createTime) {
    this.createTime = createTime;
  }
}

第四ステップ:Controllerの方法名によるカスタマイズ応答のイベントタイプ

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 *       
 * @author Mingchenchen
 *
 */
public enum LogTypeEnum {
  //  
  COMMON_LOGIN("login","login","  ");
  //  

  private String methodName;//     controller  
  private String key;//           
  private String description;//         
  private LogTypeEnum(String methodName,String key,String description){
    this.methodName = methodName;
    this.key = key;
    this.description = description;
  }
  public String getMethodName() {
    return methodName;
  }
  public void setMethodName(String methodName) {
    this.methodName = methodName;
  }
  public String getKey() {
    return key;
  }
  public void setKey(String key) {
    this.key = key;
  }
  public String getDescription() {
    return description;
  }
  public void setDescription(String description) {
    this.description = description;
  }

  /**
   *        
   * @param methodName
   * @return
   */
  public static LogTypeEnum getDesByMethodName(String methodName){
    return innerMap.map.get(methodName);
  }

  /**
   *            enum     Enum.values()    
   * @author Mingchenchen
   *
   */
  private static class innerMap{
    private static Map<String, LogTypeEnum> map = new ConcurrentHashMap<>(128);

    static{
      //         Map
      for (LogTypeEnum logTypeEnum : LogTypeEnum.values()) {
        map.put(logTypeEnum.getMethodName(), logTypeEnum);
      }
    }
  }
}

以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。