拦截器与过滤器

  1. 拦截器

   介绍:主要用于拦截用户请求并作出相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、登录验证等。

   原理:所有的拦截器 (Interceptor) 和处理器 (Handler) 都注册在 HandlerMapping 中,Spring MVC 中所有的请求都是由 DispatcherServlet 分发的。当请求进入时,首先会得到处理该请求的 Handler (即 Controller 中对应的方法)以及所有拦截该请求的拦截器

   实现:这里先定义一个拦截器

package com.elite.groovy.interceptor;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author Smith
 * @date 2023/8/23  17:08
 * @description 接口访问拦截器
 */
@Slf4j
@Component
public class ProxyInterceptor implements HandlerInterceptor {

    /**
     * 预处理回调方法,实现处理器的预处理(如登录检查)
     * 第三个参数为响应的处理器,即controller
     * 返回true,表示继续流程,调用下一个拦截器或者处理器
     * 返回false,表示流程中断,通过response产生响应
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("收到前端的请求,url:" + request.getRequestURL());
        log.info("请求参数 :" + IOUtils.toString(request.getInputStream(), "utf-8"));
        return true;
    }

    /**
     * 当前请求进行处理之后,也就是Controller方法调用之后执行,
     * 但是它会在DispatcherServlet 进行视图返回渲染之前被调用。
     * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理。
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {

    }

    /**
     * 方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行。
     * 这个方法的主要作用是用于进行资源清理工作的。
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    }
} 

  其次配置拦截器

package com.elite.groovy.config;

import com.elite.groovy.interceptor.ProxyInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Autowired
    private ProxyInterceptor ipInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(ipInterceptor)
                .addPathPatterns("/**");
    }
}
  1. 过滤器

   介绍:过滤器是Servlet的高级特性之一,是实现Filter接口的Java类。其基本功能就是对servlet的调用进行干预,在servl请求和响应的过程中增加一些特定的功能。可以使用过滤器实现的功能有:统一编码,URL级别的权限访问控制,过滤敏感词汇,压缩请求信息

   实现:

package com.elite.ngs.filter;

import com.wisdge.web.IPUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * @author smith
 * @date 2023/1/11  13:44
 */
@WebFilter(urlPatterns = {"/smsCodeSend_"}, filterName = "smsFilter")
public class SmsFilter implements Filter {
    private static final Log log = LogFactory.getLog(SmsFilter.class);
    protected RedisTemplate redisTemplate;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        ServletContext servletContext = filterConfig.getServletContext();
        WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext);
        redisTemplate = (RedisTemplate) webApplicationContext.getBean("redisTemplate");
        log.debug("------smsFilter init!-------");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        log.debug("--------start smsFilter-------------");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String ip = IPUtils.getRemoteIP(request);
        log.debug("smsSend ip :" + ip);
        String smsKey = "SMS:" + ip;
        //先看Key是否存在
        boolean flag = redisTemplate.hasKey(smsKey);
        if (flag) {
            //说明上次发送验证码的时间不超过一分钟
            log.debug("smsKey exist");
        } else {
            // 第一次调用,所以value(调用次数)设置为1
            redisTemplate.opsForValue().set(smsKey, "1", 1, TimeUnit.MINUTES);
            filterChain.doFilter(request, servletResponse);
        }
    }

    @Override
    public void destroy() {
        log.debug("------smsFilter destroy----");
    }
}

  配置filter

  第一个是上面的例子,使用WebFilter注解,但是多个filter时无法控制先后顺序,只会根据filter的首字母顺序来确定先后顺序。

  第二个是在web.xml中配置,执行顺序按配置的上下先后顺序执行

  filter标签:fliter-name:指为过滤器的名字;filter-class:过滤器的完整类名

  filter-mapping标签:fliter-name是filter标签中声明的名字;url-pattern用来设置filter所拦截的请求路径。

<filter>
    <filter-name>myFilter</filter-name>
    <filter-class>com.lsl.mylsl.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/test</url-pattern>
</filter-mapping>
<filter>
    <filter-name>myFilter</filter-name>
    <filter-class>com.lsl.mylsl.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/test</url-pattern>
</filter-mapping>
  1. 区别

  a.过滤器依赖servlet容器(tomcat等,只能在web程序中使用);而拦截器不依赖servlet容器。它是个spring组件,由spring容器管理,可以单独使用。

  b.过滤器可以拦截所有请求,包括访问静态资源的请求,拦截器只能拦截action请求,即访问controller的请求

  c.拦截器可以获取IOC容器中的各个bean,而过滤器不行。可以在拦截器里注入一个service,可以调用业务逻辑

  d.触发时机不同。过滤器是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后;拦截器是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。

posted @ 2024-05-11 16:46  写字楼间写字员  阅读(20)  评论(0编辑  收藏  举报