1.web-info下面添加logback.xml
2.web.xml引入
logbackConfigLocation
/WEB-INF/logback.xml
ch.qos.logback.ext.spring.web.LogbackConfigListener
org.springframework.web.context.request.RequestContextListener
3.springmvc.xml中添加配置
头文件中需增加:
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd"
4.定义注解
/**
* 系统日志注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {
String value() default "";
}
5.定义日志实体
/**
* @className:OperationLog
* @description: 输出日志内容
*/
public class OperationLog {
/**
* 用户编号
*/
private String userId;
/**
* 用户名
*/
private String userName;
/**
* 操作参数
*/
private String params;
/**
* 返回信息
*/
private String returnMsg;
/**
* 调用方法名称
*/
private String method;
/**
* 请求追踪id
*/
private String traceId;
/**
* 请求Ip
*/
private String requestIp;
/**
* 操作描述
*/
private String operationDescription;
/**
* 操作开始时间
*/
private String operationStarttime;
/**
* 操作结束时间
*/
private String operationEndtime;
/**
* 操作时长
*/
private long time;
}
6.切面处理类
/**
* 系统日志,切面处理类
*
*/
@Aspect
@Component
public class SysLogAspect {
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Pointcut("@annotation(com.ehl.frame.logback.SysLog)")
public void logPointCut() {
// 读取切面日志
}
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
// 记录开始时间
long beginTime = System.currentTimeMillis();
//执行方法
Object result = point.proceed();
//返回参数,暂时去掉,返回值多容易造成读写太慢
String returnMsg = "";
//if (result != null) {
// Class cls = Class.forName(result.getClass().getName());
// if (RespMsg.class.equals(cls)) {
// RespMsg respMsg = (RespMsg) result;
// returnMsg = respMsg.getMessage();
// } else if (List.class.equals(cls)) {
// List list = (List) result;
// if (!list.isEmpty()) {
// returnMsg += "返回数量:" + list.size();
// }
// } else if (Map.class.equals(cls)) {
// Map map = (Map) result;
// if (!map.isEmpty()) {
// returnMsg += "返回数量:" + map.size();
// }
// } else if (String.class.equals(cls)) {
// returnMsg += (String) result;
// } else {
// returnMsg += JSON.toJSONString(result);
// }
//}
long endTime = System.currentTimeMillis();
//保存日志
saveSysLog(point, beginTime, endTime, returnMsg);
return result;
}
private void saveSysLog(ProceedingJoinPoint joinPoint, long beginTime, long endTime, String returnMsg) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
OperationLog operationLog = new OperationLog();
// 获取用户信息 记录用户信息
HttpSession session = HttpUtil.getSession();
String userId = null;
String userName = null;
LoginUserInfo userInfo = (LoginUserInfo) session.getAttribute("userLoginInfo");
if (userInfo != null) {
userId = userInfo.getUserId();
userName = userInfo.getRealName();
}
operationLog.setUserId(userId);
operationLog.setUserName(userName);
SysLog syslog = method.getAnnotation(SysLog.class);
if (syslog != null) {
//注解上的描述
operationLog.setOperationDescription(syslog.value());
}
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String methodName = signature.getName();
operationLog.setMethod(methodName);
Logger logger = LoggerFactory.getLogger(className);
//请求的参数
Object[] args = joinPoint.getArgs();
try {
if (args != null && args.length > 0) {
String params = JSON.toJSONString(args);
operationLog.setParams(params);
}
} catch (Exception e) {
logger.error("输出日志参数获取失败");
}
operationLog.setReturnMsg(returnMsg);
// 操作用时
operationLog.setOperationStarttime(df.format(beginTime));
operationLog.setOperationEndtime(df.format(endTime));
operationLog.setTime(endTime - beginTime);
//获取request
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
//设置IP地址
operationLog.setRequestIp(IPUtils.getIpAddr(request));
// 跟踪记录id
operationLog.setTraceId(UUID.randomUUID().toString());
//保存系统日志
String sysStr = JSONObject.toJSONString(operationLog);
logger.info(sysStr);
}
}
7.使用
@SysLog("根据id查询厂商信息")
@RequestMapping(value = "/query")
@ResponseBody
public Company query(HttpServletRequest request) {
try {
String id = request.getParameter("id");
return companyServiceImpl.query(id);
} catch (Exception e) {
log.info(e.getMessage());
Log.error("查询失败");
return null;
}
}
8.其他
/**
* 获取IP地址
*
* 使用Nginx等反向代理软件, 则不能通过request.getRemoteAddr()获取IP地址
* 如果使用了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP地址,X-Forwarded-For中第一个非unknown的有效IP字符串,则为真实IP地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {
ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
} catch (Exception e) {
logger.error("IPUtils ERROR ", e);
}
// //使用代理,则获取第一个IP地址
// if(StringUtils.isEmpty(ip) && ip.length() > 15) {
// if(ip.indexOf(",") > 0) {
// ip = ip.substring(0, ip.indexOf(","));
// }
// }
return ip;
}
public class HttpContextUtils {
public static HttpServletRequest getHttpServletRequest() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
9.补充:pom引入jar包
ch.qos.logback
logback-core
1.1.1
ch.qos.logback
logback-classic
1.1.1
org.logback-extensions
logback-ext-spring
0.1.2
org.codehaus.janino
janino
3.0.7