La diferencia entre interceptor y filter en Java y la realización de sus respectivas funciones

prefacio

Esta publicación de blog principalmente quiere expresar los siguientes aspectos

  • ¿Qué es un filtro?
  • ¿Qué es un interceptor?
  • ¿Cuál es la diferencia entre filtro e interceptor?
  • ¿Cuáles son los escenarios de aplicación de filtros e interceptores?
  • Use filtros e interceptores para lograr los requisitos funcionales en el desarrollo real

¿Qué es un filtro? - Filtro

Prólogo: toma lo que piensas

  • Depende del contenedor Servlet, implementa el filtrado basado en la función de devolución de llamada de todas las solicitudes
  • El filtro se inicia cuando se inicia la aplicación web, se inicializa solo una vez y se destruye cuando se detiene la aplicación web.
    • Cargue una instancia del filtro al inicio y llame al método **init()** para inicializar la instancia
    • Cada solicitud solo se puede procesar llamando a **doFilter()**
    • Cuando se detiene el servicio, llame a destroy para destruir la instancia

defecto

  • Solo se puede llamar una vez cuando se inicializa el contenedor

¿Qué es un interceptor? - Interceptor

Forerunners: usa lo que usas

  • Confiar en el marco web y el mecanismo de reflexión de Java es el reflejo de la idea de AOP
  • Según el marco web, se pueden llamar varias dependencias en el contenedor IOC y se pueden realizar algunas operaciones comerciales
  • Dos formas de implementar interceptores (primavera)
    • Implementar la interfaz HandlerInterceptor
    • Implemente la interfaz WebRequestInterceptor o una clase que implemente WebRequestInterceptor
  • La interfaz HandlerInterceptor define los métodos preHandle, postHandle y afterCompletion
    • preHandle : el método de solicitud se intercepta previamente. Este método se llamará antes del procesamiento del controlador. Puede haber múltiples interceptores en Spring. Estos interceptores se llamarán en el orden del orden establecido. Cuando un interceptor devuelve falso en preHandle, la solicitud terminará
    • postHandle : cuando preHandle devuelve verdadero, se llama después de que se ejecuta el método del controlador y antes de que se represente la vista
  • afterCompletion : este método se ejecuta después de que preHandle devuelve verdadero y finaliza toda la solicitud.

Diferencia entre filtro e interceptor

mismo

  • Todos son la encarnación del pensamiento AOP.
  • Ambos interceptan el método solicitado y mejoran el método.

diferente

  • El principio de realización es diferente.

    • El filtro se basa en la función de devolución de llamada
    • Interceptor basado en el mecanismo de reflexión de Java (implementación de proxy dinámico)
  • Diferente alcance de uso

    • El filtro se define en la especificación de Servlet, depende de contenedores como Tomcat y solo se puede usar en programas web
    • El interceptor es un componente de Spring, administrado por Spring y se puede usar solo
  • El tiempo de disparo es diferente

    img/imagen-20211115101325025.png 0 → 100644

Implementación de la función de interceptor

Requisitos funcionales: implementar la autenticación de inicio de sesión del usuario

Clase de configuración de interceptor (InterceptorConfig)

  • Generalmente, se utiliza principalmente para configurar la ruta de interceptación/ruta de liberación
  • Inyectar Bean, que surte efecto cuando se produce la intercepción. Ejemplo: LoginInterceptor a continuación
/**
 * 拦截配置
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    
    
    @Bean
    LoginInterceptor loginInterceptor() {
    
    
        return new LoginInterceptor();
    }

    /**
     * 添加拦截路径
     * 放行拦截路径
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    
    

        // 拦截全部路径,这个跨域需要放在最上面
        registry.addInterceptor(corsInterceptor()).addPathPatterns("/**");

        // 拦截路径
        registry.addInterceptor(loginInterceptor()).addPathPatterns("/api/v1/pri/*/*/**")
                //放行路径
                .excludePathPatterns("/api/v1/pri/user/login", "/api/v1/pri/user/register");
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}

interceptor de implementos

  • Implemente la interfaz HandlerInterceptor y reescriba el método de preHandle dentro

  • Aquí hay un proceso de verificación de permisos de usuario. Cuando el front-end envía una solicitud al back-end, intercepta la solicitud, obtiene el token dentro y coloca el token "descifrado" en el campo de solicitud para devolver

  • La clase sendJsonMessage, cuando el token de verificación es nulo, responde directamente al front-end

/**
 * 登录拦截器
 * 进入到Restcontroller之前的方法
 * @author ouj
 */
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        try {
            //从请求中获取token
            String accessToken = request.getHeader("token");
            if (accessToken == null) {
                accessToken = request.getParameter("token");
            }
            // 判断token是否为null
            if (StringUtils.isNotBlank(accessToken)) {
                Claims claims = JWTUtils.checkJWT(accessToken);
                if (claims == null) {
                    sendJsonMessage(response, "登录过期,请重新登录");
                }
                Integer id = (Integer) claims.get("id");
                String name = (String) claims.get("name");

                //在request域中把id的属性放进"User_id"中
                request.setAttribute("user_id", id);
                request.setAttribute("name", name);
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 登录失败
        return false;
    }

    /**
     * 响应json数据给前端
     * @param response
     * @param obj
     */
    public static void sendJsonMessage(HttpServletResponse response, Object obj) {

        try {
            /**
             * 将数据转成Json字符串,然后以数据流的形式writer写出去
             * ObjectMapper 是Jackson库中主要用于读取和写入Json数据的类,能够很方便地将Java对象转为Json格式的数据
             * 用于后端Servlet向AJAX传递Json数据,动态地将数据展示在页面上。为了能够使用这个类,需要先下载Jackson库。
             */
            ObjectMapper objectMapper = new ObjectMapper();
            response.setContentType("application/json; charset=utf-8");
            //返回一个输出流
            PrintWriter writer = response.getWriter();
            // writeValue(参数,obj):直接将传入的对象序列化为json,并且返回给客户端
            // writeValueAsString(obj):将传入的对象序列化为json,返回给调用者
            writer.print(objectMapper.writeValueAsString(obj));
            writer.close();
            response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}

Implementación de la función de filtro

Implementar requisitos funcionales: verificación de usuario

/**
 * 过滤器
 */
@WebFilter(urlPatterns = "/api/v1/pri/*",filterName = "loginfilter")
public class LoginFilter implements Filter {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 容器加载的时候
     * @param filterConfig
     * @throws ServletException
     */
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("开启过滤器");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤开始");
        HttpServletRequest req = (HttpServletRequest) servletRequest;
        HttpServletResponse rep = (HttpServletResponse) servletResponse;

        //从headers中得到token
        String token =req.getHeader("token");
        // 如果header里面没有token时,从请求的参数里面拿token
        if (StringUtils.isEmpty(token)){
            token = req.getParameter("token");
        }
        //如果还为空,直接返回json字符串或跳转index页面
        if (!StringUtils.isEmpty(token)){
            // 判断token是否合法
            //在登录时在sessionMap里存了token,通过token取出user,若为空则未登录,若不为空则显示正确
            User user = UserServiceImpl.sessionMap.get(token);
            if(user !=null){
                filterChain.doFilter(servletRequest,servletResponse);
            }else{
                JsonData jsonData = JsonData.buildError("登录失败,token无效",-2);
                //json转字符
                String jsonStr = objectMapper.writeValueAsString(jsonData);
                renderJson(rep,jsonStr);
            }
        }else {
            JsonData jsonData = JsonData.buildError("登录失败,token无效",-3);
            String jsonStr = objectMapper.writeValueAsString(jsonData);
            renderJson(rep,jsonStr);
        }
    }

    private void renderJson(HttpServletResponse response,String json){
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        try(PrintWriter writer=response.getWriter()){
            writer.print(json);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 容器销毁的时候
     */
    @Override
    public void destroy() {
        System.out.println("destory LoginFilter");
    }
}

Escenarios de aplicación

  • filtrar
    • conversión de codificación de bytecode
    • Filtrado de palabras confidenciales (incluido para evitar la inyección de sql)
    • Validación de permisos
    • Información de respuesta comprimida
  • interceptador
    • Validación de permisos
    • Inicio sesión
    • supervisión del rendimiento
    • comportamiento genérico
      • Lea la cookie para obtener la información del usuario y coloque el objeto del usuario en la solicitud, a fin de facilitar el uso de procesos posteriores, así como la extracción de información de la configuración regional, el tema, etc., siempre que lo requieran varios procesadores, usted puede usar el interceptor para lograr 5)

Supongo que te gusta

Origin blog.csdn.net/m0_49969111/article/details/121332863
Recomendado
Clasificación