public class RedisConstants {
public static final Long CACHE_NULL_TTL = 2L;
public static final Long CACHE_SHOP_TTL = 30L;
public static final String CACHE_SHOP_KEY = "cache:shop:";
}
工具类
public class ObjectMapUtils {
// 将对象转为 Map
public static Map obj2Map(Object obj) throws IllegalAccessException {
Map result = new HashMap();
Class> clazz = obj.getClass();
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// 如果为 static 且 final 则跳过
if (Modifier.isStatic(field.getModifiers()) && Modifier.isFinal(field.getModifiers())) {
continue;
}
field.setAccessible(true); // 设置为可访问私有字段
Object fieldValue = field.get(obj);
if (fieldValue != null) {
result.put(field.getName(), field.get(obj).toString());
}
}
return result;
}
// 将 Map 转为对象
public static Object map2Obj(Map
结果返回类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
private Boolean success;
private String errorMsg;
private Object data;
private Long total;
public static Result ok(){
return new Result(true, null, null, null);
}
public static Result ok(Object data){
return new Result(true, null, data, null);
}
public static Result ok(List> data, Long total){
return new Result(true, null, data, total);
}
public static Result fail(String errorMsg){
return new Result(false, errorMsg, null, null);
}
}
控制层
@RestController
@RequestMapping("/shop")
public class ShopController {
@Resource
public IShopService shopService;
/**
* 根据id查询商铺信息
* @param id 商铺id
* @return 商铺详情数据
*/
@GetMapping("/{id}")
public Result queryShopById(@PathVariable("id") Long id) {
return shopService.queryShopById(id);
}
/**
* 新增商铺信息
* @param shop 商铺数据
* @return 商铺id
*/
@PostMapping
public Result saveShop(@RequestBody Shop shop) {
return shopService.saveShop(shop);
}
/**
* 更新商铺信息
* @param shop 商铺数据
* @return 无
*/
@PutMapping
public Result updateShop(@RequestBody Shop shop) {
return shopService.updateShop(shop);
}
}
这里选择使用布隆过滤器存储存在于数据库中的 id,原因在于,如果存储了不存在于数据库中的 id,首先由于 id 的取值范围很大,那么不存在的 id 有很多,因此更占用空间;其次,由于布隆过滤器有一定的误判率,那么可能导致少数原本存在于数据库中的 id 被判为了不存在,然后直接返回了,此时就会出现根本性的正确性错误。相反,如果存储的是数据库中存在的 id,那么即使少数不存在的 id 被判为了存在,由于数据库中确实没有对应的 id,那么也会返回空,最终结果还是正确的
这里使用 guava 依赖的布隆过滤器
依赖为:
com.google.guavaguava30.1.1-jre
封装了布隆过滤器的类(注意初始化时要把数据库中已有的 id 加入布隆过滤器):
public class ShopBloomFilter {
private BloomFilter bloomFilter;
public ShopBloomFilter(ShopMapper shopMapper) {
// 初始化布隆过滤器,设计预计元素数量为100_0000L,误差率为1%
bloomFilter = BloomFilter.create(Funnels.longFunnel(), 100_0000, 0.01);
// 将数据库中已有的店铺 id 加入布隆过滤器
List shops = shopMapper.selectList(null);
for (Shop shop : shops) {
bloomFilter.put(shop.getId());
}
}
public void add(long id) {
bloomFilter.put(id);
}
public boolean mightContain(long id){
return bloomFilter.mightContain(id);
}
}
对应的配置类(将其设置为 bean)
@Configuration
public class BloomConfig {
@Bean
public ShopBloomFilter shopBloomFilter(ShopMapper shopMapper) {
return new ShopBloomFilter(shopMapper);
}
}
首先要修改查询方法,在根据 id 查询时,如果对应 id 不在布隆过滤器中,则直接返回。然后还要修改保存方法,在保存的时候还需要将对应的 id 加入布隆过滤器中