springboot(13):spring 过滤器和拦截器的区别

在前面我们讲过拦截器怎么使用,参考:拦截器

和拦截器有个差不多的叫过滤器。

过滤器和拦截器的区别

首先看一下下面的流程图:

在这里插入图片描述
如上图,其中prehandel、posthandel、afterCompletion是拦截器的方法,filter pre和filter after是过滤器的方法。

两者区别主要有以下几点:

  1. 触发时机:过滤器是在请求进入容器后,但请求进入servlet之前进行预处理的。请求结束返回也是,是在servlet处理完后,返回给前端之前。拦截器是进入servlet之后才触发。
  2. 生命周期:Filter的生命周期由Servlet容器管理,而拦截器由spring提供,并可以使用IoC容器来管理,因此拦截器可以获取IOC容器中的各个bean,而过滤器就不行。
  3. 实现方式:过滤器实现基于回调函数,拦截器(代理模式)的实现基于反射。
  4. 执行方式:过滤器的执行由Servlet容器回调完成,而拦截器通常通过动态代理(反射)的方式来执行。
  5. 影响范围:过滤器可以修改request和response,而拦截器不能。但是过滤器只能在请求的前后使用,而拦截器可以详细到每个方法。

基于以上区别,过滤器和拦截器的使用场景通常不同。

拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现。

拦截器主要应用场景:

  • 登录验证,判断用户是否登录。
  • 权限验证,判断用户是否有权限访问资源,如校验token。
  • 日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
  • 处理cookie、本地化、国际化、主题等。
  • 性能监控,监控请求处理时长等。

过滤器主要应用场景:

  • 过滤敏感词汇(防止sql注入)
  • 设置字符编码
  • URL级别的权限访问控制
  • 压缩响应信息

过滤器的使用

有以下两种方式使用过滤器。

1.使用spring boot提供的FilterRegistrationBean

先定义Filter:只要实现接口import javax.servlet.Filter,并实现是哪个方法即可,其中最重要的是doFilter方法,在里面写我们的过滤逻辑。代码如下:

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;


public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // doFilter()方法中的servletRequest参数的类型是ServletRequest,需要转换为HttpServletRequest类型方便调用某些方法
        System.out.println("filter1");

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        String ip = request.getRemoteAddr();
        String url = request.getRequestURL().toString();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date d = new Date();
        String date = sdf.format(d);

        System.out.printf("%s %s 访问了 %s%n", date, ip, url);

        filterChain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

然后注册我们的Filter:

import com.example.server.common.MyFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean registrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new MyFilter());
        // 设置过滤的url
        filterRegistrationBean.addUrlPatterns("/*");
        // 设置优先级
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }
}

2.使用原生servlet注解定义Filter

用@WebFilter就可以进行配置。代码如下:

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.FilterConfig;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;


@Component
// 定义filterName 和过滤的url
@WebFilter(filterName = "myFilter2" ,urlPatterns = "/*")
@Order(2)
public class MyFilter2 implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("my filter2");
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}

这里需要注意一点的是@WebFilter这个注解是Servlet3.0的规范,并不是Spring boot提供的。除了这个注解以外,我们还需在启动类中加另外一个注解:@ServletComponetScan,指定扫描的包。

@SpringBootApplication
@ServletComponentScan
public class FilterTestApplication {
 
	public static void main(String[] args) {	
		ConfigurableApplicationContext applicationContext = SpringApplication.run(FilterTestApplication.class, args);
	}
}

拦截器的使用

参考文章:拦截器

参考文章:
https://blog.csdn.net/qq_49313444/article/details/107504196
https://blog.csdn.net/qq_42076204/article/details/125215984

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ethan-running

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值