专栏首页DT乱“码”基于springMVC拦截器实现操作日志统计

基于springMVC拦截器实现操作日志统计

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;
	}
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 简单的考勤系统

    连接数据库类 package com.lianrui.it; import java.sql.Connection; import java.sql.Driv...

    用户1220053
  • 原 mysql开启日志记录

    用户1220053
  • ClassPathXmlApplicationContext方式读取配置文件

    public interface BeanFactory {   public Object getBean(String id); }   //实现类Clas...

    用户1220053
  • 自然语言处理概论1.NLP相关学科2.相关术语3.知识内容4.发展概况5.中文特征6.中文语言处理发展的主要困难7.基础理论8.主要应用

    1.NLP相关学科 语言学 信息论 生物学 计算机科学 数学 等等...... 2.相关术语 中文信息处理 中文语言处理 计算语言学 自然语言理解 智能化人机接...

    JasonhavenDai
  • 聊聊nacos的DistroMapper

    nacos-1.1.3/naming/src/main/java/com/alibaba/nacos/naming/cluster/servers/Server...

    codecraft
  • 高效、易用、功能强大的 api 管理平台(内附彩蛋)

    征对于目前实际开发、测试、生产等环境中,需要用到各类的接口可达几十、甚至上百个,因此,必须需要一个统一管理的工具平台来统一管理这类接口,从而方便后续使用。

    民工哥
  • ELECTRA:用Bert欺骗Bert

    18年Bert横空出世,刷新了各大榜单之后,对齐的改进层出不穷,Ernie, Albert大多数改进都没有新意,无非就是大力出奇迹的堆叠参数。ICLR2020 ...

    lynne
  • Github 项目 - YOLOV3 的 TensorFlow 复现

    原文:Github 项目 - YOLOV3 的 TensorFlow 复现 - AIUAI

    AIHGF
  • iOS之Travis CI自动分发到蒲公英、fir

    image.png 懒是程序员的美德,作为程序员应该善用工具提高自己的工作效率。在我最早的时候,我是个“勤奋”的人,写好代码后,如果要给测试同学测试我的App,...

    BestSDK
  • Django源码学习-14-JsonResponse

    Django网络应用开发的5项基础核心技术包括模型(Model)的设计,URL 的设计与配置,View(视图)的编写,Template(模板)的设计和Form(...

    小团子

扫码关注云+社区

领取腾讯云代金券