diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index c06a160..5bce655 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -7,11 +7,11 @@
-
+
-
+
diff --git a/.idea/dictionaries/sss.xml b/.idea/dictionaries/sss.xml
index 8f2a077..031bbe4 100644
--- a/.idea/dictionaries/sss.xml
+++ b/.idea/dictionaries/sss.xml
@@ -1,10 +1,15 @@
+ adconf
creatives
finchley
getor
javaedge
+ kaiping
+ pian
+ shishusheng
+ tiepian
yyyy
diff --git a/README.md b/README.md
index b77de06..60d2e84 100644
--- a/README.md
+++ b/README.md
@@ -1,15 +1,4 @@
-# 0 联系我
-
-1.[Java开发技术交流Q群](https://jq.qq.com/?_wv=1027&k=5UB4P1T)
-
-2.[完整博客链接](http://www.shishusheng.com)
-
-3.[个人知乎](http://www.zhihu.com/people/shi-shu-sheng-)
-
-4.[gayhub](https://github.com/Wasabi1234)
-
-# SpringCloud+Kafka+MySQL实现微服务架构下的广告系统
-掌握了广告系统,就是掌握了很多互联网公司的收入核心,你自然也就是公司的核心!
+# 基于微服务架构的广告系统
# 环境参数
JDK 1.8
@@ -17,29 +6,5 @@ SpringCloud: Finchley.RELEASE
Kafka 2.0
Maven 3.5.0
MySQL 5.7
-IDE IntelliJ IDEA: 2019.1
-
-# 1 博客教程
-## 1.1 [项目简介](https://www.jianshu.com/p/69a703b080b6)
-广告系统的介绍、所使用的技术介绍、学习规划,广告系统的思想、广告系统的技术实现架构、准备工作和广告系统的代码目录结构等
-
-## 1.2 [脚手架开发](https://www.jianshu.com/p/5504269507f1)
-广告系统使用SpringCloud微服务框架开发,并使用Maven做多模块管理。该部分完成项目骨架的开发,包括搭建注册中心和服务网关,同时也会对Maven的重要特性做介绍
-
-## 1.3 [微服务通用模块开发](https://www.jianshu.com/p/e3c2b9e729dd)
-实现广告系统微服务通用的功能,例如:统一响应格式、全局异常处理、通用代码定义、通用配置定义等
-
-## 1.4 [广告投放系统的开发](https://www.jianshu.com/p/bfde2ed70106)
-实现投放系统,投放系统即实现对广告数据的存储.
-会对表结构设计进行介绍,使用 JPA 实现对各个数据表的增删改查。同时,由于会涉及Spring相关的知识点(Spring IOC、Spring MVC、SpringBoot),也会对这些做基础介绍
-
-## 1.5 [广告检索系统 - 微服务调用](https://www.jianshu.com/p/9c62c0fbd139)
-介绍使用 Ribbon 与 Feign 组件实现微服务之间的调用
-
-## 1.6 [广告检索系统 - 广告数据索引的设计与实现](https://www.jianshu.com/p/685f1a5aafd0)
-广告检索系统的核心是实现广告检索服务,为加快广告检索的速度,良好的索引设计是不可缺少的。本章首先对索引的设计与维护进行介绍,之后,实现广告数据的索引服务。
-
-## 1.7 [广告检索系统 - 加载全量索引]()
+IDE IntelliJ IDEA: 2018.3
-
-
diff --git a/ad-gateway/src/main/resources/application.yml b/ad-gateway/src/main/resources/application.yml
index deab9cf..9da5a10 100755
--- a/ad-gateway/src/main/resources/application.yml
+++ b/ad-gateway/src/main/resources/application.yml
@@ -14,4 +14,8 @@ zuul:
sponsor:
path: /ad-sponsor/**
serviceId: eureka-client-ad-sponsor
- strip-prefix: false
\ No newline at end of file
+ strip-prefix: false
+ search:
+ path: /ad-search/**
+ serviceId: eureka-client-ad-search
+ strip-prefix: false
diff --git a/javaedge-ad-service/ad-common/src/main/java/com/javaedge/ad/dump/table/AdPlanTable.java b/javaedge-ad-service/ad-common/src/main/java/com/javaedge/ad/dump/table/AdPlanTable.java
index d9af2e5..01c3113 100644
--- a/javaedge-ad-service/ad-common/src/main/java/com/javaedge/ad/dump/table/AdPlanTable.java
+++ b/javaedge-ad-service/ad-common/src/main/java/com/javaedge/ad/dump/table/AdPlanTable.java
@@ -18,6 +18,10 @@ public class AdPlanTable {
private Long id;
private Long userId;
private Integer planStatus;
+
+ /**
+ * 对于 Date 类型,由于将 binlog 转化为了字符串,需搞清楚 Date 的字符串表达形式
+ */
private Date startDate;
private Date endDate;
}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/CommonStatus.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/CommonStatus.java
new file mode 100644
index 0000000..a20ed8e
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/CommonStatus.java
@@ -0,0 +1,22 @@
+package com.javaedge.ad.index;
+
+import lombok.Getter;
+
+/**
+ * @author sss
+ * @date 2019/2/27
+ */
+@Getter
+public enum CommonStatus {
+
+ VALID(1, "有效状态"),
+ INVALID(0, "无效状态");
+
+ private Integer status;
+ private String desc;
+
+ CommonStatus(Integer status, String desc) {
+ this.status = status;
+ this.desc = desc;
+ }
+}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/DataLevel.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/DataLevel.java
new file mode 100755
index 0000000..c6c5b2a
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/DataLevel.java
@@ -0,0 +1,23 @@
+package com.javaedge.ad.index;
+
+import lombok.Getter;
+
+/**
+ * @author sss
+ * @date 2019-02-22
+ */
+@Getter
+public enum DataLevel {
+
+ LEVEL2("2", "level 2"),
+ LEVEL3("3", "level 3"),
+ LEVEL4("4", "level 4");
+
+ private String level;
+ private String desc;
+
+ DataLevel(String level, String desc) {
+ this.level = level;
+ this.desc = desc;
+ }
+}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitConstants.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitConstants.java
new file mode 100755
index 0000000..3b015f6
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitConstants.java
@@ -0,0 +1,36 @@
+package com.javaedge.ad.index.adunit;
+
+/**
+ * @author sss
+ * @date 2019-02-26
+ */
+public class AdUnitConstants {
+
+ public static class POSITION_TYPE {
+
+ /**
+ * 开屏广告位
+ */
+ public static final int KAIPING = 1;
+
+ /**
+ * 贴片广告
+ */
+ public static final int TIEPIAN = 2;
+
+ /**
+ * 视频播放中显示的广告
+ */
+ public static final int TIEPIAN_MIDDLE = 4;
+
+ /**
+ * 视频播放暂停时广告
+ */
+ public static final int TIEPIAN_PAUSE = 8;
+
+ /**
+ * 视频播放后的广告位
+ */
+ public static final int TIEPIAN_POST = 16;
+ }
+}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitIndex.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitIndex.java
index fb877e3..d4d1b62 100644
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitIndex.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitIndex.java
@@ -2,9 +2,10 @@
import com.javaedge.ad.index.IndexAware;
import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;
-import java.util.Map;
+import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
@@ -21,6 +22,42 @@ public class AdUnitIndex implements IndexAware {
objectMap = new ConcurrentHashMap<>();
}
+
+ public Set match(Integer positionType) {
+
+ Set adUnitIds = new HashSet<>();
+
+ objectMap.forEach((k, v) -> {
+ if (AdUnitObject.isAdSlotTypeOK(positionType,
+ v.getPositionType())) {
+ adUnitIds.add(k);
+ }
+ });
+
+ return adUnitIds;
+ }
+
+ public List fetch(Collection adUnitIds) {
+
+ if (CollectionUtils.isEmpty(adUnitIds)) {
+ return Collections.emptyList();
+ }
+
+ List result = new ArrayList<>();
+
+ adUnitIds.forEach(u -> {
+ AdUnitObject object = get(u);
+ if (object == null) {
+ log.error("AdUnitObject not found: {}", u);
+ return;
+ }
+ result.add(object);
+ });
+
+ return result;
+ }
+
+
@Override
public AdUnitObject get(Long key) {
return objectMap.get(key);
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitObject.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitObject.java
index 6fe69dd..d39caa0 100644
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitObject.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/adunit/AdUnitObject.java
@@ -40,4 +40,42 @@ void update(AdUnitObject newObject) {
this.adPlanObject = newObject.getAdPlanObject();
}
}
+
+ private static boolean isKaiPing(int positionType) {
+ return (positionType & AdUnitConstants.POSITION_TYPE.KAIPING) > 0;
+ }
+
+ private static boolean isTiePian(int positionType) {
+ return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN) > 0;
+ }
+
+ private static boolean isTiePianMiddle(int positionType) {
+ return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_MIDDLE) > 0;
+ }
+
+ private static boolean isTiePianPause(int positionType) {
+ return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_PAUSE) > 0;
+ }
+
+ private static boolean isTiePianPost(int positionType) {
+ return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_POST) > 0;
+ }
+
+ public static boolean isAdSlotTypeOK(int adSlotType, int positionType) {
+
+ switch (adSlotType) {
+ case AdUnitConstants.POSITION_TYPE.KAIPING:
+ return isKaiPing(positionType);
+ case AdUnitConstants.POSITION_TYPE.TIEPIAN:
+ return isTiePian(positionType);
+ case AdUnitConstants.POSITION_TYPE.TIEPIAN_MIDDLE:
+ return isTiePianMiddle(positionType);
+ case AdUnitConstants.POSITION_TYPE.TIEPIAN_PAUSE:
+ return isTiePianPause(positionType);
+ case AdUnitConstants.POSITION_TYPE.TIEPIAN_POST:
+ return isTiePianPost(positionType);
+ default:
+ return false;
+ }
+ }
}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creative/CreativeIndex.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creative/CreativeIndex.java
index 0132623..296bfa6 100644
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creative/CreativeIndex.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creative/CreativeIndex.java
@@ -27,7 +27,6 @@ public class CreativeIndex implements IndexAware {
}
public List fetch(Collection adIds) {
-
if (CollectionUtils.isEmpty(adIds)) {
return Collections.emptyList();
}
@@ -40,10 +39,8 @@ public List fetch(Collection adIds) {
log.error("CreativeObject not found: {}", u);
return;
}
-
result.add(object);
});
-
return result;
}
@@ -54,7 +51,6 @@ public CreativeObject get(Long key) {
@Override
public void add(Long key, CreativeObject value) {
-
log.info("before add: {}", objectMap);
objectMap.put(key, value);
log.info("after add: {}", objectMap);
@@ -62,7 +58,6 @@ public void add(Long key, CreativeObject value) {
@Override
public void update(Long key, CreativeObject value) {
-
log.info("before update: {}", objectMap);
CreativeObject oldObject = objectMap.get(key);
@@ -77,7 +72,6 @@ public void update(Long key, CreativeObject value) {
@Override
public void delete(Long key, CreativeObject value) {
-
log.info("before delete: {}", objectMap);
objectMap.remove(key);
log.info("after delete: {}", objectMap);
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creativeunit/CreativeUnitIndex.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creativeunit/CreativeUnitIndex.java
index fb36102..06a3de3 100644
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creativeunit/CreativeUnitIndex.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/creativeunit/CreativeUnitIndex.java
@@ -50,7 +50,6 @@ public CreativeUnitObject get(String key) {
@Override
public void add(String key, CreativeUnitObject value) {
-
log.info("before add: {}", objectMap);
objectMap.put(key, value);
@@ -74,13 +73,11 @@ public void add(String key, CreativeUnitObject value) {
@Override
public void update(String key, CreativeUnitObject value) {
-
log.error("CreativeUnitIndex not support update");
}
@Override
public void delete(String key, CreativeUnitObject value) {
-
log.info("before delete: {}", objectMap);
objectMap.remove(key);
@@ -99,7 +96,6 @@ public void delete(String key, CreativeUnitObject value) {
}
public List selectAds(List unitObjects) {
-
if (CollectionUtils.isEmpty(unitObjects)) {
return Collections.emptyList();
}
@@ -107,7 +103,6 @@ public List selectAds(List unitObjects) {
List result = new ArrayList<>();
for (AdUnitObject unitObject : unitObjects) {
-
Set adIds = unitCreativeMap.get(unitObject.getUnitId());
if (CollectionUtils.isNotEmpty(adIds)) {
result.addAll(adIds);
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/district/UnitDistrictIndex.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/district/UnitDistrictIndex.java
index d033fda..30c624c 100644
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/district/UnitDistrictIndex.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/district/UnitDistrictIndex.java
@@ -1,6 +1,7 @@
package com.javaedge.ad.index.district;
import com.javaedge.ad.index.IndexAware;
+import com.javaedge.ad.search.vo.feature.DistrictFeature;
import com.javaedge.ad.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@@ -39,16 +40,19 @@ public void add(String key, Set value) {
log.info("UnitDistrictIndex, before add: {}", unitDistrictMap);
+ changeADD(key, value, districtUnitMap, unitDistrictMap);
+
+ log.info("UnitDistrictIndex, after add: {}", unitDistrictMap);
+ }
+
+ public static void changeADD(String key, Set value, Map> districtUnitMap, Map> unitDistrictMap) {
Set unitIds = CommonUtils.getorCreate(key, districtUnitMap, ConcurrentSkipListSet::new);
unitIds.addAll(value);
for (Long unitId : value) {
-
Set districts = CommonUtils.getorCreate(unitId, unitDistrictMap, ConcurrentSkipListSet::new);
districts.add(key);
}
-
- log.info("UnitDistrictIndex, after add: {}", unitDistrictMap);
}
@Override
@@ -62,6 +66,12 @@ public void delete(String key, Set value) {
log.info("UnitDistrictIndex, before delete: {}", unitDistrictMap);
+ changeRM(key, value, districtUnitMap, unitDistrictMap);
+
+ log.info("UnitDistrictIndex, after delete: {}", unitDistrictMap);
+ }
+
+ public static void changeRM(String key, Set value, Map> districtUnitMap, Map> unitDistrictMap) {
Set unitIds = CommonUtils.getorCreate(key, districtUnitMap, ConcurrentSkipListSet::new);
unitIds.removeAll(value);
@@ -69,27 +79,25 @@ public void delete(String key, Set value) {
Set districts = CommonUtils.getorCreate(unitId, unitDistrictMap, ConcurrentSkipListSet::new);
districts.remove(key);
}
-
- log.info("UnitDistrictIndex, after delete: {}", unitDistrictMap);
}
-// public boolean match(Long adUnitId, List districts) {
-//
-// if (unitDistrictMap.containsKey(adUnitId) &&
-// CollectionUtils.isNotEmpty(unitDistrictMap.get(adUnitId))) {
-//
-// Set unitDistricts = unitDistrictMap.get(adUnitId);
-//
-// List targetDistricts = districts.stream()
-// .map(
-// d -> CommonUtils.stringConcat(
-// d.getProvince(), d.getCity()
-// )
-// ).collect(Collectors.toList());
-//
-// return CollectionUtils.isSubCollection(targetDistricts, unitDistricts);
-// }
-//
-// return false;
-// }
+ public boolean match(Long adUnitId, List districts) {
+
+ if (unitDistrictMap.containsKey(adUnitId) &&
+ CollectionUtils.isNotEmpty(unitDistrictMap.get(adUnitId))) {
+
+ Set unitDistricts = unitDistrictMap.get(adUnitId);
+
+ List targetDistricts = districts.stream()
+ .map(
+ d -> CommonUtils.stringConcat(
+ d.getProvince(), d.getCity()
+ )
+ ).collect(Collectors.toList());
+
+ return CollectionUtils.isSubCollection(targetDistricts, unitDistricts);
+ }
+
+ return false;
+ }
}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/interest/UnitItIndex.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/interest/UnitItIndex.java
index f23f6ee..90156c4 100644
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/interest/UnitItIndex.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/interest/UnitItIndex.java
@@ -1,6 +1,7 @@
package com.javaedge.ad.index.interest;
import com.javaedge.ad.index.IndexAware;
+import com.javaedge.ad.index.district.UnitDistrictIndex;
import com.javaedge.ad.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@@ -45,20 +46,7 @@ public void add(String key, Set value) {
log.info("UnitItIndex, before add: {}", unitItMap);
- Set unitIds = CommonUtils.getorCreate(
- key, itUnitMap,
- ConcurrentSkipListSet::new
- );
- unitIds.addAll(value);
-
- for (Long unitId : value) {
-
- Set its = CommonUtils.getorCreate(
- unitId, unitItMap,
- ConcurrentSkipListSet::new
- );
- its.add(key);
- }
+ UnitDistrictIndex.changeADD(key, value, itUnitMap, unitItMap);
log.info("UnitItIndex, after add: {}", unitItMap);
}
@@ -75,17 +63,7 @@ public void delete(String key, Set value) {
log.info("UnitItIndex, before delete: {}", unitItMap);
// 先取出对应的推广 单元id
- Set unitIds = CommonUtils.getorCreate(key, itUnitMap, ConcurrentSkipListSet::new);
-
- // 再对单元 ids 进行 rm 操作,考虑到部分删除,不是直接对 itunitmap 删除 key 对应值
- // 因为 key 所对应 推广单元的 ids 并不一定全量,我们要实现可删除部分兴趣
- // eg. 一个 ittag 对应到推广单元的1,2,3,我们可以删除1,2 而不是3.所以先取再删.
- unitIds.removeAll(value);
-
- for (Long unitId : value) {
- Set itTagSet = CommonUtils.getorCreate(unitId, unitItMap, ConcurrentSkipListSet::new);
- itTagSet.remove(key);
- }
+ UnitDistrictIndex.changeRM(key, value, itUnitMap, unitItMap);
log.info("UnitItIndex, after delete: {}", unitItMap);
}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/keyword/UnitKeywordIndex.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/keyword/UnitKeywordIndex.java
index 47f8c04..7cf3adf 100644
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/keyword/UnitKeywordIndex.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/index/keyword/UnitKeywordIndex.java
@@ -1,6 +1,7 @@
package com.javaedge.ad.index.keyword;
import com.javaedge.ad.index.IndexAware;
+import com.javaedge.ad.index.district.UnitDistrictIndex;
import com.javaedge.ad.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
@@ -49,17 +50,7 @@ public void add(String key, Set value) {
log.info("UnitKeywordIndex, before add: {}", unitKeywordMap);
- Set unitIdSet = CommonUtils.getorCreate(key, keywordUnitMap, ConcurrentSkipListSet::new);
-
- unitIdSet.addAll(value);
-
- for (Long unitId : value) {
- Set keywordSet = CommonUtils.getorCreate(
- unitId, unitKeywordMap,
- ConcurrentSkipListSet::new
- );
- keywordSet.add(key);
- }
+ UnitDistrictIndex.changeADD(key, value, keywordUnitMap, unitKeywordMap);
log.info("UnitKeywordIndex, after add: {}", unitKeywordMap);
}
@@ -82,16 +73,7 @@ public void delete(String key, Set value) {
log.info("UnitKeywordIndex, before delete: {}", unitKeywordMap);
- Set unitIds = CommonUtils.getorCreate(key, keywordUnitMap, ConcurrentSkipListSet::new);
-
- unitIds.removeAll(value);
-
- for (Long unitId : value) {
-
- Set keywordSet = CommonUtils.getorCreate(unitId, unitKeywordMap, ConcurrentSkipListSet::new);
-
- keywordSet.remove(key);
- }
+ UnitDistrictIndex.changeRM(key, value, keywordUnitMap, unitKeywordMap);
log.info("UnitKeywordIndex, after delete: {}", unitKeywordMap);
}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/BinlogClient.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/BinlogClient.java
new file mode 100755
index 0000000..89ea883
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/BinlogClient.java
@@ -0,0 +1,67 @@
+package com.javaedge.ad.mysql;
+
+import com.github.shyiko.mysql.binlog.BinaryLogClient;
+import com.javaedge.ad.mysql.listener.AggregationListener;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.IOException;
+
+/**
+ * @author sss
+ * @date 2019-02-25
+ */
+@Slf4j
+@Component
+public class BinlogClient {
+
+ private BinaryLogClient client;
+
+ private final BinlogConfig config;
+ private final AggregationListener listener;
+
+ @Autowired
+ public BinlogClient(BinlogConfig config, AggregationListener listener) {
+ this.config = config;
+ this.listener = listener;
+ }
+
+ public void connect() {
+
+ new Thread(() -> {
+ client = new BinaryLogClient(
+ config.getHost(),
+ config.getPort(),
+ config.getUsername(),
+ config.getPassword()
+ );
+
+ if (!StringUtils.isEmpty(config.getBinlogName()) &&
+ !config.getPosition().equals(-1L)) {
+ client.setBinlogFilename(config.getBinlogName());
+ client.setBinlogPosition(config.getPosition());
+ }
+
+ client.registerEventListener(listener);
+
+ try {
+ log.info("connecting to mysql start");
+ client.connect();
+ log.info("connecting to mysql done");
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+
+ }).start();
+ }
+
+ public void close() {
+ try {
+ client.disconnect();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/BinlogConfig.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/BinlogConfig.java
new file mode 100755
index 0000000..c191742
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/BinlogConfig.java
@@ -0,0 +1,27 @@
+package com.javaedge.ad.mysql;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author sss
+ * @date 2019-02-25
+ */
+@Component
+@ConfigurationProperties(prefix = "adconf.mysql")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class BinlogConfig {
+
+ private String host;
+ private Integer port;
+ private String username;
+ private String password;
+
+ private String binlogName;
+ private Long position;
+}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/TemplateHolder.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/TemplateHolder.java
new file mode 100755
index 0000000..5303cb8
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/TemplateHolder.java
@@ -0,0 +1,102 @@
+package com.javaedge.ad.mysql;
+
+import com.alibaba.fastjson.JSON;
+import com.javaedge.ad.mysql.constant.OpType;
+import com.javaedge.ad.mysql.dto.ParseTemplate;
+import com.javaedge.ad.mysql.dto.TableTemplate;
+import com.javaedge.ad.mysql.dto.Template;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author sss
+ * @date 2019-02-25
+ */
+@Slf4j
+@Component
+public class TemplateHolder {
+
+ private ParseTemplate template;
+ private final JdbcTemplate jdbcTemplate;
+
+ private String SQL_SCHEMA = "select table_schema, table_name, " +
+ "column_name, ordinal_position from information_schema.columns " +
+ "where table_schema = ? and table_name = ?";
+
+ @Autowired
+ public TemplateHolder(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @PostConstruct
+ private void init() {
+ loadJson("template.json");
+ }
+
+ public TableTemplate getTable(String tableName) {
+ return template.getTableTemplateMap().get(tableName);
+ }
+
+ private void loadJson(String path) {
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ InputStream inStream = cl.getResourceAsStream(path);
+
+ try {
+ Template template = JSON.parseObject(
+ inStream,
+ Charset.defaultCharset(),
+ Template.class
+ );
+ this.template = ParseTemplate.parse(template);
+ loadMeta();
+ } catch (IOException ex) {
+ log.error(ex.getMessage());
+ throw new RuntimeException("fail to parse json file");
+ }
+ }
+
+ private void loadMeta() {
+
+ for (Map.Entry entry :
+ template.getTableTemplateMap().entrySet()) {
+
+ TableTemplate table = entry.getValue();
+
+ List updateFields = table.getOpTypeFieldSetMap().get(
+ OpType.UPDATE
+ );
+ List insertFields = table.getOpTypeFieldSetMap().get(
+ OpType.ADD
+ );
+ List deleteFields = table.getOpTypeFieldSetMap().get(
+ OpType.DELETE
+ );
+
+ jdbcTemplate.query(SQL_SCHEMA, new Object[]{
+ template.getDatabase(), table.getTableName()
+ }, (rs, i) -> {
+
+ int pos = rs.getInt("ORDINAL_POSITION");
+ String colName = rs.getString("COLUMN_NAME");
+
+ if ((null != updateFields && updateFields.contains(colName))
+ || (null != insertFields && insertFields.contains(colName))
+ || (null != deleteFields && deleteFields.contains(colName))) {
+ table.getPosMap().put(pos - 1, colName);
+ }
+
+ return null;
+ });
+ }
+ }
+}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/constant/Constant.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/constant/Constant.java
new file mode 100755
index 0000000..8d84b5e
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/constant/Constant.java
@@ -0,0 +1,95 @@
+package com.javaedge.ad.mysql.constant;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author sss
+ * @date 2019-02-25
+ */
+public class Constant {
+
+ private static final String DB_NAME = "javaedge_ad_data";
+
+ public static class AD_PLAN_TABLE_INFO {
+
+ public static final String TABLE_NAME = "ad_plan";
+
+ public static final String COLUMN_ID = "id";
+ public static final String COLUMN_USER_ID = "user_id";
+ public static final String COLUMN_PLAN_STATUS = "plan_status";
+ public static final String COLUMN_START_DATE = "start_date";
+ public static final String COLUMN_END_DATE = "end_date";
+ }
+
+ public static class AD_CREATIVE_TABLE_INFO {
+
+ public static final String TABLE_NAME = "ad_creative";
+
+ public static final String COLUMN_ID = "id";
+ public static final String COLUMN_TYPE = "type";
+ public static final String COLUMN_MATERIAL_TYPE = "material_type";
+ public static final String COLUMN_HEIGHT = "height";
+ public static final String COLUMN_WIDTH = "width";
+ public static final String COLUMN_AUDIT_STATUS = "audit_status";
+ public static final String COLUMN_URL = "url";
+ }
+
+ public static class AD_UNIT_TABLE_INFO {
+
+ public static final String TABLE_NAME = "ad_unit";
+
+ public static final String COLUMN_ID = "id";
+ public static final String COLUMN_UNIT_STATUS = "unit_status";
+ public static final String COLUMN_POSITION_TYPE = "position_type";
+ public static final String COLUMN_PLAN_ID = "plan_id";
+ }
+
+ public static class AD_CREATIVE_UNIT_TABLE_INFO {
+
+ public static final String TABLE_NAME = "creative_unit";
+
+ public static final String COLUMN_CREATIVE_ID = "creative_id";
+ public static final String COLUMN_UNIT_ID = "unit_id";
+ }
+
+ public static class AD_UNIT_DISTRICT_TABLE_INFO {
+
+ public static final String TABLE_NAME = "ad_unit_district";
+
+ public static final String COLUMN_UNIT_ID = "unit_id";
+ public static final String COLUMN_PROVINCE = "province";
+ public static final String COLUMN_CITY = "city";
+ }
+
+ public static class AD_UNIT_IT_TABLE_INFO {
+
+ public static final String TABLE_NAME = "ad_unit_it";
+
+ public static final String COLUMN_UNIT_ID = "unit_id";
+ public static final String COLUMN_IT_TAG = "it_tag";
+ }
+
+ public static class AD_UNIT_KEYWORD_TABLE_INFO {
+
+ public static final String TABLE_NAME = "ad_unit_keyword";
+
+ public static final String COLUMN_UNIT_ID = "unit_id";
+ public static final String COLUMN_KEYWORD = "keyword";
+ }
+
+ public static Map table2Db;
+
+ static {
+
+ table2Db = new HashMap<>();
+
+ table2Db.put(AD_PLAN_TABLE_INFO.TABLE_NAME, DB_NAME);
+ table2Db.put(AD_CREATIVE_TABLE_INFO.TABLE_NAME, DB_NAME);
+ table2Db.put(AD_UNIT_TABLE_INFO.TABLE_NAME, DB_NAME);
+ table2Db.put(AD_CREATIVE_UNIT_TABLE_INFO.TABLE_NAME, DB_NAME);
+ table2Db.put(AD_UNIT_DISTRICT_TABLE_INFO.TABLE_NAME, DB_NAME);
+ table2Db.put(AD_UNIT_IT_TABLE_INFO.TABLE_NAME, DB_NAME);
+ table2Db.put(AD_UNIT_KEYWORD_TABLE_INFO.TABLE_NAME, DB_NAME);
+ }
+}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/constant/OpType.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/constant/OpType.java
old mode 100644
new mode 100755
index ff3612a..e6f6184
--- a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/constant/OpType.java
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/constant/OpType.java
@@ -1,13 +1,30 @@
package com.javaedge.ad.mysql.constant;
+import com.github.shyiko.mysql.binlog.event.EventType;
+
/**
* @author sss
- * @date 2019-02-12
+ * @date 2019-02-25
*/
-public enum OpType {
+public enum OpType {
ADD,
UPDATE,
DELETE,
OTHER;
+
+ public static OpType to(EventType eventType) {
+
+ switch (eventType) {
+ case EXT_WRITE_ROWS:
+ return ADD;
+ case EXT_UPDATE_ROWS:
+ return UPDATE;
+ case EXT_DELETE_ROWS:
+ return DELETE;
+
+ default:
+ return OTHER;
+ }
+ }
}
diff --git a/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/dto/BinlogRowData.java b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/dto/BinlogRowData.java
new file mode 100755
index 0000000..b20543f
--- /dev/null
+++ b/javaedge-ad-service/ad-search/src/main/java/com/javaedge/ad/mysql/dto/BinlogRowData.java
@@ -0,0 +1,25 @@
+package com.javaedge.ad.mysql.dto;
+
+import com.github.shyiko.mysql.binlog.event.EventType;
+import lombok.Data;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 日志文件相应的Java对象
+ *
+ * @author sss
+ * @date 2019-02-25
+ */
+@Data
+public class BinlogRowData {
+
+ private TableTemplate table;
+
+ private EventType eventType;
+
+ private List