[Spring cloud 一步步实现广告系统] 13. 索引服务编码实现
上一节我们分析了广告索引的维护有2种,全量索引加载
和增量索引维护
。因为广告检索是广告系统中最为重要的环节,大家一定要认真理解我们索引设计的思路,接下来我们来编码实现索引维护功能。
我们来定义一个接口,来接收所有index的增删改查操作,接口定义一个范型,来接收2个参数,K
代表我们索引的健值,V
代表返回值。
/*** IIndexAware for 实现广告索引的增删改查** @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>*/
public interface IIndexAware<K, V> {/*** 通过key 获取索引*/V get(K key);/*** 添加索引* @param key* @param value*/void add(K key, V value);/*** 更新索引*/void update(K key, V value);/*** 删除索引*/void delete(K key, V value);
}
我们一定要知道,并不是所有的数据库表都需要创建索引,比如User
表我们在数据检索的时候其实是不需要的,当然也就没必要创建索引,并且,也不是表中的所有字段都需要索引,这个也是根据具体的业务来确定字段信息,比如我们接下来要编写的推广计划
索引中,推广计划名称就可以不需要。下面,我们来实现我们的第一个正向索引
。
- 首先创建操作推广计划的实体对象
/*** AdPlanIndexObject for 推广计划索引对象* 这个索引对象我们没有添加 推广计划名称* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AdPlanIndexObject {private Long planId;private Long userId;private Integer planStatus;private Date startDate;private Date endDate;/*** 根据实际字段来更新索引*/public void update(AdPlanIndexObject newObject) {if (null != newObject.getPlanId()) {this.planId = newObject.getPlanId();}if (null != newObject.getUserId()) {this.userId = newObject.getUserId();}if (null != newObject.getPlanStatus()) {this.planStatus = newObject.getPlanStatus();}if (null != newObject.getStartDate()) {this.startDate = newObject.getStartDate();}if (null != newObject.getEndDate()) {this.endDate = newObject.getEndDate();}}
}
- 然后创建推广计划索引实现类,并实现
IIndexAware
接口。
/*** AdPlanIndexAwareImpl for 推广计划索引实现类** @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>*/
@Slf4j
@Component
public class AdPlanIndexAwareImpl implements IIndexAware<Long, AdPlanIndexObject> {private static Map<Long, AdPlanIndexObject> planIndexObjectMap;/*** 因为操作索引的过程中有可能对索引进行更新,为了防止多线程造成的线程不安全问题,我们不能使用hashmap,需要实现ConcurrentHashMap*/static {planIndexObjectMap = new ConcurrentHashMap<>();}@Overridepublic AdPlanIndexObject get(Long key) {return planIndexObjectMap.get(key);}@Overridepublic void add(Long key, AdPlanIndexObject value) {log.info("AdPlanIndexAwareImpl before add::{}", planIndexObjectMap);planIndexObjectMap.put(key, value);log.info("AdPlanIndexAwareImpl after add::{}", planIndexObjectMap);}@Overridepublic void update(Long key, AdPlanIndexObject value) {log.info("AdPlanIndexAwareImpl before update::{}", planIndexObjectMap);//查询当前的索引信息,如果不存在,直接新增索引信息AdPlanIndexObject oldObj = planIndexObjectMap.get(key);if (null == oldObj) {planIndexObjectMap.put(key, value);} else {oldObj.update(value);}log.info("AdPlanIndexAwareImpl after update::{}", planIndexObjectMap);}@Overridepublic void delete(Long key, AdPlanIndexObject value) {log.info("AdPlanIndexAwareImpl before delete::{}", planIndexObjectMap);planIndexObjectMap.remove(key);log.info("AdPlanIndexAwareImpl after delete::{}", planIndexObjectMap);}
}
至此,我们已经完成了推广计划的索引对象和索引操作的代码编写,大家可以参考上面的示例,依次完成推广单元
、推广创意
、地域
、兴趣
、关键词
以及推广创意和推广单元的关联索引
,或者可直接从 Github传送门 / Gitee传送门 下载源码。
按照上述代码展示,我们已经实现了所有的索引操作的定义,但是实际情况中,我们需要使用这些服务的时候,需要在每一个Service中
@Autowired
注入,我们那么多的索引操作类,还不包含后续还有可能需要新增的索引维度,工作量实在是太大,而且不方便维护,作为一个合格的程序员来说,这是非常不友好的,也许会让后续的开发人员骂娘。
为了防止后续被骂,我们来编写一个索引缓存工具类com.sxzhongf.ad.index.IndexDataTableUtils
,通过这个索引缓存工具类来实现一次注入,解决后顾之忧。要实现这个工具类,我们需要实现2个接口:org.springframework.context.ApplicationContextAware
和org.springframework.core.PriorityOrdered
org.springframework.context.ApplicationContextAware
, 统一通过实现该接口的类,来操作Spring容器以及其中的Bean实例。
在Spring中,以Aware
为后缀结束的类,大家可以简单的理解为应用程序想要XXX,比如ApplicationContextAware
代表应用程序想要ApplicationContext
,BeanFactoryAware
表示应用程序想要BeanFactory
...等等org.springframework.core.PriorityOrdered
组件加载顺序,也可以使用org.springframework.core.Ordered
以下代码为我们的工具类:
package com.sxzhongf.ad.index;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.PriorityOrdered;
import org.springframework.stereotype.Component;import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;/*** IndexDataTableUtils for 所有索引服务需要缓存的Java Bean** 使用方式:* 获取{@link com.sxzhongf.ad.index.creative.CreativeIndexAwareImpl}索引服务类* 如下:* {@code* IndexDataTableUtils.of(CreativeIndexAwareImpl.class)* }* @author <a href="mailto:magicianisaac@gmail.com">Isaac.Zhang | 若初</a>*/
@Component
public class IndexDataTableUtils implements ApplicationContextAware, PriorityOrdered {//注入ApplicationContextprivate static ApplicationContext applicationContext;/*** 定义用于保存所有Index的Map* Class标示我们的索引类*/private static final Map<Class, Object> dataTableMap = new ConcurrentHashMap<>();@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {IndexDataTableUtils.applicationContext = applicationContext;}/*** 获取索引服务缓存*/public static <T> T of(Class<T> klass) {T instance = (T) dataTableMap.get(klass);//如果获取到索引bean,直接返回当前beanif (null != instance) {return instance;}//首次获取索引bean为空,写入MapdataTableMap.put(klass, bean(klass));return (T) dataTableMap.get(klass);}/*** 获取Spring 容器中的Bean对象*/private static <T> T bean(String beanName) {return (T) applicationContext.getBean(beanName);}/*** 获取Spring 容器中的Bean对象*/private static <T> T bean(Class klass) {return (T) applicationContext.getBean(klass);}@Overridepublic int getOrder() {return PriorityOrdered.HIGHEST_PRECEDENCE;}
}
转载于:https://www.cnblogs.com/zhangpan1244/p/11318481.html
[Spring cloud 一步步实现广告系统] 13. 索引服务编码实现相关推荐
- [Spring cloud 一步步实现广告系统] 16. 增量索引实现以及投送数据到MQ(kafka)
实现增量数据索引 上一节中,我们为实现增量索引的加载做了充足的准备,使用到mysql-binlog-connector-java 开源组件来实现MySQL 的binlog监听,关于binlog的相关知 ...
- [Spring cloud 一步步实现广告系统] 22. 广告系统回顾总结
到目前为止,我们整个初级广告检索系统就初步开发完成了,我们来整体回顾一下我们的广告系统. 整个广告系统编码结构如下: 1.mscx-ad 父模块 主要是为了方便我们项目的统一管理 2.mscx-ad- ...
- [Spring cloud 一步步实现广告系统] 21. 系统错误汇总
广告系统学习过程中问题答疑 博客园 Eureka集群启动报错 Answer 因为Eureka在集群启动过程中,会连接集群中其他的机器进行数据同步,在这个过程中,如果别的服务还没有启动完成,就会出现Co ...
- [Spring cloud 一步步实现广告系统] 19. 监控Hystrix Dashboard
在之前的18次文章中,我们实现了广告系统的广告投放,广告检索业务功能,中间使用到了 服务发现Eureka,服务调用Feign,网关路由Zuul以及错误熔断Hystrix等Spring Cloud组件. ...
- [Spring cloud 一步步实现广告系统] 12. 广告索引介绍
索引设计介绍 在我们广告系统中,为了我们能更快的拿到我们想要的广告数据,我们需要对广告数据添加类似于数据库index一样的索引结构,分两大类:正向索引和倒排索引. 正向索引 通过唯一键/主键生成与对象 ...
- [Spring cloud 一步步实现广告系统] 14. 全量索引代码实现
上一节我们实现了索引基本操作的类以及索引缓存工具类,本小节我们开始实现加载全量索引数据,在加载全量索引数据之前,我们需要先将数据库中的表数据导出到一份文件中.Let's code. 1.首先定义一个常 ...
- [Spring cloud 一步步实现广告系统] 11. 使用Feign实现微服务调用
上一节我们使用了Ribbon(基于Http/Tcp)进行微服务的调用,Ribbon的调用比较简单,通过Ribbon组件对请求的服务进行拦截,通过Eureka Server 获取到服务实例的IP:Por ...
- feign响应拦截_[Spring cloud 一步步实现广告系统] 11. 使用Feign实现微服务调用
上一节我们使用了Ribbon(基于Http/Tcp)进行微服务的调用,Ribbon的调用比较简单,通过Ribbon组件对请求的服务进行拦截,通过Eureka Server 获取到服务实例的IP:Por ...
- [Spring cloud 一步步实现广告系统] 15. 使用开源组件监听Binlog 实现增量索引准备...
MySQL Binlog简介 什么是binlog? 一个二进制日志,用来记录对数据发生或潜在发生更改的SQL语句,并以而进行的形式保存在磁盘中. binlog 的作用? 最主要有3个用途: 数据复制( ...
最新文章
- Activity的setResult方法
- Zynq的AMP开发注意事项之禁用L2 cache
- 【字节网盘】九款超好看不同页面404源码
- cmake的一个编译报错
- 个位百位AS3实现经典算法(二) 水仙花数
- Java反射----获取Class类实例的4种方式
- 动态库的隐式链接和显示链接
- WinRAR5.60 64位 官方无广告正式版注册破解
- linux i350网卡,intel I350 网卡驱动安装方法
- 如何正确的制定目标?(只需4步)
- 2017 Multi-University Training Contest - Team 10
- 阿里巴巴的类ChatGPT产品
- 玫瑰线 matlab,如何用MATLAB画玫瑰线
- Python爬虫第二课 Selenium介绍和反爬技术
- unity3d如何获知场景中需要加载的数据_游戏中遮挡剔除方案总结
- 树莓派3b安装新系统的步骤和一些问题
- element-ui 获取当前行的 id
- 小程序流量主能赚多少_微信:6月1日起调整小程序和公众号流量主广告收入分成比例...
- 【CV】图像融合结果评价
- 10大电子书免费下载网站