├── ad-eureka ├── target │ ├── maven-status │ │ └── maven-compiler-plugin │ │ │ └── compile │ │ │ └── default-compile │ │ │ ├── createdFiles.lst │ │ │ └── inputFiles.lst │ ├── maven-archiver │ │ └── pom.properties │ ├── ad-eureka-1.0-SNAPSHOT.jar.original │ └── classes │ │ └── application.yml ├── src │ └── main │ │ ├── java │ │ └── cn │ │ │ └── lucas │ │ │ └── ad │ │ │ └── EurekaApplication.java │ │ └── resources │ │ └── application.yml └── pom.xml ├── ad-gateway ├── target │ └── classes │ │ └── application.yml ├── src │ └── main │ │ ├── java │ │ └── cn │ │ │ └── lucas │ │ │ └── ad │ │ │ ├── ZuulGatewayApplication.java │ │ │ └── filter │ │ │ ├── PreRequestFilter.java │ │ │ └── AccessLogFilter.java │ │ └── resources │ │ └── application.yml └── pom.xml ├── lucas-ad-service ├── ad-search │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── cn │ │ │ │ │ └── lucas │ │ │ │ │ └── ad │ │ │ │ │ ├── search │ │ │ │ │ ├── vo │ │ │ │ │ │ ├── feature │ │ │ │ │ │ │ ├── FeatureRelation.java │ │ │ │ │ │ │ ├── ItFeature.java │ │ │ │ │ │ │ ├── KeywordFeature.java │ │ │ │ │ │ │ └── DistrictFeature.java │ │ │ │ │ │ ├── media │ │ │ │ │ │ │ ├── Geo.java │ │ │ │ │ │ │ ├── App.java │ │ │ │ │ │ │ ├── AdSlot.java │ │ │ │ │ │ │ └── Device.java │ │ │ │ │ │ ├── SearchRequest.java │ │ │ │ │ │ └── SearchResponse.java │ │ │ │ │ └── ISearch.java │ │ │ │ │ ├── sender │ │ │ │ │ ├── ISender.java │ │ │ │ │ └── kafka │ │ │ │ │ │ └── KafkaSender.java │ │ │ │ │ ├── index │ │ │ │ │ ├── IndexAware.java │ │ │ │ │ ├── keyword │ │ │ │ │ │ ├── UnitKeywordObject.java │ │ │ │ │ │ └── UnitKeywordIndex.java │ │ │ │ │ ├── interest │ │ │ │ │ │ ├── UnitItObject.java │ │ │ │ │ │ └── UnitItIndex.java │ │ │ │ │ ├── CommonStatus.java │ │ │ │ │ ├── creativeunit │ │ │ │ │ │ ├── CreativeUnitObject.java │ │ │ │ │ │ └── CreativeUnitIndex.java │ │ │ │ │ ├── DataLevel.java │ │ │ │ │ ├── district │ │ │ │ │ │ ├── UnitDistrictObject.java │ │ │ │ │ │ └── UnitDistrictIndex.java │ │ │ │ │ ├── adunit │ │ │ │ │ │ ├── AdUnitConstants.java │ │ │ │ │ │ ├── AdUnitIndex.java │ │ │ │ │ │ └── AdUnitObject.java │ │ │ │ │ ├── adplan │ │ │ │ │ │ ├── AdPlanObject.java │ │ │ │ │ │ └── AdPlanIndex.java │ │ │ │ │ ├── creative │ │ │ │ │ │ ├── CreativeObject.java │ │ │ │ │ │ └── CreativeIndex.java │ │ │ │ │ ├── DataTable.java │ │ │ │ │ └── IndexFileLoader.java │ │ │ │ │ ├── mysql │ │ │ │ │ ├── listener │ │ │ │ │ │ ├── Ilistener.java │ │ │ │ │ │ ├── IncrementListener.java │ │ │ │ │ │ └── AggregationListener.java │ │ │ │ │ ├── dto │ │ │ │ │ │ ├── Template.java │ │ │ │ │ │ ├── MySqlRowData.java │ │ │ │ │ │ ├── JsonTable.java │ │ │ │ │ │ ├── TableTemplate.java │ │ │ │ │ │ ├── BinlogRowData.java │ │ │ │ │ │ └── ParseTemplate.java │ │ │ │ │ ├── constant │ │ │ │ │ │ ├── OpType.java │ │ │ │ │ │ └── Constant.java │ │ │ │ │ ├── BinlogConfig.java │ │ │ │ │ ├── BinlogClient.java │ │ │ │ │ └── TemplateHolder.java │ │ │ │ │ ├── client │ │ │ │ │ ├── vo │ │ │ │ │ │ ├── AdPlanGetRequest.java │ │ │ │ │ │ └── AdPlan.java │ │ │ │ │ ├── SponsorClientHystrix.java │ │ │ │ │ └── SponsorClient.java │ │ │ │ │ ├── runner │ │ │ │ │ └── BinlogRunner.java │ │ │ │ │ ├── SearchApplication.java │ │ │ │ │ ├── utils │ │ │ │ │ └── CommonUtils.java │ │ │ │ │ ├── service │ │ │ │ │ └── BinLogServiceTest.java │ │ │ │ │ ├── controller │ │ │ │ │ └── SearchController.java │ │ │ │ │ └── handler │ │ │ │ │ └── AdLevelDataHandler.java │ │ │ └── resources │ │ │ │ ├── application.yml │ │ │ │ └── template.json │ │ └── test │ │ │ ├── java │ │ │ └── cn │ │ │ │ └── lucas │ │ │ │ └── ad │ │ │ │ ├── Application.java │ │ │ │ └── search │ │ │ │ └── SearchTest.java │ │ │ └── resources │ │ │ └── application.yml │ └── pom.xml ├── ad-common │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── cn │ │ │ └── lucas │ │ │ └── ad │ │ │ ├── exception │ │ │ └── AdException.java │ │ │ ├── annotation │ │ │ └── IgnoreResponseAdvice.java │ │ │ ├── dump │ │ │ ├── table │ │ │ │ ├── AdUnitItTable.java │ │ │ │ ├── AdCreativeUnitTable.java │ │ │ │ ├── AdUnitKeywordTable.java │ │ │ │ ├── AdUnitDistrictTable.java │ │ │ │ ├── AdUnitTable.java │ │ │ │ ├── AdPlanTable.java │ │ │ │ └── AdCreativeTable.java │ │ │ └── DConstant.java │ │ │ ├── vo │ │ │ └── CommonResponse.java │ │ │ ├── conf │ │ │ └── WebConfiguration.java │ │ │ └── advice │ │ │ ├── GlobalExceptionAdvice.java │ │ │ └── CommonResponseDataAdvice.java │ └── pom.xml ├── ad-sponsor │ ├── src │ │ ├── main │ │ │ ├── java │ │ │ │ └── cn │ │ │ │ │ └── lucas │ │ │ │ │ └── ad │ │ │ │ │ ├── dao │ │ │ │ │ ├── CreativeRepository.java │ │ │ │ │ ├── unit_condition │ │ │ │ │ │ ├── AdUnitItRepository.java │ │ │ │ │ │ ├── CreativeUnitRepository.java │ │ │ │ │ │ ├── AdUnitKeywordRepository.java │ │ │ │ │ │ └── AdUnitDistrictRepository.java │ │ │ │ │ ├── AdUserRepository.java │ │ │ │ │ ├── AdUnitRepository.java │ │ │ │ │ └── AdPlanRepository.java │ │ │ │ │ ├── service │ │ │ │ │ ├── ICreativeService.java │ │ │ │ │ ├── IUserService.java │ │ │ │ │ ├── IAdUnitService.java │ │ │ │ │ ├── IAdPlanService.java │ │ │ │ │ └── impl │ │ │ │ │ │ ├── CreativeService.java │ │ │ │ │ │ ├── UserServiceImpl.java │ │ │ │ │ │ ├── AdPlanService.java │ │ │ │ │ │ └── AdUnitService.java │ │ │ │ │ ├── vo │ │ │ │ │ ├── AdPlanResponse.java │ │ │ │ │ ├── CreativeResponse.java │ │ │ │ │ ├── AdUnitItResponse.java │ │ │ │ │ ├── AdUnitKeywordResponse.java │ │ │ │ │ ├── AdUnitResponse.java │ │ │ │ │ ├── CreativeUnitResponse.java │ │ │ │ │ ├── AdUnitDistrictResponse.java │ │ │ │ │ ├── CreateUserRequest.java │ │ │ │ │ ├── CreateUserResponse.java │ │ │ │ │ ├── AdPlanGetRequest.java │ │ │ │ │ ├── AdUnitItRequest.java │ │ │ │ │ ├── CreativeUnitRequest.java │ │ │ │ │ ├── AdUnitDistrictRequest.java │ │ │ │ │ ├── AdUnitKeywordRequest.java │ │ │ │ │ ├── AdUnitRequest.java │ │ │ │ │ ├── AdPlanRequest.java │ │ │ │ │ └── CreativeReuqest.java │ │ │ │ │ ├── constant │ │ │ │ │ ├── CommonStatus.java │ │ │ │ │ ├── CreativeType.java │ │ │ │ │ ├── CreativeMetrialType.java │ │ │ │ │ └── Constants.java │ │ │ │ │ ├── SponsorApplication.java │ │ │ │ │ ├── utils │ │ │ │ │ └── CommonUtils.java │ │ │ │ │ ├── entity │ │ │ │ │ ├── unit_condition │ │ │ │ │ │ ├── AdUnitIt.java │ │ │ │ │ │ ├── CreativeUnit.java │ │ │ │ │ │ ├── AdUnitKeyword.java │ │ │ │ │ │ └── AdUnitDistrict.java │ │ │ │ │ ├── AdUser.java │ │ │ │ │ ├── AdPlan.java │ │ │ │ │ ├── AdUnit.java │ │ │ │ │ └── Creative.java │ │ │ │ │ └── controller │ │ │ │ │ ├── CreativeOPController.java │ │ │ │ │ ├── UserOPController.java │ │ │ │ │ ├── AdPlanOPController.java │ │ │ │ │ └── AdUnitOPController.java │ │ │ └── resources │ │ │ │ └── application.yml │ │ └── test │ │ │ ├── java │ │ │ └── cn │ │ │ │ └── lucas │ │ │ │ └── ad │ │ │ │ ├── Application.java │ │ │ │ └── service │ │ │ │ ├── AdUnitServiceTest.java │ │ │ │ └── AdPlanServiceTest.java │ │ │ └── resources │ │ │ └── application.yml │ └── pom.xml ├── ad-dashboard │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── application.yml │ │ │ └── java │ │ │ └── cn │ │ │ └── lucas │ │ │ └── ad │ │ │ └── DashboardApplication.java │ └── pom.xml └── pom.xml ├── README.md ├── pom.xml └── .gitignore /ad-eureka/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst: -------------------------------------------------------------------------------- 1 | cn/lucas/ad/EurekaApplication.class 2 | -------------------------------------------------------------------------------- /ad-eureka/target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Created by Apache Maven 3.5.4 2 | version=1.0-SNAPSHOT 3 | groupId=cn.lucas.ad 4 | artifactId=ad-eureka 5 | -------------------------------------------------------------------------------- /ad-eureka/target/ad-eureka-1.0-SNAPSHOT.jar.original: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chuckma/ad-spring-cloud/HEAD/ad-eureka/target/ad-eureka-1.0-SNAPSHOT.jar.original -------------------------------------------------------------------------------- /ad-eureka/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst: -------------------------------------------------------------------------------- 1 | /Users/lucasma/code/git_pro/lucas-ad-spring-cloud/ad-eureka/src/main/java/cn/lucas/ad/EurekaApplication.java 2 | -------------------------------------------------------------------------------- /ad-gateway/target/classes/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9000 3 | spring: 4 | application: 5 | name: ad-gateway 6 | eureka: 7 | client: 8 | service-url: 9 | defaultZone: http://server1:8000/eureka/ 10 | 11 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/feature/FeatureRelation.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.feature; 2 | 3 | /** 4 | * @author Administrator 5 | */ 6 | public enum FeatureRelation { 7 | OR, 8 | AND 9 | } 10 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/exception/AdException.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.exception; 2 | 3 | public class AdException extends Exception { 4 | 5 | public AdException(String message) { 6 | super(message); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/sender/ISender.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.sender; 2 | 3 | import cn.lucas.ad.mysql.dto.MySqlRowData; 4 | 5 | /** 6 | * @author Administrator 7 | */ 8 | public interface ISender { 9 | 10 | void sender(MySqlRowData rowData); 11 | } 12 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/CreativeRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao; 2 | 3 | import cn.lucas.ad.entity.Creative; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface CreativeRepository extends JpaRepository { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/IndexAware.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index; 2 | 3 | /** 4 | * @author mcg 5 | */ 6 | public interface IndexAware { 7 | 8 | V get(K key); 9 | 10 | void add(K key, V value); 11 | 12 | void update(K key, V value); 13 | 14 | void delete(K key, V value); 15 | } 16 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/unit_condition/AdUnitItRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao.unit_condition; 2 | 3 | import cn.lucas.ad.entity.unit_condition.AdUnitIt; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface AdUnitItRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/ISearch.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search; 2 | 3 | import cn.lucas.ad.search.vo.SearchRequest; 4 | import cn.lucas.ad.search.vo.SearchResponse; 5 | 6 | /** 7 | * @author Administrator 8 | */ 9 | public interface ISearch { 10 | 11 | SearchResponse fetchAds(SearchRequest request); 12 | } 13 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-dashboard/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7002 3 | 4 | spring: 5 | application: 6 | name: ad-dashboard 7 | 8 | eureka: 9 | client: 10 | service-url: 11 | defaultZone: http://server1:8000/eureka/ 12 | 13 | management: 14 | endpoints: 15 | web: 16 | exposure: 17 | include: "*" 18 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/unit_condition/CreativeUnitRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao.unit_condition; 2 | 3 | import cn.lucas.ad.entity.unit_condition.CreativeUnit; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface CreativeUnitRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/unit_condition/AdUnitKeywordRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao.unit_condition; 2 | 3 | import cn.lucas.ad.entity.unit_condition.AdUnitKeyword; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface AdUnitKeywordRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/unit_condition/AdUnitDistrictRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao.unit_condition; 2 | 3 | import cn.lucas.ad.entity.unit_condition.AdUnitDistrict; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface AdUnitDistrictRepository extends JpaRepository { 7 | } 8 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/ICreativeService.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service; 2 | 3 | import cn.lucas.ad.vo.CreativeResponse; 4 | import cn.lucas.ad.vo.CreativeReuqest; 5 | 6 | /** 7 | * @author Administrator 8 | */ 9 | public interface ICreativeService { 10 | 11 | CreativeResponse creatCreative(CreativeReuqest reuqest); 12 | } 13 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdPlanResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | @Data 8 | @NoArgsConstructor 9 | @AllArgsConstructor 10 | public class AdPlanResponse { 11 | 12 | private Long id; 13 | private String planName; 14 | } 15 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/listener/Ilistener.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.listener; 2 | 3 | import cn.lucas.ad.mysql.dto.BinlogRowData; 4 | 5 | /** 6 | * @author Administrator 7 | */ 8 | public interface Ilistener { 9 | 10 | /** 11 | * 注册监听器 12 | */ 13 | void register(); 14 | 15 | 16 | void onEvent(BinlogRowData eventData); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/CreativeResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author Administrator 9 | */ 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class CreativeResponse { 14 | private Long id; 15 | private String name; 16 | } 17 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitItResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdUnitItResponse { 16 | private List ids; 17 | } 18 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitKeywordResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdUnitKeywordResponse { 16 | 17 | private List ids; 18 | } 19 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author Administrator 9 | */ 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class AdUnitResponse { 14 | 15 | // 主键 16 | private Long id; 17 | private String unitName; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/CreativeUnitResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class CreativeUnitResponse { 16 | 17 | private List ids; 18 | } 19 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/annotation/IgnoreResponseAdvice.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.METHOD, ElementType.TYPE}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface IgnoreResponseAdvice { 11 | } 12 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitDistrictResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | * 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class AdUnitDistrictResponse { 17 | 18 | private List ids; 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/feature/ItFeature.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.feature; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class ItFeature { 17 | 18 | private List its; 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/table/AdUnitItTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 21:44 10 | **/ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class AdUnitItTable { 15 | 16 | private Long unitId; 17 | private String itTag; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/constant/CommonStatus.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.constant; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum CommonStatus { 7 | 8 | VALID(1, "有效状态"), 9 | INVALID(0, "无效状态"); 10 | 11 | private Integer status; 12 | private String desc; 13 | 14 | CommonStatus(Integer status, String desc) { 15 | this.status = status; 16 | this.desc = desc; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/constant/CreativeType.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.constant; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum CreativeType { 7 | 8 | IMAGE(1, "图片"), 9 | VIDEO(2, "视频"), 10 | TEXT(3, "文本"); 11 | 12 | private int type; 13 | private String desc; 14 | 15 | CreativeType(int type, String desc) { 16 | this.type = type; 17 | this.desc = desc; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/table/AdCreativeUnitTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 21:47 10 | **/ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class AdCreativeUnitTable { 15 | 16 | private Long adId; 17 | private Long unitId; 18 | } 19 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/test/java/cn/lucas/ad/Application.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @author Administrator 8 | */ 9 | @SpringBootApplication 10 | public class Application { 11 | public static void main(String[] args) { 12 | 13 | SpringApplication.run(Application.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/feature/KeywordFeature.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.feature; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class KeywordFeature { 17 | 18 | private List keywords; 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/AdUserRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao; 2 | 3 | import cn.lucas.ad.entity.AdUser; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | public interface AdUserRepository extends JpaRepository { 7 | 8 | 9 | /** 10 | * 根据 username 查询一个对象 AdUser 11 | * @param username 12 | * @return 13 | */ 14 | AdUser findByUsername(String username); 15 | } 16 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/table/AdUnitKeywordTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 21:43 10 | **/ 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdUnitKeywordTable { 16 | 17 | private Long unitId; 18 | private String keyword; 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/client/vo/AdPlanGetRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdPlanGetRequest { 16 | 17 | private Long userId; 18 | private List ids; 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/keyword/UnitKeywordObject.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.keyword; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/1/29 21:19 10 | **/ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class UnitKeywordObject { 15 | 16 | private Long unitId; 17 | private String keyword; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/interest/UnitItObject.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.interest; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author Administrator 9 | */ 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class UnitItObject { 14 | 15 | // 推广单元关联id 16 | private Long unitId; 17 | 18 | // 兴趣标签 19 | private String itTag; 20 | } 21 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/dto/Template.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @Author mcg 11 | * @Date 2019/2/18 20:51 12 | **/ 13 | 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class Template { 18 | 19 | private String database; 20 | private List tableList; 21 | } 22 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/CreateUserRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.apache.commons.lang.StringUtils; 7 | 8 | @Data 9 | @NoArgsConstructor 10 | @AllArgsConstructor 11 | public class CreateUserRequest { 12 | 13 | private String username; 14 | public boolean validate() { 15 | return !StringUtils.isEmpty(username); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/test/java/cn/lucas/ad/Application.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * @Author mcg 8 | * @Date 2019/2/14 21:51 9 | **/ 10 | 11 | @SpringBootApplication 12 | public class Application { 13 | 14 | public static void main(String[] args) { 15 | 16 | SpringApplication.run(Application.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/table/AdUnitDistrictTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 21:45 10 | **/ 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdUnitDistrictTable { 16 | 17 | 18 | private Long unitId; 19 | private String province; 20 | private String city; 21 | } 22 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/CommonStatus.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author Administrator 7 | */ 8 | @Getter 9 | public enum CommonStatus { 10 | 11 | VALID(1,"有效状态"), 12 | 13 | INVALID(0,"无效状态"); 14 | 15 | 16 | private Integer status; 17 | private String desc; 18 | 19 | CommonStatus(Integer status, String desc) { 20 | this.status = status; 21 | this.desc = desc; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/IUserService.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service; 2 | 3 | import cn.lucas.ad.exception.AdException; 4 | import cn.lucas.ad.vo.CreateUserRequest; 5 | import cn.lucas.ad.vo.CreateUserResponse; 6 | 7 | public interface IUserService { 8 | 9 | 10 | /** 11 | * 创建 用户 12 | * @param request 13 | * @return 14 | * @throws AdException 15 | */ 16 | CreateUserResponse createUser(CreateUserRequest request) throws AdException; 17 | } 18 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/CreateUserResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class CreateUserResponse { 13 | 14 | private Long userId; 15 | private String username; 16 | private String token; 17 | private Date createTime; 18 | private Date updateTime; 19 | } 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 广告系统 ### 2 | 3 | 广告投放,广告检索系统 一个简易的 DSP 4 | 5 | 广告系统概览 6 | 7 | * 广告主的广告投放 8 | * 媒体方的广告曝光 9 | CPM CPT CPC 10 | 11 | 一个完整的广告系统包含哪些子系统 12 | 13 | * 广告投放系统 14 | * 广告检索系统 15 | * 计费系统 16 | * 报表系统 17 | * 曝光检测系统 18 | * 其他等等 19 | 20 | 技术选型 21 | 22 | * SpringCloud 23 | * MySQL 24 | * Kafka 25 | * ... 26 | 27 | 28 | 如何扩展当前的广告系统 29 | * 更多的纬度 [ 更多的feature 条件 ] 30 | 31 | 目前只实现了地域纬度,兴趣纬度,关键词纬度,可以根据实际业务来添加更多的纬度 32 | * 用户画像 33 | 34 | * AI 35 | 36 | 37 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/creativeunit/CreativeUnitObject.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.creativeunit; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 19:47 10 | **/ 11 | 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class CreativeUnitObject { 16 | 17 | private Long adId; 18 | private Long unitId; 19 | 20 | // key 为 adId-unitId 连字符组合 21 | } 22 | -------------------------------------------------------------------------------- /ad-eureka/src/main/java/cn/lucas/ad/EurekaApplication.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 7 | 8 | @EnableEurekaServer 9 | @SpringBootApplication 10 | public class EurekaApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(EurekaApplication.class, args); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/DataLevel.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * @author Administrator 7 | */ 8 | @Getter 9 | public enum DataLevel { 10 | 11 | 12 | LEVEL2("2", "level 2"), 13 | LEVEL3("3", "level 3"), 14 | LEVEL4("4", "level 4"); 15 | private String level; 16 | private String desc; 17 | 18 | DataLevel(String level, String desc) { 19 | this.level = level; 20 | this.desc = desc; 21 | } 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/district/UnitDistrictObject.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.district; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author mcg 9 | */ 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class UnitDistrictObject { 14 | 15 | private Long unitId; 16 | private String province; 17 | private String city; 18 | 19 | // > 20 | // province-city 21 | } 22 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/constant/CreativeMetrialType.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.constant; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public enum CreativeMetrialType { 7 | 8 | JPG(1, "jpg"), 9 | BMP(2, "bmp"), 10 | 11 | MP4(3, "mp4"), 12 | AVI(4, "avi"), 13 | 14 | TXT(5, "txt"); 15 | 16 | private int type; 17 | private String desc; 18 | 19 | CreativeMetrialType(int type, String desc) { 20 | this.type = type; 21 | this.desc = desc; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ad-gateway/src/main/java/cn/lucas/ad/ZuulGatewayApplication.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.cloud.client.SpringCloudApplication; 6 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 7 | //开启zuul 网关 8 | @EnableZuulProxy 9 | @SpringCloudApplication 10 | public class ZuulGatewayApplication { 11 | 12 | public static void main(String[] args) { 13 | SpringApplication.run(ZuulGatewayApplication.class, args); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /ad-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9000 3 | spring: 4 | application: 5 | name: ad-gateway 6 | eureka: 7 | client: 8 | service-url: 9 | defaultZone: http://server1:8000/eureka/ 10 | zuul: 11 | prefix: /lucas 12 | routes: 13 | sponsor: 14 | path: /ad-sponsor/** 15 | serviceId: eureka-client-ad-sponsor 16 | strip-prefix: false 17 | search: 18 | path: /ad-search/** 19 | serviceId: eureka-client-ad-search 20 | strip-prefix: false 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/table/AdUnitTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 20:42 10 | **/ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class AdUnitTable { 15 | 16 | private Long unitId; 17 | private Integer unitStatus; 18 | private Integer positionType; 19 | 20 | // 关联字段 21 | private Long planId; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/constant/Constants.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.constant; 2 | 3 | public class Constants { 4 | 5 | public static class ErrorMsg { 6 | 7 | public static final String REQUEST_PARAM_ERROR = "请求参数错误"; 8 | public static final String SAME_NAME_ERROR = "存在同名的用户"; 9 | 10 | public static final String CAN_NOT_FIND_RECORD = "找不到数据记录"; 11 | public static final String SAME_NAME_PLAN_ERROR = "存在同名的推广计划"; 12 | 13 | public static final String SAME_NAME_UNIT_ERROR = "存在同名的推广单元"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/table/AdPlanTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * @Author mcg 11 | * @Date 2019/2/14 20:38 12 | **/ 13 | 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class AdPlanTable { 18 | 19 | 20 | private Long id; 21 | private Long userId; 22 | private Integer planStatus; 23 | private Date startDate; 24 | private Date endDate; 25 | } 26 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdPlanGetRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.util.CollectionUtils; 7 | 8 | import java.util.List; 9 | 10 | @Data 11 | @NoArgsConstructor 12 | @AllArgsConstructor 13 | public class AdPlanGetRequest { 14 | 15 | private Long userId; 16 | private List ids; 17 | 18 | public boolean validate() { 19 | return userId != null && !CollectionUtils.isEmpty(ids); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/vo/CommonResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.io.Serializable; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class CommonResponse implements Serializable { 13 | 14 | 15 | private Integer code; 16 | private String msg; 17 | private T data; 18 | 19 | public CommonResponse(Integer code, String msg) { 20 | this.code = code; 21 | this.msg = msg; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/media/Geo.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author Administrator 9 | *

10 | * 地理位置信息 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class Geo { 16 | 17 | /** 18 | * 纬度 19 | */ 20 | private Float latitude; 21 | 22 | /** 23 | * 经度 24 | */ 25 | private Float longitude; 26 | 27 | private String city; 28 | 29 | private String province; 30 | } 31 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitItRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdUnitItRequest { 16 | 17 | private List unitIts; 18 | 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public static class UnitIt { 23 | private Long unitId; 24 | private String itTag; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/client/vo/AdPlan.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdPlan { 16 | 17 | private Long id; 18 | private Long userId; 19 | private String planName; 20 | private Integer planStatus; 21 | private Date startDate; 22 | private Date endDate; 23 | private Date createTime; 24 | private Date updateTime; 25 | } 26 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/CreativeUnitRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class CreativeUnitRequest { 16 | 17 | 18 | private List unitItems; 19 | 20 | @Data 21 | @NoArgsConstructor 22 | @AllArgsConstructor 23 | public static class CreativeUnitItem { 24 | private Long creativeId; 25 | private Long unitId; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/table/AdCreativeTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 21:45 10 | **/ 11 | 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class AdCreativeTable { 17 | 18 | private Long adId; 19 | private String name; 20 | private Integer type; 21 | private Integer materialType; 22 | private Integer height; 23 | private Integer width; 24 | private Integer auditStatus; 25 | private String adUrl; 26 | } 27 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/client/SponsorClientHystrix.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.client; 2 | 3 | import cn.lucas.ad.client.vo.AdPlan; 4 | import cn.lucas.ad.client.vo.AdPlanGetRequest; 5 | import cn.lucas.ad.vo.CommonResponse; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author Administrator 12 | * 13 | * 断路器 14 | */ 15 | @Component 16 | public class SponsorClientHystrix implements SponsorClient{ 17 | @Override 18 | public CommonResponse> getAdPlans(AdPlanGetRequest request) { 19 | return new CommonResponse<>(-1,"eureka-client-ad-sponsor error"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/feature/DistrictFeature.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.feature; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class DistrictFeature { 17 | 18 | private List districts; 19 | 20 | @Data 21 | @NoArgsConstructor 22 | @AllArgsConstructor 23 | public static class ProvinceAndCity { 24 | private String province; 25 | private String city; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitDistrictRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdUnitDistrictRequest { 16 | 17 | private List unitDistricts; 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public static class UnitDistrict { 22 | private Long unitId; 23 | private String province; 24 | private String city; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitKeywordRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class AdUnitKeywordRequest { 16 | 17 | private List unitKeywords; 18 | // keyword 运行批量创建 再次定义内部类 19 | @Data 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | public static class UnitKeyword { 23 | private Long unitId; 24 | private String keyword; 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/AdUnitRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao; 2 | 3 | import cn.lucas.ad.entity.AdUnit; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface AdUnitRepository extends JpaRepository { 9 | 10 | /** 11 | * 根据 planId 和 unitName 查询 推广单元 12 | * @param planId 13 | * @param unitName 14 | * @return 15 | */ 16 | AdUnit findByPlanIdAndUnitName(Long planId, String unitName); 17 | 18 | 19 | /** 20 | * 根据推广单元的状态查询 推广单元的集合 21 | * @param status 22 | * @return 23 | */ 24 | List findAllByUnitStatus(Integer status); 25 | } 26 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-dashboard/src/main/java/cn/lucas/ad/DashboardApplication.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 6 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 7 | 8 | /** 9 | * @Author mcg 10 | * @Date 2019/2/21 20:55 11 | **/ 12 | @EnableEurekaClient 13 | @SpringBootApplication 14 | @EnableHystrixDashboard 15 | public class DashboardApplication { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(DashboardApplication.class, args); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/media/App.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author Administrator 9 | * 10 | * 媒体方 应用信息 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class App { 16 | 17 | /** 18 | * 应用编码 19 | */ 20 | private String appCode; 21 | 22 | /** 23 | * 应用名称 24 | */ 25 | private String appName; 26 | 27 | /** 28 | * 应用包名 29 | */ 30 | private String packageName; 31 | 32 | /** 33 | * activity 名称 34 | */ 35 | private String activityName; 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/constant/OpType.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.constant; 2 | 3 | import com.github.shyiko.mysql.binlog.event.EventData; 4 | import com.github.shyiko.mysql.binlog.event.EventType; 5 | 6 | public enum OpType { 7 | 8 | ADD, 9 | UPDATE, 10 | DELETE, 11 | OTHER; 12 | 13 | 14 | public static OpType to(EventType eventType) { 15 | switch (eventType) { 16 | case EXT_WRITE_ROWS: 17 | return ADD; 18 | case EXT_UPDATE_ROWS: 19 | return UPDATE; 20 | case EXT_DELETE_ROWS: 21 | return DELETE; 22 | default: 23 | return OTHER; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/dto/MySqlRowData.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.dto; 2 | 3 | import cn.lucas.ad.mysql.constant.OpType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | 13 | /** 14 | * @author Administrator 15 | */ 16 | @Data 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | public class MySqlRowData { 20 | 21 | 22 | private String tableName; 23 | /** 24 | * 数据表层级关系 25 | */ 26 | private String level; 27 | 28 | private OpType opType; 29 | 30 | private List> fieldValueMap = new ArrayList<>(); 31 | 32 | } 33 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/conf/WebConfiguration.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.conf; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.http.converter.HttpMessageConverter; 5 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 6 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 7 | 8 | import java.util.List; 9 | 10 | @Configuration 11 | public class WebConfiguration implements WebMvcConfigurer { 12 | 13 | @Override 14 | public void configureMessageConverters(List> converters) { 15 | 16 | converters.clear(); 17 | converters.add(new MappingJackson2HttpMessageConverter()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7000 3 | servlet: 4 | context-path: /ad-sponsor # 代表controller 的前缀 5 | 6 | spring: 7 | application: 8 | name: eureka-client-ad-sponsor 9 | jpa: 10 | show-sql: true 11 | hibernate: 12 | ddl-auto: none 13 | properties: 14 | hibernate.format_sql: true 15 | open-in-view: false # 对于一些开启懒加载的Bean 如果找不到对应的bean 就会报错 设置为false 就不会了 16 | datasource: 17 | url: jdbc:mysql://127.0.0.1:3306/ad_data?autoReconnect=true 18 | username: root 19 | password: 123456 20 | tomcat: 21 | max-active: 4 22 | min-idle: 2 23 | initial-size: 2 24 | 25 | 26 | eureka: 27 | client: 28 | service-url: 29 | defaultZone: http://server1:8000/eureka/ 30 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/adunit/AdUnitConstants.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.adunit; 2 | 3 | /** 4 | * @author Administrator 5 | */ 6 | public class AdUnitConstants { 7 | 8 | /** 9 | * 二进制 1 2 4 8 16 可以用 位或运算 位于运算 10 | */ 11 | public static class POSITION_TYPE { 12 | public static final int KAIPING = 1; 13 | public static final int TIEPIAN = 2; 14 | /** 15 | * 中贴广告 eg.视频播放中间 16 | */ 17 | public static final int TIEPIAN_MINDLE = 3; 18 | /** 19 | * 暂停广告 20 | */ 21 | public static final int TIEPIAN_PAUSE = 8; 22 | /** 23 | * 后贴广告 eg.视频播放完毕 24 | */ 25 | public static final int TIEPIAN_POST = 16; 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/SponsorApplication.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad; 2 | 3 | 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 8 | import org.springframework.cloud.openfeign.EnableFeignClients; 9 | 10 | @EnableFeignClients // 启用这个注解这个微服务里就可以调用其他微服务 11 | @EnableCircuitBreaker // 为了实现监控 12 | @EnableEurekaClient // 标识它是一个client 13 | @SpringBootApplication 14 | public class SponsorApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(SponsorApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/dto/JsonTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.dto; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import lombok.extern.slf4j.Slf4j; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @Author mcg 12 | * @Date 2019/2/18 20:47 13 | **/ 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class JsonTable { 18 | 19 | private String tableName; 20 | private Integer level; 21 | 22 | private List insert; 23 | private List update; 24 | private List delete; 25 | 26 | @Data 27 | @NoArgsConstructor 28 | @AllArgsConstructor 29 | public static class Column{ 30 | private String column; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/dto/TableTemplate.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.dto; 2 | 3 | import cn.lucas.ad.mysql.constant.OpType; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * @Author mcg 14 | * @Date 2019/2/18 20:52 15 | **/ 16 | 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class TableTemplate { 21 | private String tableName; 22 | private String level; 23 | 24 | // 操作类型 insert update delete 25 | private Map> opTypeFieldSetMap = new HashMap<>(); 26 | 27 | // 表示 字段索引 -> 字段名 的映射 28 | private Map posMap = new HashMap<>(); 29 | } 30 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/advice/GlobalExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.advice; 2 | 3 | import cn.lucas.ad.exception.AdException; 4 | import cn.lucas.ad.vo.CommonResponse; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.RestControllerAdvice; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | @RestControllerAdvice 11 | public class GlobalExceptionAdvice { 12 | 13 | @ExceptionHandler(value = AdException.class) 14 | public CommonResponse handlerAdException(HttpServletRequest request, AdException ex) { 15 | 16 | CommonResponse response = new CommonResponse<>(-1, "business error"); 17 | response.setData(ex.getMessage()); 18 | return response; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/BinlogConfig.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @author Administrator 12 | */ 13 | @Component 14 | @ConfigurationProperties(prefix = "adconf.mysql") 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class BinlogConfig { 19 | 20 | private String host; 21 | private Integer port; 22 | private String username; 23 | private String password; 24 | 25 | private String binlogName; 26 | private Long position; 27 | } 28 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7000 3 | servlet: 4 | context-path: /ad-sponsor # 代表controller 的前缀 5 | 6 | spring: 7 | application: 8 | name: eureka-client-ad-sponsor 9 | jpa: 10 | show-sql: true 11 | hibernate: 12 | ddl-auto: none 13 | properties: 14 | hibernate.format_sql: true 15 | open-in-view: false # 对于一些开启懒加载的Bean 如果找不到对应的bean 就会报错 设置为false 就不会了 16 | datasource: 17 | url: jdbc:mysql://127.0.0.1:3306/ad_data?autoReconnect=true 18 | username: root 19 | password: 123456 20 | tomcat: 21 | max-active: 4 22 | min-idle: 2 23 | initial-size: 2 24 | 25 | 26 | eureka: 27 | client: 28 | service-url: 29 | defaultZone: http://server1:8000/eureka/ 30 | enabled: false # false 就不会将服务注册到 defaultZone 31 | -------------------------------------------------------------------------------- /lucas-ad-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lucas-ad 7 | cn.lucas.ad 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | lucas-ad-service 13 | 1.0-SNAPSHOT 14 | 15 | ad-common 16 | ad-sponsor 17 | ad-search 18 | ad-dashboard 19 | 20 | pom 21 | 22 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/media/AdSlot.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author Administrator 11 | * 12 | * 广告位信息 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class AdSlot { 18 | 19 | /** 20 | * 广告位编码 21 | */ 22 | private String adSlotCode; 23 | 24 | /** 25 | * 流量类型 26 | */ 27 | private Integer positionType; 28 | 29 | private Integer width; 30 | 31 | private Integer height; 32 | 33 | /** 34 | * 广告物料类型 eg. 图片,视频... 支持多类型 35 | */ 36 | private List type; 37 | 38 | /** 39 | * 最低出价 40 | */ 41 | private Integer minCpm; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdUnitRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.apache.commons.lang.StringUtils; 7 | 8 | /** 9 | * @author mcg 10 | */ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | public class AdUnitRequest { 15 | 16 | // 推广计划id 每一个推广单元都需要一个推广计划 17 | private Long planId; 18 | private String unitName; 19 | private Integer positionType; 20 | private Long budget; 21 | 22 | /** 23 | * 简单的校验 24 | * @return 25 | */ 26 | public boolean createValidate() { 27 | return null != planId 28 | && !StringUtils.isEmpty(unitName) 29 | && positionType != null 30 | && budget != null; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/utils/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.utils; 2 | 3 | 4 | import cn.lucas.ad.exception.AdException; 5 | import org.apache.commons.codec.digest.DigestUtils; 6 | import org.apache.commons.lang.time.DateUtils; 7 | 8 | import java.util.Date; 9 | 10 | public class CommonUtils { 11 | 12 | private static String[] parsePatterns={ 13 | "yyyy-MM-dd","yyyy/MM/dd","yyyy.MM.dd" 14 | }; 15 | 16 | public static String md5(String value) { 17 | return DigestUtils.md5Hex(value).toUpperCase(); 18 | } 19 | 20 | public static Date parseStringDate(String dateString) throws AdException { 21 | try { 22 | return DateUtils.parseDate(dateString, parsePatterns); 23 | } catch (Exception ex) { 24 | throw new AdException(ex.getMessage()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/IAdUnitService.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service; 2 | 3 | import cn.lucas.ad.entity.Creative; 4 | import cn.lucas.ad.exception.AdException; 5 | import cn.lucas.ad.vo.*; 6 | 7 | /** 8 | * @author Administrator 9 | */ 10 | public interface IAdUnitService { 11 | 12 | /** 13 | * 创建推广单元 14 | * 15 | * @param request 16 | * @return 17 | * @throws AdException 18 | */ 19 | AdUnitResponse createUnit(AdUnitRequest request) throws AdException; 20 | 21 | AdUnitKeywordResponse createUnitKeyword(AdUnitKeywordRequest request) throws AdException; 22 | 23 | AdUnitItResponse createUnitIt(AdUnitItRequest request) throws AdException; 24 | 25 | AdUnitDistrictResponse createUnitDistrict(AdUnitDistrictRequest request) throws AdException; 26 | 27 | 28 | CreativeUnitResponse createCreativeUnit(CreativeUnitRequest request) throws AdException; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/media/Device.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @author Administrator 9 | *

10 | * 媒体方设备信息 11 | */ 12 | @Data 13 | @NoArgsConstructor 14 | @AllArgsConstructor 15 | public class Device { 16 | 17 | /** 18 | * 设备 ID 19 | */ 20 | private String deviceCode; 21 | 22 | /** 23 | * 设备的 mac 地址 24 | */ 25 | private String mac; 26 | 27 | /** 28 | * 设备的IP 29 | */ 30 | private String ip; 31 | 32 | /** 33 | * 机型编码 34 | */ 35 | private String model; 36 | 37 | /** 38 | * 分辨率尺寸 39 | */ 40 | private String displaySize; 41 | 42 | /** 43 | * 屏幕尺寸 44 | */ 45 | private String screenSize; 46 | 47 | /** 48 | * 设备序列号 49 | */ 50 | private String serialName; 51 | } 52 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/client/SponsorClient.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.client; 2 | 3 | import cn.lucas.ad.client.vo.AdPlan; 4 | import cn.lucas.ad.client.vo.AdPlanGetRequest; 5 | import cn.lucas.ad.vo.CommonResponse; 6 | import org.springframework.cloud.openfeign.FeignClient; 7 | import org.springframework.web.bind.annotation.RequestBody; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RequestMethod; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author Administrator 15 | * 一旦 ad-sponsor 不可用,就会在这里进行降级操作 SponsorClientHystrix.class 16 | */ 17 | @FeignClient(value = "eureka-client-ad-sponsor",fallback = SponsorClientHystrix.class) 18 | public interface SponsorClient { 19 | 20 | @RequestMapping(value = "/ad-sponsor/get/adPlan", method = RequestMethod.POST) 21 | CommonResponse> getAdPlans(@RequestBody AdPlanGetRequest request); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/runner/BinlogRunner.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.runner; 2 | 3 | import cn.lucas.ad.mysql.BinlogClient; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.boot.CommandLineRunner; 7 | import org.springframework.stereotype.Component; 8 | 9 | /** 10 | * @author Administrator 11 | */ 12 | @Slf4j 13 | @Component 14 | public class BinlogRunner implements CommandLineRunner { 15 | 16 | private final BinlogClient client; 17 | 18 | @Autowired 19 | public BinlogRunner(BinlogClient client) { 20 | this.client = client; 21 | } 22 | 23 | /** 24 | * spring 程序启动的时候会自动运行 25 | * @param args 26 | * @throws Exception 27 | */ 28 | @Override 29 | public void run(String... args) throws Exception { 30 | log.info("connecting in BinlogRunner..."); 31 | client.connect(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/dto/BinlogRowData.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.dto; 2 | 3 | import com.github.shyiko.mysql.binlog.event.EventType; 4 | import lombok.Data; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author Administrator 11 | * 12 | * 13 | * BinlogRowData 是为了将 binlog的日志数据,也就是 event 这个开源工具传递进来的 evnet 14 | * 将它定义成 java 对象 15 | */ 16 | 17 | @Data 18 | public class BinlogRowData { 19 | 20 | /** 21 | * binlog 一定是对表的操作才有的数据,所以将表里包含的所有信息都包含 22 | */ 23 | private TableTemplate table; 24 | 25 | /** 26 | * 操作类型 27 | */ 28 | private EventType type; 29 | 30 | 31 | /** 32 | * 定义所有的已经变更的值为after 33 | * insert 和 delete 是没有 before 的,一定有after,就是更新之后的值 34 | * 35 | * key ->操作列的名字,value ->操作列的值 36 | */ 37 | private List> after; 38 | 39 | /** 40 | * update 操作是有 before 的 41 | */ 42 | private List> before; 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/AdPlanRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.apache.commons.lang.StringUtils; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class AdPlanRequest { 13 | 14 | private Long id; 15 | // 标识推广计划是属于哪个用户 16 | private Long userId; 17 | 18 | private String planName; 19 | 20 | private String startDate; 21 | 22 | private String endDate; 23 | 24 | 25 | public boolean createValidate() { 26 | 27 | return userId != null 28 | && !StringUtils.isEmpty(planName) 29 | && !StringUtils.isEmpty(startDate) 30 | && !StringUtils.isEmpty(endDate); 31 | } 32 | 33 | public boolean updateValidate() { 34 | return id != null && userId != null; 35 | } 36 | 37 | public boolean deleteValidate() { 38 | return id != null && userId != null; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/dao/AdPlanRepository.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dao; 2 | 3 | import cn.lucas.ad.entity.AdPlan; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | public interface AdPlanRepository extends JpaRepository { 9 | 10 | /** 11 | * 根据 adplan id 和 userid 查询 广告计划 12 | * @param id 13 | * @param userId 14 | * @return 15 | */ 16 | AdPlan findByIdAndUserId(Long id,Long userId); 17 | 18 | /** 19 | * 根据 ids 和 userid 查询广告计划集合 20 | * @param ids 21 | * @param userId 22 | * @return 23 | */ 24 | List findAllByIdInAndUserId(List ids, Long userId); 25 | 26 | 27 | /** 28 | * userId 和 planName 查询 AdPlan 29 | * @param userId 30 | * @param planName 31 | * @return 32 | */ 33 | AdPlan findByUserIdAndPlanName(Long userId, String planName); 34 | 35 | /** 36 | * 根据状态查询 AdPlan 集合 37 | * @param status 38 | * @return 39 | */ 40 | List findAllByPlanStatus(Integer status); 41 | } 42 | -------------------------------------------------------------------------------- /ad-gateway/src/main/java/cn/lucas/ad/filter/PreRequestFilter.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.filter; 2 | 3 | import com.netflix.zuul.ZuulFilter; 4 | import com.netflix.zuul.context.RequestContext; 5 | import com.netflix.zuul.exception.ZuulException; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 8 | import org.springframework.stereotype.Component; 9 | 10 | @Slf4j 11 | @Component 12 | public class PreRequestFilter extends ZuulFilter { 13 | 14 | // 定义 filter 的类型 15 | @Override 16 | public String filterType() { 17 | return FilterConstants.PRE_TYPE; 18 | } 19 | 20 | // filter 执行的优先级 越小越先 21 | @Override 22 | public int filterOrder() { 23 | return 0; 24 | } 25 | 26 | // 是否需要执行这个过滤器 当某些条件成立的时候才去执行过滤器 27 | @Override 28 | public boolean shouldFilter() { 29 | return true; 30 | } 31 | 32 | @Override 33 | public Object run() throws ZuulException { 34 | RequestContext ctx = RequestContext.getCurrentContext(); 35 | ctx.set("startTime",System.currentTimeMillis()); 36 | return null; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/dump/DConstant.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.dump; 2 | 3 | /** 4 | * @Author mcg 5 | * @Date 2019/2/14 20:30 6 | * 7 | * 8 | **/ 9 | 10 | public class DConstant { 11 | 12 | // 数据文件存储目录 13 | // public static final String DATA_ROOT_DIR = "/Users/lucasma/code/git_pro/lucas-ad-spring-cloud/mysql_data/"; 14 | public static final String DATA_ROOT_DIR = "C:/Users/Administrator/Desktop/mysql_data/"; 15 | 16 | // 各个数据表的文件名称 17 | public static final String AD_PLAN = "ad_plan.data"; 18 | public static final String AD_UNIT = "ad_unit.data"; 19 | public static final String AD_CREATIVE = "ad_creative.data"; 20 | public static final String AD_CREATIVE_UNIT = "ad_creative_unit.data"; 21 | public static final String AD_UNIT_IT = "ad_unit_it.data"; 22 | public static final String AD_UNIT_DISTRICT = "ad_unit_district.data"; 23 | public static final String AD_UNIT_KEYWORD = "ad_unit_keyword.data"; 24 | 25 | 26 | public static void main(String[] args) { 27 | System.out.println(String.format("%s%s", DConstant.DATA_ROOT_DIR, DConstant.AD_PLAN)); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/unit_condition/AdUnitIt.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.Basic; 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.Table; 14 | 15 | /** 16 | * 兴趣限制 17 | */ 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Entity 22 | @Table(name = "ad_unit_it") 23 | public class AdUnitIt { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | @Column(name = "id", nullable = false) 28 | private Long id; 29 | 30 | @Basic 31 | @Column(name = "unit_id", nullable = false) 32 | private Long unitId; 33 | 34 | @Basic 35 | @Column(name = "it_tag", nullable = false) 36 | private String itTag; 37 | 38 | public AdUnitIt(Long unitId, String itTag) { 39 | this.unitId = unitId; 40 | this.itTag = itTag; 41 | } 42 | } -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/unit_condition/CreativeUnit.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.Basic; 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.Table; 14 | 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Entity 19 | @Table(name = "creative_unit") 20 | public class CreativeUnit { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | @Column(name = "id", nullable = false) 25 | private Long id; 26 | 27 | @Basic 28 | @Column(name = "creative_id", nullable = false) 29 | private Long creativeId; 30 | 31 | @Basic 32 | @Column(name = "unit_id", nullable = false) 33 | private Long unitId; 34 | 35 | public CreativeUnit(Long creativeId, Long unitId) { 36 | this.creativeId = creativeId; 37 | this.unitId = unitId; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/unit_condition/AdUnitKeyword.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.Basic; 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.Table; 14 | 15 | /** 16 | * 关键词限制 17 | */ 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Entity 22 | @Table(name = "ad_unit_keyword") 23 | public class AdUnitKeyword { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | @Column(name = "id", nullable = false) 28 | private Long id; 29 | 30 | @Basic 31 | @Column(name = "unit_id", nullable = false) 32 | private Long unitId; 33 | 34 | @Basic 35 | @Column(name = "keyword", nullable = false) 36 | private String keyword; 37 | 38 | public AdUnitKeyword(Long unitId, String keyword) { 39 | this.unitId = unitId; 40 | this.keyword = keyword; 41 | } 42 | } -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7001 3 | servlet: 4 | context-path: /ad-search # 代表controller 的前缀 5 | 6 | spring: 7 | application: 8 | name: eureka-client-ad-search 9 | jpa: 10 | show-sql: true 11 | hibernate: 12 | ddl-auto: none 13 | properties: 14 | hibernate.format_sql: true 15 | open-in-view: false # 对于一些开启懒加载的Bean 如果找不到对应的bean 就会报错 设置为false 就不会了 16 | datasource: 17 | url: jdbc:mysql://127.0.0.1:3306/ad-data?autoReconnect=true 18 | username: root 19 | password: rootpwd 20 | tomcat: 21 | max-active: 4 22 | min-idle: 2 23 | initial-size: 2 24 | 25 | 26 | eureka: 27 | client: 28 | service-url: 29 | defaultZone: http://server1:8000/eureka/ 30 | 31 | 32 | feign: 33 | hystrix: 34 | enabled: true 35 | 36 | 37 | # 服务的监控,开启监控信息 38 | 39 | management: 40 | endpoints: 41 | web: 42 | exposure: 43 | include: "*" 44 | 45 | adconf: 46 | mysql: 47 | host: 127.0.0.1 48 | port: 3306 49 | username: root 50 | password: rootpwd 51 | binlogName: "" 52 | position: -1 53 | 54 | kafka: 55 | topic: ad-search-mysql-data 56 | 57 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/IAdPlanService.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service; 2 | 3 | import cn.lucas.ad.entity.AdPlan; 4 | import cn.lucas.ad.exception.AdException; 5 | import cn.lucas.ad.vo.AdPlanGetRequest; 6 | import cn.lucas.ad.vo.AdPlanRequest; 7 | import cn.lucas.ad.vo.AdPlanResponse; 8 | 9 | import java.util.List; 10 | 11 | public interface IAdPlanService { 12 | 13 | /** 14 | * 创建 推广计划 AdPlan 15 | * @param request 16 | * @return 17 | * @throws AdException 18 | */ 19 | AdPlanResponse createAdPlan(AdPlanRequest request) throws AdException; 20 | 21 | 22 | /** 23 | * 批量获取 AdPlan 24 | * @param request 25 | * @return 26 | * @throws AdException 27 | */ 28 | List getAdPlanByIds(AdPlanGetRequest request) throws AdException; 29 | 30 | 31 | /** 32 | * 更新推广计划 33 | * @param request 34 | * @return 35 | * @throws AdException 36 | */ 37 | AdPlanResponse updateAdPlan(AdPlanRequest request) throws AdException; 38 | 39 | /** 40 | * 删除推广计划 41 | * @param request 42 | * @throws AdException 43 | */ 44 | void deleteAdPlan(AdPlanRequest request) throws AdException; 45 | } 46 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/impl/CreativeService.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service.impl; 2 | 3 | import cn.lucas.ad.dao.CreativeRepository; 4 | import cn.lucas.ad.entity.Creative; 5 | import cn.lucas.ad.service.ICreativeService; 6 | import cn.lucas.ad.vo.CreativeResponse; 7 | import cn.lucas.ad.vo.CreativeReuqest; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | /** 13 | * @author Administrator 14 | */ 15 | @Slf4j 16 | @Service 17 | public class CreativeService implements ICreativeService { 18 | 19 | 20 | private final CreativeRepository creativeRepository; 21 | 22 | @Autowired 23 | public CreativeService(CreativeRepository creativeRepository) { 24 | this.creativeRepository = creativeRepository; 25 | } 26 | 27 | @Override 28 | public CreativeResponse creatCreative(CreativeReuqest reuqest) { 29 | // TODO 略去校验 30 | 31 | Creative creative = creativeRepository.save( 32 | reuqest.convertToEntity() 33 | ); 34 | 35 | return new CreativeResponse(creative.getId(),creative.getName()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7001 3 | servlet: 4 | context-path: /ad-search # 代表controller 的前缀 5 | 6 | spring: 7 | application: 8 | name: eureka-client-ad-search 9 | jpa: 10 | show-sql: true 11 | hibernate: 12 | ddl-auto: none 13 | properties: 14 | hibernate.format_sql: true 15 | open-in-view: false # 对于一些开启懒加载的Bean 如果找不到对应的bean 就会报错 设置为false 就不会了 16 | datasource: 17 | url: jdbc:mysql://127.0.0.1:3306/ad_data?autoReconnect=true 18 | username: root 19 | password: 123456 20 | tomcat: 21 | max-active: 4 22 | min-idle: 2 23 | initial-size: 2 24 | 25 | 26 | eureka: 27 | client: 28 | service-url: 29 | defaultZone: http://server1:8000/eureka/ 30 | enabled: false 31 | 32 | 33 | feign: 34 | hystrix: 35 | enabled: true 36 | 37 | 38 | # 服务的监控,开启监控信息 39 | 40 | management: 41 | endpoints: 42 | web: 43 | exposure: 44 | include: "*" 45 | 46 | adconf: 47 | mysql: 48 | host: 127.0.0.1 49 | port: 3306 50 | username: root 51 | password: 123456 52 | binlogName: "" 53 | position: -1 54 | 55 | kafka: 56 | topic: ad-search-mysql-data 57 | 58 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/controller/CreativeOPController.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.controller; 2 | 3 | import cn.lucas.ad.exception.AdException; 4 | import cn.lucas.ad.service.ICreativeService; 5 | import cn.lucas.ad.vo.CreativeResponse; 6 | import cn.lucas.ad.vo.CreativeReuqest; 7 | import com.alibaba.fastjson.JSON; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | /** 15 | * @author Administrator 16 | */ 17 | @Slf4j 18 | @RestController 19 | public class CreativeOPController { 20 | 21 | private final ICreativeService creativeService; 22 | 23 | @Autowired 24 | public CreativeOPController(ICreativeService creativeService) { 25 | this.creativeService = creativeService; 26 | } 27 | 28 | @PostMapping("/create/creative") 29 | public CreativeResponse createCreative(@RequestBody CreativeReuqest reuqest) throws AdException { 30 | log.info("ad-sponsor: createCreative -> {}", JSON.toJSONString(reuqest)); 31 | return creativeService.creatCreative(reuqest); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/unit_condition/AdUnitDistrict.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.Basic; 8 | import javax.persistence.Column; 9 | import javax.persistence.Entity; 10 | import javax.persistence.GeneratedValue; 11 | import javax.persistence.GenerationType; 12 | import javax.persistence.Id; 13 | import javax.persistence.Table; 14 | 15 | /** 16 | * 地域限制 17 | */ 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Entity 22 | @Table(name = "ad_unit_district") 23 | public class AdUnitDistrict { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | @Column(name = "id", nullable = false) 28 | private Long id; 29 | 30 | @Basic 31 | @Column(name = "unit_id", nullable = false) 32 | private Long unitId; 33 | 34 | @Basic 35 | @Column(name = "province", nullable = false) 36 | private String province; 37 | 38 | @Basic 39 | @Column(name = "city", nullable = false) 40 | private String city; 41 | 42 | public AdUnitDistrict(Long unitId, String province, String city) { 43 | this.unitId = unitId; 44 | this.province = province; 45 | this.city = city; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/controller/UserOPController.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.controller; 2 | 3 | import cn.lucas.ad.exception.AdException; 4 | import cn.lucas.ad.service.IUserService; 5 | import cn.lucas.ad.vo.CreateUserRequest; 6 | import cn.lucas.ad.vo.CreateUserResponse; 7 | import com.alibaba.fastjson.JSON; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | /** 15 | * @author Administrator 16 | */ 17 | @Slf4j 18 | @RestController 19 | public class UserOPController { 20 | 21 | private final IUserService userService; 22 | 23 | @Autowired 24 | public UserOPController(IUserService userService) { 25 | this.userService = userService; 26 | } 27 | 28 | 29 | /** 30 | * 创建用户 31 | * @param request 32 | * @return 33 | * @throws AdException 34 | */ 35 | @PostMapping("create/user") 36 | public CreateUserResponse createUser(@RequestBody CreateUserRequest request) throws AdException { 37 | log.info("ad-sponsor create user ->{}", JSON.toJSONString(request)); 38 | return userService.createUser(request); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/SearchApplication.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 8 | import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 9 | import org.springframework.cloud.netflix.hystrix.EnableHystrix; 10 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 11 | import org.springframework.cloud.openfeign.EnableFeignClients; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.web.client.RestTemplate; 14 | 15 | /** 16 | * @author Administrator 17 | */ 18 | @EnableFeignClients 19 | @EnableEurekaClient 20 | @EnableHystrix 21 | @EnableCircuitBreaker 22 | @EnableDiscoveryClient 23 | @EnableHystrixDashboard 24 | @SpringBootApplication 25 | public class SearchApplication { 26 | 27 | 28 | public static void main(String[] args) { 29 | SpringApplication.run(SearchApplication.class, args); 30 | } 31 | 32 | 33 | @Bean 34 | @LoadBalanced/*可以开启负载均衡的能力*/ 35 | RestTemplate restTemplate() { 36 | 37 | return new RestTemplate(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/adplan/AdPlanObject.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.adplan; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * @author mcg 11 | *

12 | * adplan 索引对象 13 | * 包含 adplan 的基本信息 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class AdPlanObject { 19 | 20 | /** 21 | * 只需要给检索时需要的字段添加索引 22 | * 我们会把数据表的实体类转换成一个索引对象 23 | */ 24 | 25 | private Long planId; 26 | private Long userId; 27 | private Integer planStatus; 28 | private Date startDate; 29 | private Date endDate; 30 | 31 | 32 | /** 33 | * 更新索引 34 | */ 35 | void update(AdPlanObject newObject) { 36 | if (null != newObject.getPlanId()) { 37 | this.planId = newObject.getPlanId(); 38 | } 39 | 40 | if (null != newObject.getUserId()) { 41 | this.userId = newObject.getUserId(); 42 | } 43 | 44 | if (null != newObject.planStatus) { 45 | this.planStatus = newObject.getPlanStatus(); 46 | } 47 | 48 | if (null != newObject.getStartDate()) { 49 | this.startDate = newObject.getStartDate(); 50 | } 51 | 52 | if (null != newObject.getEndDate()) { 53 | this.endDate = newObject.getEndDate(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ad-gateway/src/main/java/cn/lucas/ad/filter/AccessLogFilter.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.filter; 2 | 3 | import com.netflix.zuul.ZuulFilter; 4 | import com.netflix.zuul.context.RequestContext; 5 | import com.netflix.zuul.exception.ZuulException; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | 12 | 13 | @Slf4j 14 | @Component 15 | public class AccessLogFilter extends ZuulFilter { 16 | 17 | 18 | @Override 19 | public String filterType() { 20 | return FilterConstants.POST_TYPE; 21 | } 22 | 23 | @Override 24 | public int filterOrder() { 25 | return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1; 26 | } 27 | 28 | @Override 29 | public boolean shouldFilter() { 30 | return true; 31 | } 32 | 33 | @Override 34 | public Object run() throws ZuulException { 35 | RequestContext ctx = RequestContext.getCurrentContext(); 36 | HttpServletRequest request = ctx.getRequest(); 37 | Long startTime = (Long) ctx.get("startTime"); 38 | 39 | String uri = request.getRequestURI(); 40 | 41 | long duration = System.currentTimeMillis() - startTime; 42 | log.info(" uri : " + uri + ", duration : " + duration / 100 + "ms"); 43 | 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ad-eureka/target/classes/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ad-eureka 4 | 5 | server: 6 | port: 8000 7 | 8 | eureka: 9 | instance: 10 | hostname: localhost 11 | client: 12 | fetch-registry: false 13 | # 是否将自己注册为 eureka server ,当前应用本身就一个eureka server 所有她自己本身就是eureka server 14 | register-with-eureka: false 15 | service-url: 16 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 17 | 18 | --- 19 | spring: 20 | application: 21 | name: ad-eureka 22 | profiles: server1 23 | server: 24 | port: 8000 25 | eureka: 26 | instance: 27 | hostname: server1 28 | prefer-ip-address: false 29 | client: 30 | service-url: 31 | defaultZone: http://server2:8001/eureka/,http://server3:8002/eureka/ 32 | 33 | --- 34 | spring: 35 | application: 36 | name: ad-eureka 37 | profiles: server2 38 | server: 39 | port: 8001 40 | eureka: 41 | instance: 42 | hostname: server2 43 | prefer-ip-address: false 44 | client: 45 | service-url: 46 | defaultZone: http://server1:8000/eureka/,http://server3:8002/eureka/ 47 | 48 | --- 49 | spring: 50 | application: 51 | name: ad-eureka 52 | profiles: server3 53 | server: 54 | port: 8002 55 | eureka: 56 | instance: 57 | hostname: server3 58 | prefer-ip-address: false 59 | client: 60 | service-url: 61 | defaultZone: http://server1:8000/eureka/,http://server2:8001/eureka/ 62 | 63 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/AdUser.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity; 2 | 3 | import cn.lucas.ad.constant.CommonStatus; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.persistence.*; 9 | import java.util.Date; 10 | 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Entity 15 | @Table(name = "ad_user") 16 | public class AdUser { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | @Column(name = "id", nullable = false) 21 | private Long id; 22 | 23 | @Basic 24 | @Column(name = "username", nullable = false) 25 | private String username; 26 | 27 | @Basic 28 | @Column(name = "token", nullable = false) 29 | private String token; 30 | 31 | @Basic 32 | @Column(name = "user_status", nullable = false) 33 | private Integer userStatus; 34 | 35 | @Basic 36 | @Column(name = "create_time", nullable = false) 37 | private Date createTime; 38 | 39 | @Basic 40 | @Column(name = "update_time", nullable = false) 41 | private Date updateTime; 42 | 43 | 44 | public AdUser(String username, String token) { 45 | this.username = username; 46 | this.token = token; 47 | this.userStatus = CommonStatus.VALID.getStatus(); 48 | this.createTime = new Date(); 49 | this.updateTime = this.createTime; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ad-eureka/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ad-eureka 4 | 5 | server: 6 | port: 8000 7 | 8 | eureka: 9 | instance: 10 | hostname: localhost 11 | client: 12 | fetch-registry: false 13 | # 是否将自己注册为 eureka server ,当前应用本身就一个eureka server 所有她自己本身就是eureka server 14 | register-with-eureka: false 15 | service-url: 16 | defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 17 | 18 | --- 19 | spring: 20 | application: 21 | name: ad-eureka 22 | profiles: server1 23 | server: 24 | port: 8000 25 | eureka: 26 | instance: 27 | hostname: server1 28 | prefer-ip-address: false 29 | client: 30 | service-url: 31 | defaultZone: http://server2:8001/eureka/,http://server3:8002/eureka/ 32 | 33 | --- 34 | spring: 35 | application: 36 | name: ad-eureka 37 | profiles: server2 38 | server: 39 | port: 8001 40 | eureka: 41 | instance: 42 | hostname: server2 43 | prefer-ip-address: false 44 | client: 45 | service-url: 46 | defaultZone: http://server1:8000/eureka/,http://server3:8002/eureka/ 47 | 48 | --- 49 | spring: 50 | application: 51 | name: ad-eureka 52 | profiles: server3 53 | server: 54 | port: 8002 55 | eureka: 56 | instance: 57 | hostname: server3 58 | prefer-ip-address: false 59 | client: 60 | service-url: 61 | defaultZone: http://server1:8000/eureka/,http://server2:8001/eureka/ 62 | 63 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/test/java/cn/lucas/ad/service/AdUnitServiceTest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service; 2 | 3 | import cn.lucas.ad.Application; 4 | import cn.lucas.ad.exception.AdException; 5 | import cn.lucas.ad.vo.AdUnitKeywordRequest; 6 | import cn.lucas.ad.vo.AdUnitRequest; 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.test.context.SpringBootTest; 11 | import org.springframework.test.context.junit4.SpringRunner; 12 | 13 | import javax.validation.constraints.Max; 14 | import java.util.ArrayList; 15 | import java.util.Collection; 16 | import java.util.List; 17 | 18 | /** 19 | * @author Administrator 20 | */ 21 | @RunWith(SpringRunner.class) 22 | @SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE) 23 | public class AdUnitServiceTest { 24 | 25 | @Autowired 26 | private IAdUnitService unitService; 27 | 28 | 29 | /** 30 | * insert 依然有 乱码问题 31 | * @throws AdException 32 | */ 33 | @Test 34 | public void testCreateUnit() throws AdException{ 35 | 36 | System.out.println(unitService.createUnit( 37 | new AdUnitRequest( 38 | 10L, 39 | "第四个推广单元", 40 | 1, 41 | 10000L 42 | 43 | ) 44 | )); 45 | } 46 | 47 | 48 | @Test 49 | public void testCreateUnitKeyword() throws AdException { 50 | 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /ad-eureka/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lucas-ad 7 | cn.lucas.ad 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | 13 | 14 | ad-eureka 15 | 1.0-SNAPSHOT 16 | jar 17 | 18 | 19 | ad-eureka 20 | Spring Cloud Eureka 21 | 22 | 23 | 24 | 25 | org.springframework.cloud 26 | spring-cloud-starter-netflix-eureka-server 27 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-maven-plugin 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/vo/CreativeReuqest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.vo; 2 | 3 | import cn.lucas.ad.constant.CommonStatus; 4 | import cn.lucas.ad.entity.Creative; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * @author Administrator 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class CreativeReuqest { 18 | 19 | // 创意名称 20 | private String name; 21 | 22 | // 创意主类型 23 | private Integer type; 24 | 25 | // 创意子类型 26 | private Integer materialType; 27 | 28 | // 高度 29 | private Integer height; 30 | 31 | // 宽度 32 | private Integer weight; 33 | 34 | // 大小 35 | private Long size; 36 | 37 | // 持续时长 38 | private Integer duration; 39 | 40 | private Long userId; 41 | 42 | private String url; 43 | 44 | 45 | public Creative convertToEntity() { 46 | Creative creative = new Creative(); 47 | creative.setName(name); 48 | creative.setType(type); 49 | creative.setMaterialType(materialType); 50 | creative.setHeight(height); 51 | creative.setWidth(weight); 52 | creative.setSize(size); 53 | creative.setAuditStatus(CommonStatus.VALID.getStatus()); 54 | creative.setDuration(duration); 55 | creative.setUserId(userId); 56 | creative.setUrl(url); 57 | creative.setCreateTime(new Date()); 58 | creative.setUpdateTime(creative.getCreateTime()); 59 | return creative; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lucas-ad-service 7 | cn.lucas.ad 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | 13 | ad-common 14 | 1.0-SNAPSHOT 15 | jar 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 24 | 25 | com.alibaba 26 | fastjson 27 | 1.2.31 28 | 29 | 30 | 31 | 35 | 43 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/adplan/AdPlanIndex.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.adplan; 2 | 3 | import cn.lucas.ad.index.IndexAware; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Component; 6 | 7 | import java.util.Map; 8 | import java.util.concurrent.ConcurrentHashMap; 9 | 10 | /** 11 | * @author mcg 12 | * 13 | * 正向索引 14 | */ 15 | 16 | @Slf4j 17 | @Component 18 | public class AdPlanIndex implements IndexAware { 19 | 20 | private static Map objectMap; 21 | 22 | static { 23 | objectMap = new ConcurrentHashMap<>(); 24 | } 25 | 26 | @Override 27 | 28 | public AdPlanObject get(Long key) { 29 | 30 | return objectMap.get(key); 31 | } 32 | 33 | @Override 34 | public void add(Long key, AdPlanObject value) { 35 | log.info("before add: {}", objectMap); 36 | objectMap.put(key, value); 37 | log.info("after add: {}", objectMap); 38 | } 39 | 40 | @Override 41 | public void update(Long key, AdPlanObject value) { 42 | log.info("before update: {}", objectMap); 43 | AdPlanObject oldObject = objectMap.get(key); 44 | if (null != oldObject) { 45 | objectMap.put(key, value); 46 | } else { 47 | oldObject.update(value); 48 | } 49 | 50 | log.info("after update: {}", objectMap); 51 | 52 | } 53 | 54 | @Override 55 | public void delete(Long key, AdPlanObject value) { 56 | log.info("before delete: {}", objectMap); 57 | objectMap.remove(key); 58 | log.info("after delete: {}", objectMap); 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/AdPlan.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity; 2 | 3 | import cn.lucas.ad.constant.CommonStatus; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.persistence.*; 9 | import java.util.Date; 10 | 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Entity 15 | @Table(name = "ad_plan") 16 | public class AdPlan { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | @Column(name = "id", nullable = false) 21 | private Long id; 22 | 23 | @Basic 24 | @Column(name = "user_id", nullable = false) 25 | private Long userId; 26 | 27 | @Basic 28 | @Column(name = "plan_name", nullable = false) 29 | private String planName; 30 | 31 | 32 | @Basic 33 | @Column(name = "plan_status", nullable = false) 34 | private Integer planStatus; 35 | 36 | 37 | @Basic 38 | @Column(name = "start_date", nullable = false) 39 | private Date startDate; 40 | 41 | @Basic 42 | @Column(name = "end_date", nullable = false) 43 | private Date endDate; 44 | 45 | @Basic 46 | @Column(name = "create_time", nullable = false) 47 | private Date createTime; 48 | 49 | 50 | @Basic 51 | @Column(name = "update_time", nullable = false) 52 | private Date updateTime; 53 | 54 | 55 | public AdPlan(Long userId, String planName, Date startDate, Date endDate) { 56 | this.userId = userId; 57 | this.planName = planName; 58 | this.planStatus = CommonStatus.VALID.getStatus(); 59 | this.startDate = startDate; 60 | this.endDate = endDate; 61 | this.createTime = new Date(); 62 | this.updateTime = this.createTime; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/utils/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.utils; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.apache.commons.lang.time.DateUtils; 5 | 6 | import java.text.DateFormat; 7 | import java.text.ParseException; 8 | import java.text.SimpleDateFormat; 9 | import java.util.Date; 10 | import java.util.Locale; 11 | import java.util.Map; 12 | import java.util.function.Supplier; 13 | 14 | /** 15 | * @Author mcg 16 | * @Date 2019/1/29 21:45 17 | **/ 18 | @Slf4j 19 | public class CommonUtils { 20 | 21 | 22 | public static V getOrCreate(K key, Map map, Supplier factory) { 23 | 24 | return map.computeIfAbsent(key, k -> factory.get()); 25 | } 26 | 27 | public static String stringConcat(String... args) { 28 | 29 | StringBuilder result = new StringBuilder(); 30 | for (String arg : args) { 31 | result.append(arg); 32 | result.append("-"); 33 | } 34 | result.deleteCharAt(result.length() - 1); 35 | return result.toString(); 36 | } 37 | 38 | /** 39 | * 解析日期格式 Tue Jan 01 08:00:00 CST 2019 40 | * @param dateString 41 | * @return 42 | */ 43 | public static Date parseStringDate(String dateString) { 44 | 45 | try { 46 | 47 | DateFormat dateFormat = new SimpleDateFormat( 48 | "EEE MMM dd HH:mm:ss zzz yyyy", 49 | Locale.US 50 | ); 51 | return DateUtils.addHours( 52 | dateFormat.parse(dateString), 53 | -8 54 | ); 55 | 56 | } catch (ParseException ex) { 57 | log.error("parseStringDate error: {}", dateString); 58 | return null; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/creative/CreativeObject.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.creative; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * @Author mcg 9 | * @Date 2019/2/14 19:29 10 | **/ 11 | 12 | 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class CreativeObject { 17 | 18 | private Long adId; 19 | private String name; 20 | private Integer type; 21 | // 子类型 22 | private Integer materialType; 23 | private Integer height; 24 | private Integer width; 25 | // 审核状态 26 | private Integer auditStatus; 27 | private String adUrl; 28 | 29 | 30 | // 定义 update 方法 对 object 进行更新 31 | 32 | public void update(CreativeObject newObject) { 33 | if (null != newObject.getAdId()) { 34 | this.adId = newObject.getAdId(); 35 | } 36 | 37 | if (null != newObject.getName()) { 38 | this.name = newObject.getName(); 39 | } 40 | 41 | if (null != newObject.getType()) { 42 | this.type = newObject.getType(); 43 | } 44 | 45 | if (null != newObject.getMaterialType()) { 46 | this.materialType = newObject.getMaterialType(); 47 | } 48 | 49 | if (null != newObject.getHeight()) { 50 | this.height = newObject.getHeight(); 51 | } 52 | 53 | if (null != newObject.getWidth()) { 54 | this.width = newObject.getWidth(); 55 | } 56 | 57 | if (null != newObject.getAuditStatus()) { 58 | this.auditStatus = newObject.getAuditStatus(); 59 | } 60 | 61 | if (null != newObject.getAdUrl()) { 62 | this.adUrl = newObject.getAdUrl(); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/DataTable.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | import org.springframework.core.PriorityOrdered; 7 | 8 | import java.util.Map; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import org.springframework.stereotype.Component; 11 | 12 | 13 | /** 14 | * @Author mcg 15 | * @Date 2019/2/16 14:23 16 | **/ 17 | 18 | @Component 19 | public class DataTable implements ApplicationContextAware, PriorityOrdered { 20 | 21 | private static ApplicationContext applicationContext; 22 | 23 | public static final Map dataTableMap = 24 | new ConcurrentHashMap<>(); 25 | 26 | @Override 27 | public void setApplicationContext( 28 | ApplicationContext applicationContext) throws BeansException { 29 | DataTable.applicationContext = applicationContext; 30 | } 31 | 32 | @Override 33 | public int getOrder() { 34 | return PriorityOrdered.HIGHEST_PRECEDENCE; 35 | } 36 | 37 | @SuppressWarnings("all") 38 | public static T of(Class clazz) { 39 | 40 | T instance = (T) dataTableMap.get(clazz); 41 | if (null != instance) { 42 | return instance; 43 | } 44 | 45 | dataTableMap.put(clazz, bean(clazz)); 46 | return (T) dataTableMap.get(clazz); 47 | } 48 | 49 | @SuppressWarnings("all") 50 | private static T bean(String beanName) { 51 | return (T) applicationContext.getBean(beanName); 52 | } 53 | 54 | @SuppressWarnings("all") 55 | private static T bean(Class clazz) { 56 | return (T) applicationContext.getBean(clazz); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/AdUnit.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity; 2 | 3 | import cn.lucas.ad.constant.CommonStatus; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.persistence.*; 9 | import java.util.Date; 10 | 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Entity 15 | @Table(name = "ad_unit") 16 | public class AdUnit { 17 | 18 | 19 | @Id 20 | @GeneratedValue(strategy = GenerationType.IDENTITY) 21 | @Column(name = "id",nullable = false) 22 | private Long id; 23 | 24 | 25 | @Basic 26 | @Column(name = "plan_id",nullable = false) 27 | private Long planId; 28 | 29 | @Basic 30 | @Column(name = "unit_name",nullable = false) 31 | private String unitName; 32 | 33 | @Basic 34 | @Column(name = "unit_status", nullable = false) 35 | private Integer unitStatus; 36 | 37 | /** 广告位类型(开屏, 贴片, 中贴...) */ 38 | @Basic 39 | @Column(name = "position_type", nullable = false) 40 | private Integer positionType; 41 | 42 | @Basic 43 | @Column(name = "budget", nullable = false) 44 | private Long budget; 45 | 46 | @Basic 47 | @Column(name = "create_time", nullable = false) 48 | private Date createTime; 49 | 50 | @Basic 51 | @Column(name = "update_time", nullable = false) 52 | private Date updateTime; 53 | 54 | public AdUnit(Long planId, String unitName, 55 | Integer positionType, Long budget) { 56 | this.planId = planId; 57 | this.unitName = unitName; 58 | this.unitStatus = CommonStatus.VALID.getStatus(); 59 | this.positionType = positionType; 60 | this.budget = budget; 61 | this.createTime = new Date(); 62 | this.updateTime = this.createTime; 63 | } 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/SearchRequest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo; 2 | 3 | import cn.lucas.ad.search.vo.feature.DistrictFeature; 4 | import cn.lucas.ad.search.vo.feature.FeatureRelation; 5 | import cn.lucas.ad.search.vo.feature.ItFeature; 6 | import cn.lucas.ad.search.vo.feature.KeywordFeature; 7 | import cn.lucas.ad.search.vo.media.AdSlot; 8 | import cn.lucas.ad.search.vo.media.App; 9 | import cn.lucas.ad.search.vo.media.Device; 10 | import cn.lucas.ad.search.vo.media.Geo; 11 | import com.sun.org.apache.regexp.internal.RE; 12 | import lombok.AllArgsConstructor; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * @author Administrator 20 | */ 21 | @Data 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | public class SearchRequest { 25 | 26 | /** 27 | * 媒体方的请求标识 28 | */ 29 | private String mediaId; 30 | 31 | /** 32 | * 请求基本信息 33 | */ 34 | private RequestInfo requestInfo; 35 | 36 | /** 37 | * 匹配信息 38 | */ 39 | private FeatureInfo featureInfo; 40 | 41 | @Data 42 | @NoArgsConstructor 43 | @AllArgsConstructor 44 | public static class RequestInfo { 45 | private String requestId; 46 | 47 | /** 48 | * 广告位信息 49 | */ 50 | private List adSlots; 51 | private App app; 52 | private Geo geo; 53 | private Device device; 54 | } 55 | 56 | 57 | @Data 58 | @NoArgsConstructor 59 | @AllArgsConstructor 60 | public static class FeatureInfo{ 61 | private KeywordFeature keywordFeature; 62 | private DistrictFeature districtFeature; 63 | private ItFeature itFeature; 64 | 65 | // 默认是都需要满足匹配条件 66 | private FeatureRelation relation = FeatureRelation.AND; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service.impl; 2 | 3 | import cn.lucas.ad.constant.Constants; 4 | import cn.lucas.ad.dao.AdUserRepository; 5 | import cn.lucas.ad.entity.AdUser; 6 | import cn.lucas.ad.exception.AdException; 7 | import cn.lucas.ad.service.IUserService; 8 | import cn.lucas.ad.utils.CommonUtils; 9 | import cn.lucas.ad.vo.CreateUserRequest; 10 | import cn.lucas.ad.vo.CreateUserResponse; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | @Slf4j 17 | @Service 18 | public class UserServiceImpl implements IUserService { 19 | 20 | private final AdUserRepository adUserRepository; 21 | 22 | @Autowired 23 | public UserServiceImpl(AdUserRepository adUserRepository) { 24 | this.adUserRepository = adUserRepository; 25 | } 26 | 27 | @Override 28 | @Transactional 29 | public CreateUserResponse createUser(CreateUserRequest request) throws AdException { 30 | 31 | if (!request.validate()) { 32 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 33 | } 34 | 35 | AdUser oldUser = adUserRepository.findByUsername(request.getUsername()); 36 | if (oldUser != null) { 37 | throw new AdException(Constants.ErrorMsg.SAME_NAME_ERROR); 38 | } 39 | 40 | AdUser newUser = adUserRepository.save(new AdUser(request.getUsername(), 41 | CommonUtils.md5(request.getUsername()))); 42 | 43 | return new CreateUserResponse(newUser.getId(), 44 | newUser.getUsername(),newUser.getToken(), 45 | newUser.getCreateTime(),newUser.getUpdateTime()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /ad-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lucas-ad 7 | cn.lucas.ad 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | 13 | 14 | ad-gateway 15 | 1.0-SNAPSHOT 16 | jar 17 | 18 | 19 | ad-gateway 20 | ad-gateway 21 | 22 | 23 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-starter-netflix-eureka-client 30 | 31 | 32 | 33 | org.springframework.cloud 34 | spring-cloud-starter-netflix-zuul 35 | 36 | 37 | 38 | 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-maven-plugin 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/sender/kafka/KafkaSender.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.sender.kafka; 2 | 3 | import cn.lucas.ad.mysql.dto.MySqlRowData; 4 | import cn.lucas.ad.sender.ISender; 5 | import com.alibaba.fastjson.JSON; 6 | import org.apache.kafka.clients.consumer.ConsumerRecord; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.kafka.annotation.KafkaListener; 10 | import org.springframework.kafka.core.KafkaTemplate; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.Optional; 14 | 15 | /** 16 | * @author Administrator 17 | */ 18 | @Component("kafkaSender") 19 | public class KafkaSender implements ISender { 20 | 21 | @Value("${adconf.kafka.topic}") 22 | private String topic; 23 | 24 | private final KafkaTemplate kafkaTemplate; 25 | 26 | @Autowired 27 | public KafkaSender(KafkaTemplate kafkaTemplate) { 28 | this.kafkaTemplate = kafkaTemplate; 29 | } 30 | 31 | @Override 32 | public void sender(MySqlRowData rowData) { 33 | kafkaTemplate.send( 34 | topic, 35 | JSON.toJSONString(rowData) 36 | ); 37 | } 38 | 39 | 40 | /** 41 | * kafka 接收方法 测试 42 | */ 43 | @KafkaListener(topics = {"ad-search-mysql-data"},groupId = "ad-search") 44 | public void processMySQLRowData(ConsumerRecord record) { 45 | Optional kafkaMessage = Optional.ofNullable(record.value()); 46 | if (kafkaMessage.isPresent()) { 47 | Object message = kafkaMessage.get(); 48 | MySqlRowData rowData = JSON.parseObject(message.toString(), MySqlRowData.class); 49 | System.out.println("kafka processMySqlRowData :" + JSON.toJSONString(rowData)); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/entity/Creative.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.entity; 2 | 3 | 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import javax.persistence.*; 9 | import java.util.Date; 10 | 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Entity 15 | @Table(name = "ad_creative") 16 | public class Creative { 17 | 18 | @Id 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | @Column(name = "id", nullable = false) 21 | private Long id; 22 | 23 | @Basic 24 | @Column(name = "name", nullable = false) 25 | private String name; 26 | 27 | @Basic 28 | @Column(name = "type", nullable = false) 29 | private Integer type; 30 | 31 | /** 物料的类型, 比如图片可以是 bmp, jpg等等 */ 32 | @Basic 33 | @Column(name = "material_type", nullable = false) 34 | private Integer materialType; 35 | 36 | @Basic 37 | @Column(name = "height", nullable = false) 38 | private Integer height; 39 | 40 | @Basic 41 | @Column(name = "width", nullable = false) 42 | private Integer width; 43 | 44 | /** 物料大小 */ 45 | @Basic 46 | @Column(name = "size", nullable = false) 47 | private Long size; 48 | 49 | /** 持续时长, 只有视频不为0 */ 50 | @Basic 51 | @Column(name = "duration", nullable = false) 52 | private Integer duration; 53 | 54 | /** 审核状态 */ 55 | @Basic 56 | @Column(name = "audit_status", nullable = false) 57 | private Integer auditStatus; 58 | 59 | @Basic 60 | @Column(name = "user_id", nullable = false) 61 | private Long userId; 62 | 63 | @Basic 64 | @Column(name = "url", nullable = false) 65 | private String url; 66 | 67 | @Basic 68 | @Column(name = "create_time", nullable = false) 69 | private Date createTime; 70 | 71 | @Basic 72 | @Column(name = "updateTime", nullable = false) 73 | private Date updateTime; 74 | } 75 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/search/vo/SearchResponse.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search.vo; 2 | 3 | import cn.lucas.ad.index.creative.CreativeObject; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.apache.kafka.common.protocol.types.Field; 8 | 9 | import java.util.Arrays; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * @author Administrator 16 | */ 17 | 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | public class SearchResponse { 22 | 23 | /** 24 | * key adSlotCode 广告位编码 25 | */ 26 | public Map> adSlot2Ads = new HashMap<>(); 27 | 28 | /** 29 | * 广告创意 30 | */ 31 | @Data 32 | @NoArgsConstructor 33 | @AllArgsConstructor 34 | 35 | public static class Creative { 36 | private Long adId; 37 | private String url; 38 | private Integer width; 39 | private Integer height; 40 | private Integer type; 41 | private Integer materialType; 42 | 43 | // 监测 点击 url 正常来说是和 创意(Creative)本身绑定的 44 | 45 | /** 46 | * 展示监测 url 47 | */ 48 | private List showMonitorUrl = Arrays.asList("www.baidu.com", "www.ali.com"); 49 | 50 | /** 51 | * 点击监测 url 52 | */ 53 | private List clickMonitorUrl = Arrays.asList("www.baidu.com", "www.ali.com"); 54 | } 55 | 56 | 57 | /** 58 | * 将索引对象装换成 Creative 对象 59 | */ 60 | public static Creative convert(CreativeObject object) { 61 | Creative creative = new Creative(); 62 | creative.setAdId(object.getAdId()); 63 | creative.setUrl(object.getAdUrl()); 64 | creative.setWidth(object.getWidth()); 65 | creative.setHeight(object.getHeight()); 66 | creative.setType(object.getType()); 67 | creative.setMaterialType(object.getMaterialType()); 68 | return creative; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/BinlogClient.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql; 2 | 3 | import cn.lucas.ad.mysql.listener.AggregationListener; 4 | import com.github.shyiko.mysql.binlog.BinaryLogClient; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.lang.StringUtils; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * @author Administrator 14 | */ 15 | @Slf4j 16 | @Component 17 | public class BinlogClient { 18 | 19 | private BinaryLogClient client; 20 | 21 | private final BinlogConfig config; 22 | 23 | private final AggregationListener listener; 24 | 25 | @Autowired 26 | public BinlogClient(BinlogConfig config, AggregationListener listener) { 27 | this.config = config; 28 | this.listener = listener; 29 | } 30 | 31 | public void connect() { 32 | new Thread(()->{ 33 | client = new BinaryLogClient( 34 | config.getHost(), 35 | config.getPort(), 36 | config.getUsername(), 37 | config.getPassword() 38 | ); 39 | if (!StringUtils.isEmpty(config.getBinlogName()) 40 | && !config.getPosition().equals(-1L)) { 41 | client.setBinlogFilename(config.getBinlogName()); 42 | client.setBinlogPosition(config.getPosition()); 43 | } 44 | 45 | client.registerEventListener(listener); 46 | 47 | try { 48 | log.info("connecting to mysql start"); 49 | client.connect(); 50 | log.info("connecting to mysql done"); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | } 54 | }).start(); 55 | } 56 | 57 | public void close() { 58 | try { 59 | client.disconnect(); 60 | } catch (IOException e) { 61 | e.printStackTrace(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/controller/AdPlanOPController.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.controller; 2 | 3 | import cn.lucas.ad.entity.AdPlan; 4 | import cn.lucas.ad.exception.AdException; 5 | import cn.lucas.ad.service.IAdPlanService; 6 | import cn.lucas.ad.vo.AdPlanGetRequest; 7 | import cn.lucas.ad.vo.AdPlanRequest; 8 | import cn.lucas.ad.vo.AdPlanResponse; 9 | import com.alibaba.fastjson.JSON; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | import java.util.List; 15 | 16 | /** 17 | * @author Administrator 18 | */ 19 | @Slf4j 20 | @RestController 21 | public class AdPlanOPController { 22 | 23 | private final IAdPlanService planService; 24 | 25 | @Autowired 26 | public AdPlanOPController(IAdPlanService planService) { 27 | this.planService = planService; 28 | } 29 | 30 | @PostMapping("/create/adPlan") 31 | public AdPlanResponse createAdPlan(@RequestBody AdPlanRequest request) throws AdException{ 32 | log.info("ad-sponsor: createAdPlan ->{}", JSON.toJSONString(request)); 33 | return planService.createAdPlan(request); 34 | } 35 | 36 | @PostMapping("/get/adPlan") 37 | public List getAdPlanByIds(@RequestBody AdPlanGetRequest request) throws AdException{ 38 | log.info("ad-sponsor: getAdPlanByIds ->{}", JSON.toJSONString(request)); 39 | return planService.getAdPlanByIds(request); 40 | } 41 | 42 | 43 | @PutMapping("/update/adPlan") 44 | public AdPlanResponse updateAdPlan(@RequestBody AdPlanRequest request) throws AdException{ 45 | log.info("ad-sponsor: updateAdPlan ->{}", JSON.toJSONString(request)); 46 | return planService.updateAdPlan(request); 47 | } 48 | 49 | @DeleteMapping("/delete/adPlan") 50 | public void deleteAdPlan(@RequestBody AdPlanRequest request) throws AdException{ 51 | log.info("ad-sponsor: deleteAdPlan ->{}", JSON.toJSONString(request)); 52 | planService.deleteAdPlan(request); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-dashboard/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lucas-ad-service 7 | cn.lucas.ad 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | ad-dashboard 13 | 1.0-SNAPSHOT 14 | jar 15 | 16 | 17 | 18 | 19 | org.springframework.cloud 20 | spring-cloud-starter-netflix-hystrix 21 | 22 | 23 | 24 | org.springframework.cloud 25 | spring-cloud-starter-netflix-hystrix-dashboard 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-actuator 31 | 32 | 36 | 37 | org.springframework.cloud 38 | spring-cloud-starter-netflix-eureka-client 39 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | org.springframework.boot 50 | spring-boot-maven-plugin 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-common/src/main/java/cn/lucas/ad/advice/CommonResponseDataAdvice.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.advice; 2 | 3 | import cn.lucas.ad.annotation.IgnoreResponseAdvice; 4 | import cn.lucas.ad.vo.CommonResponse; 5 | import org.springframework.core.MethodParameter; 6 | import org.springframework.http.MediaType; 7 | import org.springframework.http.converter.HttpMessageConverter; 8 | import org.springframework.http.server.ServerHttpRequest; 9 | import org.springframework.http.server.ServerHttpResponse; 10 | import org.springframework.lang.Nullable; 11 | import org.springframework.web.bind.annotation.RestControllerAdvice; 12 | import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; 13 | 14 | @RestControllerAdvice 15 | public class CommonResponseDataAdvice implements ResponseBodyAdvice { 16 | 17 | // 根据相关添加去判断响应是否需要去拦截 18 | @Override 19 | @SuppressWarnings("all") 20 | public boolean supports(MethodParameter methodParameter, 21 | Class> aClass) { 22 | // 拿到的类 被 注解 IgnoreResponseAdvice 标识 ,就不用被commonresponse 影响 23 | if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreResponseAdvice.class)) { 24 | return false; 25 | } 26 | // 方法被 注解 IgnoreResponseAdvice 标识,就不用被 commonresponse 影响 27 | if (methodParameter.getMethod().isAnnotationPresent(IgnoreResponseAdvice.class)) { 28 | return false; 29 | } 30 | return true; 31 | } 32 | 33 | @Nullable 34 | @Override 35 | @SuppressWarnings("all") 36 | public Object beforeBodyWrite(@Nullable Object o, MethodParameter methodParameter, 37 | MediaType mediaType, 38 | Class> aClass, 39 | ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { 40 | 41 | CommonResponse response = new CommonResponse<>(0, ""); 42 | if (null == o) { 43 | return response; 44 | } else if (o instanceof CommonResponse) { 45 | response = (CommonResponse) o; 46 | } else { 47 | response.setData(o); 48 | } 49 | 50 | return response; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/dto/ParseTemplate.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.dto; 2 | 3 | import cn.lucas.ad.mysql.constant.OpType; 4 | import lombok.Data; 5 | 6 | import java.util.ArrayList; 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | import java.util.function.Supplier; 11 | 12 | /** 13 | * @Author mcg 14 | * @Date 2019/2/18 20:58 15 | **/ 16 | @Data 17 | public class ParseTemplate { 18 | 19 | 20 | private String database; 21 | 22 | private Map tableTemplateMap = new HashMap<>(); 23 | 24 | 25 | public static ParseTemplate pase(Template template) { 26 | ParseTemplate parseTemplate = new ParseTemplate(); 27 | parseTemplate.setDatabase(template.getDatabase()); 28 | 29 | for (JsonTable table : template.getTableList()) { 30 | String name = table.getTableName(); 31 | Integer level = table.getLevel(); 32 | 33 | TableTemplate tableTemplate = new TableTemplate(); 34 | tableTemplate.setTableName(name); 35 | tableTemplate.setLevel(level.toString()); 36 | parseTemplate.tableTemplateMap.put(name, tableTemplate); 37 | 38 | // 遍历操作类型对应的列 39 | Map> opTypeFieldSetMap = 40 | tableTemplate.getOpTypeFieldSetMap(); 41 | 42 | for (JsonTable.Column column : table.getInsert()) { 43 | getAndCreateIfNeed(OpType.ADD, opTypeFieldSetMap, ArrayList::new) 44 | .add(column.getColumn()); 45 | } 46 | 47 | for (JsonTable.Column column : table.getUpdate()) { 48 | getAndCreateIfNeed(OpType.UPDATE, opTypeFieldSetMap, ArrayList::new) 49 | .add(column.getColumn()); 50 | } 51 | for (JsonTable.Column column : table.getDelete()) { 52 | getAndCreateIfNeed(OpType.DELETE, opTypeFieldSetMap, ArrayList::new) 53 | .add(column.getColumn()); 54 | } 55 | } 56 | 57 | return parseTemplate; 58 | } 59 | 60 | 61 | private static R getAndCreateIfNeed(T key, Map map, Supplier factory) { 62 | 63 | return map.computeIfAbsent(key, k -> factory.get()); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | cn.lucas.ad 8 | lucas-ad 9 | 1.0-SNAPSHOT 10 | 11 | ad-eureka 12 | ad-gateway 13 | lucas-ad-service 14 | 15 | 16 | pom 17 | 18 | lucas-ad-spring-cloud 19 | Project For Lucas Ad SpringCloud 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-parent 24 | 2.0.2.RELEASE 25 | 26 | 27 | 28 | Finchley.RELEASE 29 | 30 | 31 | 32 | 33 | org.projectlombok 34 | lombok 35 | 1.16.18 36 | 37 | 38 | org.springframework.boot 39 | spring-boot-starter-test 40 | test 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.cloud 48 | spring-cloud-dependencies 49 | ${spring-cloud.version} 50 | pom 51 | import 52 | 53 | 54 | 55 | 56 | 57 | 58 | spring-milestones 59 | Spring Milestones 60 | https://repo.spring.io/milestone 61 | 62 | false 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 4 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 5 | 6 | # User-specific stuff 7 | .idea/**/workspace.xml 8 | .idea/**/tasks.xml 9 | .idea/**/dictionaries 10 | .idea/**/shelf 11 | .idea 12 | *.iml 13 | 14 | # Sensitive or high-churn files 15 | .idea/**/dataSources/ 16 | .idea/**/dataSources.ids 17 | .idea/**/dataSources.local.xml 18 | .idea/**/sqlDataSources.xml 19 | .idea/**/dynamic.xml 20 | .idea/**/uiDesigner.xml 21 | 22 | # Gradle 23 | .idea/**/gradle.xml 24 | .idea/**/libraries 25 | 26 | # CMake 27 | cmake-build-debug/ 28 | cmake-build-release/ 29 | 30 | # Mongo Explorer plugin 31 | .idea/**/mongoSettings.xml 32 | 33 | # File-based project format 34 | *.iws 35 | 36 | # IntelliJ 37 | out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Cursive Clojure plugin 46 | .idea/replstate.xml 47 | 48 | # Crashlytics plugin (for Android Studio and IntelliJ) 49 | com_crashlytics_export_strings.xml 50 | crashlytics.properties 51 | crashlytics-build.properties 52 | fabric.properties 53 | 54 | # Editor-based Rest Client 55 | .idea/httpRequests 56 | ### macOS template 57 | # General 58 | .DS_Store 59 | .AppleDouble 60 | .LSOverride 61 | 62 | # Icon must end with two \r 63 | Icon 64 | 65 | # Thumbnails 66 | ._* 67 | 68 | # Files that might appear in the root of a volume 69 | .DocumentRevisions-V100 70 | .fseventsd 71 | .Spotlight-V100 72 | .TemporaryItems 73 | .Trashes 74 | .VolumeIcon.icns 75 | .com.apple.timemachine.donotpresent 76 | 77 | # Directories potentially created on remote AFP share 78 | .AppleDB 79 | .AppleDesktop 80 | Network Trash Folder 81 | Temporary Items 82 | .apdisk 83 | ### Java template 84 | # Compiled class file 85 | *.class 86 | 87 | # Log file 88 | *.log 89 | 90 | # BlueJ files 91 | *.ctxt 92 | 93 | # Mobile Tools for Java (J2ME) 94 | .mtj.tmp/ 95 | 96 | # Package Files # 97 | *.jar 98 | *.war 99 | *.nar 100 | *.ear 101 | *.zip 102 | *.tar.gz 103 | *.rar 104 | 105 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 106 | hs_err_pid* 107 | 108 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/service/BinLogServiceTest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service; 2 | 3 | import com.github.shyiko.mysql.binlog.BinaryLogClient; 4 | import com.github.shyiko.mysql.binlog.event.DeleteRowsEventData; 5 | import com.github.shyiko.mysql.binlog.event.EventData; 6 | import com.github.shyiko.mysql.binlog.event.UpdateRowsEventData; 7 | import com.github.shyiko.mysql.binlog.event.WriteRowsEventData; 8 | 9 | import java.io.IOException; 10 | 11 | /** 12 | * @Author mcg 13 | * @Date 2019/2/17 19:48 14 | **/ 15 | 16 | public class BinLogServiceTest { 17 | 18 | // write --------- 19 | // WriteRowsEventData{tableId=224, includedColumns={0, 1, 2}, rows=[ 20 | // [16, 10, 迈巴赫] 21 | //]} 22 | // update -------- 23 | // UpdateRowsEventData{tableId=224, includedColumnsBeforeUpdate={0, 1, 2}, includedColumns={0, 1, 2}, rows=[ 24 | // {before=[14, 10, 宝来], after=[14, 10, 保时捷]} 25 | //]} 26 | // delete ------- 27 | // DeleteRowsEventData{tableId=224, includedColumns={0, 1, 2}, rows=[ 28 | // [15, 10, 马自达] 29 | //]} 30 | 31 | // 32 | // write --------- 33 | // WriteRowsEventData{tableId=110, includedColumns={0, 1, 2, 3, 4, 5, 6, 7}, rows=[ 34 | // [11, 10, plan, 1, Tue Jan 01 08:00:00 CST 2019, Tue Jan 01 08:00:00 CST 2019, Tue Jan 01 08:00:00 CST 2019, Tue Jan 01 08:00:00 CST 2019] 35 | // Tue Jan 01 08:00:00 CST 2019 36 | //]} 37 | 38 | public static void main(String[] args) throws IOException { 39 | BinaryLogClient client = new BinaryLogClient( 40 | "127.0.0.1", 41 | 3306, 42 | "root", 43 | "123456" 44 | ); 45 | 46 | // client.setBinlogFilename(); 47 | 48 | 49 | client.registerEventListener(event -> { 50 | EventData data = event.getData(); 51 | if (data instanceof UpdateRowsEventData) { 52 | System.out.println("update -------- "); 53 | System.out.println(data.toString()); 54 | } else if (data instanceof WriteRowsEventData) { 55 | System.out.println("write --------- "); 56 | System.out.println(data.toString()); 57 | } else if (data instanceof DeleteRowsEventData) { 58 | System.out.println("delete ------- "); 59 | System.out.println(data.toString()); 60 | } 61 | }); 62 | 63 | client.connect(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/creative/CreativeIndex.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.creative; 2 | 3 | import cn.lucas.ad.index.IndexAware; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.apache.commons.collections4.CollectionUtils; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.*; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | /** 12 | * @Author mcg 13 | * @Date 2019/2/14 19:38 14 | * 15 | * 正向索引 16 | **/ 17 | 18 | @Slf4j 19 | @Component 20 | public class CreativeIndex implements IndexAware { 21 | 22 | private static Map objectMap; 23 | 24 | static { 25 | objectMap = new ConcurrentHashMap<>(); 26 | } 27 | 28 | /** 29 | * 11-6 5:00 30 | * @param adIds 31 | * @return 32 | */ 33 | public List fetch(Collection adIds) { 34 | if (CollectionUtils.isEmpty(adIds)) { 35 | return Collections.emptyList(); 36 | } 37 | 38 | List result = new ArrayList<>(); 39 | adIds.forEach(u->{ 40 | CreativeObject object = get(u); 41 | // 获取到的索引对象不存在 42 | if (null == object) { 43 | log.error("CreativeObject not found :{}", u); 44 | return; 45 | } 46 | result.add(object); 47 | }); 48 | return result; 49 | } 50 | 51 | @Override 52 | public CreativeObject get(Long key) { 53 | return objectMap.get(key); 54 | } 55 | 56 | @Override 57 | public void add(Long key, CreativeObject value) { 58 | log.info("CreativeIndex before add : {}", objectMap); 59 | objectMap.put(key, value); 60 | log.info("CreativeIndex after add : {}", objectMap); 61 | 62 | } 63 | 64 | @Override 65 | public void update(Long key, CreativeObject value) { 66 | log.info("CreativeIndex before update : {}", objectMap); 67 | 68 | CreativeObject oldObject = objectMap.get(key); 69 | if (null == oldObject) { 70 | objectMap.put(key, value); 71 | } else { 72 | oldObject.update(value); 73 | } 74 | 75 | log.info("CreativeIndex after update : {}", objectMap); 76 | 77 | } 78 | 79 | @Override 80 | public void delete(Long key, CreativeObject value) { 81 | log.info("CreativeIndex after delete : {}", objectMap); 82 | objectMap.remove(key); 83 | log.info("CreativeIndex after delete : {}", objectMap); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/controller/SearchController.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.controller; 2 | 3 | import cn.lucas.ad.annotation.IgnoreResponseAdvice; 4 | import cn.lucas.ad.client.SponsorClient; 5 | import cn.lucas.ad.client.vo.AdPlan; 6 | import cn.lucas.ad.client.vo.AdPlanGetRequest; 7 | import cn.lucas.ad.search.ISearch; 8 | import cn.lucas.ad.search.vo.SearchRequest; 9 | import cn.lucas.ad.search.vo.SearchResponse; 10 | import cn.lucas.ad.vo.CommonResponse; 11 | import com.alibaba.fastjson.JSON; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.web.bind.annotation.PostMapping; 15 | import org.springframework.web.bind.annotation.RequestBody; 16 | import org.springframework.web.bind.annotation.RestController; 17 | import org.springframework.web.client.RestTemplate; 18 | 19 | import java.util.List; 20 | 21 | /** 22 | * @author Administrator 23 | */ 24 | @Slf4j 25 | @RestController 26 | public class SearchController { 27 | 28 | private final ISearch iSearch; 29 | private final SponsorClient sponsorClient; 30 | private final RestTemplate restTemplate; 31 | 32 | @Autowired 33 | public SearchController(RestTemplate restTemplate, SponsorClient sponsorClient, ISearch iSearch) { 34 | this.restTemplate = restTemplate; 35 | this.sponsorClient = sponsorClient; 36 | this.iSearch = iSearch; 37 | } 38 | 39 | /** 40 | * 广告请求外部调用接口 41 | * @param request 42 | * @return 43 | */ 44 | @PostMapping("/fetchAds") 45 | public SearchResponse fetchAds(@RequestBody SearchRequest request) { 46 | log.info("ad-search: fetchAds ->{}", JSON.toJSONString(request)); 47 | return iSearch.fetchAds(request); 48 | } 49 | 50 | @IgnoreResponseAdvice 51 | @PostMapping("/getAdPlans") 52 | public CommonResponse> getAdPlans(@RequestBody AdPlanGetRequest request) { 53 | log.info("ad-search: getAdPlans-{}", JSON.toJSONString(request)); 54 | return sponsorClient.getAdPlans(request); 55 | } 56 | 57 | @SuppressWarnings("all") 58 | @IgnoreResponseAdvice 59 | @PostMapping("/getAdPlansByRebbon") 60 | public CommonResponse> getAdPlansByRebbon(@RequestBody AdPlanGetRequest request) { 61 | log.info("ad-search: getAdPlansByRebbon -> {}", JSON.toJSONString(request)); 62 | return restTemplate.postForEntity( 63 | "http://eureka-client-ad-sponsor/ad-sponsor/get/adPlan", 64 | request, 65 | CommonResponse.class 66 | ).getBody(); 67 | } 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/adunit/AdUnitIndex.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.adunit; 2 | 3 | import cn.lucas.ad.index.IndexAware; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.stereotype.Component; 6 | import org.springframework.util.CollectionUtils; 7 | 8 | import java.util.*; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | 12 | /** 13 | * @Author mcg 14 | * @Date 2019/1/29 15 | *

16 | *

17 | * 正向索引 18 | **/ 19 | @Slf4j 20 | @Component 21 | public class AdUnitIndex implements IndexAware { 22 | 23 | private static Map objectMap; 24 | 25 | static { 26 | objectMap = new ConcurrentHashMap<>(); 27 | } 28 | 29 | public Set match(Integer positionType) { 30 | Set adUnitIds = new HashSet<>(); 31 | objectMap.forEach((k, v) -> { 32 | if (AdUnitObject.isAdSlotTypeOk(positionType, v.getPositionType())) { 33 | adUnitIds.add(k); 34 | } 35 | }); 36 | return adUnitIds; 37 | } 38 | 39 | // 根据 推广单元的 ids 来获取索引对象 40 | public List fetch(Collection adUnitIds) { 41 | if (CollectionUtils.isEmpty(adUnitIds)) { 42 | return Collections.emptyList(); 43 | } 44 | 45 | List result = new ArrayList<>(); 46 | 47 | adUnitIds.forEach(u -> { 48 | AdUnitObject object = get(u); 49 | if (object == null) { 50 | log.error("AdUnitObject not found "); 51 | return; 52 | } 53 | result.add(object); 54 | }); 55 | return result; 56 | } 57 | 58 | @Override 59 | public AdUnitObject get(Long key) { 60 | return objectMap.get(key); 61 | } 62 | 63 | @Override 64 | public void add(Long key, AdUnitObject value) { 65 | log.info("before add : {}", objectMap); 66 | objectMap.put(key, value); 67 | log.info("after add : {}", objectMap); 68 | } 69 | 70 | @Override 71 | public void update(Long key, AdUnitObject value) { 72 | log.info("before update :{}", objectMap); 73 | AdUnitObject oldObject = objectMap.get(key); 74 | if (null == oldObject) { 75 | objectMap.put(key, value); 76 | } else { 77 | oldObject.update(value); 78 | } 79 | log.info("after update : {}", objectMap); 80 | } 81 | 82 | @Override 83 | public void delete(Long key, AdUnitObject value) { 84 | log.info("before delete :{}", objectMap); 85 | objectMap.remove(key); 86 | log.info("after delete: {}", objectMap); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/controller/AdUnitOPController.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.controller; 2 | 3 | import cn.lucas.ad.entity.unit_condition.AdUnitDistrict; 4 | import cn.lucas.ad.exception.AdException; 5 | import cn.lucas.ad.service.IAdUnitService; 6 | import cn.lucas.ad.vo.*; 7 | import com.alibaba.fastjson.JSON; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.web.bind.annotation.PostMapping; 11 | import org.springframework.web.bind.annotation.RequestBody; 12 | import org.springframework.web.bind.annotation.ResponseBody; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * @author Administrator 17 | */ 18 | @Slf4j 19 | @RestController 20 | public class AdUnitOPController { 21 | 22 | private final IAdUnitService unitService; 23 | 24 | @Autowired 25 | public AdUnitOPController(IAdUnitService unitService) { 26 | this.unitService = unitService; 27 | } 28 | 29 | 30 | /** 31 | * 创建 ad_unit 32 | * 33 | * @param request 34 | * @return 35 | * @throws AdException 36 | */ 37 | @PostMapping("/create/AdUnit") 38 | public AdUnitResponse createUnit(@RequestBody AdUnitRequest request) throws AdException { 39 | log.info("ad-sponsor: createUnit -> {}", JSON.toJSONString(request)); 40 | return unitService.createUnit(request); 41 | } 42 | 43 | @PostMapping("/create/unitKeyword") 44 | public AdUnitKeywordResponse createUnitKeyword(@RequestBody AdUnitKeywordRequest request) throws AdException { 45 | log.info("ad-sponsor: createUnitKeyword -> {}", JSON.toJSONString(request)); 46 | return unitService.createUnitKeyword(request); 47 | } 48 | 49 | @PostMapping("/create/unitIt") 50 | public AdUnitItResponse createUnitIt(@RequestBody AdUnitItRequest request) throws AdException { 51 | log.info("ad-sponsor: createUnitIt-> {}", JSON.toJSONString(request)); 52 | return unitService.createUnitIt(request); 53 | } 54 | 55 | @PostMapping("/create/unitDistrict") 56 | public AdUnitDistrictResponse createUnitDistrict(@RequestBody AdUnitDistrictRequest request) throws AdException { 57 | log.info("ad-sponsor: createUnitDistrict -> {}", JSON.toJSONString(request)); 58 | return unitService.createUnitDistrict(request); 59 | } 60 | 61 | 62 | @PostMapping("/create/CreativeUnit") 63 | public CreativeUnitResponse createCreativeUnit(@RequestBody CreativeUnitRequest request) throws AdException { 64 | log.info("ad-sponsor: createCreativeUnit -> {}", JSON.toJSONString(request)); 65 | return unitService.createCreativeUnit(request); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/test/java/cn/lucas/ad/service/AdPlanServiceTest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service; 2 | 3 | import cn.lucas.ad.Application; 4 | import cn.lucas.ad.exception.AdException; 5 | import cn.lucas.ad.vo.AdPlanGetRequest; 6 | import cn.lucas.ad.vo.AdPlanRequest; 7 | import net.bytebuddy.asm.Advice; 8 | import org.junit.Test; 9 | import org.junit.runner.RunWith; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.boot.test.context.SpringBootTest; 12 | import org.springframework.test.context.junit4.SpringRunner; 13 | 14 | import java.util.Collections; 15 | 16 | /** 17 | * @author Administrator 18 | */ 19 | @RunWith(SpringRunner.class) 20 | @SpringBootTest(classes = {Application.class},webEnvironment = SpringBootTest.WebEnvironment.NONE) 21 | public class AdPlanServiceTest { 22 | 23 | 24 | /** 25 | * 提问 14-2 企业级开发中 接口的测试覆盖率如何检测的 手动? 26 | */ 27 | 28 | @Autowired 29 | private IAdPlanService planService; 30 | 31 | /** 32 | * 测试 推广计划 33 | * @throws AdException 34 | */ 35 | @Test 36 | public void testGetAdPlan() throws AdException { 37 | System.out.println(planService.getAdPlanByIds( 38 | new AdPlanGetRequest( 39 | 15L, 40 | Collections.singletonList(10L) 41 | ) 42 | )); 43 | } 44 | 45 | /** 46 | * 创建推广计划 存在问题 入库中文乱码,参数对象id 47 | * @throws AdException 48 | */ 49 | @Test 50 | public void testAddAdPlan() throws AdException { 51 | System.out.println(planService.createAdPlan( 52 | new AdPlanRequest( 53 | null, 54 | 15L, 55 | "推广计划1", 56 | "2019-02-22", 57 | "2019-03-22" 58 | 59 | ) 60 | )); 61 | } 62 | 63 | 64 | /** 65 | * 更新 推广计划测试 66 | * @throws AdException 67 | */ 68 | @Test 69 | public void testUpdateAdPlan() throws AdException { 70 | System.out.println(planService.updateAdPlan( 71 | new AdPlanRequest( 72 | 11L, 73 | 15L, 74 | "1111test", 75 | "2019-02-22", 76 | "2019-05-22" 77 | ) 78 | )); 79 | } 80 | 81 | @Test 82 | public void testDeleteAdPlan() throws AdException { 83 | planService.deleteAdPlan( 84 | new AdPlanRequest( 85 | 11L, 86 | 15L, 87 | null, 88 | null,null 89 | ) 90 | ); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/adunit/AdUnitObject.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.adunit; 2 | 3 | 4 | import cn.lucas.ad.index.adplan.AdPlanObject; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | @Data 10 | @NoArgsConstructor 11 | @AllArgsConstructor 12 | public class AdUnitObject { 13 | 14 | 15 | private Long unitId; 16 | private Integer unitStatus; 17 | private Integer positionType; 18 | private Long planId; 19 | 20 | private AdPlanObject adPlanObject; 21 | 22 | 23 | void update(AdUnitObject newObject) { 24 | if (null != newObject.getUnitId()) { 25 | this.unitId = newObject.getUnitId(); 26 | } 27 | 28 | if (null != newObject.getUnitStatus()) { 29 | this.unitStatus = newObject.getUnitStatus(); 30 | } 31 | 32 | if (null != newObject.getPositionType()) { 33 | this.positionType = newObject.getPositionType(); 34 | } 35 | if (null != newObject.getPlanId()) { 36 | this.planId = newObject.getPlanId(); 37 | } 38 | if (null != newObject.getAdPlanObject()) { 39 | this.adPlanObject = newObject.getAdPlanObject(); 40 | } 41 | } 42 | 43 | 44 | private static boolean isKaiPing(int positionType) { 45 | return (positionType & AdUnitConstants.POSITION_TYPE.KAIPING) > 0; 46 | } 47 | 48 | private static boolean isTiePian(int positionType) { 49 | return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN) > 0; 50 | } 51 | 52 | private static boolean isTiePianMiddle(int positionType) { 53 | return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_MINDLE) > 0; 54 | } 55 | 56 | private static boolean isTiePianPause(int positionType) { 57 | return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_PAUSE) > 0; 58 | } 59 | 60 | private static boolean isTiePianPost(int positionType) { 61 | return (positionType & AdUnitConstants.POSITION_TYPE.TIEPIAN_POST) > 0; 62 | } 63 | 64 | public static boolean isAdSlotTypeOk(int adSlotType, int positionType) { 65 | switch (adSlotType) { 66 | case AdUnitConstants.POSITION_TYPE.KAIPING: 67 | return isKaiPing(positionType); 68 | case AdUnitConstants.POSITION_TYPE.TIEPIAN: 69 | return isTiePian(positionType); 70 | case AdUnitConstants.POSITION_TYPE.TIEPIAN_MINDLE: 71 | return isTiePianMiddle(positionType); 72 | case AdUnitConstants.POSITION_TYPE.TIEPIAN_PAUSE: 73 | return isTiePianPause(positionType); 74 | case AdUnitConstants.POSITION_TYPE.TIEPIAN_POST: 75 | return isTiePianPost(positionType); 76 | default: 77 | return false; 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/listener/IncrementListener.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.listener; 2 | 3 | import cn.lucas.ad.mysql.constant.Constant; 4 | import cn.lucas.ad.mysql.constant.OpType; 5 | import cn.lucas.ad.mysql.dto.BinlogRowData; 6 | import cn.lucas.ad.mysql.dto.MySqlRowData; 7 | import cn.lucas.ad.mysql.dto.TableTemplate; 8 | import cn.lucas.ad.sender.ISender; 9 | import com.github.shyiko.mysql.binlog.event.EventType; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.stereotype.Component; 13 | 14 | import javax.annotation.PostConstruct; 15 | import javax.annotation.Resource; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | /** 21 | * @author Administrator 22 | *

23 | * 增量数据处理器 24 | */ 25 | @Slf4j 26 | @Component 27 | public class IncrementListener implements Ilistener { 28 | 29 | @Resource(name = "indexSender") 30 | private ISender iSender; 31 | private final AggregationListener aggregationListener; 32 | 33 | @Autowired 34 | public IncrementListener(AggregationListener aggregationListener) { 35 | this.aggregationListener = aggregationListener; 36 | } 37 | 38 | /** 39 | * 将表注册 40 | * 这里所有的表都注册同一个 listener IncrementListener 41 | *

42 | * 给各个表注册处理器 发生在 lisrtener 实例化的时候 放在 String 容器时候就应该执行 register 实现注册 43 | */ 44 | @Override 45 | @PostConstruct 46 | public void register() { 47 | log.info("IncrementListener register db and table info"); 48 | Constant.table2Db.forEach((k,v)-> 49 | aggregationListener.register(v,k,this)); 50 | } 51 | 52 | /** 53 | * // 将 BinlogRowData 转换成 MySqlRowData 然后投放出去 54 | * 55 | * @param eventData 56 | */ 57 | @Override 58 | public void onEvent(BinlogRowData eventData) { 59 | TableTemplate table = eventData.getTable(); 60 | EventType eventType = eventData.getType(); 61 | 62 | // 包装成最后需要投递的数据 MySqlRowData 63 | MySqlRowData rowData = new MySqlRowData(); 64 | rowData.setTableName(table.getTableName()); 65 | rowData.setLevel(eventData.getTable().getLevel()); 66 | OpType opType = OpType.to(eventType); 67 | rowData.setOpType(opType); 68 | 69 | // 取出模板中该操作对应的字段列表 70 | List fieldList = table.getOpTypeFieldSetMap().get(opType); 71 | if (null == fieldList) { 72 | log.warn("{} not support for {}", opType, table.getTableName()); 73 | return; 74 | } 75 | 76 | for (Map map : eventData.getAfter()) { 77 | Map afterMap = new HashMap<>(); 78 | for (Map.Entry entry : map.entrySet()) { 79 | String colName = entry.getKey(); 80 | String colValue = entry.getValue(); 81 | afterMap.put(colName, colValue); 82 | } 83 | rowData.getFieldValueMap().add(afterMap); 84 | } 85 | 86 | // 投递 增量数据 87 | iSender.sender(rowData); 88 | 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/interest/UnitItIndex.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.interest; 2 | 3 | import cn.lucas.ad.index.IndexAware; 4 | import cn.lucas.ad.utils.CommonUtils; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.apache.commons.collections4.CollectionUtils; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.io.Serializable; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.Set; 16 | import java.util.concurrent.ConcurrentHashMap; 17 | import java.util.concurrent.ConcurrentSkipListSet; 18 | 19 | /** 20 | * @author Administrator 21 | */ 22 | @Slf4j 23 | @Component 24 | public class UnitItIndex implements IndexAware> { 25 | 26 | // 27 | private static Map> itUnitMap; 28 | 29 | // 30 | private static Map> unitItMap; 31 | 32 | 33 | static { 34 | itUnitMap = new ConcurrentHashMap<>(); 35 | unitItMap = new ConcurrentHashMap<>(); 36 | } 37 | 38 | @Override 39 | public Set get(String key) { 40 | return itUnitMap.get(key); 41 | } 42 | 43 | @Override 44 | public void add(String key, Set value) { 45 | log.info("UnitItIndex, before add :{}", unitItMap); 46 | Set unitIds = CommonUtils.getOrCreate( 47 | key, itUnitMap, 48 | ConcurrentSkipListSet::new 49 | ); 50 | unitIds.addAll(value); 51 | 52 | for (Long unitId : value) { 53 | Set its = CommonUtils.getOrCreate( 54 | unitId, unitItMap, 55 | ConcurrentSkipListSet::new 56 | ); 57 | its.add(key); 58 | } 59 | 60 | log.info("UnitItIndex, after add: {}", unitItMap); 61 | } 62 | 63 | @Override 64 | public void update(String key, Set value) { 65 | log.info("it index can not support update"); 66 | } 67 | 68 | @Override 69 | public void delete(String key, Set value) { 70 | 71 | log.info("UnitItIndex before delete:{}", unitItMap); 72 | Set unitIds = CommonUtils.getOrCreate( 73 | key, itUnitMap, 74 | ConcurrentSkipListSet::new 75 | ); 76 | unitIds.removeAll(value); 77 | 78 | for (Long unitId : value) { 79 | Set itTagSet = CommonUtils.getOrCreate( 80 | unitId, unitItMap, 81 | ConcurrentSkipListSet::new 82 | ); 83 | itTagSet.remove(key); 84 | } 85 | log.info("UnitItIndex after delete:{}", unitItMap); 86 | } 87 | 88 | public boolean match(Long unitId, List itTags) { 89 | if (unitItMap.containsKey(unitId) 90 | && CollectionUtils.isNotEmpty(unitItMap.get(unitId))) { 91 | Set unitKeywords = unitItMap.get(unitId); 92 | return CollectionUtils.isSubCollection(itTags, unitKeywords); 93 | } 94 | 95 | return false; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/resources/template.json: -------------------------------------------------------------------------------- 1 | { 2 | "database": "ad_data", 3 | "tableList": [ 4 | { 5 | "tableName": "ad_plan", 6 | "level": 2, 7 | "insert": [ 8 | {"column": "id"}, 9 | {"column": "user_id"}, 10 | {"column": "plan_status"}, 11 | {"column": "start_date"}, 12 | {"column": "end_date"} 13 | ], 14 | "update": [ 15 | {"column": "id"}, 16 | {"column": "user_id"}, 17 | {"column": "plan_status"}, 18 | {"column": "start_date"}, 19 | {"column": "end_date"} 20 | ], 21 | "delete": [ 22 | {"column": "id"} 23 | ] 24 | }, 25 | { 26 | "tableName": "ad_unit", 27 | "level": 3, 28 | "insert": [ 29 | {"column": "id"}, 30 | {"column": "unit_status"}, 31 | {"column": "position_type"}, 32 | {"column": "plan_id"} 33 | ], 34 | "update": [ 35 | {"column": "id"}, 36 | {"column": "unit_status"}, 37 | {"column": "position_type"}, 38 | {"column": "plan_id"} 39 | ], 40 | "delete": [ 41 | {"column": "id"} 42 | ] 43 | }, 44 | { 45 | "tableName": "ad_creative", 46 | "level": 2, 47 | "insert": [ 48 | {"column": "id"}, 49 | {"column": "type"}, 50 | {"column": "material_type"}, 51 | {"column": "height"}, 52 | {"column": "width"}, 53 | {"column": "audit_status"}, 54 | {"column": "url"} 55 | ], 56 | "update": [ 57 | {"column": "id"}, 58 | {"column": "type"}, 59 | {"column": "material_type"}, 60 | {"column": "height"}, 61 | {"column": "width"}, 62 | {"column": "audit_status"}, 63 | {"column": "url"} 64 | ], 65 | "delete": [ 66 | {"column": "id"} 67 | ] 68 | }, 69 | { 70 | "tableName": "creative_unit", 71 | "level": 3, 72 | "insert": [ 73 | {"column": "creative_id"}, 74 | {"column": "unit_id"} 75 | ], 76 | "update": [ 77 | ], 78 | "delete": [ 79 | {"column": "creative_id"}, 80 | {"column": "unit_id"} 81 | ] 82 | }, 83 | { 84 | "tableName": "ad_unit_district", 85 | "level": 4, 86 | "insert": [ 87 | {"column": "unit_id"}, 88 | {"column": "province"}, 89 | {"column": "city"} 90 | ], 91 | "update": [ 92 | ], 93 | "delete": [ 94 | {"column": "unit_id"}, 95 | {"column": "province"}, 96 | {"column": "city"} 97 | ] 98 | }, 99 | { 100 | "tableName": "ad_unit_it", 101 | "level": 4, 102 | "insert": [ 103 | {"column": "unit_id"}, 104 | {"column": "it_tag"} 105 | ], 106 | "update": [ 107 | ], 108 | "delete": [ 109 | {"column": "unit_id"}, 110 | {"column": "it_tag"} 111 | ] 112 | }, 113 | { 114 | "tableName": "ad_unit_keyword", 115 | "level": 4, 116 | "insert": [ 117 | {"column": "unit_id"}, 118 | {"column": "keyword"} 119 | ], 120 | "update": [ 121 | ], 122 | "delete": [ 123 | {"column": "unit_id"}, 124 | {"column": "keyword"} 125 | ] 126 | } 127 | ] 128 | } -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/TemplateHolder.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql; 2 | 3 | import cn.lucas.ad.mysql.constant.OpType; 4 | import cn.lucas.ad.mysql.dto.ParseTemplate; 5 | import cn.lucas.ad.mysql.dto.TableTemplate; 6 | import cn.lucas.ad.mysql.dto.Template; 7 | import com.alibaba.fastjson.JSON; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.jdbc.core.JdbcTemplate; 11 | import org.springframework.stereotype.Component; 12 | 13 | import javax.annotation.PostConstruct; 14 | import java.io.IOException; 15 | import java.io.InputStream; 16 | import java.nio.charset.Charset; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | /** 21 | * @Author mcg 22 | * @Date 2019/2/18 21:40 23 | **/ 24 | 25 | @Slf4j 26 | @Component 27 | public class TemplateHolder { 28 | 29 | private ParseTemplate template; 30 | private final JdbcTemplate jdbcTemplate; 31 | 32 | private String SQL_SCHEMA = "SELECT table_schema,table_name, column_name,ordinal_position from " + 33 | "information_schema.COLUMNS WHERE table_schema = ? and table_name = ?"; 34 | 35 | @Autowired 36 | public TemplateHolder(JdbcTemplate jdbcTemplate) { 37 | this.jdbcTemplate = jdbcTemplate; 38 | } 39 | 40 | 41 | @PostConstruct 42 | private void init() { 43 | loadJson("template.json"); 44 | } 45 | 46 | // 对外服务的 解析 binlog 【对表的解析】 47 | public TableTemplate getTable(String tableName) { 48 | return template.getTableTemplateMap().get(tableName); 49 | } 50 | 51 | private void loadJson(String path) { 52 | ClassLoader cl = Thread.currentThread().getContextClassLoader(); 53 | InputStream is = cl.getResourceAsStream(path); 54 | try { 55 | 56 | Template template = JSON.parseObject(is, Charset.defaultCharset(), Template.class); 57 | this.template = ParseTemplate.pase(template); 58 | loadMeta(); 59 | } catch (IOException ex) { 60 | log.error(ex.getMessage()); 61 | throw new RuntimeException("fail to parse json file"); 62 | } 63 | } 64 | 65 | private void loadMeta() { 66 | for (Map.Entry entry: template.getTableTemplateMap().entrySet()) { 67 | TableTemplate table = entry.getValue(); 68 | 69 | List updateFields = table.getOpTypeFieldSetMap().get( 70 | OpType.UPDATE 71 | ); 72 | List insertFields = table.getOpTypeFieldSetMap().get( 73 | OpType.ADD 74 | ); 75 | List deleteFields = table.getOpTypeFieldSetMap().get( 76 | OpType.DELETE 77 | ); 78 | 79 | jdbcTemplate.query(SQL_SCHEMA,new Object[]{ 80 | template.getDatabase(),table.getTableName() 81 | },(rs,i)->{ 82 | int pos = rs.getInt("ORDINAL_POSITION"); 83 | String colName = rs.getString("COLUMN_NAME"); 84 | 85 | if ((null != updateFields && updateFields.contains(colName)) 86 | || (null!=insertFields && insertFields.contains(colName)) 87 | || (null!=deleteFields && deleteFields.contains(colName))) { 88 | 89 | table.getPosMap().put(pos - 1,colName); 90 | } 91 | return null; 92 | }); 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/district/UnitDistrictIndex.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.district; 2 | 3 | import cn.lucas.ad.index.IndexAware; 4 | import cn.lucas.ad.search.vo.feature.DistrictFeature; 5 | import cn.lucas.ad.utils.CommonUtils; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.commons.collections4.CollectionUtils; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | import java.util.concurrent.ConcurrentHashMap; 14 | import java.util.concurrent.ConcurrentSkipListSet; 15 | import java.util.stream.Collectors; 16 | 17 | /** 18 | * @author Administrator 19 | */ 20 | @Slf4j 21 | @Component 22 | public class UnitDistrictIndex implements IndexAware> { 23 | 24 | private static Map> districtUnitMap; 25 | private static Map> unitDistrictMap; 26 | 27 | static { 28 | districtUnitMap = new ConcurrentHashMap<>(); 29 | unitDistrictMap = new ConcurrentHashMap<>(); 30 | } 31 | 32 | @Override 33 | public Set get(String key) { 34 | // key 是 province-city 连接起来的 key 35 | return districtUnitMap.get(key); 36 | } 37 | 38 | @Override 39 | public void add(String key, Set value) { 40 | log.info("UnitDistrictIndex before add :{}", unitDistrictMap); 41 | Set unitIds = CommonUtils.getOrCreate( 42 | key, districtUnitMap, 43 | ConcurrentSkipListSet::new 44 | ); 45 | unitIds.addAll(value); 46 | 47 | for (Long unitId : value) { 48 | Set districts = CommonUtils.getOrCreate( 49 | unitId, unitDistrictMap, 50 | ConcurrentSkipListSet::new 51 | ); 52 | districts.add(key); 53 | } 54 | 55 | log.info("UnitDistrictIndex after :{}", unitDistrictMap); 56 | } 57 | 58 | @Override 59 | public void update(String key, Set value) { 60 | log.error("UnitDistrictIndex can not support update"); 61 | } 62 | 63 | @Override 64 | public void delete(String key, Set value) { 65 | log.info("UnitDistrictIndex before delete :{}", unitDistrictMap); 66 | Set unitIds = CommonUtils.getOrCreate( 67 | key, districtUnitMap, 68 | ConcurrentSkipListSet::new 69 | ); 70 | unitIds.removeAll(value); 71 | 72 | for (Long unitId : value) { 73 | Set districts = CommonUtils.getOrCreate( 74 | unitId, unitDistrictMap, 75 | ConcurrentSkipListSet::new 76 | ); 77 | districts.remove(key); 78 | } 79 | log.info("UnitDistrictIndex after delete :{}", unitDistrictMap); 80 | 81 | } 82 | 83 | public boolean match(Long adUnitId, List districts) { 84 | if (unitDistrictMap.containsKey(adUnitId) && 85 | CollectionUtils.isNotEmpty(unitDistrictMap.get(adUnitId))) { 86 | Set unitDistricts = unitDistrictMap.get(adUnitId); 87 | 88 | List targetDistricts = districts.stream() 89 | .map( 90 | d -> CommonUtils.stringConcat(d.getProvince(), d.getCity()) 91 | ).collect(Collectors.toList()); 92 | //TODO 93 | return CollectionUtils.isSubCollection(targetDistricts, unitDistricts); 94 | } 95 | return false; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/keyword/UnitKeywordIndex.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.keyword; 2 | 3 | import cn.lucas.ad.index.IndexAware; 4 | import cn.lucas.ad.utils.CommonUtils; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.collections4.CollectionUtils; 7 | import org.apache.commons.lang.StringUtils; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Set; 14 | import java.util.concurrent.ConcurrentHashMap; 15 | import java.util.concurrent.ConcurrentSkipListSet; 16 | 17 | /** 18 | * @Author mcg 19 | * @Date 2019/1/29 21:20 20 | *

21 | * 推广单元的限制 使用倒排索引 22 | * 以关键词的形式寻找索引的ID 23 | **/ 24 | @Slf4j 25 | @Component 26 | public class UnitKeywordIndex implements IndexAware> { 27 | 28 | private static Map> keywordUnitMap; 29 | private static Map> unitKeywordMap; 30 | 31 | static { 32 | keywordUnitMap = new ConcurrentHashMap<>(); 33 | unitKeywordMap = new ConcurrentHashMap<>(); 34 | } 35 | 36 | @Override 37 | 38 | public Set get(String key) { 39 | if (StringUtils.isEmpty(key)) { 40 | return Collections.emptySet(); 41 | } 42 | 43 | Set result = keywordUnitMap.get(key); 44 | if (result == null) { 45 | return Collections.emptySet(); 46 | } 47 | return result; 48 | } 49 | 50 | @Override 51 | public void add(String key, Set value) { 52 | log.info("UnitKeywordIndex before add :{}", unitKeywordMap); 53 | 54 | Set unitIdSet = CommonUtils.getOrCreate(key, keywordUnitMap, 55 | ConcurrentSkipListSet::new 56 | ); 57 | unitIdSet.addAll(value); 58 | 59 | for (Long unitId : value) { 60 | Set keywordSet = CommonUtils.getOrCreate(unitId, unitKeywordMap, 61 | ConcurrentSkipListSet::new); 62 | keywordSet.add(key); 63 | } 64 | log.info("UnitKeywordIndex after add: {}", unitKeywordMap); 65 | } 66 | 67 | @Override 68 | public void update(String key, Set value) { 69 | log.error("keyword index can not support update"); 70 | } 71 | 72 | @Override 73 | public void delete(String key, Set value) { 74 | log.info("UnitKeywordIndex before delete :{}", unitKeywordMap); 75 | 76 | Set unitIds = CommonUtils.getOrCreate( 77 | key, keywordUnitMap, ConcurrentSkipListSet::new 78 | ); 79 | unitIds.removeAll(value); 80 | 81 | for (Long unitId : value) { 82 | 83 | Set keywordSet = CommonUtils.getOrCreate( 84 | unitId, unitKeywordMap, ConcurrentSkipListSet::new 85 | ); 86 | keywordSet.remove(key); 87 | } 88 | 89 | log.info("UnitKeywordIndex after delete :{}", unitKeywordMap); 90 | 91 | } 92 | 93 | 94 | public boolean match(Long unitId, List keywords) { 95 | if (unitKeywordMap.containsKey(unitId) && CollectionUtils.isNotEmpty(unitKeywordMap.get(unitId))) { 96 | 97 | Set unitKeywords = unitKeywordMap.get(unitId); 98 | 99 | // 是否是子集判断 param1 是 param2 的子集时 才为 true 100 | return CollectionUtils.isSubCollection(keywords, unitKeywords); 101 | } 102 | 103 | return false; 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/constant/Constant.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.constant; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author Administrator 8 | */ 9 | public class Constant { 10 | 11 | private static final String DB_NAME = "ad_data"; 12 | 13 | public static class AD_PALN_TABLE_INFO { 14 | public static final String TABLE_NAME = "ad_plan"; 15 | 16 | public static final String COLUMN_ID = "id"; 17 | public static final String COLUMN_USER_ID = "user_id"; 18 | public static final String COLUMN_STATUS = "plan_status"; 19 | public static final String COLUMN_START_DATE = "start_date"; 20 | public static final String COLUMN_END_DATE = "end_date"; 21 | } 22 | 23 | public static class AD_CREATIVE_TABLE_INFO { 24 | public static final String TABLE_NAME = "ad_creative"; 25 | 26 | public static final String COLUMN_ID = "id"; 27 | public static final String COLUMN_TYPE = "type"; 28 | public static final String COLUMN_METERIAL_TYPE = "material_type"; 29 | public static final String COLUMN_HEIGHT = "height"; 30 | public static final String COLUMN_WIDTH = "width"; 31 | public static final String COLUMN_AUDIT_STATUS = "audit_status"; 32 | public static final String COLUMN_URL = "url"; 33 | } 34 | 35 | public static class AD_UNIT_TABLE_INFO { 36 | public static final String TABLE_NAME = "ad_unit"; 37 | 38 | public static final String COLUMN_ID = "id"; 39 | public static final String COLUMN_UNIT_STATUS = "unit_status"; 40 | public static final String COLUMN_POSITION_TYPE = "position_type"; 41 | public static final String COLUMN_PLAN_ID = "plan_id"; 42 | } 43 | 44 | public static class AD_CREATIVE_UNIT_TABLE_INFO { 45 | public static final String TABLE_NAME = "creative_unit"; 46 | public static final String COLUMN_CREATIVE_ID = "creative_id"; 47 | public static final String COLUMN_UNIT_ID = "unit_id"; 48 | } 49 | 50 | public static class AD_UNIT_DISTRICT_TABLE_INFO { 51 | public static final String TABLE_NAME = "ad_unit_district"; 52 | 53 | public static final String COLUMN_UNIT_ID = "unit_id"; 54 | public static final String COLUMN_PROVINCE = "province"; 55 | public static final String COLUMN_CITY = "city"; 56 | } 57 | 58 | 59 | public static class AD_UNIT_IT_TABLE_INFO { 60 | public static final String TABLE_NAME = "ad_unit_it"; 61 | 62 | public static final String COLUMN_UNIT_ID = "unit_id"; 63 | public static final String COLUMN_IT_TAG = "it_tag"; 64 | } 65 | 66 | public static class AD_UNIT_KEYWORD_TABLE_INFO { 67 | public static final String TABLE_NAME = "ad_unit_keyword"; 68 | 69 | public static final String COLUMN_UNIT_ID = "unit_id"; 70 | public static final String COLUMN_KEYWORD = "keyword"; 71 | } 72 | 73 | 74 | public static Map table2Db; 75 | static{ 76 | table2Db = new HashMap<>(); 77 | table2Db.put(AD_PALN_TABLE_INFO.TABLE_NAME, DB_NAME); 78 | table2Db.put(AD_CREATIVE_TABLE_INFO.TABLE_NAME, DB_NAME); 79 | table2Db.put(AD_UNIT_TABLE_INFO.TABLE_NAME, DB_NAME); 80 | table2Db.put(AD_CREATIVE_UNIT_TABLE_INFO.TABLE_NAME, DB_NAME); 81 | table2Db.put(AD_UNIT_DISTRICT_TABLE_INFO.TABLE_NAME, DB_NAME); 82 | table2Db.put(AD_UNIT_IT_TABLE_INFO.TABLE_NAME, DB_NAME); 83 | table2Db.put(AD_UNIT_KEYWORD_TABLE_INFO.TABLE_NAME, DB_NAME); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/creativeunit/CreativeUnitIndex.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index.creativeunit; 2 | 3 | import cn.lucas.ad.index.IndexAware; 4 | import cn.lucas.ad.index.adunit.AdUnitObject; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.collections4.CollectionUtils; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.*; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | import java.util.concurrent.ConcurrentSkipListSet; 12 | 13 | /** 14 | * @Author mcg 15 | * @Date 2019/2/14 19:48 16 | **/ 17 | @Slf4j 18 | @Component 19 | public class CreativeUnitIndex implements IndexAware { 20 | 21 | // key 22 | private static Map objectMap; 23 | // 创意和推广单元是多对多的关系 24 | private static Map> creativeUnitMap; 25 | 26 | // 27 | private static Map> unitCreativeMap; 28 | 29 | static { 30 | objectMap = new ConcurrentHashMap<>(); 31 | creativeUnitMap = new ConcurrentHashMap<>(); 32 | unitCreativeMap = new ConcurrentHashMap<>(); 33 | } 34 | 35 | @Override 36 | public CreativeUnitObject get(String key) { 37 | return objectMap.get(key); 38 | } 39 | 40 | @Override 41 | public void add(String key, CreativeUnitObject value) { 42 | log.info("CreativeUnitIndex before add : {}", objectMap); 43 | objectMap.put(key, value); 44 | Set unitSet = creativeUnitMap.get(value.getAdId()); 45 | if (CollectionUtils.isEmpty(unitSet)) { 46 | unitSet = new ConcurrentSkipListSet<>(); 47 | creativeUnitMap.put(value.getAdId(), unitSet); 48 | } 49 | 50 | unitSet.add(value.getUnitId()); 51 | 52 | Set creativeSet = unitCreativeMap.get(value.getUnitId()); 53 | if (CollectionUtils.isEmpty(creativeSet)) { 54 | creativeSet = new ConcurrentSkipListSet<>(); 55 | unitCreativeMap.put(value.getUnitId(), creativeSet); 56 | } 57 | creativeSet.add(value.getUnitId()); 58 | 59 | log.info("CreativeUnitIndex after add : {}", objectMap); 60 | } 61 | 62 | @Override 63 | public void update(String key, CreativeUnitObject value) { 64 | log.info("CreativeUnitIndex can not support update"); 65 | } 66 | 67 | @Override 68 | public void delete(String key, CreativeUnitObject value) { 69 | 70 | log.info("CreativeUnitIndex before delete :{}", objectMap); 71 | objectMap.remove(key); 72 | 73 | Set unitSet = creativeUnitMap.get(value.getAdId()); 74 | if (CollectionUtils.isNotEmpty(unitSet)) { 75 | unitSet.remove(value.getUnitId()); 76 | } 77 | 78 | Set creativeSet = unitCreativeMap.get(value.getUnitId()); 79 | if (CollectionUtils.isNotEmpty(creativeSet)) { 80 | creativeSet.remove(value.getAdId()); 81 | } 82 | log.info("CreativeUnitIndex after delete :{}", objectMap); 83 | } 84 | 85 | /** 86 | * 11-6 4:00 说明 87 | * @param unitObjects 88 | * @return 89 | */ 90 | public List selectAds(List unitObjects) { 91 | if (CollectionUtils.isEmpty(unitObjects)) { 92 | return Collections.emptyList(); 93 | } 94 | List result = new ArrayList<>(); 95 | for (AdUnitObject unitObject : unitObjects) { 96 | 97 | Set adIds = unitCreativeMap.get(unitObject.getUnitId()); 98 | if (CollectionUtils.isNotEmpty(adIds)) { 99 | result.addAll(adIds); 100 | } 101 | } 102 | return result; 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lucas-ad-service 7 | cn.lucas.ad 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | 13 | ad-sponsor 14 | 1.0-SNAPSHOT 15 | jar 16 | 17 | 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-web 22 | 23 | 27 | 28 | org.springframework.cloud 29 | spring-cloud-starter-netflix-eureka-client 30 | 31 | 32 | 33 | org.springframework.cloud 34 | spring-cloud-starter-openfeign 35 | 36 | 37 | 38 | org.springframework.cloud 39 | spring-cloud-starter-netflix-hystrix 40 | 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-netflix-ribbon 45 | 46 | 47 | 48 | org.springframework.boot 49 | spring-boot-starter-data-jpa 50 | 51 | 52 | 53 | org.springframework.boot 54 | spring-boot-starter-jdbc 55 | 56 | 57 | 58 | mysql 59 | mysql-connector-java 60 | 5.1.47 61 | runtime 62 | 63 | 64 | 65 | cn.lucas.ad 66 | ad-common 67 | 1.0-SNAPSHOT 68 | 69 | 70 | 71 | commons-codec 72 | commons-codec 73 | 1.9 74 | 75 | 76 | 77 | 81 | 82 | 83 | 84 | org.springframework.boot 85 | spring-boot-maven-plugin 86 | 87 | 88 | org.apache.maven.plugins 89 | maven-compiler-plugin 90 | 91 | 1.8 92 | 1.8 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/index/IndexFileLoader.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.index; 2 | 3 | import cn.lucas.ad.dump.DConstant; 4 | import cn.lucas.ad.dump.table.*; 5 | import cn.lucas.ad.handler.AdLevelDataHandler; 6 | import cn.lucas.ad.mysql.constant.OpType; 7 | import com.alibaba.fastjson.JSON; 8 | import org.springframework.context.annotation.DependsOn; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.annotation.PostConstruct; 12 | import java.io.BufferedReader; 13 | import java.io.IOException; 14 | import java.nio.file.Files; 15 | import java.nio.file.Paths; 16 | import java.util.List; 17 | import java.util.stream.Collectors; 18 | 19 | /** 20 | * @Author mcg 21 | * @Date 2019/2/16 14:57 22 | **/ 23 | 24 | @Component 25 | @DependsOn("dataTable") 26 | public class IndexFileLoader { 27 | 28 | @PostConstruct 29 | public void init() { 30 | 31 | List adPlanStrings = loadDumpData( 32 | String.format("%s%s", 33 | DConstant.DATA_ROOT_DIR, 34 | DConstant.AD_PLAN) 35 | ); 36 | adPlanStrings.forEach(p -> AdLevelDataHandler.handleLevel2( 37 | JSON.parseObject(p, AdPlanTable.class), 38 | OpType.ADD 39 | )); 40 | 41 | List adCreativeStrings = loadDumpData( 42 | String.format("%s%s", 43 | DConstant.DATA_ROOT_DIR, 44 | DConstant.AD_CREATIVE) 45 | ); 46 | adCreativeStrings.forEach(c -> AdLevelDataHandler.handleLevel2( 47 | JSON.parseObject(c, AdCreativeTable.class), 48 | OpType.ADD 49 | )); 50 | 51 | List adUnitStrings = loadDumpData( 52 | String.format("%s%s", 53 | DConstant.DATA_ROOT_DIR, 54 | DConstant.AD_UNIT) 55 | ); 56 | adUnitStrings.forEach(u -> AdLevelDataHandler.handleLevel3( 57 | JSON.parseObject(u, AdUnitTable.class), 58 | OpType.ADD 59 | )); 60 | 61 | List adCreativeUnitStrings = loadDumpData( 62 | String.format("%s%s", 63 | DConstant.DATA_ROOT_DIR, 64 | DConstant.AD_CREATIVE_UNIT) 65 | ); 66 | adCreativeUnitStrings.forEach(cu -> AdLevelDataHandler.handleLevel3( 67 | JSON.parseObject(cu, AdCreativeUnitTable.class), 68 | OpType.ADD 69 | )); 70 | 71 | List adUnitDistrictStrings = loadDumpData( 72 | String.format("%s%s", 73 | DConstant.DATA_ROOT_DIR, 74 | DConstant.AD_UNIT_DISTRICT) 75 | ); 76 | adUnitDistrictStrings.forEach(d -> AdLevelDataHandler.handleLevel4( 77 | JSON.parseObject(d, AdUnitDistrictTable.class), 78 | OpType.ADD 79 | )); 80 | 81 | List adUnitItStrings = loadDumpData( 82 | String.format("%s%s", 83 | DConstant.DATA_ROOT_DIR, 84 | DConstant.AD_UNIT_IT) 85 | ); 86 | adUnitItStrings.forEach(i -> AdLevelDataHandler.handleLevel4( 87 | JSON.parseObject(i, AdUnitItTable.class), 88 | OpType.ADD 89 | )); 90 | 91 | List adUnitKeywordStrings = loadDumpData( 92 | String.format("%s%s", 93 | DConstant.DATA_ROOT_DIR, 94 | DConstant.AD_UNIT_KEYWORD) 95 | ); 96 | adUnitKeywordStrings.forEach(k -> AdLevelDataHandler.handleLevel4( 97 | JSON.parseObject(k, AdUnitKeywordTable.class), 98 | OpType.ADD 99 | )); 100 | } 101 | 102 | private List loadDumpData(String fileName) { 103 | 104 | try (BufferedReader br = Files.newBufferedReader( 105 | Paths.get(fileName) 106 | )) { 107 | return br.lines().collect(Collectors.toList()); 108 | } catch (IOException ex) { 109 | throw new RuntimeException(ex.getMessage()); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/test/java/cn/lucas/ad/search/SearchTest.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.search; 2 | 3 | import cn.lucas.ad.Application; 4 | import cn.lucas.ad.search.vo.SearchRequest; 5 | import cn.lucas.ad.search.vo.feature.DistrictFeature; 6 | import cn.lucas.ad.search.vo.feature.FeatureRelation; 7 | import cn.lucas.ad.search.vo.feature.ItFeature; 8 | import cn.lucas.ad.search.vo.feature.KeywordFeature; 9 | import cn.lucas.ad.search.vo.media.AdSlot; 10 | import cn.lucas.ad.search.vo.media.App; 11 | import cn.lucas.ad.search.vo.media.Device; 12 | import cn.lucas.ad.search.vo.media.Geo; 13 | import com.alibaba.fastjson.JSON; 14 | import org.junit.Test; 15 | import org.junit.runner.RunWith; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.boot.test.context.SpringBootTest; 18 | import org.springframework.test.context.junit4.SpringRunner; 19 | 20 | import java.util.Arrays; 21 | import java.util.Collection; 22 | import java.util.Collections; 23 | import java.util.List; 24 | 25 | /** 26 | * @author Administrator 27 | */ 28 | @RunWith(SpringRunner.class) 29 | @SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.NONE) 30 | public class SearchTest { 31 | 32 | @Autowired 33 | private ISearch iSearch; 34 | 35 | @Test 36 | public void testFetchAds() { 37 | SearchRequest request = new SearchRequest(); 38 | request.setMediaId("imooc-ad"); 39 | 40 | // 第一个测试条件 41 | request.setRequestInfo(new SearchRequest.RequestInfo( 42 | "aaaa", Collections.singletonList( 43 | new AdSlot( 44 | "ad-x", 1, 1080, 720, Arrays.asList(1, 2), 45 | 1000 46 | )), 47 | buildExampleApp(), 48 | buildExampleGeo(), 49 | buildExampleDevice() 50 | )); 51 | 52 | request.setFeatureInfo(buildExampleFeatureInfo( 53 | Arrays.asList("宝马", "大众"), 54 | Collections.singletonList( 55 | new DistrictFeature.ProvinceAndCity( 56 | "安徽省", "合肥市" 57 | )), 58 | Arrays.asList("台球", "游泳"), 59 | FeatureRelation.OR 60 | )); 61 | 62 | System.out.println(JSON.toJSONString(request)); 63 | System.out.println(JSON.toJSONString(iSearch.fetchAds(request))); 64 | 65 | 66 | 67 | 68 | // 第二个测试条件 69 | request.setRequestInfo(new SearchRequest.RequestInfo( 70 | "aaaa", Collections.singletonList( 71 | new AdSlot( 72 | "ad-y", 1, 1080, 720, Arrays.asList(1, 2), 73 | 1000 74 | )), 75 | buildExampleApp(), 76 | buildExampleGeo(), 77 | buildExampleDevice() 78 | )); 79 | 80 | request.setFeatureInfo(buildExampleFeatureInfo( 81 | Arrays.asList("宝马", "大众","标志"), 82 | Collections.singletonList( 83 | new DistrictFeature.ProvinceAndCity( 84 | "安徽省", "合肥市" 85 | )), 86 | Arrays.asList("台球", "游泳"), 87 | FeatureRelation.AND 88 | )); 89 | 90 | System.out.println(JSON.toJSONString(request)); 91 | System.out.println(JSON.toJSONString(iSearch.fetchAds(request))); 92 | 93 | } 94 | 95 | /** 96 | * 97 | */ 98 | private App buildExampleApp() { 99 | return new App("imooc", "imooc", "com.imooc", "video"); 100 | } 101 | 102 | private Geo buildExampleGeo() { 103 | return new Geo((float) 100.23, (float) 88.23, "北京市", "北京市"); 104 | } 105 | 106 | private Device buildExampleDevice() { 107 | return new Device("iphone", "0xcfvxdf", "127.0.0.1", "x", "1920 1080", 108 | "1080,720", "1231223213"); 109 | } 110 | 111 | private SearchRequest.FeatureInfo buildExampleFeatureInfo( 112 | List keywords, 113 | List provinceAndCities, 114 | List its, 115 | FeatureRelation featureRelation 116 | ) { 117 | 118 | return new SearchRequest.FeatureInfo( 119 | new KeywordFeature(keywords), 120 | new DistrictFeature(provinceAndCities), 121 | new ItFeature(its), 122 | featureRelation 123 | ); 124 | } 125 | 126 | } 127 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/impl/AdPlanService.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service.impl; 2 | 3 | import cn.lucas.ad.constant.CommonStatus; 4 | import cn.lucas.ad.constant.Constants; 5 | import cn.lucas.ad.dao.AdPlanRepository; 6 | import cn.lucas.ad.dao.AdUserRepository; 7 | import cn.lucas.ad.entity.AdPlan; 8 | import cn.lucas.ad.entity.AdUser; 9 | import cn.lucas.ad.exception.AdException; 10 | import cn.lucas.ad.service.IAdPlanService; 11 | import cn.lucas.ad.utils.CommonUtils; 12 | import cn.lucas.ad.vo.AdPlanGetRequest; 13 | import cn.lucas.ad.vo.AdPlanRequest; 14 | import cn.lucas.ad.vo.AdPlanResponse; 15 | import lombok.extern.slf4j.Slf4j; 16 | import org.springframework.beans.factory.annotation.Autowired; 17 | import org.springframework.stereotype.Service; 18 | import org.springframework.transaction.annotation.Transactional; 19 | 20 | import java.util.Date; 21 | import java.util.List; 22 | import java.util.Optional; 23 | 24 | @Slf4j 25 | @Service 26 | public class AdPlanService implements IAdPlanService { 27 | 28 | private final AdUserRepository userRepository; 29 | 30 | private final AdPlanRepository planRepository; 31 | 32 | @Autowired 33 | public AdPlanService(AdUserRepository userRepository, AdPlanRepository planRepository) { 34 | this.userRepository = userRepository; 35 | this.planRepository = planRepository; 36 | } 37 | 38 | @Override 39 | public AdPlanResponse createAdPlan(AdPlanRequest request) throws AdException { 40 | if (!request.createValidate()) { 41 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 42 | } 43 | 44 | // 确保关联的 user 是存在的 45 | Optional adUser = userRepository.findById(request.getUserId()); 46 | if (!adUser.isPresent()) { 47 | throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD); 48 | } 49 | 50 | AdPlan oldPlan = planRepository.findByUserIdAndPlanName(request.getUserId(), request.getPlanName()); 51 | if (oldPlan != null) { 52 | throw new AdException(Constants.ErrorMsg.SAME_NAME_PLAN_ERROR); 53 | } 54 | 55 | AdPlan newPlan = planRepository.save( 56 | new AdPlan( 57 | request.getUserId(), 58 | request.getPlanName(), 59 | CommonUtils.parseStringDate(request.getStartDate()), 60 | CommonUtils.parseStringDate(request.getEndDate()) 61 | ) 62 | ); 63 | return new AdPlanResponse(newPlan.getId(), newPlan.getPlanName()); 64 | } 65 | 66 | @Override 67 | public List getAdPlanByIds(AdPlanGetRequest request) throws AdException { 68 | if (!request.validate()) { 69 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 70 | } 71 | 72 | return planRepository.findAllByIdInAndUserId(request.getIds(), request.getUserId()); 73 | } 74 | 75 | @Override 76 | @Transactional 77 | public AdPlanResponse updateAdPlan(AdPlanRequest request) throws AdException { 78 | if (!request.updateValidate()) { 79 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 80 | } 81 | AdPlan plan = planRepository.findByIdAndUserId(request.getId(), request.getUserId()); 82 | if (plan == null) { 83 | throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD); 84 | } 85 | 86 | if (request.getPlanName() != null) { 87 | plan.setPlanName(request.getPlanName()); 88 | } 89 | 90 | if (request.getStartDate() != null) { 91 | plan.setStartDate(CommonUtils.parseStringDate(request.getStartDate())); 92 | } 93 | 94 | if (request.getEndDate() != null) { 95 | plan.setEndDate(CommonUtils.parseStringDate(request.getEndDate())); 96 | } 97 | 98 | plan.setUpdateTime(new Date()); 99 | 100 | plan = planRepository.save(plan); 101 | return new AdPlanResponse(plan.getId(),plan.getPlanName()); 102 | } 103 | 104 | @Override 105 | @Transactional 106 | public void deleteAdPlan(AdPlanRequest request) throws AdException { 107 | if (!request.deleteValidate()) { 108 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 109 | } 110 | AdPlan plan = planRepository.findByIdAndUserId(request.getId(), request.getUserId()); 111 | if (plan == null) { 112 | throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD); 113 | } 114 | plan.setPlanStatus(CommonStatus.INVALID.getStatus()); 115 | plan.setUpdateTime(new Date()); 116 | planRepository.save(plan); 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | lucas-ad-service 7 | cn.lucas.ad 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | 13 | ad-search 14 | 1.0-SNAPSHOT 15 | jar 16 | 17 | 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-netflix-hystrix-dashboard 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-actuator 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-starter-web 32 | 33 | 37 | 38 | org.springframework.cloud 39 | spring-cloud-starter-netflix-eureka-client 40 | 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-starter-openfeign 45 | 46 | 47 | 48 | org.springframework.cloud 49 | spring-cloud-starter-netflix-hystrix 50 | 51 | 52 | 53 | org.springframework.cloud 54 | spring-cloud-starter-netflix-ribbon 55 | 56 | 57 | 58 | org.springframework.boot 59 | spring-boot-starter-data-jpa 60 | 61 | 62 | 63 | org.springframework.boot 64 | spring-boot-starter-jdbc 65 | 66 | 67 | 68 | mysql 69 | mysql-connector-java 70 | 5.1.47 71 | runtime 72 | 73 | 74 | 75 | cn.lucas.ad 76 | ad-common 77 | 1.0-SNAPSHOT 78 | 79 | 80 | 81 | commons-codec 82 | commons-codec 83 | 1.9 84 | 85 | 86 | 87 | org.apache.commons 88 | commons-collections4 89 | 4.0 90 | 91 | 92 | 93 | com.github.shyiko 94 | mysql-binlog-connector-java 95 | 0.13.0 96 | 97 | 98 | 99 | org.springframework.boot 100 | spring-boot-configuration-processor 101 | 102 | 103 | 104 | org.springframework.kafka 105 | spring-kafka 106 | 2.1.5.RELEASE 107 | 108 | 109 | 110 | 114 | 115 | 116 | 117 | org.springframework.boot 118 | spring-boot-maven-plugin 119 | 120 | 121 | org.apache.maven.plugins 122 | maven-compiler-plugin 123 | 124 | 1.8 125 | 1.8 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/mysql/listener/AggregationListener.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.mysql.listener; 2 | 3 | import cn.lucas.ad.mysql.TemplateHolder; 4 | import cn.lucas.ad.mysql.dto.BinlogRowData; 5 | import cn.lucas.ad.mysql.dto.TableTemplate; 6 | import com.github.shyiko.mysql.binlog.BinaryLogClient; 7 | import com.github.shyiko.mysql.binlog.event.*; 8 | import lombok.extern.slf4j.Slf4j; 9 | import org.apache.commons.lang.StringUtils; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.util.CollectionUtils; 13 | 14 | import java.io.Serializable; 15 | import java.util.*; 16 | import java.util.stream.Collectors; 17 | 18 | /** 19 | * @author Administrator 20 | *

21 | * 收集聚合 mysql binlog 22 | * 实现对 binlog 的监听 并获取对表有兴趣的监听器, 23 | */ 24 | @Slf4j 25 | @Component 26 | public class AggregationListener implements BinaryLogClient.EventListener { 27 | 28 | /** 29 | * binlog 一定包含 dbname 30 | */ 31 | private String dbName; 32 | 33 | /** 34 | * binlog 里的 tableName 35 | */ 36 | private String tableName; 37 | 38 | /** 39 | * 1. binlog 解析出来的数据对象 BinlogRowData 需要给其一些处理方法 40 | * 2. 同一个监听器可以多次实现注册不同的数据库,数据表 41 | * 3. 由于数据库的每张表可以有不同的处理方法 ,所以可以用 map 42 | * 4. key->String 对应一张表,value->Ilistener 对应处理方法 43 | */ 44 | private Map ilistenerMap = new HashMap<>(); 45 | 46 | private final TemplateHolder templateHolder; 47 | 48 | @Autowired 49 | public AggregationListener(TemplateHolder templateHolder) { 50 | this.templateHolder = templateHolder; 51 | } 52 | 53 | /** 54 | * 定义一个可以产生 ilistenerMap 的key 55 | * @param dbName 56 | * @param tableName 57 | * @return key 58 | */ 59 | private String getKey(String dbName,String tableName) { 60 | return dbName + ":" + tableName; 61 | } 62 | 63 | /** 64 | * 注册监听器 65 | * @param dbName 66 | * @param tableName 67 | * @param ilistener 68 | */ 69 | public void register(String dbName, String tableName, Ilistener ilistener) { 70 | // 对 tableName 实现了注册 71 | log.info("register : {}-{}", dbName, tableName); 72 | this.ilistenerMap.put(getKey(dbName, tableName), ilistener); 73 | } 74 | 75 | @Override 76 | public void onEvent(Event event) { 77 | // 目的是将 event 解析成 BinlogRowData,然后把 BinlogRowData 传递给 listener 实现增量数据的更新 78 | 79 | EventType type = event.getHeader().getEventType(); 80 | log.debug("event type : {}", type); 81 | if (type == EventType.TABLE_MAP) { 82 | // table_map 里包含了数据库 已经数据表的名字 83 | TableMapEventData data = event.getData(); 84 | this.tableName = data.getTable(); 85 | this.dbName = data.getDatabase(); 86 | // 接下来的一条binlog 是真正的处理方法,所以这里返回 87 | return; 88 | } 89 | 90 | /** 91 | * 如果是不是这三种就直接返回,因为增量的操作一定是对数据的 更新 写入 删除 92 | * 注意 EventType 这里和 mysql 的版本有关系 93 | */ 94 | if (type != EventType.EXT_UPDATE_ROWS 95 | && type != EventType.EXT_WRITE_ROWS 96 | && type != EventType.EXT_DELETE_ROWS) { 97 | return; 98 | } 99 | 100 | // 表名和库名是否已经完成了填充 101 | if (StringUtils.isEmpty(dbName) || StringUtils.isEmpty(tableName)) { 102 | log.error("no meta data event"); 103 | return; 104 | } 105 | 106 | // 找出对应表有兴趣的监听器 [之前 register 完成了注册 对应数据表的 listener ] 107 | String key = getKey(this.dbName, this.tableName); 108 | Ilistener ilistener = this.ilistenerMap.get(key); 109 | if (null == ilistener) { 110 | // 如果监听器为空 111 | log.debug("skip {}", key); 112 | return; 113 | } 114 | log.info("trigger event : {}", type.name()); 115 | try { 116 | // 最终目的是将 event 里的 data 转变为 BinlogRowData 117 | BinlogRowData rowData = buildRowData(event.getData()); 118 | if (rowData == null) { 119 | return; 120 | } 121 | 122 | rowData.setType(type); 123 | // 将转换完成的 binlogRowData 交给 listener 处理 124 | // 对检索服务实现来说 就是增量数据的更新 125 | ilistener.onEvent(rowData); 126 | 127 | } catch (Exception ex) { 128 | ex.printStackTrace(); 129 | log.error(ex.getMessage()); 130 | }finally { 131 | // 当处理完了一条事件之后,需要将 dbName 和 tableName 清空 132 | this.dbName = ""; 133 | this.tableName = ""; 134 | } 135 | 136 | 137 | 138 | } 139 | 140 | private List getAfterValues(EventData eventData) { 141 | if (eventData instanceof WriteRowsEventData) { 142 | return ((WriteRowsEventData) eventData).getRows(); 143 | } 144 | 145 | if (eventData instanceof UpdateRowsEventData) { 146 | return ((UpdateRowsEventData) eventData).getRows().stream() 147 | .map(Map.Entry::getValue).collect(Collectors.toList()); 148 | } 149 | 150 | if (eventData instanceof DeleteRowsEventData) { 151 | return ((DeleteRowsEventData) eventData).getRows(); 152 | } 153 | 154 | return Collections.emptyList(); 155 | } 156 | 157 | private BinlogRowData buildRowData(EventData eventData) { 158 | TableTemplate table = templateHolder.getTable(tableName); 159 | if (null == table) { 160 | log.warn("table {} not found", tableName); 161 | return null; 162 | } 163 | 164 | // 用来存 BinlogRowData 里的 after 165 | List> afterMapList = new ArrayList<>(); 166 | 167 | for (Serializable[] after : getAfterValues(eventData)) { 168 | Map afterMap = new HashMap<>(); 169 | int collen = after.length; 170 | 171 | for (int i = 0; i< collen; i++) { 172 | // 取出当前位置对应的列名 173 | String colName = table.getPosMap().get(i); 174 | 175 | // 如果没有则说明不关心这个列 176 | if (null == colName) { 177 | log.debug("ignore position :{}", i); 178 | continue; 179 | } 180 | 181 | String colValue = after[i].toString(); 182 | afterMap.put(colName, colValue); 183 | } 184 | afterMapList.add(afterMap); 185 | 186 | } 187 | 188 | BinlogRowData rowData = new BinlogRowData(); 189 | rowData.setAfter(afterMapList); 190 | rowData.setTable(table); 191 | return rowData; 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-search/src/main/java/cn/lucas/ad/handler/AdLevelDataHandler.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.handler; 2 | 3 | import cn.lucas.ad.dump.table.*; 4 | import cn.lucas.ad.index.DataTable; 5 | import cn.lucas.ad.index.IndexAware; 6 | import cn.lucas.ad.index.adplan.AdPlanIndex; 7 | import cn.lucas.ad.index.adplan.AdPlanObject; 8 | import cn.lucas.ad.index.adunit.AdUnitIndex; 9 | import cn.lucas.ad.index.adunit.AdUnitObject; 10 | import cn.lucas.ad.index.creative.CreativeIndex; 11 | import cn.lucas.ad.index.creative.CreativeObject; 12 | import cn.lucas.ad.index.creativeunit.CreativeUnitIndex; 13 | import cn.lucas.ad.index.creativeunit.CreativeUnitObject; 14 | import cn.lucas.ad.index.district.UnitDistrictIndex; 15 | import cn.lucas.ad.index.interest.UnitItIndex; 16 | import cn.lucas.ad.index.keyword.UnitKeywordIndex; 17 | import cn.lucas.ad.mysql.constant.OpType; 18 | import cn.lucas.ad.utils.CommonUtils; 19 | import com.alibaba.fastjson.JSON; 20 | import lombok.extern.slf4j.Slf4j; 21 | 22 | import java.util.Collections; 23 | import java.util.HashSet; 24 | import java.util.Set; 25 | 26 | /** 27 | * @author Administrator 28 | *

29 | * 1. 索引之间存在着层级的划分,也就是依赖关系的划分 30 | * 2. 加载全量索引是增量索引 "添加" 的一种特殊实现 31 | */ 32 | @Slf4j 33 | public class AdLevelDataHandler { 34 | 35 | 36 | public static void handleLevel2(AdPlanTable planTable,OpType type){ 37 | 38 | AdPlanObject adPlanObject = new AdPlanObject( 39 | planTable.getId(), 40 | planTable.getUserId(), 41 | planTable.getPlanStatus(), 42 | planTable.getStartDate(), 43 | planTable.getEndDate() 44 | ); 45 | handlerBinlogEvent( 46 | DataTable.of(AdPlanIndex.class), 47 | adPlanObject.getPlanId(), 48 | adPlanObject, 49 | type 50 | ); 51 | 52 | } 53 | public static void handleLevel2(AdCreativeTable creativeTable, 54 | OpType type) { 55 | 56 | CreativeObject creativeObject = new CreativeObject( 57 | creativeTable.getAdId(), 58 | creativeTable.getName(), 59 | creativeTable.getType(), 60 | creativeTable.getMaterialType(), 61 | creativeTable.getHeight(), 62 | creativeTable.getWidth(), 63 | creativeTable.getAuditStatus(), 64 | creativeTable.getAdUrl() 65 | ); 66 | handlerBinlogEvent( 67 | DataTable.of(CreativeIndex.class), 68 | creativeObject.getAdId(), 69 | creativeObject, 70 | type 71 | ); 72 | } 73 | 74 | 75 | public static void handleLevel3(AdUnitTable unitTable, OpType type) { 76 | 77 | AdPlanObject adPlanObject = DataTable.of( 78 | AdPlanIndex.class 79 | ).get(unitTable.getPlanId()); 80 | if (null == adPlanObject) { 81 | log.error("handleLevel3 found AdPlanObject error: {}", 82 | unitTable.getPlanId()); 83 | return; 84 | } 85 | 86 | AdUnitObject unitObject = new AdUnitObject( 87 | unitTable.getUnitId(), 88 | unitTable.getUnitStatus(), 89 | unitTable.getPositionType(), 90 | unitTable.getPlanId(), 91 | adPlanObject 92 | ); 93 | 94 | handlerBinlogEvent( 95 | DataTable.of(AdUnitIndex.class), 96 | unitTable.getUnitId(), 97 | unitObject, 98 | type 99 | ); 100 | } 101 | public static void handleLevel3(AdCreativeUnitTable creativeUnitTable, 102 | OpType type) { 103 | 104 | if (type == OpType.UPDATE) { 105 | log.error("CreativeUnitIndex not support update"); 106 | return; 107 | } 108 | 109 | AdUnitObject unitObject = DataTable.of( 110 | AdUnitIndex.class 111 | ).get(creativeUnitTable.getUnitId()); 112 | CreativeObject creativeObject = DataTable.of( 113 | CreativeIndex.class 114 | ).get(creativeUnitTable.getAdId()); 115 | 116 | if (null == unitObject || null == creativeObject) { 117 | log.error("AdCreativeUnitTable index error: {}", 118 | JSON.toJSONString(creativeUnitTable)); 119 | return; 120 | } 121 | 122 | CreativeUnitObject creativeUnitObject = new CreativeUnitObject( 123 | creativeUnitTable.getAdId(), 124 | creativeUnitTable.getUnitId() 125 | ); 126 | handlerBinlogEvent( 127 | DataTable.of(CreativeUnitIndex.class), 128 | CommonUtils.stringConcat( 129 | creativeUnitObject.getAdId().toString(), 130 | creativeUnitObject.getUnitId().toString() 131 | ), 132 | creativeUnitObject, 133 | type 134 | ); 135 | } 136 | 137 | public static void handleLevel4(AdUnitDistrictTable unitDistrictTable, 138 | OpType type) { 139 | 140 | if (type == OpType.UPDATE) { 141 | log.error("district index can not support update"); 142 | return; 143 | } 144 | 145 | AdUnitObject unitObject = DataTable.of( 146 | AdUnitIndex.class 147 | ).get(unitDistrictTable.getUnitId()); 148 | if (unitObject == null) { 149 | log.error("AdUnitDistrictTable index error: {}", 150 | unitDistrictTable.getUnitId()); 151 | return; 152 | } 153 | 154 | String key = CommonUtils.stringConcat( 155 | unitDistrictTable.getProvince(), 156 | unitDistrictTable.getCity() 157 | ); 158 | Set value = new HashSet<>( 159 | Collections.singleton(unitDistrictTable.getUnitId()) 160 | ); 161 | handlerBinlogEvent( 162 | DataTable.of(UnitDistrictIndex.class), 163 | key, value, 164 | type 165 | ); 166 | } 167 | 168 | public static void handleLevel4(AdUnitItTable unitItTable, OpType type) { 169 | 170 | if (type == OpType.UPDATE) { 171 | log.error("it index can not support update"); 172 | return; 173 | } 174 | 175 | AdUnitObject unitObject = DataTable.of( 176 | AdUnitIndex.class 177 | ).get(unitItTable.getUnitId()); 178 | if (unitObject == null) { 179 | log.error("AdUnitItTable index error: {}", 180 | unitItTable.getUnitId()); 181 | return; 182 | } 183 | 184 | Set value = new HashSet<>( 185 | Collections.singleton(unitItTable.getUnitId()) 186 | ); 187 | handlerBinlogEvent( 188 | DataTable.of(UnitItIndex.class), 189 | unitItTable.getItTag(), 190 | value, 191 | type 192 | ); 193 | } 194 | 195 | public static void handleLevel4(AdUnitKeywordTable keywordTable, 196 | OpType type) { 197 | 198 | if (type == OpType.UPDATE) { 199 | log.error("keyword index can not support update"); 200 | return; 201 | } 202 | 203 | AdUnitObject unitObject = DataTable.of( 204 | AdUnitIndex.class 205 | ).get(keywordTable.getUnitId()); 206 | if (unitObject == null) { 207 | log.error("AdUnitKeywordTable index error: {}", 208 | keywordTable.getUnitId()); 209 | return; 210 | } 211 | 212 | Set value = new HashSet<>( 213 | Collections.singleton(keywordTable.getUnitId()) 214 | ); 215 | handlerBinlogEvent( 216 | DataTable.of(UnitKeywordIndex.class), 217 | keywordTable.getKeyword(), 218 | value, 219 | type 220 | ); 221 | } 222 | private static void handlerBinlogEvent( 223 | IndexAware index, 224 | K key, 225 | V value, 226 | OpType type) { 227 | switch (type) { 228 | case ADD: 229 | index.add(key, value); 230 | break; 231 | case UPDATE: 232 | index.update(key, value); 233 | break; 234 | case DELETE: 235 | index.delete(key, value); 236 | break; 237 | default: 238 | break; 239 | 240 | } 241 | 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /lucas-ad-service/ad-sponsor/src/main/java/cn/lucas/ad/service/impl/AdUnitService.java: -------------------------------------------------------------------------------- 1 | package cn.lucas.ad.service.impl; 2 | 3 | import cn.lucas.ad.constant.Constants; 4 | import cn.lucas.ad.dao.AdPlanRepository; 5 | import cn.lucas.ad.dao.AdUnitRepository; 6 | import cn.lucas.ad.dao.CreativeRepository; 7 | import cn.lucas.ad.dao.unit_condition.AdUnitDistrictRepository; 8 | import cn.lucas.ad.dao.unit_condition.AdUnitItRepository; 9 | import cn.lucas.ad.dao.unit_condition.AdUnitKeywordRepository; 10 | import cn.lucas.ad.dao.unit_condition.CreativeUnitRepository; 11 | import cn.lucas.ad.entity.AdPlan; 12 | import cn.lucas.ad.entity.AdUnit; 13 | import cn.lucas.ad.entity.unit_condition.AdUnitDistrict; 14 | import cn.lucas.ad.entity.unit_condition.AdUnitIt; 15 | import cn.lucas.ad.entity.unit_condition.AdUnitKeyword; 16 | import cn.lucas.ad.entity.unit_condition.CreativeUnit; 17 | import cn.lucas.ad.exception.AdException; 18 | import cn.lucas.ad.service.IAdUnitService; 19 | import cn.lucas.ad.vo.*; 20 | import lombok.extern.slf4j.Slf4j; 21 | import org.springframework.beans.factory.annotation.Autowired; 22 | import org.springframework.stereotype.Service; 23 | import org.springframework.util.CollectionUtils; 24 | 25 | import java.util.*; 26 | import java.util.stream.Collectors; 27 | 28 | /** 29 | * @author Administrator 30 | */ 31 | @Slf4j 32 | @Service 33 | public class AdUnitService implements IAdUnitService { 34 | 35 | private final AdUnitRepository unitRepository; 36 | private final AdPlanRepository planRepository; 37 | 38 | private final AdUnitKeywordRepository unitKeywordRepository; 39 | private final AdUnitItRepository unitItRepository; 40 | private final AdUnitDistrictRepository unitDistrictRepository; 41 | 42 | private final CreativeUnitRepository creativeUnitrepository; 43 | 44 | private final CreativeRepository creativeRepository; 45 | 46 | @Autowired 47 | public AdUnitService(AdUnitRepository unitRepository, 48 | AdPlanRepository planRepository, 49 | AdUnitDistrictRepository unitDistrictRepository, 50 | AdUnitItRepository unitItRepository, 51 | AdUnitKeywordRepository unitKeywordRepository, 52 | CreativeUnitRepository creativeUnitrepository, 53 | CreativeRepository creativeRepository) { 54 | this.unitRepository = unitRepository; 55 | this.planRepository = planRepository; 56 | this.unitDistrictRepository = unitDistrictRepository; 57 | this.unitItRepository = unitItRepository; 58 | this.unitKeywordRepository = unitKeywordRepository; 59 | this.creativeUnitrepository = creativeUnitrepository; 60 | this.creativeRepository = creativeRepository; 61 | } 62 | 63 | @Override 64 | public AdUnitResponse createUnit(AdUnitRequest request) throws AdException { 65 | if (!request.createValidate()) { 66 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 67 | } 68 | Optional adPlan = planRepository.findById(request.getPlanId()); 69 | if (!adPlan.isPresent()) { 70 | throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD); 71 | } 72 | 73 | AdUnit oldUnit = unitRepository.findByPlanIdAndUnitName( 74 | request.getPlanId(), request.getUnitName() 75 | ); 76 | 77 | if (oldUnit != null) { 78 | throw new AdException(Constants.ErrorMsg.SAME_NAME_UNIT_ERROR); 79 | } 80 | 81 | AdUnit newUnit = unitRepository.save(new AdUnit( 82 | request.getPlanId(), request.getUnitName(), 83 | request.getPositionType(), request.getBudget())); 84 | 85 | 86 | return new AdUnitResponse(newUnit.getId(), newUnit.getUnitName()); 87 | } 88 | 89 | 90 | @Override 91 | public AdUnitKeywordResponse createUnitKeyword(AdUnitKeywordRequest request) throws AdException { 92 | List unitIds = request.getUnitKeywords().stream() 93 | .map(AdUnitKeywordRequest.UnitKeyword::getUnitId) 94 | .collect(Collectors.toList()); 95 | 96 | if (!isRelatedUnitExist(unitIds)) { 97 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 98 | } 99 | 100 | // unit 主键 101 | List ids = Collections.emptyList(); 102 | 103 | List unitKeywords = new ArrayList<>(); 104 | if (!CollectionUtils.isEmpty(request.getUnitKeywords())) { 105 | request.getUnitKeywords().forEach(i -> unitKeywords.add( 106 | new AdUnitKeyword(i.getUnitId(), i.getKeyword()))); 107 | ids = unitKeywordRepository.saveAll(unitKeywords).stream() 108 | .map(AdUnitKeyword::getUnitId).collect(Collectors.toList()); 109 | } 110 | 111 | return new AdUnitKeywordResponse(ids); 112 | } 113 | 114 | @Override 115 | public AdUnitItResponse createUnitIt(AdUnitItRequest request) throws AdException { 116 | List unitIds = request.getUnitIts().stream() 117 | .map(AdUnitItRequest.UnitIt::getUnitId).collect(Collectors.toList()); 118 | 119 | if (!isRelatedUnitExist(unitIds)) { 120 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 121 | } 122 | 123 | List unitIts = new ArrayList<>(); 124 | request.getUnitIts().forEach(i -> unitIts.add(new AdUnitIt(i.getUnitId(), i.getItTag()))); 125 | 126 | List ids = unitItRepository.saveAll(unitIts).stream() 127 | .map(AdUnitIt::getId) 128 | .collect(Collectors.toList()); 129 | return new AdUnitItResponse(ids); 130 | } 131 | 132 | @Override 133 | public AdUnitDistrictResponse createUnitDistrict(AdUnitDistrictRequest request) throws AdException { 134 | List unitIds = request.getUnitDistricts().stream() 135 | .map(AdUnitDistrictRequest.UnitDistrict::getUnitId) 136 | .collect(Collectors.toList()); 137 | if (!isRelatedUnitExist(unitIds)) { 138 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 139 | } 140 | 141 | List unitDistricts = new ArrayList<>(); 142 | request.getUnitDistricts().forEach(i -> unitDistricts.add( 143 | new AdUnitDistrict(i.getUnitId(), i.getProvince(), i.getCity()) 144 | )); 145 | List ids = unitDistrictRepository.saveAll(unitDistricts).stream() 146 | .map(AdUnitDistrict::getId) 147 | .collect(Collectors.toList()); 148 | 149 | return new AdUnitDistrictResponse(ids); 150 | } 151 | 152 | @Override 153 | public CreativeUnitResponse createCreativeUnit(CreativeUnitRequest request) throws AdException { 154 | List unitIds = request.getUnitItems().stream() 155 | .map(CreativeUnitRequest.CreativeUnitItem::getUnitId) 156 | .collect(Collectors.toList()); 157 | 158 | List creativeIds = request.getUnitItems().stream() 159 | .map(CreativeUnitRequest.CreativeUnitItem::getCreativeId) 160 | .collect(Collectors.toList()); 161 | 162 | if (!(isRelatedUnitExist(unitIds) && isRelateCreativeExist(creativeIds))) { 163 | throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR); 164 | } 165 | 166 | List creativeUnits = new ArrayList<>(); 167 | request.getUnitItems().forEach(i -> creativeUnits.add(new CreativeUnit(i.getCreativeId(), i.getUnitId()))); 168 | List ids = creativeUnitrepository.saveAll(creativeUnits) 169 | .stream() 170 | .map(CreativeUnit::getId) 171 | .collect(Collectors.toList()); 172 | return new CreativeUnitResponse(ids); 173 | } 174 | 175 | /** 176 | * 相关推广单元是否存在 177 | * 178 | * @param unitIds 推广单元 id 179 | * @return 180 | */ 181 | private boolean isRelatedUnitExist(List unitIds) { 182 | if (CollectionUtils.isEmpty(unitIds)) { 183 | return false; 184 | } 185 | 186 | // unitid 可能重复 所以用 hashset 来判断 187 | // 通过 unitIds 查询的推广单元集合大小 是否和 去重的推广单元id 集合大小相等 188 | 189 | return unitRepository.findAllById(unitIds).size() == new HashSet<>(unitIds).size(); 190 | } 191 | 192 | 193 | private boolean isRelateCreativeExist(List creativeIds) { 194 | if (CollectionUtils.isEmpty(creativeIds)) { 195 | return false; 196 | } 197 | return creativeRepository.findAllById(creativeIds).size() == new HashSet<>(creativeIds).size(); 198 | } 199 | 200 | } 201 | --------------------------------------------------------------------------------