之前用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;
}