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;
    }
}
原文地址:https://www.cnblogs.com/gmq-sh/p/6135220.html