一个人至少拥有一个梦想,有一个理由去坚强

心若没有栖息的地方,到哪里都是在流浪

AOP异常统一处理

之前都是try{ }catch{}直接抛异常,日志直接在抛异常处打印logger,后来老大要异常统一处理,一个项目统一用

一个异常,最后统一打印日志。

AOP真是个强大的东西。

直接上代码:

ErrorCode:

package com.common.constant.errorcode;

public interface ErrorCode {
  
  int getCode();
  
  String getMsg();
  
  String getOutDesc();

}

公共的异常类,所有异常都统一抛为:SystemExcception:

package com.common.exception;

import java.io.PrintStream;
import java.io.PrintWriter;
import java.util.Map;
import java.util.TreeMap;

import com.linkingmed.raic.common.constant.errorcode.ErrorCode;

/**
 * @author
 *
 */
public class SystemException extends RuntimeException {

  /**
   * 
   */
  private static final long serialVersionUID = 8443921938965840886L;

  public static SystemException wrap(Throwable exception, ErrorCode errorCode) {
    if (exception instanceof SystemException) {
      SystemException se = (SystemException) exception;
      if (errorCode != null && errorCode != se.getErrorCode()) {
        return new SystemException(exception, errorCode);
      }
      return se;
    } else {
      return new SystemException(exception, errorCode);
    }
  }

  public static SystemException wrap(Throwable exception) {
    return wrap(exception, null);
  }

  private ErrorCode errorCode;
  private final Map<String, Object> properties = new TreeMap<String, Object>();

  
  public SystemException() {
    super();
    // TODO Auto-generated constructor stub
  }


  public SystemException(Throwable cause) {
    super(cause);
    // TODO Auto-generated constructor stub
  }

  
  public SystemException(ErrorCode errorCode) {
    this.errorCode = errorCode;
  }

  public SystemException(Throwable cause, ErrorCode errorCode) {
    super(cause);
    this.errorCode = errorCode;
  }


  public ErrorCode getErrorCode() {
    return errorCode;
  }

  public SystemException setErrorCode(ErrorCode errorCode) {
    this.errorCode = errorCode;
    return this;
  }

  public Map<String, Object> getProperties() {
    return properties;
  }

  @SuppressWarnings("unchecked")
  public <T> T get(String name) {
    return (T) properties.get(name);
  }

  public SystemException set(String name, Object value) {
    properties.put(name, value);
    return this;
  }

  public void printStackTrace(PrintStream s) {
    synchronized (s) {
      printStackTrace(new PrintWriter(s));
    }
  }

  public void printStackTrace(PrintWriter s) {
    synchronized (s) {
      s.println(this);
      s.println("\t-------------------------------");
      if (errorCode != null) {
        s.println("\t" + errorCode + ":" + errorCode.getClass().getName());
      }
      for (String key : properties.keySet()) {
        s.println("\t" + key + "=[" + properties.get(key) + "]");
      }
      s.println("\t-------------------------------");
      StackTraceElement[] trace = getStackTrace();
      /*for (int i = 0; i < trace.length; i++)
        s.println("\tat " + trace[i]);*/
      for (int i = 0; i < 3; i++)
        s.println("\tat " + trace[i]);

      /*Throwable ourCause = getCause();
      if (ourCause != null) {
        ourCause.printStackTrace(s);
      }*/
      s.flush();
    }
  }

}

aop切面捕获异常类:

package com.app.aspect;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.linkingmed.raic.common.exception.SystemException;

@Aspect
@Component
//@Order(1)
public class LoggerAspect {
  
  private Logger logger = LoggerFactory.getLogger(getClass());
  
  private static ThreadLocal<Long> startTime =null;
  
  private static final long  MS_UNIT=1000000L;
  
  private static final ObjectMapper objectMapper;
  
  
  static{
    startTime= new ThreadLocal<Long>();
    objectMapper = new ObjectMapper();
  }
  
  @Before("execution(* com.linkingmed.raic.*.api.controller..*.*(..))")
  public void doBefore(JoinPoint joinPoint) throws Throwable {
    // 接收到请求,记录请求内容
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder
        .getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    // 记录下请求内容
    doBeforeLogger(request,joinPoint);
  }

  @AfterReturning(returning = "ret", pointcut = "execution(* com.linkingmed.raic.*.api.controller..*.*(..))")
  public void doAfterReturning(Object ret) throws Throwable {
    // 处理完请求,返回内容
    logger.info("Return  Data: " + objectMapper.writeValueAsString(ret));
    
    //Integer e=TimeUtils.getInstantCurrentNanoDataTimestamp();
    Calendar calendar = Calendar.getInstance();
    //Integer e = new Date().getDate();
    Integer e = calendar.get(Calendar.DATE);
    logger.info("{} - {}","Time consuming",(e-startTime.get())/MS_UNIT+"ms");
    logger.info("{} - {}","endTime","--------------------------"+e+"(ns)----------------------------------------");
  }
  
  
  /**  
     * 异常通知 用于拦截service层记录异常日志  
     *  
     * @param joinPoint  
     * @param e  
     */    
    @AfterThrowing(pointcut = "execution(* com.linkingmed.raic.*.service..*.*(..))) ", throwing = "e")    
     public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {    
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();    
        //获取请求ip    
        String ip = request.getRemoteAddr();    
        //获取用户请求方法的参数并序列化为JSON格式字符串
        
        try {
        	printExceptionLog(joinPoint, e, ip);    
        }  catch (Exception ex) {    
            //记录本地异常日志    
            logger.info("=======================================异常通知异常======================================");    
            logger.info("{} - {}","Exception information", e.getMessage()); 
        }    
    }

    
  private void printExceptionLog(JoinPoint joinPoint, Throwable e, String ip) throws JsonProcessingException {
    StringBuilder strBuilder=new StringBuilder();
     if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) { 
         for ( int i = 0; i < joinPoint.getArgs().length; i++) {    
        	 strBuilder.append(objectMapper.writeValueAsString(joinPoint.getArgs()[i])).append(";");    
        }    
    }    
      /*========控制台输出=========*/    
    logger.info("=======================================异常通知开始====================================="); 
    if (e instanceof SystemException) {
      SystemException businessException = (SystemException) e;
      logger.error("{}-{} {}-{}","Exception infoCode:", businessException.getErrorCode().getCode(),"Exception Message:",businessException.getErrorCode().getMsg());
      StringWriter sw = new StringWriter();
      PrintWriter pw = new PrintWriter(sw);
      businessException.printStackTrace(pw);
      logger.error("{}", sw.toString());
    }
    logger.error("{} - {}","Exception Name", e.getClass().getName());    
    logger.error("{} - {}","Exception information", e.getMessage());    
    logger.error("{} - {}","Exception ClassName And Method",(joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));    
    logger.error("{} - {}","Exception Request User", "");    
    logger.error("{} - {}","Exception Host", ip);    
    logger.error("{} - {}","Parameter", strBuilder.toString());    
    logger.error("=====异常通知结束=====");
  }    
  
  /**
   * 请求打印
   * 
   * @param request
   * @param handler
   * @throws Exception
   */
  private void doBeforeLogger(HttpServletRequest request,JoinPoint joinPoint) throws Exception {
    //long b = TimeUtils.getInstantCurrentNanoDataTimestamp();
    long b = new Date().getTime();
    startTime.set(b);
    StringBuilder sb = new StringBuilder(1000);
    sb.append("-----------------------")
        .append(b)
        .append("(ns)-------------------------------------\n");
    logger.info("{} - {}", "startTime", sb.toString());
    String class_name = joinPoint.getTarget().getClass().getName();
        String method_name = joinPoint.getSignature().getName();
    	logger.info("{} : {}", "Controller", class_name);
    logger.info("{} - {} ", request.getMethod(), request.getRequestURI());
    logger.info("{} - {}", "Method", method_name);
    Enumeration<String> headNames = request.getHeaderNames();

    logger.info("Header:");
    while (headNames.hasMoreElements()) {
      String headName = headNames.nextElement();
      logger.info("    {} : {}", headName,
          Collections.list(request.getHeaders(headName)));
    }
    logger.info("Parameter:");
    // 请求参数获取
    getParam(request);
  }
  
  /**
   * 获取request的参数
   * 
   * @param request
   */
  private void getParam(HttpServletRequest request) {
    Enumeration<String> parameterNames = request.getParameterNames();
    while (parameterNames.hasMoreElements()) {
      String parameterName = parameterNames.nextElement();
      logger.info("    {} : {}", parameterName, request.getParameterValues(parameterName));
    }
  }
  
  /**
   * 拦截器具体实现
   * 
   * @param pjp
   * @return JsonResult(被拦截方法的执行结果,或需要登录的错误提示。)
   * @throws Throwable
   */
  /*
  @Around("execution(* com.linkingmed.raic.*.api.controller..*.*(..))")
  public Object Interceptor(ProceedingJoinPoint pjp) throws Throwable {
    Object result = null;
    try {
      result = pjp.proceed();
    } catch (SystemException e) {
      System.out.println("错误信息" + e.getMessage());
      System.out.println("返回值:" + objectMapper.writeValueAsString(new ReturnResult(e.getMessage())));
      return new ReturnResult(e.getMessage());
    }
    return result;
  }*/
}

抛出的异常都写在枚举中:

package com.base.api.constant;

import com.common.constant.errorcode.ErrorCode;

public enum BaseErrorCode implements ErrorCode {
  /*公共的*/
  ERR_CHECKOUT_PARAM(300001,"校验参数不够!","校验参数不够!"),
  ;
  
  private Integer code;
  private String msg;
  private String outDesc;
  
  private BaseErrorCode(Integer code, String msg, String outDesc) {
    this.code = code;
    this.msg = msg;
    this.outDesc = outDesc;
  }

  @Override
  public int getCode() {
    return code;
  }

  @Override
  public String getMsg() {
    return msg;
  }

  @Override
  public String getOutDesc() {
    return outDesc;
  }

}

抛出异常实例:

public ModelTaskInfo getAppointmentInfo(Integer prescriptionId){
  if (prescriptionId == null) {
    throw new SystemException(CommonErrorCode.ERR_COMMON_LOSE_PARAMS);
  }
  ModelTaskInfo modelTask = new ModelTaskInfo();
  try {
    modelTask = modelMapper.getModelTaskInfo(prescriptionId);
    return modelTask;
  } catch (Exception e) {
    throw new SystemException(e, BaseErrorCode .ERR_CHECKOUT_PARAM);
  }
}

 

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注