1.spring配置文件配置。
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 日志拦截器 -->
<bean class="cn.jeeweb.modules.common.interceptor.LogInterceptor" >
<property name="openAccessLog" value="${openAccessLog}" />
</bean>
<mvc:interceptor>
<mvc:mapping path="/**" />
<!-- 需排除拦截的地址 -->
<mvc:exclude-mapping path="/static/**" />
<!-- 需排除拦截的地址 -->
<mvc:exclude-mapping path="/upload/**" />
<bean class="cn.jeeweb.core.interceptor.EncodingInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
2.控制类
package cn.jeeweb.modules.common.interceptor;
import java.text.SimpleDateFormat;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import cn.jeeweb.core.utils.DateUtils;
import cn.jeeweb.modules.sys.utils.LogUtils;
/**
*
* All rights Reserved, Designed By www.zhisuaninfo.com
*
* @title: LogInterceptor.java
* @package cn.jeeweb.modules.common.interceptor
* @description: 访问日志拦截器
* @author: gulf
* @date: 2018年1月11日 下午12:17:54
* @version V1.0
* @copyright: 2017 www.zhisuaninfo.com Inc. All rights reserved.
*
*/
public class LogInterceptor implements HandlerInterceptor {
private Boolean openAccessLog = Boolean.FALSE;
public void setOpenAccessLog(Boolean openAccessLog) {
this.openAccessLog = openAccessLog;
}
private static final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("ThreadLocal StartTime");
/**
* 日志对象
*/
protected Logger logger = LoggerFactory.getLogger(getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if (logger.isDebugEnabled()) {
long beginTime = System.currentTimeMillis();// 1、开始时间
startTimeThreadLocal.set(beginTime); // 线程绑定变量(该数据只有当前请求的线程可见)
logger.debug("开始计时: {} URI: {}", new SimpleDateFormat("hh:mm:ss.SSS").format(beginTime),
request.getRequestURI());
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
if (modelAndView != null) {
logger.info("ViewName: " + modelAndView.getViewName());
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
if (openAccessLog) {
// 保存日志
LogUtils.saveLog(request, handler, ex, null);
// 打印JVM信息。
if (logger.isDebugEnabled()) {
long beginTime = startTimeThreadLocal.get();// 得到线程绑定的局部变量(开始时间)
long endTime = System.currentTimeMillis(); // 2、结束时间
// logger.debug("计时结束:{} 耗时:{} URI: {} 最大内存: {}m 已分配内存: {}m 已分配内存中的剩余空间: {}m 最大可用内存: {}m",
// new SimpleDateFormat("hh:mm:ss.SSS").format(endTime),
// DateUtils.formatDateTime(endTime - beginTime), request.getRequestURI(),
// Runtime.getRuntime().maxMemory() / 1024 / 1024,
// Runtime.getRuntime().totalMemory() / 1024 / 1024,
// Runtime.getRuntime().freeMemory() / 1024 / 1024,
// (Runtime.getRuntime().maxMemory() - Runtime.getRuntime().totalMemory()
// + Runtime.getRuntime().freeMemory()) / 1024 / 1024);
}
}
}
}
3.工具类
package cn.jeeweb.modules.sys.utils;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.web.method.HandlerMethod;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import cn.jeeweb.core.utils.CacheUtils;
import cn.jeeweb.core.utils.Exceptions;
import cn.jeeweb.core.utils.IpUtils;
import cn.jeeweb.core.utils.SpringContextHolder;
import cn.jeeweb.core.utils.StringUtils;
import cn.jeeweb.modules.sys.entity.Log;
import cn.jeeweb.modules.sys.entity.Menu;
import cn.jeeweb.modules.sys.entity.User;
import cn.jeeweb.modules.sys.service.ILogService;
import cn.jeeweb.modules.sys.service.IMenuService;
import cn.jeeweb.modules.sys.tags.SysFunctions;
public class LogUtils {
public static final String CACHE_MENU_NAME_PATH_MAP = "menuNamePathMap";
private static ILogService logService = SpringContextHolder.getBean(ILogService.class);
private static IMenuService menuService = SpringContextHolder.getBean(IMenuService.class);
/**
* 保存日志
*/
public static void saveLog(HttpServletRequest request, String title) {
saveLog(request, null, null, title, null);
}
/**
* 保存日志
*/
public static void saveLog(HttpServletRequest request, String title, String content) {
saveLog(request, null, null, title, content);
}
public static void saveLog(HttpServletRequest request, Object handler, Exception ex, String title) {
saveLog(request, handler, ex, title, null);
}
/**
* 保存日志
*/
public static void saveLog(HttpServletRequest request, Object handler, Exception ex, String title, String content) {
User user = UserUtils.getUser();
if (user != null && user.getId() != null) {
Log log = new Log();
log.setTitle(title);
log.setType(ex == null ? Log.TYPE_ACCESS : Log.TYPE_EXCEPTION);
log.setRemoteAddr(IpUtils.getIpAddr(request));
log.setUserAgent(request.getHeader("user-agent"));
log.setRequestUri(request.getRequestURI());
log.setParams(request.getParameterMap());
log.setMethod(request.getMethod());
log.setContent(content);
// 异步保存日志
new SaveLogThread(log, handler, ex).start();
}
}
/**
* 保存日志线程
*/
public static class SaveLogThread extends Thread {
private Log log;
private Object handler;
private Exception ex;
public SaveLogThread(Log log, Object handler, Exception ex) {
super(SaveLogThread.class.getSimpleName());
this.log = log;
this.handler = handler;
this.ex = ex;
}
@Override
public void run() {
// 获取日志标题
if (StringUtils.isBlank(log.getTitle())) {
String permission = "";
if (handler instanceof HandlerMethod) {
Method m = ((HandlerMethod) handler).getMethod();
RequiresPermissions rp = m.getAnnotation(RequiresPermissions.class);
permission = (rp != null ? StringUtils.join(rp.value(), ",") : "");
}
log.setTitle(getMenuNamePath(log.getRequestUri(), permission));
}
// 如果有异常,设置异常信息
log.setException(Exceptions.getStackTraceAsString(ex));
// 如果无标题并无异常日志,则不保存信息
if (StringUtils.isEmpty(log.getTitle()) && StringUtils.isEmpty(log.getException())) {
return;
}
// 保存日志信息
logService.insert(log);
}
}
/**
* 获取菜单名称路径(如:系统设置-机构用户-用户管理-编辑)
*/
public static String getMenuNamePath(String requestUri, String permission) {
String url = StringUtils.substringAfter(requestUri, SysFunctions.getAdminUrlPrefix() + "/");
@SuppressWarnings("unchecked")
Map<String, String> menuMap = (Map<String, String>) CacheUtils.get(CACHE_MENU_NAME_PATH_MAP);
if (menuMap == null) {
menuMap = Maps.newHashMap();
List<Menu> menuList = menuService.selectList(new EntityWrapper<Menu>());
for (Menu menu : menuList) {
// 获取菜单名称路径(如:系统设置-机构用户-用户管理-编辑)
String namePath = "";
if (menu.getParentIds() != null) {
List<String> namePathList = Lists.newArrayList();
for (String id : StringUtils.split(menu.getParentIds(), "/")) {
/*
* if (Menu.getRootId().equals(id)){ continue; // 过滤跟节点
* }
*/
for (Menu m : menuList) {
if (m.getId().equals(id)) {
namePathList.add(m.getName());
break;
}
}
}
namePathList.add(menu.getName());
namePath = StringUtils.join(namePathList, "-");
}
// 设置菜单名称路径
if (StringUtils.isNotBlank(menu.getUrl())) {
menuMap.put(menu.getUrl(), namePath);
} else if (StringUtils.isNotBlank(menu.getPermission())) {
for (String p : StringUtils.split(menu.getPermission())) {
menuMap.put(p, namePath);
}
}
}
CacheUtils.put(CACHE_MENU_NAME_PATH_MAP, menuMap);
}
String menuNamePath = menuMap.get(url);
if (menuNamePath == null) {
for (String p : StringUtils.split(permission)) {
menuNamePath = menuMap.get(p);
if (StringUtils.isNotBlank(menuNamePath)) {
break;
}
}
if (menuNamePath == null) {
return "";
}
}
return menuNamePath;
}
}