spring拦截器 实现应用之性能监控
package cn.ximi.erp.web.common.interceptors; import cn.ximi.core.common.utils.string.StringUtil; import cn.ximi.erp.web.constant.Constants; import cn.ximi.erp.web.base.UserContext; import cn.ximi.manage.entity.SysResource; import cn.ximi.manage.entity.SysUser; import cn.ximi.manage.service.ResourceService; import cn.ximi.manage.service.SysUserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.NamedThreadLocal; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; import java.util.Set; /** * 登录拦截器 * ( * 实现应用之性能监控 * 拦截器是实现成单例的,因此不管用户请求多少次都只访问同一个拦截器实现,即线程不安全。 * 解决方案是:使用ThreadLocal,它是线程绑定的变量,提供线程局部变量(一个线程一个ThreadLocal, * A线程的ThreadLocal只能看到A线程的ThreadLocal,不能看到B线程的ThreadLocal)。 * ) * Created by gmq on 2016/4/28. */ public class LoginInterceptor implements HandlerInterceptor { private static final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class); // 统计应用性能 private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<>("StopWatch-StartTime"); @javax.annotation.Resource private SysUserService sysUserService; @Autowired private ResourceService resourceService; private Set<String> excludeURIs; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 设置起始时间 // 1、开始时间 long startTime = System.currentTimeMillis(); // 线程绑定变量(该数据只有当前请求的线程可见) startTimeThreadLocal.set(startTime); String requestUri = request.getRequestURI(); UserContext loginUser = (UserContext) request.getSession().getAttribute(Constants.CURRENT_USER); if (excludeURIs.contains(requestUri)) { return true; } else { // 判断是否已经登录 Subject subject = SecurityUtils.getSubject(); String userId = (String) subject.getPrincipal(); if (StringUtil.isNotEmpty(userId)) { SysUser user = sysUserService.findByUsername(userId); // menu菜单 Set<String> permissions = sysUserService.findPermissions(user.getUsername()); List<SysResource> menus = resourceService.findByMenus(permissions); if (user != null) { UserContext userContext = new UserContext(user.getId(), user.getOrganizationId(), user.getUsername(), user.getRoleIds(), user.getLocked(), user.getRealname(), user.getSex(), user.getMobile(), user.getRoleNames(), menus,"/static/images/pixel-admin/avatar.png"); request.getSession().setAttribute(Constants.CURRENT_USER, userContext); } } UserContext loginInfo = (UserContext) request.getSession().getAttribute(Constants.CURRENT_USER); if (loginInfo == null) { response.sendRedirect(getBasePath(request) + "login.htm"); return false; } return true; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 统计应用的性能 // 2、结束时间 long endTime = System.currentTimeMillis(); // 得到线程绑定的局部变量(开始时间) long beginTime = startTimeThreadLocal.get(); // 3、消耗的时间 long consumeTime = endTime - beginTime; // 此处认为处理时间超过500毫秒的请求为慢请求 if(consumeTime > 500) { //TODO 记录到日志文件 logger.warn("监控==========================: " + String.format("%s consume %d millis", request.getRequestURI(), consumeTime)); } } private boolean contains(Set<String> sets, String key) { boolean result = false; if (sets != null && sets.size() > 0) { for (String s : sets) { if (s.indexOf(key) != -1) { result = true; break; } } } return result; } private String getBasePath(HttpServletRequest request) { int port = request.getServerPort(); return request.getScheme() + "://" + request.getServerName() + ((port == 80) ? "" : (":" + port)) + request.getContextPath() + "/"; } public Set<String> getExcludeURIs() { return excludeURIs; } public void setExcludeURIs(Set<String> excludeURIs) { this.excludeURIs = excludeURIs; } }
弱水_穿云天