spring aop 切面记录log4j日志 之around记录异常信息

之前用spring的xml配置文件做的aop切面日志记录,现在呢,想实现当方法中有异常时,将异常信息写入日志文件中且不抛出错误信息

查了好多博客,大部分是在方法的try catch中log.error记录异常信息,but,aop是切面,就想着用aop:aspect下的某种方式实现,减少修改量和代码的重复,aop:around和aop:after-throwing都试了试,若在方法中进行了trycatch,日志类则捕获不到异常,所以对方法直接throw。

aop:after-throwing其意为当方法执行抛出一个异常后,会执行这个方法。即已经捕获到了异常
它的配置文件直接将异常抛出,页面会展示出错误的信息,这是不允许被用户看到的;若不加throwing,启动项目时会报错。也想过对捕获的异常进行处理不抛出,但是没有实现。

<aop:after-throwing method="afterThrow" pointcut-ref="logPointCut" throwing="ex"/>
public void afterThrow(JoinPoint jp,Exception ex){

}

around可以解决我的问题。
用Object result = methodInvocation.proceed();执行方法,否则方法不会执行。
相当于around中调用了要访问的方法,方法throw出的异常,谁调用谁处理,故能用trycatch去进行处理不抛出并记录下异常信息。

<!-- 激活自动代理功能 -->
        <aop:aspectj-autoproxy proxy-target-class="true" />

        <bean id="logInterceptor" class="com.gray.interceptor.LogInterceptor" />
        <aop:config>  
            <aop:aspect id="logAspect" ref="logInterceptor">  
                <aop:pointcut expression="execution(* com.gray..*.*(..))" id="logPointCut"/>  
                <aop:before method="before" pointcut-ref="logPointCut"/>
                <aop:around method="around" pointcut-ref="logPointCut" />
            </aop:aspect>  
        </aop:config>
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.apache.struts2.ServletActionContext;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

import com.opensymphony.xwork2.ActionContext;

public class LogInterceptor{

    private final Logger logger = Logger.getLogger(LogInterceptor.class);//log4j

    /**
     * 前置方法,在目标方法执行前执行
     */
    public void before(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();//执行的方法名
        String entity = joinPoint.getTarget().getClass().getName();//执行的类
        logger.info("start! "+entity+"."+methodName);
    }


    public Object  around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
        String methodName = proceedingJoinPoint.getSignature().getName();
        String entity = proceedingJoinPoint.getTarget().getClass().getName();
        JSONObject result =new JSONObject();
        try {
                result = (JSONObject) proceedingJoinPoint.proceed();//test方法的返回值
        } catch (Exception ex) {
        //test方法若有异常,则进行处理写入日志
            result.put("success", false);
            result.put("desc", "exception");

            HttpServletRequest request = (HttpServletRequest) ActionContext.getContext().get(ServletActionContext.HTTP_REQUEST);
            //获取请求的URL
            StringBuffer requestURL = request.getRequestURL();
            //获取参 数信息
            String queryString = request.getQueryString(); 
            //封装完整请求URL带参数
            if(queryString != null){  
                requestURL .append("?").append(queryString);  
            }

            String errorMsg = "";
            StackTraceElement[] trace = ex.getStackTrace();
            for (StackTraceElement s : trace) {
                errorMsg += "\tat " + s + "\r\n";
            }

            StringBuffer sb=new StringBuffer();
            sb.append("exception!!!\r\n");
            sb.append("   请求URL:"+requestURL+"\r\n");
            sb.append("   接口方法:"+entity+"."+methodName+"\r\n");
            sb.append("   详细错误信息:"+ex+"\r\n");
            sb.append(errorMsg+"\r\n");
            logger.error(sb.toString());
        }
        if(result!=null && !result.isEmpty()){
             HttpServletResponse response = (HttpServletResponse) ActionContext.getContext().get(ServletActionContext.HTTP_RESPONSE);
             response.getWriter().print(result.toString());
        }
        return null;
    }
}

测试方法:(方法中的异常不try catch,否则日志类捕获不到异常)

public JSONObject test()throws Exception{
    JSONObject result =new JSONObject();
    result.put("success", true);
    result.put("desc", "success");
    int i = 1/0;//制造异常
    return result;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值