精华内容
下载资源
问答
  • java中的过滤器
    千次阅读
    2021-03-16 15:23:47

    什么是过滤器?

    其实过滤器(Filter)跟Servlet很相似,都是java的一个组件。即请求发送到servlet之前,可以将其拦截和处理请求,也可以在serlvet结束工作之后,在响应发回之前处理响应,做一些事情。因此,可以理解为过滤器filter就是是拦截请求(request)和响应(response),并对传给请求资源的ServletRequest 或 ServletResponse 进行处理的一个对象。可以参见下图:

    29917475_1415758917qzbF.jpg

    请求过滤器的作用:完成安全检查

    重新格式化请求首部或者体

    建立请求审计和日志

    响应过滤器的作用:压缩相应流

    追加或者修改流

    创建一个完全不同的响应

    Servlet API中提供了一个Filter接口,开发应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。很多java教程里面都有介绍,Filter的实现类实现了一个J2EE的过滤器,过滤器的api允许访问ServletCOntext,同样可以链接到另一个Filter。

    Filter类似于Servlet一个样,有一个生命周期。里面有:init(), destroy(),还有个核心方法:doFilter()。init(FilterConfig):这是Filter的初始化方法,Servlet容器创建Filter实例后将调用这个方法。在这个方法中可以读取web.xml文件中Filter的初始化参数

    doFilter(ServletRequest,ServletResponse,FilterChain): 这个方法完成实际的过滤操作,当客户请求访问于Filter关联的URL时,Servlet容器将先调用Filter的doFilter方法。FilterChain参数用于访问后续Filters

    destroy():  Servlet容器在销毁Filter实例前调用该方法,这个方法中可以释放Filter占用的资源

    29917475_1415759383e6wD.jpg

    大家主要看看这个参数:ServletRequest /ServletResponse 。这个方法不取HTTP请求和相应对象做参数,而只是常规的ServletRequest /ServletResponse 对象。这里是对通用性的设计,过滤器的设计的要通用,如果过滤器用于一个非web应用,所以实现非Http接口。但不用担心的是,ServletResponse 是HttpServletResponse的超类。

    拦截器的使用场景:处理乱码问题;

    统计request和response的时间,有助于我们分析代码的效率;

    过滤非法请求路径

    更多相关内容
  • 下面小编就为大家分享一篇Java实现简单文件过滤器功能,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 下面小编就为大家带来一篇java 过滤器filter防sql注入的实现代码。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Filter也称之为过滤器,它是Servlet技术中最实用的技术,本文章WEB开发人员通过Filter技术,对web服务器管理的所有web资源进行拦截,从而实现一些特殊的功能,本文章将向大家介绍Java 中的 Filter 过滤器,需要的朋友...
  • 主要介绍了JAVA实现较完善的布隆过滤器的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • Java 实现的高性能布隆过滤器!.zip,Advanced Bloom Filter Based Algorithms for Efficient Approximate Data De-Duplication in Streams
  • 布隆过滤器 java实现代码

    热门讨论 2012-06-29 11:16:23
    布隆过滤器 源码 java版 /** * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software ...
  • Logstash过滤器Java 通过实现Java接口编写logstash过滤器
  • 使用Java多线程实现管道过滤器,本文档写了六个线程,五个管道,内容很简单,如果想要复杂功能请手动添加。
  • 主要为大家详细介绍了cookie、session和java过滤器结合实现登陆程序的具体代码,感兴趣的朋友可以参考一下
  • 一耳光消息过滤器实现 的功能代码,效果不错
  • JAVA过滤器标准代码

    2008-11-05 08:32:33
    关于JAVA过滤器的编写,和一些要求!代码精简,方便使用
  • 本文实例讲述了thinkPHP框架实现类似java过滤器的简单方法。分享给大家供大家参考,具体如下: 写java web代码的时候,可以定义过滤器,对控制器进行过滤,可以实现权限验证等等 在thinkphp中也可以通过继承父类的...
  • Java实现布隆过滤器

    千次阅读 2022-01-28 16:09:47
    布隆过滤器 海量数据处理以及缓存穿透这两个场景让我认识了 布隆过滤器 ...通过 Java 编程手动实现布隆过滤器。 利用 Google 开源的 Guava 中自带的布隆过滤器。 Redis 中的布隆过滤器。 什么是布隆过滤器? 首先,我

    布隆过滤器

    海量数据处理以及缓存穿透这两个场景让我认识了 布隆过滤器 ,我查阅了一些资料来了解它,但是很多现成资料并不满足我的需求,所以就决定自己总结一篇关于布隆过滤器的文章。希望通过这篇文章让更多人了解布隆过滤器,并且会实际去使用它!

    下面我们将分为几个方面来介绍布隆过滤器:

    1. 什么是布隆过滤器?
    2. 布隆过滤器的原理介绍。
    3. 布隆过滤器使用场景。
    4. 通过 Java 编程手动实现布隆过滤器。
    5. 利用 Google 开源的 Guava 中自带的布隆过滤器。
    6. Redis 中的布隆过滤器。

    什么是布隆过滤器?

    首先,我们需要了解布隆过滤器的概念。

    布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于 1970 年提出的。我们可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。相比于我们平时常用的的 List、Map 、Set 等数据结构,它占用空间更少并且效率更高,但是缺点是其返回的结果是概率性的,而不是非常准确的。理论情况下添加到集合中的元素越多,误报的可能性就越大。并且,存放在布隆过滤器的数据不容易删除。

    布隆过滤器示意图

    位数组中的每个元素都只占用 1 bit ,并且每个元素只能是 0 或者 1。这样申请一个 100w 个元素的位数组只占用 1000000Bit / 8 = 125000 Byte = 125000/1024 kb ≈ 122kb 的空间。

    总结:一个名叫 Bloom 的人提出了一种来检索元素是否在给定大集合中的数据结构,这种数据结构是高效且性能很好的,但缺点是具有一定的错误识别率和删除难度。并且,理论情况下,添加到集合中的元素越多,误报的可能性就越大。

    布隆过滤器的原理介绍

    当一个元素加入布隆过滤器中的时候,会进行如下操作:

    1. 使用布隆过滤器中的哈希函数对元素值进行计算,得到哈希值(有几个哈希函数得到几个哈希值)。
    2. 根据得到的哈希值,在位数组中把对应下标的值置为 1。

    当我们需要判断一个元素是否存在于布隆过滤器的时候,会进行如下操作:

    1. 对给定元素再次进行相同的哈希计算;
    2. 得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。

    举个简单的例子:

    布隆过滤器hash计算

    如图所示,当字符串存储要加入到布隆过滤器中时,该字符串首先由多个哈希函数生成不同的哈希值,然后将对应的位数组的下标设置为 1(当位数组初始化时,所有位置均为 0)。当第二次存储相同字符串时,因为先前的对应位置已设置为 1,所以很容易知道此值已经存在(去重非常方便)。

    如果我们需要判断某个字符串是否在布隆过滤器中时,只需要对给定字符串再次进行相同的哈希计算,得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。

    不同的字符串可能哈希出来的位置相同,这种情况我们可以适当增加位数组大小或者调整我们的哈希函数。

    综上,我们可以得出:布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

    布隆过滤器使用场景

    1. 判断给定数据是否存在:比如判断一个数字是否存在于包含大量数字的数字集中(数字集很大,5 亿以上!)、 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。
    2. 去重:比如爬给定网址的时候对已经爬取过的 URL 去重。

    编码实战

    通过 Java 编程手动实现布隆过滤器

    我们上面已经说了布隆过滤器的原理,知道了布隆过滤器的原理之后就可以自己手动实现一个了。

    如果你想要手动实现一个的话,你需要:

    1. 一个合适大小的位数组保存数据
    2. 几个不同的哈希函数
    3. 添加元素到位数组(布隆过滤器)的方法实现
    4. 判断给定元素是否存在于位数组(布隆过滤器)的方法实现。

    下面给出一个我觉得写的还算不错的代码(参考网上已有代码改进得到,对于所有类型对象皆适用):

    import java.util.BitSet;
    
    public class MyBloomFilter {
    
        /**
         * 位数组的大小
         */
        private static final int DEFAULT_SIZE = 2 << 24;
        /**
         * 通过这个数组可以创建 6 个不同的哈希函数
         */
        private static final int[] SEEDS = new int[]{3, 13, 46, 71, 91, 134};
    
        /**
         * 位数组。数组中的元素只能是 0 或者 1
         */
        private BitSet bits = new BitSet(DEFAULT_SIZE);
    
        /**
         * 存放包含 hash 函数的类的数组
         */
        private SimpleHash[] func = new SimpleHash[SEEDS.length];
    
        /**
         * 初始化多个包含 hash 函数的类的数组,每个类中的 hash 函数都不一样
         */
        public MyBloomFilter() {
            // 初始化多个不同的 Hash 函数
            for (int i = 0; i < SEEDS.length; i++) {
                func[i] = new SimpleHash(DEFAULT_SIZE, SEEDS[i]);
            }
        }
    
        /**
         * 添加元素到位数组
         */
        public void add(Object value) {
            for (SimpleHash f : func) {
                bits.set(f.hash(value), true);
            }
        }
    
        /**
         * 判断指定元素是否存在于位数组
         */
        public boolean contains(Object value) {
            boolean ret = true;
            for (SimpleHash f : func) {
                ret = ret && bits.get(f.hash(value));
            }
            return ret;
        }
    
        /**
         * 静态内部类。用于 hash 操作!
         */
        public static class SimpleHash {
    
            private int cap;
            private int seed;
    
            public SimpleHash(int cap, int seed) {
                this.cap = cap;
                this.seed = seed;
            }
    
            /**
             * 计算 hash 值
             */
            public int hash(Object value) {
                int h;
                return (value == null) ? 0 : Math.abs(seed * (cap - 1) & ((h = value.hashCode()) ^ (h >>> 16)));
            }
    
        }
    }
    

    测试:

    String value1 = "https://javaguide.cn/";
    String value2 = "https://github.com/Snailclimb";
    MyBloomFilter filter = new MyBloomFilter();
    System.out.println(filter.contains(value1));
    System.out.println(filter.contains(value2));
    filter.add(value1);
    filter.add(value2);
    System.out.println(filter.contains(value1));
    System.out.println(filter.contains(value2));
    

    Output:

    false
    false
    true
    true
    

    测试:

    Integer value1 = 13423;
    Integer value2 = 22131;
    MyBloomFilter filter = new MyBloomFilter();
    System.out.println(filter.contains(value1));
    System.out.println(filter.contains(value2));
    filter.add(value1);
    filter.add(value2);
    System.out.println(filter.contains(value1));
    System.out.println(filter.contains(value2));
    

    Output:

    false
    false
    true
    true
    

    利用 Google 开源的 Guava 中自带的布隆过滤器

    自己实现的目的主要是为了让自己搞懂布隆过滤器的原理,Guava 中布隆过滤器的实现算是比较权威的,所以实际项目中我们不需要手动实现一个布隆过滤器。

    首先我们需要在项目中引入 Guava 的依赖:

    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>28.0-jre</version>
    </dependency>
    

    实际使用如下:

    我们创建了一个最多存放 最多 1500 个整数的布隆过滤器,并且我们可以容忍误判的概率为百分之(0.01)

    // 创建布隆过滤器对象
    BloomFilter<Integer> filter = BloomFilter.create(
        Funnels.integerFunnel(),
        1500,
        0.01);
    // 判断指定元素是否存在
    System.out.println(filter.mightContain(1));
    System.out.println(filter.mightContain(2));
    // 将元素添加进布隆过滤器
    filter.put(1);
    filter.put(2);
    System.out.println(filter.mightContain(1));
    System.out.println(filter.mightContain(2));
    

    在我们的示例中,当 mightContain() 方法返回 true 时,我们可以 99%确定该元素在过滤器中,当过滤器返回 false 时,我们可以 100%确定该元素不存在于过滤器中。

    Guava 提供的布隆过滤器的实现还是很不错的(想要详细了解的可以看一下它的源码实现),但是它有一个重大的缺陷就是只能单机使用(另外,容量扩展也不容易),而现在互联网一般都是分布式的场景。为了解决这个问题,我们就需要用到 Redis 中的布隆过滤器了。

    Redis 中的布隆过滤器

    介绍

    Redis v4.0 之后有了 Module(模块/插件) 功能,Redis Modules 让 Redis 可以使用外部模块扩展其功能 。布隆过滤器就是其中的 Module。详情可以查看 Redis 官方对 Redis Modules 的介绍 :https://redis.io/modules

    另外,官网推荐了一个 RedisBloom 作为 Redis 布隆过滤器的 Module,地址:https://github.com/RedisBloom/RedisBloom
    其他还有:

    • redis-lua-scaling-bloom-filter(lua 脚本实现):https://github.com/erikdubbelboer/redis-lua-scaling-bloom-filter
    • pyreBloom(Python 中的快速 Redis 布隆过滤器) :https://github.com/seomoz/pyreBloom

    RedisBloom 提供了多种语言的客户端支持,包括:Python、Java、JavaScript 和 PHP。

    使用 Docker 安装

    如果我们需要体验 Redis 中的布隆过滤器非常简单,通过 Docker 就可以了!我们直接在 Google 搜索 docker redis bloomfilter 然后在排除广告的第一条搜素结果就找到了我们想要的答案(这是我平常解决问题的一种方式,分享一下),具体地址:https://hub.docker.com/r/redislabs/rebloom/ (介绍的很详细 )。

    具体操作如下:

    ➜  ~ docker run -p 6379:6379 --name redis-redisbloom redislabs/rebloom:latest
    ➜  ~ docker exec -it redis-redisbloom bash
    root@21396d02c252:/data# redis-cli
    127.0.0.1:6379>
    

    常用命令一览

    注意: key : 布隆过滤器的名称,item : 添加的元素。

    1. BF.ADD:将元素添加到布隆过滤器中,如果该过滤器尚不存在,则创建该过滤器。格式:BF.ADD {key} {item}
    2. BF.MADD : 将一个或多个元素添加到“布隆过滤器”中,并创建一个尚不存在的过滤器。该命令的操作方式BF.ADD与之相同,只不过它允许多个输入并返回多个值。格式:BF.MADD {key} {item} [item ...]
    3. BF.EXISTS : 确定元素是否在布隆过滤器中存在。格式:BF.EXISTS {key} {item}
    4. BF.MEXISTS : 确定一个或者多个元素是否在布隆过滤器中存在格式:BF.MEXISTS {key} {item} [item ...]

    另外, BF. RESERVE 命令需要单独介绍一下:

    这个命令的格式如下:

    BF. RESERVE {key} {error_rate} {capacity} [EXPANSION expansion]

    下面简单介绍一下每个参数的具体含义:

    1. key:布隆过滤器的名称
    2. error_rate : 期望的误报率。该值必须介于 0 到 1 之间。例如,对于期望的误报率 0.1%(1000 中为 1),error_rate 应该设置为 0.001。该数字越接近零,则每个项目的内存消耗越大,并且每个操作的 CPU 使用率越高。
    3. capacity: 过滤器的容量。当实际存储的元素个数超过这个值之后,性能将开始下降。实际的降级将取决于超出限制的程度。随着过滤器元素数量呈指数增长,性能将线性下降。

    可选参数:

    • expansion:如果创建了一个新的子过滤器,则其大小将是当前过滤器的大小乘以expansion。默认扩展值为 2。这意味着每个后续子过滤器将是前一个子过滤器的两倍。

    实际使用

    127.0.0.1:6379> BF.ADD myFilter java
    (integer) 1
    127.0.0.1:6379> BF.ADD myFilter javaguide
    (integer) 1
    127.0.0.1:6379> BF.EXISTS myFilter java
    (integer) 1
    127.0.0.1:6379> BF.EXISTS myFilter javaguide
    (integer) 1
    127.0.0.1:6379> BF.EXISTS myFilter github
    (integer) 0
    
    展开全文
  • JAVA字符集过滤器函数代码
  • 我们在开发系统或者应用的过程中,经常需要对用户提交的评论或者文章进行审核,对其中的敏感词进行校验或者过滤,本资源可以帮助各位小伙伴以一个简单的方式实现敏感词的过滤代码精简易懂,可以应用在实际开发过程...
  • 以下是实现未登录不能进入页面的实现使用了thyemeleaf+SpringBoot+过滤器实现的,过滤器的核心代码如下:@Component@WebFilter(filterName= "TestFilter",urlPatterns = "/*")@Order(1) //Order(1)在定义多个Filter...

    以下是实现未登录不能进入页面的实现

    使用了thyemeleaf+SpringBoot+过滤器实现的,过滤器的核心代码如下:

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    @Component

    @WebFilter(filterName= "TestFilter",urlPatterns = "/*")

    @Order(1) //Order(1)在定义多个Filter时,用于决定执行顺序的,数字越小,越先执行。

    public class TestFilter implementsFilter {private static final Set ALLOWED_PATHS = Collections.unmodifiableSet(new HashSet<>(

    Arrays.asList("/index", "/login")));

    @Overridepublic void init(FilterConfig filterConfig) throwsServletException {

    }

    @Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throwsIOException, ServletException {// //这样在每个Servlet执行的时候都会先进行这个

    HttpServletRequest request=(HttpServletRequest) servletRequest;

    HttpServletResponse response=(HttpServletResponse) servletResponse;

    System.out.println("过滤器实现");if(needLogin(request)) {//需要登录则跳转到登录Controller

    String userName = (String)((HttpServletRequest) request).getSession().getAttribute("userName");

    System.out.println("userName="+userName);

    System.out.println(Optional.ofNullable(userName).map(String::length).orElse(0));if(Optional.ofNullable(userName).map(String::length).orElse(0) <= 0){

    response.sendRedirect("login");//response.sendRedirect(request.getContextPath()+"/login");

    }

    filterChain.doFilter(servletRequest, servletResponse);return;

    }else{

    }//因为有可能不止这一个过滤器,所以需要将所有的过滤器执行//注意 这一行代码一定要写到最后

    filterChain.doFilter(servletRequest, servletResponse);

    }

    @Overridepublic voiddestroy() {

    }private booleanneedLogin(HttpServletRequest request) {//进行是否需要登录的判断操作

    String path = request.getRequestURI().substring(request.getContextPath().length()).replaceAll("[/]+$", "");

    System.out.println(path);boolean allowedPath =ALLOWED_PATHS.contains(path);

    System.out.println(allowedPath);return !allowedPath;

    }

    }

    View Code

    代码链接:

    链接:https://pan.baidu.com/s/1Kvh4JWCM3aIpiaqK67Rw3g 密码:pa57

    过滤器虽然也能实现,但是用起来会有个问题,假如说是我请求http://localhost:8080/usercenter,时,我期望的过程是,在过滤器里发现未登录,直接就跳转进入login,但是,实际山遇到的情况是,会先进入我的usercenter方法,跑过这个方法之后再进过滤器,再走login,这就会出现情况,假如说是我的usercenter方法(由于未登录导致出现方法中出现null的情况)有问题,导致最后页面报500

    ,为了解决这个问题,采用了拦截器,正好就是自己想要的效果,未登录的时候不进入usercenter,直接进入login

    一下是拦截器代码:

    拦截器的:

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    @Configurationpublic class LoginInterceptor implementsHandlerInterceptor {

    @Override//在执行目标方法之前执行

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throwsException {

    System.out.println("------:进来拦截器了!--1");//获取session

    HttpSession session = request.getSession(true);//判断用户ID是否存在,不存在就跳转到登录界面

    if(session.getAttribute("phoneNum") == null){

    System.out.println("------:跳转到login页面!");

    response.sendRedirect(request.getContextPath()+"/login");return false;

    }else{

    session.setAttribute("phoneNum", session.getAttribute("phoneNum"));return true;

    }

    }

    @Override//执行目标方法之后执行

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throwsException {

    System.out.println("------:进来拦截器了!--2");

    }

    @Override//在请求已经返回之后执行

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throwsException {

    System.out.println("------:进来拦截器了!--3");

    }

    }

    View Code

    配置文件的:WebConfig.java的代码:

    8f900a89c6347c561fdf2122f13be562.png

    961ddebeb323a10fe0623af514929fc1.png

    @Configuration

    @EnableWebMvc

    @ComponentScanpublic class WebConfig extends WebMvcConfigurerAdapter implementsApplicationContextAware {privateApplicationContext applicationContext;publicWebConfig(){super();

    }

    @Overridepublic voidaddResourceHandlers(ResourceHandlerRegistry registry) {

    registry.addResourceHandler("/static/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX+"/static/");

    registry.addResourceHandler("/templates/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX+"/templates/");super.addResourceHandlers(registry);

    }

    @Overridepublic void setApplicationContext(ApplicationContext applicationContext) throwsBeansException {this.applicationContext =applicationContext;

    }

    @Overridepublic voidaddInterceptors(InterceptorRegistry registry) {//拦截规则:除了login,其他都拦截判断

    registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/index", "/login","register");super.addInterceptors(registry);

    }

    }

    View Code

    这样就能完美的解决过滤器时遇到的问题

    结束

    代码链接:链接:https://pan.baidu.com/s/1QusjeJ2EVo4K55xN_saooQ 密码:nh85

    展开全文
  • 主要为大家详细介绍了java监听器实现在线人数统计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • Java实现布隆过滤器

    千次阅读 2020-05-11 15:47:03
    Java 实现布隆过滤器 1.什么是布隆过滤器? 布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于1970年提出的。 实际上可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的...

    1.什么是布隆过滤器?

    • 布隆过滤器(Bloom Filter)是一个叫做 Bloom 的老哥于1970年提出的。
    • 实际上可以把它看作由二进制向量(或者说位数组)和一系列随机映射函数(哈希函数)两部分组成的数据结构。
    • 它的优点是空间效率和查询时间都比一般的算法要好的多,缺点是有一定的误识别率和删除困难。

    在这里插入图片描述

    2.布隆过滤器的原理介绍

    • 图解:

    在这里插入图片描述

    • 如图所示,布隆过滤器添加元素时,该元素首先由多个哈希函数生成不同的哈希值,然后在对应的位数组的下表的元素设置为 1(当位数组初始化时 ,所有位置均为0)。当第二次存储相同字符串时,因为先前的对应位置已设置为1,所以很容易知道此值已经存在。

    • 如果我们需要判断某个元素是否在布隆过滤器中时,只需要对给定字符串再次进行相同的哈希计算,得到值之后判断位数组中的每个元素是否都为 1,如果值都为 1,那么说明这个值在布隆过滤器中,如果存在一个值不为 1,说明该元素不在布隆过滤器中。

    • 不同的字符串可能哈希出来的位置相同,这种情况我们可以适当增加位数组大小或者调整我们的哈希函数。

    • 所以,布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

    3.布隆过滤器使用场景

    1. 判断给定数据是否存在。
    2. 防止缓存穿透(判断请求的数据是否有效避免直接绕过缓存请求数据库)等等、邮箱的垃圾邮件过滤、黑名单功能等等。。

    4.用Java 实现布隆过滤器

    • 下面是我参考网上已有代码改的:
    /**
     * 布隆过滤器
     *
     * @author wangjie
     * @version V1.0
     * @date 2020/5/11
     */
    public class BloomFilterDemo {
        /**
         * 位数组的大小
         */
        private static  int SIZE;
        /**
         * 通过这个数组可以创建不同的哈希函数
         */
        private static  int[] SEEDS;
        /**
         * 位数组。数组中的元素只能是 0 或者 1
         */
        private BitSet bits;
    
        /**
         * 存放包含 hash 函数的类的数组
         */
        private SimpleHash[] func;
        /**
         * 误判率
         */
        private MisjudgmentRate rate;
        /**
         * 自动清空
         */
        private  Double autoClearRate;
        /**
         * 使用数量
         */
        private final AtomicInteger useCount = new AtomicInteger(0);
        /**
         * 静态内部类。hash 函数
         */
        public static class SimpleHash {
    
            private int cap;
            private int seed;
    
            public SimpleHash(int cap, int seed) {
                this.cap = cap;
                this.seed = seed;
            }
    
            /**
             * 计算 hash 值
             */
            public int hash(Object value) {
                int h;
                return (value == null) ? 0 : Math.abs(seed * (cap - 1) & ((h = value.hashCode()) ^ (h >>> 16)));
            }
    
        }
    
        /**
         * 误判率
         */
        public enum MisjudgmentRate {
            /**
             * 每个字符串分配4个位
             */
            VERY_SMALL(new int[] { 2, 3, 5, 7 }),
            /**
             * 每个字符串分配8个位
             */
            SMALL(new int[] { 2, 3, 5, 7, 11, 13, 17, 19 }),
            /**
             * 每个字符串分配16个位
             */
            MIDDLE(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53 }),
            /**
             * 每个字符串分配32个位
             */
            HIGH(new int[] { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
                    101, 103, 107, 109, 113, 127, 131 });
    
            private int[] seeds;
    
            private MisjudgmentRate(int[] seeds) {
                this.seeds = seeds;
            }
    
            public int[] getSeeds() {
                return seeds;
            }
    
            public void setSeeds(int[] seeds) {
                this.seeds = seeds;
            }
    
        }
    
        /**
         * 默认中等程序的误判率
         * @param dataCount 预期处理的数据规模,如预期用于处理1百万数据的查重,这里则填写1000000
         */
        public BloomFilterDemo(int dataCount){
            this(MisjudgmentRate.MIDDLE, dataCount, null);
        }
    
        /**
         *
         * @param rate 枚举类型的误判率
         * @param dataCount 预期处理的数据规模,如预期用于处理1百万数据的查重,这里则填写1000000
         * @param autoClearRate 自动清空过滤器内部信息的使用比率
         */
        public BloomFilterDemo(MisjudgmentRate rate, int dataCount, Double autoClearRate){
            long bitSize = rate.seeds.length * dataCount;
            if (bitSize < 0 || bitSize > Integer.MAX_VALUE) {
                throw new RuntimeException("位数太大溢出了,请降低误判率或者降低数据大小");
            }
            this.rate = rate;
            SEEDS = rate.seeds;
            SIZE = (int) bitSize;
            func = new SimpleHash[SEEDS.length];
            for (int i = 0; i < SEEDS.length; i++) {
                func[i] = new SimpleHash(SIZE, SEEDS[i]);
            }
            bits = new BitSet(SIZE);
            this.autoClearRate = autoClearRate;
        }
    
        /**
         * 添加元素到位数组
         */
        public void add(Object value) {
    
            checkNeedClear();
    
            if(!contains(value)){
    	       for (SimpleHash f : func) {
    	           bits.set(f.hash(value), true);
    	       }
    	       useCount.getAndIncrement();
            }
            
        }
    
        /**
         * 判断指定元素是否存在于位数组
         */
        public boolean contains(Object value) {
            boolean ret = true;
            for (SimpleHash f : func) {
                ret = ret && bits.get(f.hash(value));
            }
            return ret;
        }
    
        /**
         * 检查是否需要清空
         */
        private void checkNeedClear() {
            if (autoClearRate != null) {
                if (getUseRate() >= autoClearRate) {
                    synchronized (this) {
                        if (getUseRate() >= autoClearRate) {
                            bits.clear();
                            useCount.set(0);
                        }
                    }
                }
            }
        }
        public double getUseRate() {
            return (double) useCount.intValue() / (double) SIZE;
        }
    
        public static void main(String[] args) {
            String value1 = "fffdfg";
            String value2 = "ddbgbfgbfbbgfb";
            BloomFilterDemo filter = new BloomFilterDemo(2<<24);
            System.out.println(filter.contains(value1));
            System.out.println(filter.contains(value2));
            filter.add(value1);
            filter.add(value2);
            System.out.println(filter.contains(value1));
            System.out.println(filter.contains(value2));
            Integer value11 = 13423;
            Integer value21 = 22131;
            System.out.println(filter.contains(value11));
            System.out.println(filter.contains(value21));
            filter.add(value11);
            filter.add(value21);
            System.out.println(filter.contains(value11));
            System.out.println(filter.contains(value21));
        }
    
    }
    
    • 运行结果:
    false
    false
    true
    true
    false
    false
    true
    true
    
    展开全文
  • 管道过滤器实现java

    2012-11-20 20:06:44
    管道过滤器实现java,希望大家能够一起学习,我只是将文件放到了里面,希望大家自己搭建工程
  • 一、使浏览器不缓存页面的过滤器 二、检测用户是否登陆的过滤器 三、字符编码的过滤器 …………………………
  • Servlet过滤器示例代码

    2014-06-09 09:13:34
    这里面的代码,是对Servlet的过滤器,进行学习的,里面详尽的写出了Servlet过滤器的作用,以及一些使用方法!
  • JAVA实现较完善的布隆过滤器

    万次阅读 多人点赞 2017-07-30 17:17:22
    布隆过滤器是可以用于判断一个元素是不是在一个集合里,并且相比于其它的数据结构,布隆过滤器...简单来说,布隆过滤器实现方法就是:利用内存中一个长度为M的位数组B并初始化里面的所有位都为0,如下面的表格所示:
  • Java使用过滤器防止SQL注入XSS脚本注入

    千次阅读 多人点赞 2020-12-17 20:29:45
    前几天有个客户在系统上面写... 一. 定义过滤器 package com.cn.unit.filter; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; im
  • java过滤器实现登录拦截处理

    万次阅读 2019-03-17 16:22:13
    一、什么是过滤器 过滤器是处于客户端与服务器资源文件之间的一道过滤网(驻留在服务器端的Web组件),在访问资源文件之前,通过一系列的过滤器对请求进行修改、判断等,把不符合规则的请求在中途拦截或修改。也可以...
  • java过滤器全局解析token

    千次阅读 2020-05-23 16:53:34
    java过滤器全局解析token 文章目录java过滤器全局解析token使用过滤器定义一个全局的token解析器一般接口定义全局AOP解析接口使用注解@RequestHeader我的需求以及方法需求和现状实践注意点 使用过滤器定义一个全局的...
  • spring mvc过滤器实现

    2013-10-30 16:42:05
    spring mvc 过滤器实现url过滤,权限模块经常用到的,很不错
  • 本文实例为大家分享了jsp实现登录验证的过滤器,供大家参考,具体内容如下 1.新建一个Dynamic Web Project项目,里面新建1个filter文件、1个servlet文件和2个jsp文件,整体的框架如图所示: 2.LoginFilter.java里面...
  • 首先我们先定义一个过滤器Filter 实现HandlerInterceptor 接口。 package com.mlb.filter; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; ...
  • 将一个单词排序程序并进行调试,体会数据流架构风格系统的构件和连接件原理和实现方法。在此基础上,改为通过键盘输入单词排序过滤器实时进行排序输出到屏幕、控制台,并在程序结束后将最终结果写入到文件中。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 210,197
精华内容 84,078
关键字:

java过滤器的实现代码

java 订阅