我们日常开发项目的时候,都是要记录用户的行为,后台代码出错等事情,因此需要记录日志。而这里我总结了针对后台产生的异常记录日志的办法。先补充下springmvc中处理异常的方式:
使用@ExcpeitonHandler注解
在Controller类中,方法随便写,参数为Excepiton对象,是程序抛出的Exception,springmvc捕获并传到这里
@ExceptionHandler
public String testException(Exception e){
if(e instanceof TestException){
return "test2";
}else{
return "test1";
}
}
每次抛出的异常,springmvc会在该方法中进行处理
关于一些异常处理的工具类
/**
* Copyright (c) 2005-2012 springside.org.cn
*
* Licensed under the Apache License, Version 2.0 (the "License");
*/
package lms.common.utils;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lms.common.config.Global;
import lms.modules.sys.aop.GetMethodNameAOP;
import lms.modules.sys.entity.Log;
import lms.modules.sys.entity.User;
import lms.modules.sys.interceptor.LogInterceptor;
import lms.modules.sys.service.LogService;
import lms.modules.sys.support.Users;
/**
* 关于异常的工具类.
* @author calvin
* @version 2013-01-15
*/
public class Exceptions {
/**
* 假如由框架得到异常,那么拦截器将不会得到异常,此时需要先用flagEx把这个异常存起,拦截器保存时再取
*/
private static Exception flagEx = null;
private static Logger logger = LoggerFactory.getLogger(LogInterceptor.class);
private static LogService logService = SpringContextHolder.getBean(LogService.class);
/**
* 将CheckedException转换为UncheckedException.
*/
public static RuntimeException unchecked(Exception e) {
if (e instanceof RuntimeException) {
return (RuntimeException) e;
} else {
return new RuntimeException(e);
}
}
/**
* 将ErrorStack转化为String.
*/
public static String getStackTraceAsString(Exception e) {
StringWriter stringWriter = new StringWriter();
e.printStackTrace(new PrintWriter(stringWriter));
return stringWriter.toString();
}
/**
* 判断异常是否由某些底层的异常引起.
*/
@SafeVarargs
public static boolean isCausedBy(Exception ex, Class<? extends Exception>... causeExceptionClasses) {
Throwable cause = ex.getCause();
while (cause != null) {
for (Class<? extends Exception> causeClass : causeExceptionClasses) {
if (causeClass.isInstance(cause)) {
return true;
}
}
cause = cause.getCause();
}
return false;
}
/**
* whc,打印异常信息
*/
public static String getTips(String exception,Exception e){
StringBuffer tips = new StringBuffer();
StackTraceElement[] stacks = e.getStackTrace();
tips.append("Exception:").append(exception).append("; Class:").append(stacks[0].getClassName())
.append("; Method:").append(stacks[0].getMethodName())
.append("; Line:").append(stacks[0].getLineNumber());
return tips.toString();
}
/**
* whc,手动保存异常
*/
public static void saveException(Exception ex,HttpServletRequest request){
request.setAttribute("haveSave", "true");
saveLog(ex.toString(),request,null);
//控制台打印异常信息
System.out.println(getTips("Custom_Exception",ex));
}
/**
* whc,
*/
public static void saveLog(String ex,HttpServletRequest request,Object handler){
//lms.properties设置的开关
//当值为true表示开,flase表示关
String crud = Global.getCrud();
String exception = Global.getException();
/*
* 当CRUD开关为开的时候,则判断该操作是不是CRUD操作
* 当CRUD开关为关的时候,则不管是不是CRUD操作,都记录,此时optionCrud恒为true
*/
boolean optionCrud;
if(crud.equals("true")) optionCrud = isCRUD(request);
else optionCrud = true;
/*
* 只需要判断配置文件的设置和实际的方法是否配置即可,不存在开关的说法
*/
boolean optionMethodType = methodType(request);
/*
* 当异常开关为开的时候,则有异常才记录,此时先判断该操作是不是有异常操作
* 当异常开关为关的时候,则不管有没有异常,都记录,此时optionException恒为true
*/
boolean optionException;
if(exception.equals("true")) optionException = isException(ex);
else optionException = true;
if(optionCrud && optionMethodType && optionException){
User user = Users.currentUser();
if (user != null && StringUtils.isNotEmpty(user.getId()))
{
Log log = new Log();
log.setUser(user);
log.setUserName(user.getName());
log.setLoginName(user.getLoginName());
String uri = request.getRequestURI();
log.setUri(uri.substring(request.getContextPath().length()));
log.setMethod(request.getMethod());
log.setAccessorIp(getRemoteIp(request));
StringBuilder params = new StringBuilder();
int index = 0;
for (Object param : request.getParameterMap().keySet()){
params.append((index++ == 0 ? "" : "&") + param + "=");
params.append(StringUtils.abbr(StringUtils.endsWithIgnoreCase((String)param, "password")
? "" : request.getParameter((String)param), 100));
}
log.setParams(params.toString());
if(handler != null)
log.setHandlers(handler.toString());
else
log.setHandlers("");
log.setException(ex!=null?ex:"");
log.setType(ex == null ? Log.TYPE_ACCESS : Log.TYPE_EXCEPTION);
//mac地址,用户浏览器,用户操作系统 暂无
log.setCon_class(GetMethodNameAOP.getConClassName());
log.setCon_method(GetMethodNameAOP.getConMethodName());
log.setSer_class(GetMethodNameAOP.getSerClassName());
log.setSer_method(GetMethodNameAOP.getSerMethodName());
//操作状态,备注信息 暂无
logService.save(log);
logger.info("save log {type: {}, loginName: {}, uri: {}}, ", log.getType(), user.getLoginName(), log.getUri());
}
}
}
/**
* whc,@return true=match,false=not match
*/
private static boolean isCRUD(HttpServletRequest request){
String uri = request.getRequestURI();
boolean flag = StringUtils.endsWith(uri, "/save") || StringUtils.endsWith(uri, "/delete") ||
StringUtils.endsWith(uri, "/potatoTask") || StringUtils.endsWith(uri, "/list") ||
StringUtils.endsWith(uri, "/saveEdit") || StringUtils.endsWith(uri, "/getTaskDetail") ;
return flag;
}
/**
* whc,@return true=match,false=not match
*/
private static boolean methodType(HttpServletRequest request){
return request.getMethod().equalsIgnoreCase(Global.getMethodTyle());
}
/**
* whc,@return true=有异常,false=没有异常
*/
private static boolean isException(String ex){
return ex.equals("") ? false:true;
}
/**
* 得到远程IP
*/
private static String getRemoteIp(HttpServletRequest request) {
String ip = request.getRemoteAddr();
String rip = request.getHeader("X-Real-IP");
if (rip == null) {
rip = request.getHeader("X-Forwarded-For");
}
return rip != null ? rip : ip;
}
public static Exception getFlagEx() {
return flagEx;
}
public static void setFlagEx(Exception flag) {
flagEx = flag;
}
}