使用google guava框架实现
场景:我们以判断用户是否已经注册为例。主要思路是我们简单以项目启动的过程中,把已经注册的用户编号存入布隆过滤器中,然后调用查询接口直接查找布隆过滤器中是否存在指定用户编号,若不存在,则代表用户没有注册。实现步骤如下:
1、创建表及添加数据
CREATE TABLE `sys_user` (
`userId` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`username` varchar(25) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '用户名',
`password` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT '密码',
PRIMARY KEY (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
BEGIN;
INSERT INTO `user` VALUES (1, '张三', '123455');
INSERT INTO `user` VALUES (2, '李四', '123456');
INSERT INTO `user` VALUES (3, '王五', '123457');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
2、新建spring boot项目,添加如下pom依赖
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
另外,要记得配置好mysql连接池和mybatis的依赖,后面要用到哦。
3、在项目中controller中新建UserController类
这个类主要添加一个接口ifExists方法,目的是为了验证布隆过滤器的结果。其内容如下:
package com.example.controller;
import com.example.service.impl.BloomFilterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author william liu
* @date 2021/3/8
* @Description TODO
*/
@RestController
@RequestMapping("/sys")
public class UserController {
@Autowired
private BloomFilterService bloomFilterService;
@GetMapping("idExists/{id}")
public boolean ifExists(@PathVariable("id") Integer id){
return bloomFilterService.userIdExists(id);
}
}
4、在service层,添加BloomFilterService类
这个类是核心,它有两个方法,第一个run()方法主要是为了在项目启动时,查询mysql获取所有用户id,添加到布隆过滤器中。当然,我这是稍微粗暴的方式,实际工作使用中,你可以结合业务特点,使用其他机制添加所有用户ID哦。
另一个方法是上面ifExists的service实现。根据用户编号查找布隆过滤器是否存在此用户。内容如下:
package com.example.service.impl;
import com.example.dao.SysUserDao;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.util.List;
@Slf4j
@Service
public class BloomFilterService implements ApplicationRunner {
@Autowired
private SysUserDao sysUserDao;
private BloomFilter<Integer> bf;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("MyRunner");
log.info("====启动========");
//查询所有用户编号
List<Integer> userIdList = sysUserDao.findAllId();
if (CollectionUtils.isEmpty(userIdList)) return;
//创建布隆过滤器
bf = BloomFilter.create(Funnels.integerFunnel(), userIdList.size());
//添加用户编号到布隆过滤器
for (Integer userId : userIdList) {
bf.put(userId);
}
log.info("====结束========");
}
public boolean userIdExists(int userId) {
return bf.mightContain(userId);
}
}
5、在dao层添加UserDao接口
这个就是不用多说了,内容如下:
package com.example.dao;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author william liu
* @date 2021/3/8
* @Description TODO
*/
@Mapper
public interface SysUserDao{
List<Integer> findAllId();
}
最后是添加mybatis的SysUserDao.xml,内容是添加findAllId方法。完成以上步骤就大功告成了。接下来就是验证结果。
6、启动项目,验证结果
项目启动后,会发现控制台会打印相应的信息。说明数据已经添加到布隆过滤器里了,一切正常。然后浏览器地址栏输入:http://localhost:8080/sys/idExists/1,回车后,查看结果。这里传入了一个已存在的用户编号,结果返回true,说明正常。
最后再使用一个不存在的用户编号,看看返回结果是不是false。如下图所示:
从上图可以看到,我们传入了用户编号,很显然是在布隆过滤器中不存在的,自然结果是false啦。
总结:这一节中,笔者使用google guava框架实现布隆过滤器,使用它来验证用户是否已经注册的例子。启动项目时,添加了所有用户编号,然后用一个接口验证用户是否存在,进而验证了用户是否已经注册。达到了预期的效果。