java过滤器和拦截器的使用及其区别

1.过滤器:

依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,获取我们想要获取的数据,比如:在过滤器中修改字符编码;在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等

过滤器的顺序每一次都将chain对象传入,达到最后接口回调的效果:

java过滤器和拦截器的使用及其区别_第1张图片

一、实现原理不同

过滤器的实现基于回调函数拦截器基于Java的反射机制【动态代理】实现。

二、使用范围不同

过滤器是Servlet的规范,需要实现javax.servlet.Filter接口,Filter使用需要依赖于Tomcat等容器。拦截器是Spring组件,定义在org.springframework.web.servlet包下,由Spring容器管理【又有更加丰富的生缪那个周期处理方法,细粒度,且能够使用Spring中的资源】,不依赖Tomcat等容器。

2.拦截器:

依赖于web框架,在SpringMVC中就是依赖于SpringMVC框架。在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个controller生命周期之内可以多次调用。但是缺点是只能对controller请求进行拦截,对其他的一些比如直接访问静态资源的请求则没办法进行拦截处理

拦截器的顺序preHandle1 -> preHande2 -> 【Controller】 -> postHandle2 -> postHandle1 -> afterCompletion2 -> afterComplention1

preHandle按照注册顺序,后两个与注册顺序相反。

一个拦截器的preHandle为false,则之后的所有拦截器都不会执行。一个拦截器的preHandle为true,则这个拦截器的triggerAfterCompletion一定会执行。只有所有的拦截器preHandler都为true,也就是正常执行,postHandle才会执行。

简而言之:

  1. 相比于拦截器,过滤器更加底层,执行时机更靠前,有利于防渗透扫描
  2. 过滤器可以拦截静态资源,方便我们做一些权限控制
  3. 部分Web框架根本就没有提供拦截器功能,但几乎所有的Web框架都会提供过滤器机制

但是过滤器也有一些缺点,比如:

  1. 由于太过底层,导致无法率先拿到HandlerMethod对象,无法据此添加一些额外功能
  2. 由于拦截的太全面了,导致我们需要对很多特殊路由(如/favicon.ico)做一些额外处理
  3. 在Spring中,过滤器中抛出的异常无法进入全局@ExceptionHandler,我们必须额外编写代码进行异常处理

主要区别:

1、拦截器是基于Java的反射机制的,而过滤器是基于函数回调。

2、拦截器不依赖于servlet容器,过滤器依赖于servlet容器。

3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。

4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。

5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次

6、拦截器可以获取IOC容器中的各个bean(基于FactoryBean接口 ),而过滤器就不行,在拦截器里注入一个service,可以调用业务逻辑。

本质区别:   

从灵活性上说拦截器功能更强大些,Filter能做的事情它都能做,而且可以在请求前,请求后执行,比较灵活。

Filter主要是针对URL地址做一个编码的事情、过滤掉没用的参数、安全校验,其他的还是建议用interceptor。

java过滤器和拦截器的使用及其区别_第2张图片

过滤器-----拦截前-----Action处理-----拦截后-----过滤后。

java过滤器和拦截器的使用及其区别_第3张图片

java过滤器和拦截器的使用及其区别_第4张图片

 过滤器中获取流丢失问题解决

import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StreamUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.Charset;

/**
 * 单点登录Filter
 *
 * @author hbw
 */
@Slf4j
@Component
public class LoginFilter implements Filter {

    private final Logger logger = LoggerFactory.getLogger(getClass());

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        String loginUrl = "http://server.smart-sso.com:8080/login?appId=demo1&redirectUri=http://demo.smart-sso.com:8082/";
        log.info("前" + loginUrl);
//        ServletRequest requestWrapper= new ContentCachingRequestWrapper((HttpServletRequest) request);
        // 一个request的包装类,初始化时缓存了body,重写了getInputStream返回缓存的body,实现重复读取body
        BodyCacheReaderRequestWrapper requestWrapper = new BodyCacheReaderRequestWrapper(httpRequest);
        String requestURI = requestWrapper.getRequestURI();
        System.out.println("--------------------->过滤器:请求地址" + requestURI);
        String str = getBody(requestWrapper);
        log.info(str);
//		httpResponse.sendRedirect(loginUrl);
        filterChain.doFilter(requestWrapper, httpResponse);
        log.info("后" + loginUrl);
        log.info(JsonHelper.toJson(httpRequest.getAttributeNames()));

    }

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


    public String getBody(HttpServletRequest request) {
        try {
            ServletInputStream in = request.getInputStream();
            String body;
            body = StreamUtils.copyToString(in, Charset.forName("UTF-8"));
            return body;
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }
}

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;

public class BodyCacheReaderRequestWrapper extends HttpServletRequestWrapper {
    private final String body;
 
    /**
     *
     * @param request
     */
    public BodyCacheReaderRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        StringBuilder sb = new StringBuilder();
        InputStream ins = request.getInputStream();
        BufferedReader isr = null;
        try{
            if(ins != null){
                isr = new BufferedReader(new InputStreamReader(ins));
                char[] charBuffer = new char[128];
                int readCount = 0;
                while((readCount = isr.read(charBuffer)) != -1){
                    sb.append(charBuffer,0,readCount);
                }
            }else{
                sb.append("");
            }
        }catch (IOException e){
            throw e;
        }finally {
            if(isr != null) {
                isr.close();
            }
        }
 
        sb.toString();
        body = sb.toString();
    }
 
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }
 
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
        ServletInputStream servletIns = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }
 
            @Override
            public boolean isReady() {
                return false;
            }
 
            @Override
            public void setReadListener(ReadListener readListener) {
 
            }
 
            @Override
            public int read() throws IOException {
                return byteArrayIns.read();
            }
        };
        return  servletIns;
    }
}

你可能感兴趣的:(java,开发语言)