JAVA中的拦截器、过滤器

news2025/2/12 21:39:57

JAVA变成拦截器、过滤器

  • 一、拦截器
    • 1、简介说明
    • 2、源码及方法说明
    • 3、拦截器自定义应用
  • 二、过滤器
    • 1、简介说明
    • 2、源码及方法说明
    • 3、过滤器的自定义应用
  • 三、Springboot中的WebMvcConfigurer
    • 1、简介
    • 2、主要方法
    • 3、添加拦截器
  • 四、区别
    • 1、原理
    • 2、触发
    • 3、其他

一、拦截器

1、简介说明

相关解释:拦截器依赖于页面有访问controller的操作,且属于SpringMVC体系的动态拦截调用机制,是java中AOP思想的运用。
来看看源码作者的注释:
在这里插入图片描述
其中倒数第二段话,描述其类似于过滤器,但其特点只允许使用自定义预处理,不能处理程序本身。此处可体现AOP思想。
过滤器是在web.xml中配置,web.xml是应用程序上下文中的HandlerInterceptor。

最后一段话,则体现了拦截器常用情况,如常见处理程序代码和授权检查。
而过滤器非常适合请求内容和视图内容处理,如多部分表单和GZIP压缩。

2、源码及方法说明

HandlerInterceptor
在这里插入图片描述

HandlerInterceptor接口中有3个方法:
preHandler():该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作。
postHandle():该方法会在控制器方法调用之后,且解析视图之前执行。可以通过此方法对请求域中的模型和视图做出进一步的修改。
afterCompletion():该方法会在整个请求完成,即视图渲染结束之后执行。可以通过此方法实现一些资源清理、记录日志信息等工作。

3、拦截器自定义应用

实现 org.springframework.web.servlet.HandlerInterceptor 接口
如常见的白名单控制

package com.framework;

import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class WhiteRosterInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if(checkWhiteList()){
            return true;
        }
        response.setContentType("application/json; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        response.getWriter().append(JSON.toJSONString("白名单暂未设置"));
        return false;
    }

    private Boolean checkWhiteList(){
        //业务处理
        return true;
    }

}

二、过滤器

1、简介说明

相关解释:java过滤器能够对目标资源的请求和响应进行截取。
来看看源码作者的注释:
在这里插入图片描述
其描述中说明该过滤器为基于(a servlet or static content)。
同时也将其现有应用场景进行了说明,如权限过滤,加密过滤,图像转换过滤等等。

2、源码及方法说明

Filter
在这里插入图片描述
Filter接口中有3个方法:
init():初始化参数,在创建Filter时自动调用,如需要设置初始化参数,可写到该方法中。
doFilter():拦截到要执行的请求时,doFilter就会执行。写对请求和响应的预处理。
destroy():销毁时Filter自动调用。
init()和destroy(),为default方法,可不实现,但doFilter()必须实现,且方法中传进来的FilterChain对象用来调用下一个过滤器。

3、过滤器的自定义应用

实现javax.servlet.Filter 接口
如常见的加解密过滤器

package com.framework;

import com.AesUtil;
import com.response.ResponseWrapper;
import org.springframework.stereotype.Component;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Component
public class EncryptFilter implements Filter{

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        if(isExcept(request)){
            chain.doFilter(request, response);
            return;
        }
        response.setContentType("application/json; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        ResponseWrapper responseWrapper = new ResponseWrapper((HttpServletResponse) response);
        chain.doFilter(request, responseWrapper);
        byte[] resData = responseWrapper.getResponseData();
        String encrypt = AesUtil.encrypt(new String(resData, "utf-8"), "AesKey");
        PrintWriter out = response.getWriter();
        out.print(encrypt.replaceAll("[\\s*\t\n\r]", ""));
        out.flush();
        out.close();
    }

    private Boolean isExcept(ServletRequest HttpRequest){
        //业务处理,是否不加密
        return true;
    }

    @Override
    public void destroy() {

    }
}

依赖的 ResponseWrapper.java

package com.response;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;

public class ResponseWrapper extends HttpServletResponseWrapper {
    private ByteArrayOutputStream byteArrayOutputStream = null;
    private ServletOutputStream servletOutputStream = null;
    private PrintWriter printWriter = null;

    public ResponseWrapper(HttpServletResponse response) throws IOException {
        super(response);
        byteArrayOutputStream = new ByteArrayOutputStream();
        servletOutputStream = new WrapperOutputStream(byteArrayOutputStream);
        printWriter = new PrintWriter(new OutputStreamWriter(byteArrayOutputStream,this.getCharacterEncoding()));
    }

    private class WrapperOutputStream extends ServletOutputStream {
        private ByteArrayOutputStream bos = null;

        public WrapperOutputStream(ByteArrayOutputStream stream) throws IOException {
            bos = stream;
        }

        @Override
        public void write(int b) throws IOException {
            bos.write(b);
        }

        @Override
        public void write(byte[] b) throws IOException {
            bos.write(b, 0, b.length);
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setWriteListener(WriteListener writeListener) {

        }
    }

}

当需要使用多个过滤器时,需要设置过滤器先后顺序。
即在EncryptFilter类中使用 @Order() 注解,数值越小,优先级越高,执行顺序越靠前。

加密相关链接:
Springboot项目报文加密(采用AES、RSA动态加密策略):
https://blog.csdn.net/qq_38254635/article/details/129275971
Springboot集成AES加密:
https://blog.csdn.net/qq_38254635/article/details/129622075

三、Springboot中的WebMvcConfigurer

1、简介

为Spring内部的配置方式,通过JavaBean的方式来替代传统的xml配置文件形式,可自定义一些Handler,Interceptor,ViewResolver,MessageConverter,需创建配置类并实现WebMvcConfigurer接口

2、主要方法

addViewControllers:将一个请求转到一个页面。
addResourceHandlers:静态资源的地址映射。
configureMessageConverters:将@ResponseBody实体转FastJson字符串返回,可以返回实体进行重写。
addCorsMappings:实现ajax跨域请求。
addInterceptors:添加拦截器。

3、添加拦截器

1、自定义一个注解,用作手动单个接口忽略拦截

package com.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreInterceptor {
}

2、自定义配置,用作某路径下的请求批量忽略拦截
放置在yml配置文件中。
SpringBoot加载自定义yml中的配置参数:https://blog.csdn.net/qq_38254635/article/details/112033193

3、编写拦截器类 WebMvcConfig.java

package com.config;

import com.alibaba.fastjson.JSON;
import com.annotation.IgnoreInterceptor;
import com.framework.WhiteRosterInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Value("#{'${spring.excludePath}'.split(',')}")
    private List<String> excludePath;
    @Resource
    private WhiteRosterInterceptor whiteRosterInterceptor;

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("index");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new HandlerInterceptor() {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                if (handler instanceof HandlerMethod) {
                    HandlerMethod method = (HandlerMethod) handler;
                    IgnoreInterceptor methodAnnotation = method.getMethodAnnotation(IgnoreInterceptor.class);
                    if(null != methodAnnotation) return true;
                    if (!isLogin(request)) {
                        response.setContentType("application/json; charset=utf-8");
                        response.setCharacterEncoding("UTF-8");
                        response.getWriter().append(JSON.toJSONString("未登录"));
                        return false;
                    }
                    refreshLogin(request);
                    return true;
                }
                return true;
            }
            private Boolean isLogin(HttpServletRequest request) {
                //判断用户是否登录
                return true;
            }

            private void refreshLogin(HttpServletRequest request) {
                //刷新登录信息
            }

            @Override
            public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                //处理完业务后,清除用户的登录相关信息,永远放在最后处理

            }
        }).addPathPatterns("/**").excludePathPatterns(excludePath);
        registry.addInterceptor(whiteRosterInterceptor).addPathPatterns("/api/**");
    }

}

4、说明
拦截器方式addInterceptors中,可实现多个拦截器。
可通过 registry.addInterceptor()增加拦截器,如上接口,增加了文中白名单拦截器。
addPathPatterns:拦截路径,**表示匹配后续所有路径
excludePathPatterns:忽略路径,接口中excludePath使用yml配置的路径,进行忽略操作。
IgnoreInterceptor:自定义注解,手动忽略某请求,在拦截器做了单独处理。
如自定义拦截器,可通过注入的方式添加。
执行顺序也根据配置的顺序,依次执行。

四、区别

1、原理

拦截器方法都是通过代理的方式来调用的,是基于反射机制实现的,依赖于web框架。
过滤器的实现是基于回调函数的。依赖于Servlet容器。

2、触发

如1.1中源码注释所说。
拦截器:对请求在handler【Controller】前后进行处理,属于应用上下文。
过滤器:对请求在进入后Servlet之前或之后进行处理,允许交换请求和响应对象,使用web.xml配置。
在这里插入图片描述
拦截器和过滤器执行顺序:
1、Filter.init();
2、Filter.doFilter(); before doFilter
3、HandlerInterceptor.preHandle();
4、Controller方法执行
5、HandlerInterceptor.postHandle();
6、DispatcherServlet视图渲染
7、HandlerInterceptor.afterCompletion();
8、Filter.doFilter(); after doFilter
9、Filter.destroy();

在这里插入图片描述

3、其他

过滤器:每一次都传入FilterChain对象,达到最后接口回调的效果。
拦截器:任何一个拦截器的preHandle为false,则其后的所有拦截器都不会执行。只有所有的拦截器preHandler都为true,postHandle才会执行。

多个过滤器设置执行顺序:增加 @Order() 注解,数值越小,优先级越高,执行顺序越靠前。
在这里插入图片描述
多个拦截器设置执行顺序:可通过实现Ordered接口来实现。
在这里插入图片描述

参考链接:
https://baijiahao.baidu.com/s?id=1677716748772601748
https://blog.csdn.net/m0_53123540/article/details/124924596
https://blog.csdn.net/king101125s/article/details/104372380

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/645668.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Scala学习笔记

累了&#xff0c;基础配置不想写了&#xff0c;直接抄了→Scala的环境搭建 这里需要注意的是&#xff0c;创建新项目时&#xff0c;不要用默认的Class类&#xff0c;用Object&#xff0c;原因看→scala中的object为什么可以直接运行 一、Scala简介 1.1 图解Scala和Java的关系 1…

HQChart实战教程63-自定义手机端K线tooltip显示数据

HQChart实战教程63-自定义手机端K线tooltip显示数据 手机端K线tooltip步骤1. 配置手机端tooltip2. 替换k线tooltip格式化输出函数2. 格式化输出函数说明HQChart插件源码地址完整的demo源码手机端K线tooltip hqchart手机端内置一个tooltip,显示手势所在K线的信息。默认显示 日期…

了解D-Galactopyranose pentaacetate,CAS号25878-60-8的性质和应用

​ 中文名称&#xff1a;1,2,3,4,6-D-葡萄糖五乙酸酯 英文名称&#xff1a;D-Galactopyranose pentaacetate 规格标准&#xff1a;1g、5g、10g CAS&#xff1a;25878-60-8 分子式&#xff1a;C16H22O11 分子量&#xff1a;390.34 熔点&#xff1a;113C 沸点&#xff1a;451C 密…

迷宫生成算法

迷宫生成 ① 十字分割 递归版本 ② BFS&#xff08;即广度算法&#xff09; 十字分割方法生成 要求初始时迷宫内全是通路&#xff0c;然后随机十字建墙&#xff0c;然后随机在三面墙上打洞&#xff0c;使四个子空间连通。 要求&#xff1a;十字点横纵坐标均要求为偶数&…

【unity】URP的shader开发中支持多光源,_ADDITIONAL_LIGHTS_VERTEX 和 _ADDITIONAL_LIGHTS 区别

项目里有一个其他同事实现的shader&#xff0c;美术那边希望能支持多个光源&#xff0c; 我一看代码里面&#xff0c; frag 函数里已经实现了 #ifdef _ADDITIONAL_LIGHTSuint pixelLightCount GetAdditionalLightsCount();for (uint lightIndex 0u; lightIndex < pixelL…

什么决定了我们的命运?

一、什么决定了我们的命运&#xff1f; 一个学生时代看起来特别优秀的人&#xff0c; 后来成了特别平凡的人&#xff1b; 而那时候看起来平淡无奇的一些人&#xff0c; 后来做出了一些似乎超越了他水平的事情。 不禁想问&#xff0c;到底是什么决定了我们的命运&#xff1f; 关…

Transformer在CV领域有可能替代CNN吗?

目前已经有基于Transformer在三大图像问题上的应用&#xff1a;分类&#xff08;ViT&#xff09;&#xff0c;检测&#xff08;DETR&#xff09;和分割&#xff08;SETR&#xff09;&#xff0c;并且都取得了不错的效果。那么未来&#xff0c;Transformer有可能替换CNN吗&#…

uniapp创建vue3项目(持续更新)

一.项目全局配置 1. 创建项目 使用Hbuilderx工具创建项目, 使用Hbuilderx工具创建项目&#xff0c;选择uni-ui项目模版&#xff0c;VUE3 2.底部菜单栏配置tabBar uniapp官网&#xff1a; 全局文件--pages.json页面路由 -- tabBar 项目文件&#xff1a;pages.json--文件底部…

MM32F3273G8P火龙果开发板MindSDK开发教程18 -sfud库的移植

MM32F3273G8P火龙果开发板MindSDK开发教程18 -sfud库的移植 1、sfud简介 SFUD (Serial Flash Universal Driver) 串行 Flash 通用驱动库 推荐查看官方文档&#xff1a;一款使用 JEDEC SFDP 标准的串行 (SPI) Flash 通用驱动库 2、实验设备 主控&#xff1a;MM32F3273G8P火龙…

Matlab与ROS---深度学习(九)

0. 简介 在了解完上面8讲内容后&#xff0c;基本上ROS和Matlab最关键的部分已经介绍完毕。我们最后一讲就来简单的讲述一下如何在Matlab中结合ROS来完成障碍物的识别与检测。 1. 在Matlab中使用CUDA 配置SimulinkCoder以从Simulink模型生成和构建的CUDA的ROS节点是我们这一小…

如何选择接口测试工具?

目录 前言&#xff1a; 一、易用性 二、灵活性 三、可靠性 四、成本 如何正确选择接口测试工具 测试用例 接口测试数据 自动化测试 测试报告 总结 前言&#xff1a; 接口测试是一种重要的测试类型&#xff0c;常用于Web应用程序和服务的测试。选择一个合适的接口测…

一分钟了解物联存储柜的特点和功能

物联存储柜是一种智能存储柜&#xff0c;具有多种传感器和通信技术&#xff0c;集成物联网和云计算技术&#xff0c;通过自动化、智能化、网络化将传统存储柜与智能设备相结合&#xff0c;自动识别、存取物品&#xff0c;通过网络进行数据交互&#xff0c;实现远程监测和管理功…

矿业变革进行中,北斗技术赋能智慧矿山

近年来&#xff0c;在国家政策支持和技术创新驱动下&#xff0c;国内矿山一直致力于向智能化、数字化方向发展&#xff0c;智慧矿山建设正在加速推进中。 我国自主研发的北斗导航系统&#xff0c;不断与千行百业融合&#xff0c;广泛应用于生产生活的各个领域。“北斗矿业”也成…

怎么自学网安?过程中遇到问题怎么解决

趁着今天下班&#xff0c;我花了几个小时整理了下&#xff0c;非常不易&#xff0c;希望大家可以点赞收藏支持一波&#xff0c;谢谢。 我的经历&#xff1a; 我 19 年毕业&#xff0c;大学专业是物联网工程&#xff0c;我相信很多人在象牙塔里都很迷茫&#xff0c;到了大三大…

JavaScript数学对象-数字进制转换

关注“大前端私房菜”微信公众号&#xff0c;输入暗号【面试宝典】即可免费领取107页前端面试题。 什么是进制 进制就是达到指定位置时候进一位 常见的进制 十进制: 0 1 2 3 4 5 6 7 8 9 10 11 12 ... 99 100 101 二进制: 0 1 10 11 100 101 110 111 1000 八进制: 0 1 2 3 4 …

在thinkBook16的win11基础上安装ubuntu22.04

简介 背景&#xff1a;联想ThinkBook16 pro 32G/512G&#xff0c;系统盘已安装Win11&#xff0c;加装一条M.2-2T固态&#xff0c;想在2T上分一个300GB的EXT4分区&#xff0c;然后把ubuntu22.04安装在该分区上&#xff0c;并实现Win11Linux多系统共存。 目标&#xff1a;实现多…

【C++】STL基本介绍

目录 1、什么是STL 2、STL六大组件 2.1容器 2.2算法 2.3迭代器 1、什么是STL 概念: STL (standard template libaray - 标准模板库)&#xff1a;是 C 标准库的重要组成部分&#xff0c;不仅是一个可复用的组件库&#xff0c;而且是一个包罗数据结构与算法的软件框架。 …

重回游戏公平,向游戏打金工作室宣战!

什么是打金工作室&#xff1f; 近几年中国游戏市场持续发展&#xff0c;国产自研精品游戏层出不穷&#xff0c;游戏产业精品化、高质量健康发展趋势稳定。根据中国音数协游戏工委&#xff08;GPC&#xff09;与中国游戏产业研究院发布的《2022年中国游戏产业报告》显示&#xf…

总结2023开放原子全球开源峰会,中兴国产操作系统的开源贡献

近年来&#xff0c;随着信息技术的不断发展&#xff0c;催生出越来越多的智能场景&#xff0c;作为信息产业的底层技术&#xff0c;国产操作系统所面临的问题也变得越来越复杂。面对新技术和新场景对国产操作系统提出的新挑战、新要求&#xff0c;如何凝聚生态合作伙伴的优势力…

看了这几个C语言例子,你一定和我一样连说5个卧槽,声音一次比一次大

曾经我一直以为自己C语言学的还挺好的&#xff0c;直到看到这几个例子。 例1 首先来看一下&#xff0c;大师是如何求圆周率的&#xff0c;一口君实在词穷&#xff0c;first卧槽。 #include <stdio.h>long a10000,b0,c10000,d,e,f[10001],g;void main(){for(;b ! c; f[…