通过拦截器拦截访问url获取接口中数据进行日志保存

xml配置
web.xml中配置加载路径 参考spring.xml加载文章,进行配置加载
因为项目是maven引用加载在.pom中加载所以拦截器在底层,父类不能调用子类的方法,新写spring.xml文件拦截器进行加载(如下图)

>
>

这里写图片描述

>

HandlerInterceptor概述

在SpringMVC 中定义一个Interceptor是比较非常简单,主要有两种方式: 
第一种:实现HandlerInterceptor 接口,或者是继承实现了HandlerInterceptor 接口的类,例如HandlerInterceptorAdapter; 
第二种:实现Spring的WebRequestInterceptor接口,或者是继承实现了WebRequestInterceptor的类。 
现在主要结合一个例子说一下第一种方式:实现HandlerInterceptor接口。 

HandlerInterceptor接口主要定义了三个方法:

1. boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handle)方法:该方法将在请求处理之前进行调用,只有该方法返回true,才会继续执行后续的Interceptor和Controller,当返回值为true 时就会继续调用下一个Interceptor的preHandle 方法,如果已经是最后一个Interceptor的时候就会是调用当前请求的Controller方法; 
2.void postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法:该方法将在请求处理之后,DispatcherServlet进行视图返回渲染之前进行调用,可以在这个方法中对Controller 处理之后的ModelAndView 对象进行操作。 
3.void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法:该方法也是需要当前对应的Interceptor的preHandle方法的返回值为true时才会执行,该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。

>

方法详情

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)  
    throws Exception {  
    return true;  
}  
public void postHandle(  
        HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)  
        throws Exception {  
}  
public void afterCompletion(  
        HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)  
        throws Exception {  
}

分别实现预处理、后处理(调用了Service并返回ModelAndView,但未进行页面渲染)、返回处理(已经渲染了页面)
在preHandle中,可以进行编码、安全控制等处理;
在postHandle中,有机会修改ModelAndView;
在afterCompletion中,可以根据ex是否为null判断是否发生了异常,进行日志记录。

>

具体实现

package com.qxwljs.app.origin.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.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import com.qxwljs.app.origin.utils.DateUtils;
import com.qxwljs.app.origin.utils.LogUtils;
/**
 * origin门户登陆权限验证拦截器
 */
public class OriginLoginInterceptor extends HandlerInterceptorAdapter {
/**
 * 日志对象
 */
protected Logger logger = LoggerFactory.getLogger(getClass());
private static final ThreadLocal<Long> startTimeThreadLocal =
        new NamedThreadLocal<Long>("ThreadLocal StartTime");
@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 {
    // 保存日志
    try {
        long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)  
        long endTime = System.currentTimeMillis();  //2、结束时间  
        Long timer = endTime - beginTime;//计算耗时
        request.setAttribute("timer", timer);
        LogUtils.saveLog(request, handler, ex, null);//调用保存日志方法(方法在公共方法中)
    } catch (Exception e) {   
        e.printStackTrace();  
    }
    // 打印JVM信息。
    if (logger.isDebugEnabled()){
        long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)  
        long endTime = System.currentTimeMillis();  //2、结束时间  
        Object[] obj = new Object[10];
        obj[0] = new SimpleDateFormat("hh:mm:ss.SSS").format(endTime);
        obj[1] = DateUtils.formatDateTime(endTime - beginTime);
        obj[2] = request.getRequestURI();
        obj[3] = Runtime.getRuntime().maxMemory()/1024/1024;
        obj[4] = Runtime.getRuntime().totalMemory()/1024/1024; 
        obj[5] = Runtime.getRuntime().freeMemory()/1024/1024;
        obj[6] = (Runtime.getRuntime().maxMemory()-Runtime.getRuntime().totalMemory()+Runtime.getRuntime().freeMemory())/1024/1024;
        logger.debug("计时结束:{}  耗时:{}  URI: {}  最大内存: {}m  已分配内存: {}m  已分配内存中的剩余空间: {}m  最大可用内存: {}m",obj); 
        //删除线程变量中的数据,防止内存泄漏
        startTimeThreadLocal.remove();
    }
}
}

>

保存日志方法

package com.qxwljs.app.origin.utils;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import javax.servlet.http.HttpServletRequest;
import org.springframework.web.method.HandlerMethod;
import com.qxwljs.app.origin.annotation.Logger;
import com.qxwljs.app.origin.core.sys.model.Log;
import com.qxwljs.app.origin.core.sys.model.User;
import com.qxwljs.app.origin.core.sys.service.impl.LogService;
import com.qxwljs.framework.context.spring.SpringContextHolder;
import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
public class LogUtils {
    //工具类中的service注入不能用注解方式   所以用spring方式载入
    private static LogService logService = SpringContextHolder.getBean("logService");
    /**
     * 保存日志
     * @throws UnsupportedEncodingException 
     */
    public static void saveLog(HttpServletRequest request, Object handler, Exception ex, String title) throws UnsupportedEncodingException{
        User user = UserUtils.getSession(User.SESSION_KEY);
        if (user != null && user.getId() != null){
            Log log = new Log();
            log.setTitle(title);
            log.setType(ex == null ? Log.TYPE_ACCESS : Log.TYPE_EXCEPTION);// 类型(1:接入日志;2:错误日志)
            log.setTimer(Long.parseLong(request.getAttribute("timer")+""));// 耗时
            log.setRemoteaddr(StringUtils.getRemoteAddr(request));// 操作用户的IP地址
            log.setUseragent(request.getHeader("user-agent"));// 操作用户代理信息
            log.setRequesturi(request.getRequestURI());// 操作的URI
            log.setParams(request.getParameterMap());// 操作提交的数据
            log.setMethod(request.getMethod()); // 操作的方式
        UserAgent userAgent = UserAgent.parseUserAgentString(request.getHeader("User-Agent"));
        String browser =userAgent.getBrowser().getName();//获取浏览器名称
        String windows =userAgent.getOperatingSystem().getName();//获取操作系统
        log.setBrowsername(browser);// 浏览器名称
        log.setWindows(windows);//操作系统名称
        log.setCity(IpAddress.getAddresses("ip="+StringUtils.getRemoteAddr(request), "utf-8"));//ip所在市
        User u = UserUtils.getSession(User.SESSION_KEY);
        if (u != null) {
            log.setCreateby(u.getId().toString());
            log.setUpdateby(u.getId().toString());
        }
        log.setCreatedate(System.currentTimeMillis());
        log.setUpdatedate(System.currentTimeMillis());
    // 异步保存日志
        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 title = null ;
            if (handler instanceof HandlerMethod){
                Method m = ((HandlerMethod)handler).getMethod();
                Logger clazz = m.getDeclaringClass().getAnnotation(Logger.class);//类注解
                Logger method = m.getAnnotation(Logger.class);//方法注解

                if(clazz != null && method != null) {
                    String[] s = new String[2];
                    s[0] = clazz.name();
                    s[1] = method.name();
                    title = StringUtils.join(s, "-");
                }else {
                    title = ""; 
                }
            }
            log.setTitle(title);
        }
        // 如果有异常,设置异常信息
        log.setException(Exceptions.getStackTraceAsString(ex));
        // 如果无标题并无异常日志,则不保存信息
        if (StringUtils.isBlank(log.getTitle()) && StringUtils.isBlank(log.getException())){
            return;
        }
        // 保存日志信息
        logService.save(log);
    }
}
}
  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计的实现,以及它们在MATLAB环境的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值