├── .gitignore ├── Spring cloud 实现广告系统.pdf ├── kafka-demo ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── sxzhongf │ └── kafkademo │ ├── CustomKafkaPartitioner.java │ ├── KafkaDemoConsumer.java │ ├── KafkaDemoProducer.java │ ├── KafkaKeyCategory.java │ └── ProducerDemoCallback.java ├── mscx-ad-common ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── sxzhongf │ └── ad │ └── common │ ├── advice │ ├── CommonRequestAdvice.java │ ├── CommonResponseDataAdvice.java │ └── GlobalExceptionAdvice.java │ ├── annotation │ └── IgnoreResponseAdvice.java │ ├── config │ └── WebConfiguration.java │ ├── exception │ └── AdException.java │ ├── export │ ├── FileConstant.java │ └── table │ │ ├── AdCreativeRelationUnitTable.java │ │ ├── AdCreativeTable.java │ │ ├── AdPlanTable.java │ │ ├── AdUnitDistrictTable.java │ │ ├── AdUnitHobbyTable.java │ │ ├── AdUnitKeywordTable.java │ │ └── AdUnitTable.java │ ├── utils │ └── CommonUtils.java │ └── vo │ └── CommonResponse.java ├── mscx-ad-dashboard ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── sxzhongf │ │ └── ad │ │ └── AdDashboardApplication.java │ └── resources │ └── application.yml ├── mscx-ad-db ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── sxzhongf │ │ │ └── ad │ │ │ ├── DBExportApplication.java │ │ │ └── service │ │ │ ├── IExportDataService.java │ │ │ ├── controller │ │ │ └── ExportDataController.java │ │ │ └── impl │ │ │ └── ExportDataServiceImpl.java │ └── resources │ │ ├── application.yml │ │ └── db │ │ ├── init-data.sql │ │ └── migration │ │ └── V1__CREATE_NEW_DATABASE_AD.sql │ └── test │ └── java │ └── TestTable.java ├── mscx-ad-discovery ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── sxzhongf │ │ └── ad │ │ └── discovery │ │ └── DiscoveryApplication.java │ └── resources │ └── application.yml ├── mscx-ad-feign-sdk ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── sxzhongf │ └── ad │ └── feign │ └── client │ ├── ISponsorFeignClient.java │ ├── SponsorClientHystrix.java │ └── vo │ ├── AdPlanGetRequestVO.java │ └── AdPlanVO.java ├── mscx-ad-gateway ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── sxzhongf │ │ └── ad │ │ └── gateway │ │ ├── GatewayApplication.java │ │ ├── filter │ │ ├── AccessLogFilter.java │ │ ├── CORSFilter.java │ │ └── TokenFilter.java │ │ └── route │ │ └── GatewayRoutes.java │ └── resources │ └── application.yml ├── mscx-ad-search ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── sxzhongf │ │ │ └── ad │ │ │ ├── AdSearchApplication.java │ │ │ ├── client │ │ │ ├── ISponsorFeignClient.java │ │ │ ├── SponsorClientHystrix.java │ │ │ └── vo │ │ │ │ ├── AdPlanGetRequestVO.java │ │ │ │ └── AdPlanVO.java │ │ │ ├── config │ │ │ └── BinlogConfig.java │ │ │ ├── controller │ │ │ ├── SearchController.java │ │ │ └── SearchFeignController.java │ │ │ ├── handler │ │ │ └── AdLevelDataHandler.java │ │ │ ├── index │ │ │ ├── AdDataLevel.java │ │ │ ├── CommonStatus.java │ │ │ ├── IIndexAware.java │ │ │ ├── IndexDataTableUtils.java │ │ │ ├── IndexFileLoader.java │ │ │ ├── adplan │ │ │ │ ├── AdPlanIndexAwareImpl.java │ │ │ │ └── AdPlanIndexObject.java │ │ │ ├── adunit │ │ │ │ ├── AdUnitConstants.java │ │ │ │ ├── AdUnitIndexAwareImpl.java │ │ │ │ └── AdUnitIndexObject.java │ │ │ ├── creative │ │ │ │ ├── CreativeIndexAwareImpl.java │ │ │ │ └── CreativeIndexObject.java │ │ │ ├── creative_relation_unit │ │ │ │ ├── CreativeRelationUnitIndexAwareImpl.java │ │ │ │ └── CreativeRelationUnitIndexObject.java │ │ │ ├── district │ │ │ │ ├── UnitDistrictIndexAwareImpl.java │ │ │ │ └── UnitDistrictIndexObject.java │ │ │ ├── hobby │ │ │ │ ├── UnitHobbyIndexAwareImpl.java │ │ │ │ └── UnitHobbyIndexObject.java │ │ │ └── keyword │ │ │ │ ├── UnitKeywordIndexAwareImpl.java │ │ │ │ └── UnitKeywordIndexObject.java │ │ │ ├── mysql │ │ │ ├── CustomBinlogClient.java │ │ │ ├── TemplateHolder.java │ │ │ ├── constant │ │ │ │ ├── Constant.java │ │ │ │ └── OperationTypeEnum.java │ │ │ ├── dto │ │ │ │ ├── BinlogRowData.java │ │ │ │ ├── BinlogTemplate.java │ │ │ │ ├── JsonTable.java │ │ │ │ ├── MysqlRowData.java │ │ │ │ ├── ParseCustomTemplate.java │ │ │ │ └── TableTemplate.java │ │ │ └── listener │ │ │ │ ├── AggregationListener.java │ │ │ │ ├── Ilistener.java │ │ │ │ └── IncrementListener.java │ │ │ ├── runner │ │ │ └── BinlogRunner.java │ │ │ ├── search │ │ │ ├── ISearch.java │ │ │ ├── SearchImpl.java │ │ │ └── vo │ │ │ │ ├── SearchRequest.java │ │ │ │ ├── SearchResponse.java │ │ │ │ ├── feature │ │ │ │ ├── DistrictFeature.java │ │ │ │ ├── FeatureRelation.java │ │ │ │ ├── HobbyFeatrue.java │ │ │ │ └── KeywordFeature.java │ │ │ │ └── media │ │ │ │ ├── AdSlot.java │ │ │ │ ├── App.java │ │ │ │ ├── Device.java │ │ │ │ └── Geo.java │ │ │ ├── sender │ │ │ ├── ISender.java │ │ │ ├── index │ │ │ │ └── IndexSender.java │ │ │ └── kafka │ │ │ │ └── KafkaSender.java │ │ │ ├── service │ │ │ └── BinlogServiceTest.java │ │ │ └── utils │ │ │ └── CommonUtils.java │ └── resources │ │ ├── MySQL BinLog.md │ │ ├── application.yml │ │ ├── index-note.md │ │ └── template.json │ └── test │ ├── java │ └── com │ │ └── sxzhongf │ │ └── ad │ │ ├── AdSearchApplication.java │ │ └── search │ │ └── SearchTest.java │ └── resources │ └── application.yml ├── mscx-ad-sponsor ├── pom.xml └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── sxzhongf │ │ │ └── ad │ │ │ ├── SponsorApplication.java │ │ │ ├── client │ │ │ └── vo │ │ │ │ ├── CreativeRequestVO.java │ │ │ │ ├── CreativeResponseVO.java │ │ │ │ ├── CreativeUnitRelationshipRequestVO.java │ │ │ │ ├── CreativeUnitRelationshipResponseVO.java │ │ │ │ ├── PlanGetRequestVO.java │ │ │ │ ├── PlanRequestVO.java │ │ │ │ ├── PlanResponseVO.java │ │ │ │ ├── UnitDistrictRequestVO.java │ │ │ │ ├── UnitDistrictResponseVO.java │ │ │ │ ├── UnitHobbyRequestVO.java │ │ │ │ ├── UnitHobbyResponseVO.java │ │ │ │ ├── UnitKeywordRequestVO.java │ │ │ │ ├── UnitKeywordResponseVO.java │ │ │ │ ├── UnitRequestVO.java │ │ │ │ ├── UnitResponseVO.java │ │ │ │ ├── UserRequestVO.java │ │ │ │ └── UserResponseVO.java │ │ │ ├── constant │ │ │ ├── CommonStatus.java │ │ │ ├── Constants.java │ │ │ ├── CreativeMaterielType.java │ │ │ └── CreativeType.java │ │ │ ├── controller │ │ │ ├── CreativeController.java │ │ │ ├── PlanController.java │ │ │ ├── UnitController.java │ │ │ └── UserController.java │ │ │ ├── dao │ │ │ ├── AdPlanRepository.java │ │ │ ├── AdUnitRepository.java │ │ │ ├── AdUserRepository.java │ │ │ ├── CreativeRepository.java │ │ │ └── unit_condition │ │ │ │ ├── AdUnitDistrictRepository.java │ │ │ │ ├── AdUnitHobbyRepository.java │ │ │ │ ├── AdUnitKeywordRepository.java │ │ │ │ └── RelationshipCreativeUnitRepository.java │ │ │ ├── entity │ │ │ ├── AdCreative.java │ │ │ ├── AdPlan.java │ │ │ ├── AdUnit.java │ │ │ ├── AdUser.java │ │ │ └── unit_condition │ │ │ │ ├── AdUnitDistrict.java │ │ │ │ ├── AdUnitHobby.java │ │ │ │ ├── AdUnitKeyword.java │ │ │ │ └── RelationshipCreativeUnit.java │ │ │ └── service │ │ │ ├── ICreativeService.java │ │ │ ├── IPlanService.java │ │ │ ├── IUnitService.java │ │ │ ├── IUserService.java │ │ │ └── impl │ │ │ ├── CreativeServiceImpl.java │ │ │ ├── PlanServiceImpl.java │ │ │ ├── UnitServiceImpl.java │ │ │ └── UserServiceImpl.java │ └── resources │ │ └── application.yml │ └── test │ └── java │ └── com │ └── sxzhongf │ └── ad │ ├── SponsorApplication.java │ └── service │ ├── AdPlanServiceTest.java │ ├── AdUnitServiceTest.java │ └── UserServiceTest.java ├── mscx-ad-zuul ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── sxzhongf │ │ └── ad │ │ └── gateway │ │ ├── GatewayApplication.java │ │ └── filter │ │ ├── AccessLogFilter.java │ │ ├── PreRequestFilter.java │ │ └── ValidateTokenFilter.java │ └── resources │ └── application.yml └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.war 15 | *.ear 16 | *.zip 17 | *.tar.gz 18 | *.rar 19 | 20 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 21 | hs_err_pid* 22 | 23 | # eclipse ignore 24 | .settings/ 25 | .project 26 | .classpath 27 | 28 | # idea ignore 29 | .idea/ 30 | *.ipr 31 | *.iml 32 | *.iws 33 | target 34 | 35 | # temp ignore 36 | *.log 37 | *.cache 38 | *.diff 39 | *.patch 40 | *.tmp 41 | 42 | # system ignore 43 | .DS_Store 44 | Thumbs.db 45 | 46 | # others 47 | .extract 48 | -------------------------------------------------------------------------------- /Spring cloud 实现广告系统.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Isaac-Zhang/mscx-ad/2b4d3504be79589dadbbd1b975e1128e41445010/Spring cloud 实现广告系统.pdf -------------------------------------------------------------------------------- /kafka-demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | com.sxzhongf 9 | kafka-demo 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 14 | org.apache.kafka 15 | kafka_2.11 16 | 2.3.0 17 | 18 | 19 | 20 | 21 | 22 | 23 | org.apache.maven.plugins 24 | maven-compiler-plugin 25 | 3.7.0 26 | 27 | 1.8 28 | 1.8 29 | UTF-8 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /kafka-demo/src/main/java/com/sxzhongf/kafkademo/CustomKafkaPartitioner.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.kafkademo; 2 | 3 | import org.apache.kafka.clients.producer.Partitioner; 4 | import org.apache.kafka.common.Cluster; 5 | import org.apache.kafka.common.PartitionInfo; 6 | import org.apache.kafka.common.record.InvalidRecordException; 7 | import org.apache.kafka.common.utils.Utils; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * CustomKafkaPartitioner for 自定义消息分配器 14 | * 15 | * @author Isaac.Zhang | 若初 16 | * @since 2019/8/14 17 | */ 18 | public class CustomKafkaPartitioner implements Partitioner { 19 | 20 | /** 21 | * 决定消息将被写入哪个分区 22 | * 23 | * @param cluster kafka集群信息 24 | */ 25 | @Override 26 | public int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) { 27 | 28 | //获取集群中topic对应的所有的partition 29 | List partitionInfoList = cluster.partitionsForTopic(topic); 30 | int partitionCount = 0; 31 | //获取partition 个数 32 | if (null != partitionInfoList && partitionInfoList.size() > 0) { 33 | partitionCount = partitionInfoList.size(); 34 | } 35 | 36 | //自定义一个分区规则,必须传递消息的key,如果不传,则报错 37 | if (null == keyBytes || !(key instanceof String)) { 38 | throw new InvalidRecordException("Kafka message key is invalid."); 39 | } 40 | if (partitionCount == 1) { 41 | return 0; 42 | } 43 | switch (String.valueOf(key)) { 44 | case "demo-key": 45 | case "demo-asyn-key": 46 | case "demo-sync-key": 47 | case "demo-partitioner-key": 48 | return partitionCount - 1; 49 | } 50 | 51 | //使用kafka默认分区算法,murmur2获取字节数组hash值,然后对分区数取余 52 | return Math.abs(Utils.murmur2(keyBytes)) % (partitionCount - 1); 53 | } 54 | 55 | @Override 56 | public void close() { 57 | 58 | } 59 | 60 | @Override 61 | public void configure(Map configs) { 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /kafka-demo/src/main/java/com/sxzhongf/kafkademo/KafkaKeyCategory.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.kafkademo; 2 | 3 | /** 4 | * KafkaKeyCategory for TODO 5 | * 6 | * @author Isaac.Zhang | 若初 7 | * @since 2019/8/14 8 | */ 9 | public enum KafkaKeyCategory { 10 | 11 | asyn(0, "demo-asyn-key"), 12 | normal(1, "demo-key"), 13 | sync(2, "demo-sync-key"); 14 | 15 | public int getCode() { 16 | return code; 17 | } 18 | 19 | public String getValue() { 20 | return value; 21 | } 22 | 23 | private int code; 24 | private String value; 25 | 26 | KafkaKeyCategory(int code, String value) { 27 | this.code = code; 28 | this.value = value; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kafka-demo/src/main/java/com/sxzhongf/kafkademo/ProducerDemoCallback.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.kafkademo; 2 | 3 | import org.apache.kafka.clients.producer.Callback; 4 | import org.apache.kafka.clients.producer.RecordMetadata; 5 | 6 | /** 7 | * ProducerDemoCallback for 实现异步生产消息结束后的回调处理 8 | * 9 | * @author Isaac.Zhang | 若初 10 | * @since 2019/8/14 11 | */ 12 | public class ProducerDemoCallback implements Callback { 13 | 14 | @Override 15 | public void onCompletion(RecordMetadata recordMetadata, Exception exception) { 16 | if (null != exception) { 17 | System.out.println(exception.getStackTrace()); 18 | return; 19 | } 20 | System.out.printf("Asyn Topic : %s, Partition: %s, Offset : %s \n" 21 | , recordMetadata.topic(), recordMetadata.partition(), recordMetadata.offset()); 22 | 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mscx-ad-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | jar 13 | 14 | com.sxzhongf 15 | mscx-ad-common 16 | 1.0-SNAPSHOT 17 | mscx-ad-common 18 | 公共逻辑 and 帮助类 19 | 20 | 21 | 22 | org.springframework.boot 23 | spring-boot-starter-web 24 | 25 | 26 | com.alibaba 27 | fastjson 28 | 1.2.46 29 | 30 | 31 | commons-codec 32 | commons-codec 33 | 34 | 35 | org.apache.commons 36 | commons-lang3 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/advice/CommonRequestAdvice.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.advice; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.core.MethodParameter; 5 | import org.springframework.http.HttpInputMessage; 6 | import org.springframework.http.converter.HttpMessageConverter; 7 | import org.springframework.web.bind.annotation.RestControllerAdvice; 8 | import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice; 9 | 10 | import java.io.IOException; 11 | import java.lang.reflect.Type; 12 | 13 | /** 14 | * CommonRequestAdvice for TODO 15 | * 16 | * @author Isaac.Zhang 17 | * @since 2019/6/13 18 | */ 19 | @Slf4j 20 | @RestControllerAdvice 21 | public class CommonRequestAdvice implements RequestBodyAdvice { 22 | @Override 23 | public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { 24 | log.info("Sxzhongf -> CommonRequestAdvice#supports"); 25 | return false; 26 | } 27 | 28 | @Override 29 | public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) throws IOException { 30 | log.info("Sxzhongf -> CommonRequestAdvice#beforeBodyRead"); 31 | return null; 32 | } 33 | 34 | @Override 35 | public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { 36 | log.info("Sxzhongf -> CommonRequestAdvice#afterBodyRead"); 37 | return null; 38 | } 39 | 40 | @Override 41 | public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { 42 | log.info("Sxzhongf -> CommonRequestAdvice#handleEmptyBody"); 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/advice/CommonResponseDataAdvice.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.advice; 2 | 3 | import com.sxzhongf.ad.common.annotation.IgnoreResponseAdvice; 4 | import com.sxzhongf.ad.common.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.web.bind.annotation.RestControllerAdvice; 11 | import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; 12 | 13 | /** 14 | * CommonResponseDataAdvice for 统一拦截处理 15 | * 在响应体返回之前做一些处理;比如,修改返回值、加密等 16 | * 17 | * @author Isaac.Zhang 18 | * @see 19 | * @since 2019/6/13 20 | */ 21 | @RestControllerAdvice 22 | public class CommonResponseDataAdvice implements ResponseBodyAdvice { 23 | 24 | /** 25 | * 判断是否需要对响应进行处理 26 | * 27 | * @return false:不需要处理,true:需要处理 28 | */ 29 | @Override 30 | public boolean supports(MethodParameter methodParameter, Class> converterType) { 31 | // 32 | // //获取当前处理请求的controller的方法 33 | // String methodName = methodParameter.getMethod().getName().toLowerCase(); 34 | // // 不拦截/不需要处理返回值 的方法 35 | // String method = "login"; //如登录 36 | // //不拦截 37 | // return !method.equals(methodName); 38 | 39 | // 如果类上标记了@IgnoreResponseAdvice,则不拦截 40 | if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnoreResponseAdvice.class)) { 41 | return false; 42 | } 43 | 44 | // 如果方法上标记了@IgnoreResponseAdvice,则不拦截 45 | if (methodParameter.getMethod().isAnnotationPresent(IgnoreResponseAdvice.class)) { 46 | return false; 47 | } 48 | 49 | //对响应进行处理,执行beforeBodyWrite方法 50 | return true; 51 | } 52 | 53 | /** 54 | * 目的 拦截CommonResponse 55 | * 56 | * @param body 原始的Controller需要返回的数据 57 | */ 58 | @Override 59 | public Object beforeBodyWrite(Object body, MethodParameter returnType, 60 | MediaType selectedContentType, 61 | Class> selectedConverterType, 62 | ServerHttpRequest request, 63 | ServerHttpResponse response) { 64 | 65 | CommonResponse commonResponse = new CommonResponse<>(0, ""); 66 | 67 | if (null == body) { 68 | return commonResponse; 69 | } else if (body instanceof CommonResponse) { 70 | commonResponse = (CommonResponse) body; 71 | } else { 72 | commonResponse.setData(body); 73 | } 74 | return commonResponse; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/advice/GlobalExceptionAdvice.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.advice; 2 | 3 | import com.sxzhongf.ad.common.exception.AdException; 4 | import com.sxzhongf.ad.common.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 | /** 11 | * GlobalExceptionAdvice for 全局统一异常拦截 12 | * 13 | * @author Isaac.Zhang 14 | * @see RestControllerAdvice 15 | * @see ExceptionHandler 16 | * @since 2019/6/13 17 | */ 18 | @RestControllerAdvice 19 | public class GlobalExceptionAdvice { 20 | 21 | /** 22 | * 对 {@link AdException} 进行统一处理 23 | * {@link ExceptionHandler} 对指定的异常进行拦截 24 | * 可优化: 25 | * 定义多种类异常,实现对应的异常处理, 26 | * 例如: 27 | *
    28 | *
  • 29 | * 推广单元操作异常,抛出 AdUnitException 30 | *
  • 31 | *
  • 32 | * Binlog 解析异常,抛出 BinlogException 33 | *
  • 34 | *
35 | * 拦截Spring Exception 使用 {@link ExceptionHandler}注解 36 | */ 37 | @ExceptionHandler(value = AdException.class) 38 | public CommonResponse handlerAdException(HttpServletRequest request, AdException ex) { 39 | CommonResponse response = new CommonResponse<>(-1, "广告业务报错。"); 40 | response.setData(ex.getMessage()); 41 | return response; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/annotation/IgnoreResponseAdvice.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.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 | /** 9 | * IgnoreResponseAdvice for 标示需要忽略拦截动作 10 | * 11 | * @author Isaac.Zhang 12 | * @since 2019/6/13 13 | */ 14 | @Target({ElementType.TYPE, ElementType.METHOD}) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | public @interface IgnoreResponseAdvice { 17 | } 18 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/config/WebConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.format.FormatterRegistry; 5 | import org.springframework.http.converter.HttpMessageConverter; 6 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 7 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 8 | import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; 9 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 10 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 11 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * WebConfiguration for 对Spring的配置和行为进行定制修改 17 | * 18 | * @author Isaac.Zhang 19 | * @see WebMvcConfigurer 20 | * @since 2019/6/13 21 | */ 22 | @Configuration 23 | public class WebConfiguration implements WebMvcConfigurer { 24 | /** 25 | * 匹配路由请求规则 26 | */ 27 | @Override 28 | public void configurePathMatch(PathMatchConfigurer configurer) { 29 | 30 | } 31 | 32 | /** 33 | * 注册自定义的Formatter 和 Convert 34 | */ 35 | @Override 36 | public void addFormatters(FormatterRegistry registry) { 37 | 38 | } 39 | 40 | /** 41 | * 添加静态资源处理器 42 | */ 43 | @Override 44 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 45 | 46 | } 47 | 48 | /** 49 | * 添加自定义视图控制器 50 | */ 51 | @Override 52 | public void addViewControllers(ViewControllerRegistry registry) { 53 | 54 | } 55 | 56 | /** 57 | * 添加自定义方法参数处理器 58 | */ 59 | @Override 60 | public void addArgumentResolvers(List resolvers) { 61 | 62 | } 63 | 64 | /** 65 | * 配置消息转换器 66 | */ 67 | @Override 68 | public void configureMessageConverters(List> converters) { 69 | //清空所有转换器 70 | converters.clear(); 71 | // Java Obj -> Json Obj (http header: application/json) 72 | converters.add(new MappingJackson2HttpMessageConverter()); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/exception/AdException.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.exception; 2 | 3 | /** 4 | * AdException for 统一异常处理类 5 | * 6 | * @author Isaac.Zhang 7 | * @since 2019/6/13 8 | */ 9 | public class AdException extends Exception { 10 | 11 | public AdException(String message) { 12 | super(message); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/FileConstant.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export; 2 | 3 | /** 4 | * FileConstant for 定义索引与存储对象的常量关系说明 5 | * 6 | * @author Isaac.Zhang | 若初 7 | * @since 2019/6/25 8 | */ 9 | public class FileConstant { 10 | 11 | public static final String DATA_ROOT_DIR = "/Users/zhangpan/Documents/promotion/data/mysql/"; 12 | 13 | //各个表数据的存储文件名 14 | public static final String AD_PLAN = "ad_plan.data"; 15 | public static final String AD_UNIT = "ad_unit.data"; 16 | public static final String AD_CREATIVE = "ad_creative.data"; 17 | public static final String AD_CREATIVE_RELARION_UNIT = "ad_creative_relation_unit.data"; 18 | public static final String AD_UNIT_HOBBY = "ad_unit_hobby.data"; 19 | public static final String AD_UNIT_DISTRICT = "ad_unit_district.data"; 20 | public static final String AD_UNIT_KEYWORD = "ad_unit_keyword.data"; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/table/AdCreativeRelationUnitTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * AdCreativeRelationUnitTable for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class AdCreativeRelationUnitTable { 17 | /** 18 | * 创意/广告ID 19 | */ 20 | private Long adId; 21 | /** 22 | * 推广单元ID 23 | */ 24 | private Long unitId; 25 | } 26 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/table/AdCreativeTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * AdCreativeTable for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class AdCreativeTable { 17 | private Long adId; 18 | private String name; 19 | private Integer type; 20 | private Integer materialType; 21 | private Integer height; 22 | private Integer width; 23 | private Integer auditStatus; 24 | private String adUrl; 25 | } 26 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/table/AdPlanTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * AdPlanTable for 需要导出的表字段信息 => 是搜索索引字段一一对应 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/25 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class AdPlanTable { 19 | private Long planId; 20 | private Long userId; 21 | private Integer planStatus; 22 | private Date startDate; 23 | private Date endDate; 24 | } 25 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/table/AdUnitDistrictTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * AdUnitDistrictTable for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class AdUnitDistrictTable { 17 | private Long unitId; 18 | private String province; 19 | private String city; 20 | } 21 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/table/AdUnitHobbyTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * AdUnitHobbyTable for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class AdUnitHobbyTable { 17 | private Long unitId; 18 | private String hobbyTag; 19 | } 20 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/table/AdUnitKeywordTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * AdUnitKeywordTable for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class AdUnitKeywordTable { 17 | private Long unitId; 18 | private String keyword; 19 | } 20 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/export/table/AdUnitTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.export.table; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * AdUnitTable for 需要导出的表字段信息 => 是搜索索引字段一一对应 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class AdUnitTable { 17 | private Long unitId; 18 | private Long planId; 19 | private Integer unitStatus; 20 | private Integer positionType; 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/utils/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.utils; 2 | 3 | 4 | import com.sxzhongf.ad.common.exception.AdException; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.codec.digest.DigestUtils; 7 | import org.apache.commons.lang3.time.DateUtils; 8 | 9 | import java.text.DateFormat; 10 | import java.text.ParseException; 11 | import java.text.SimpleDateFormat; 12 | import java.util.Date; 13 | import java.util.Locale; 14 | 15 | /** 16 | * CommonUtils for 工具类 17 | * 18 | * @author Isaac.Zhang | 若初 19 | * @since 2019/6/19 20 | */ 21 | @Slf4j 22 | public class CommonUtils { 23 | 24 | private static String[] parsePatterns = { 25 | "yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd" 26 | }; 27 | 28 | /** 29 | * md5 加密 30 | */ 31 | public static String md5(String value) { 32 | return DigestUtils.md5Hex(value).toUpperCase(); 33 | } 34 | 35 | /** 36 | * 日期转换 37 | */ 38 | public static Date parseStringDate(String dateStr) throws AdException { 39 | Date date = null; 40 | 41 | try { 42 | date = DateUtils.parseDate(dateStr, parsePatterns); 43 | } catch (ParseException pex) { 44 | throw new AdException("日期转换错误:" + pex.getMessage()); 45 | } 46 | return date; 47 | } 48 | 49 | /** 50 | * 处理字符串用'-'拼接 51 | * 52 | * @param args 可变参数数组 53 | * @return 拼接后结果 54 | */ 55 | public static String stringConcat(String... args) { 56 | StringBuilder builder = new StringBuilder(); 57 | for (String arg : args) { 58 | builder.append(arg); 59 | builder.append("-"); 60 | } 61 | builder.deleteCharAt(builder.length() - 1); 62 | return builder.toString(); 63 | } 64 | 65 | /** 66 | * Thu Jun 27 08:00:00 CST 2019 67 | */ 68 | public static Date parseBinlogString2Date(String dateString) { 69 | try { 70 | DateFormat dateFormat = new SimpleDateFormat( 71 | "EEE MMM dd HH:mm:ss zzz yyyy", 72 | Locale.US 73 | ); 74 | return DateUtils.addHours(dateFormat.parse(dateString), -8); 75 | 76 | } catch (ParseException ex) { 77 | log.error("parseString2Date error:{}", dateString); 78 | return null; 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /mscx-ad-common/src/main/java/com/sxzhongf/ad/common/vo/CommonResponse.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.common.vo; 2 | 3 | import lombok.*; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * CommonResponse for 统一响应体 9 | * 因为我们不确定要返回的数据的Data类型,因此我们使用泛型T来替代 10 | * 11 | * @author Isaac.Zhang 12 | * @since 2019/6/13 13 | */ 14 | 15 | /** 16 | * @Data是下属注解的组合注解 17 | * 18 | * @see Getter 19 | * @see Setter 20 | * @see RequiredArgsConstructor 21 | * @see ToString 22 | * @see EqualsAndHashCode 23 | * @see lombok.Value 24 | */ 25 | @Data 26 | @NoArgsConstructor //无参构造函数 27 | @AllArgsConstructor //全参构造函数 28 | public class CommonResponse implements Serializable { 29 | private Integer code = 0; 30 | private String message = "success"; 31 | /** 32 | * 具体的数据对象信息 33 | */ 34 | private T data; 35 | 36 | public CommonResponse(Integer code, String message) { 37 | this.code = code; 38 | this.message = message; 39 | } 40 | 41 | public CommonResponse(T data) { 42 | this.data = data; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mscx-ad-dashboard/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | com.sxzhongf 13 | mscx-ad-dashboard 14 | 1.0-SNAPSHOT 15 | 16 | 17 | 18 | org.springframework.cloud 19 | spring-cloud-starter-hystrix 20 | 1.2.7.RELEASE 21 | 22 | 23 | org.springframework.cloud 24 | spring-cloud-starter-hystrix-dashboard 25 | 1.2.7.RELEASE 26 | 27 | 28 | 29 | org.springframework.cloud 30 | spring-cloud-starter-netflix-eureka-client 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-actuator 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-maven-plugin 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /mscx-ad-dashboard/src/main/java/com/sxzhongf/ad/AdDashboardApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 7 | 8 | /** 9 | * AdDashboardApplication for Hystrix Dashboard 启动类 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/8/15 13 | */ 14 | @SpringBootApplication 15 | @EnableDiscoveryClient 16 | @EnableHystrixDashboard 17 | public class AdDashboardApplication { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(AdDashboardApplication.class, args); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /mscx-ad-dashboard/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 1234 3 | spring: 4 | application: 5 | name: mscx-ad-dashboard 6 | eureka: 7 | client: 8 | service-url: 9 | defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ 10 | management: 11 | endpoints: 12 | web: 13 | exposure: 14 | include: "*" 15 | -------------------------------------------------------------------------------- /mscx-ad-db/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | com.sxzhongf 13 | mscx-ad-db 14 | 1.0-SNAPSHOT 15 | ad-database-script 16 | 使用flyway实现脚本管理数据库 17 | 18 | 19 | 20 | root 21 | 12345678 22 | 23 | advertisement 24 | jdbc:mysql://127.0.0.1:3306/advertisement 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | mysql 35 | mysql-connector-java 36 | 8.0.12 37 | 38 | 39 | com.sxzhongf 40 | mscx-ad-sponsor 41 | 1.0-SNAPSHOT 42 | 43 | 44 | org.apache.commons 45 | commons-collections4 46 | 4.1 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /mscx-ad-db/src/main/java/com/sxzhongf/ad/DBExportApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | /** 7 | * DBExportApplication for 数据导出服务启动类 8 | * 9 | * @author Isaac.Zhang | 若初 10 | * @since 2019/6/25 11 | */ 12 | @SpringBootApplication 13 | public class DBExportApplication { 14 | 15 | public static void main(String[] args) { 16 | SpringApplication.run(DBExportApplication.class, args); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /mscx-ad-db/src/main/java/com/sxzhongf/ad/service/IExportDataService.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | /** 4 | * IExportDataService for 导出数据库广告索引初始化数据 5 | * 6 | * @author Isaac.Zhang | 若初 7 | * @since 2019/6/25 8 | */ 9 | public interface IExportDataService { 10 | } 11 | -------------------------------------------------------------------------------- /mscx-ad-db/src/main/java/com/sxzhongf/ad/service/controller/ExportDataController.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service.controller; 2 | 3 | import com.sxzhongf.ad.common.export.FileConstant; 4 | import com.sxzhongf.ad.common.vo.CommonResponse; 5 | import com.sxzhongf.ad.service.impl.ExportDataServiceImpl; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | 12 | /** 13 | * ExportDataController for TODO 14 | * 15 | * @author Isaac.Zhang | 若初 16 | * @since 2019/6/25 17 | */ 18 | @Slf4j 19 | @Controller 20 | @RequestMapping("/export") 21 | public class ExportDataController { 22 | 23 | private final ExportDataServiceImpl exportDataService; 24 | 25 | 26 | @Autowired 27 | public ExportDataController(ExportDataServiceImpl exportDataService) { 28 | this.exportDataService = exportDataService; 29 | } 30 | 31 | @GetMapping("/plan") 32 | public CommonResponse exportAdPlans() { 33 | 34 | exportDataService.exportAdPlanTable(String.format("%s%s", FileConstant.DATA_ROOT_DIR, FileConstant.AD_PLAN)); 35 | exportDataService.exportAdCreativeRelationUnit(String.format("%s%s" 36 | , FileConstant.DATA_ROOT_DIR, FileConstant.AD_CREATIVE_RELARION_UNIT)); 37 | exportDataService.exportAdCreativeTable(String.format("%s%s", FileConstant.DATA_ROOT_DIR, FileConstant.AD_CREATIVE)); 38 | exportDataService.exportAdUnitDistrict(String.format("%s%s", FileConstant.DATA_ROOT_DIR, FileConstant.AD_UNIT_DISTRICT)); 39 | exportDataService.exportAdUnitHobby(String.format("%s%s", FileConstant.DATA_ROOT_DIR, FileConstant.AD_UNIT_HOBBY)); 40 | exportDataService.exportAdUnitKeywords(String.format("%s%s", FileConstant.DATA_ROOT_DIR, FileConstant.AD_UNIT_KEYWORD)); 41 | exportDataService.exportAdUnitTable(String.format("%s%s", FileConstant.DATA_ROOT_DIR, FileConstant.AD_UNIT)); 42 | return new CommonResponse(); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mscx-ad-db/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7002 3 | servlet: 4 | context-path: /ad-db #http请求的根路径(请求前缀,在handle的mapping之前,需要127.0.0.1/ad-sponsor/XXXX) 5 | spring: 6 | application: 7 | name: mscx-ad-db 8 | jpa: 9 | show-sql: true #执行时是否打印sql语句,方便调试 10 | hibernate: 11 | ddl-auto: none 12 | properties: 13 | hibernate.format_sql: true 14 | open-in-view: false #控制是否在懒加载时,有可能会找不到bean报错 15 | datasource: 16 | username: root 17 | url: jdbc:mysql://127.0.0.1:3306/advertisement?useSSL=false&autoReconnect=true 18 | password: 12345678 19 | tomcat: 20 | max-active: 4 #最大连接数 21 | min-idle: 2 #最小空闲连接数 22 | initial-size: 2 #默认初始化连接数 23 | 24 | 25 | -------------------------------------------------------------------------------- /mscx-ad-db/src/main/resources/db/init-data.sql: -------------------------------------------------------------------------------- 1 | 2 | -- 3 | -- init data for table `ad_user` 4 | -- 5 | 6 | INSERT INTO `ad_user` VALUES (10,'Isaac','B2E56F2420D73FEC125D2D51641C5713',1,'2019-08-14 20:29:01','2019-08-14 20:29:01'); 7 | 8 | -- 9 | -- init data for table `ad_creative` 10 | -- 11 | 12 | INSERT INTO `ad_creative` VALUES (10,'第一个创意',1,1,720,1080,1024,0,1,10,'https://www.life-runner.com','2019-08-14 21:31:31','2019-08-14 21:31:31'); 13 | 14 | -- 15 | -- init data for table `ad_plan` 16 | -- 17 | 18 | INSERT INTO `ad_plan` VALUES (10,10,'推广计划名称',1,'2019-11-28 00:00:00','2019-11-20 00:00:00','2019-11-19 20:42:27','2019-08-14 20:57:12'); 19 | 20 | -- 21 | -- init data for table `ad_unit` 22 | -- 23 | 24 | INSERT INTO `ad_unit` VALUES (10,10,'第一个推广单元',1,1,10000000,'2019-11-20 11:43:26','2019-11-20 11:43:26'),(12,10,'第二个推广单元',1,1,15000000,'2019-01-01 00:00:00','2019-01-01 00:00:00'); 25 | 26 | -- 27 | -- init data for table `ad_unit_district` 28 | -- 29 | 30 | INSERT INTO `ad_unit_district` VALUES (10,10,'陕西省','西安市'),(11,10,'陕西省','西安市'),(12,10,'陕西省','西安市'),(14,10,'山西省','阳泉市'); 31 | 32 | -- 33 | -- init data for table `ad_unit_hobby` 34 | -- 35 | 36 | INSERT INTO `ad_unit_hobby` VALUES (10,10,'爬山'),(11,10,'读书'),(12,10,'写代码'); 37 | 38 | -- 39 | -- init data for table `ad_unit_keyword` 40 | -- 41 | 42 | INSERT INTO `ad_unit_keyword` VALUES (10,10,'汽车'),(11,10,'火车'),(12,10,'飞机'); 43 | 44 | -- 45 | -- init data for table `relationship_creative_unit` 46 | -- 47 | 48 | INSERT INTO `relationship_creative_unit` VALUES (10,10,10); 49 | -------------------------------------------------------------------------------- /mscx-ad-db/src/test/java/TestTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad; 2 | 3 | import java.awt.*; 4 | import java.awt.image.BufferedImage; 5 | import java.io.BufferedOutputStream; 6 | import java.io.FileOutputStream; 7 | 8 | import com.sun.image.codec.jpeg.JPEGCodec; 9 | import com.sun.image.codec.jpeg.JPEGImageEncoder; 10 | 11 | public class TestTable { 12 | BufferedImage image; 13 | 14 | void createImage(String fileLocation) { 15 | try { 16 | FileOutputStream fos = new FileOutputStream(fileLocation); 17 | BufferedOutputStream bos = new BufferedOutputStream(fos); 18 | JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(bos); 19 | encoder.encode(image); 20 | bos.close(); 21 | } catch (Exception e) { 22 | e.printStackTrace(); 23 | } 24 | } 25 | 26 | public void graphicsGeneration() { 27 | //实际数据行数+标题+备注 28 | int totalrow = 10; //todo: 动态获取 29 | int totalcol = 8; //todo: 动态获取 30 | int imageWidth = 1000; //todo: 动态计算 31 | int imageHeight = totalrow * 40 + 20; 32 | int rowheight = 40; 33 | int startHeight = 10; 34 | int startWidth = 10; 35 | int colwidth = (int) ((imageWidth - 20) / totalcol); 36 | 37 | image = new BufferedImage(imageWidth, imageHeight, BufferedImage.TYPE_INT_RGB); 38 | Graphics2D graphics = image.createGraphics(); 39 | 40 | graphics.setColor(new Color(250, 250, 250)); 41 | graphics.fillRect(0, 0, imageWidth, imageHeight); 42 | 43 | // //设置字体 44 | Font font = new Font("PingFangSC-Thin", Font.BOLD, 16); 45 | 46 | graphics.setColor(new Color(51, 51, 51)); 47 | graphics.setFont(font); 48 | graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); 49 | graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON); 50 | graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,RenderingHints.VALUE_STROKE_DEFAULT); 51 | 52 | //写入表头 53 | String[] headCells = {"尺码", "XXS", "XS", "S", "M", "L", "XL", "XXL"}; 54 | for (int m = 0; m < headCells.length; m++) { 55 | graphics.drawString(headCells[m].toString(), startWidth + colwidth * m + 5, startHeight + rowheight * 2 - 10); 56 | } 57 | 58 | //设置字体 59 | font = new Font("PingFangSC-Thin", Font.PLAIN, 16); 60 | graphics.setFont(font); 61 | String[][] cellsValue = { 62 | {"肩宽", "70", "-", "-", "-", "-", "-", "-"}, 63 | {"胸围", "-", "-", "80", "-", "-", "-", "-"}, 64 | {"腰围", "-", "74", "-", "-", "-", "-", "-"}, 65 | {"臀围", "-", "-", "90", "-", "-", "-", "-"}, 66 | {"臀围", "-", "-", "90", "-", "-", "-", "-"}, 67 | {"臀围", "-", "-", "90", "-", "-", "-", "-"}, 68 | {"臀围", "-", "-", "90", "-", "-", "-", "-"}, 69 | {"臀围", "-", "-", "90", "-", "-", "-", "-"}, 70 | {"裙长", "-", "-", "-", "-", "-", "80", "-"} 71 | }; 72 | //写入内容 73 | for (int n = 0; n < cellsValue.length; n++) { 74 | String[] arr = cellsValue[n]; 75 | for (int l = 0; l < arr.length; l++) { 76 | graphics.drawString(cellsValue[n][l].toString(), startWidth + colwidth * l + 5, startHeight + rowheight * (n + 3) - 10); 77 | } 78 | } 79 | 80 | createImage("1.jpg"); 81 | } 82 | 83 | public static void main(String[] args) { 84 | TestTable cg = new TestTable(); 85 | try { 86 | cg.graphicsGeneration(); 87 | } catch (Exception e) { 88 | e.printStackTrace(); 89 | } 90 | } 91 | 92 | } -------------------------------------------------------------------------------- /mscx-ad-discovery/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | jar 13 | 14 | com.sxzhongf 15 | mscx-ad-discovery 16 | 1.0-SNAPSHOT 17 | 服务发现组件 18 | 先使用eureka实现,后续会使用nacos替换掉 19 | 20 | 21 | 22 | org.springframework.cloud 23 | 24 | spring-cloud-starter-eureka-server 25 | 1.2.7.RELEASE 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-maven-plugin 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /mscx-ad-discovery/src/main/java/com/sxzhongf/ad/discovery/DiscoveryApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.discovery; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 | 7 | /** 8 | * DiscoveryApplication for 服务发现组件启动类 9 | * 10 | * @author Isaac.Zhang 11 | * @since 2019/6/12 12 | */ 13 | @SpringBootApplication 14 | @EnableEurekaServer 15 | public class DiscoveryApplication { 16 | 17 | public static void main(String[] args) { 18 | SpringApplication.run(DiscoveryApplication.class, args); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-discovery/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | ##注释为单节点服务发现配置 2 | #spring: 3 | # application: 4 | # name: ad-discovery-server 5 | #server: 6 | # port: 8888 7 | #eureka: 8 | # instance: 9 | # hostname: localhost #单机版 10 | # client: 11 | # fetch-registry: false #是否从eureka server获取注册信息 12 | # register-with-eureka: false #注册自己到eureka 13 | # service-url: 14 | # defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 15 | 16 | --- 17 | spring: 18 | application: 19 | name: ad-discovery 20 | profiles: server1 21 | server: 22 | port: 7777 23 | eureka: 24 | instance: 25 | hostname: server1 26 | prefer-ip-address: false 27 | client: 28 | service-url: 29 | defaultZone: http://server2:8888/eureka/,http://server3:9999/eureka/ 30 | 31 | --- 32 | spring: 33 | application: 34 | name: ad-discovery 35 | profiles: server2 36 | server: 37 | port: 8888 38 | eureka: 39 | instance: 40 | hostname: server2 41 | prefer-ip-address: false 42 | client: 43 | service-url: 44 | defaultZone: http://server1:7777/eureka/,http://server3:9999/eureka/ 45 | 46 | --- 47 | spring: 48 | application: 49 | name: ad-discovery 50 | profiles: server3 51 | server: 52 | port: 9999 53 | eureka: 54 | instance: 55 | hostname: server3 56 | prefer-ip-address: false 57 | client: 58 | service-url: 59 | defaultZone: http://server2:8888/eureka/,http://server1:7777/eureka/ -------------------------------------------------------------------------------- /mscx-ad-feign-sdk/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | jar 13 | mscx-ad-feign-sdk 14 | 只定义微服务Feign调用用到的请求对象和响应对象,而不涉及具体的实现类。 15 | 16 | com.sxzhongf 17 | mscx-ad-feign-sdk 18 | 1.0-SNAPSHOT 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-openfeign 28 | 29 | 30 | com.sxzhongf 31 | mscx-ad-common 32 | 1.0-SNAPSHOT 33 | 34 | 35 | 36 | org.springframework.cloud 37 | spring-cloud-starter-hystrix 38 | 1.2.7.RELEASE 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /mscx-ad-feign-sdk/src/main/java/com/sxzhongf/ad/feign/client/ISponsorFeignClient.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.feign.client; 2 | 3 | import com.sxzhongf.ad.common.vo.CommonResponse; 4 | import com.sxzhongf.ad.feign.client.vo.AdPlanGetRequestVO; 5 | import com.sxzhongf.ad.feign.client.vo.AdPlanVO; 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 | import org.springframework.web.bind.annotation.RequestParam; 11 | 12 | import java.util.List; 13 | 14 | /** 15 | * ISponsorFeignClient for service using 16 | * 17 | * @author Isaac.Zhang | 若初 18 | * @since 2019/6/21 19 | */ 20 | @FeignClient(value = "mscx-ad-sponsor", fallback = SponsorClientHystrix.class) 21 | public interface ISponsorFeignClient { 22 | @RequestMapping(value = "/ad-sponsor/plan/get", method = RequestMethod.POST) 23 | CommonResponse> getAdPlansUseFeign(@RequestBody AdPlanGetRequestVO requestVO); 24 | 25 | @RequestMapping(value = "/ad-sponsor/user/get", method = RequestMethod.GET) 26 | /** 27 | * Feign 埋坑之 如果是Get请求,必须在所有参数前添加{@link RequestParam},不能使用{@link Param} 28 | * 会被自动转发为POST请求。 29 | */ 30 | CommonResponse getUsers(@RequestParam(value = "username") String username); 31 | } 32 | -------------------------------------------------------------------------------- /mscx-ad-feign-sdk/src/main/java/com/sxzhongf/ad/feign/client/SponsorClientHystrix.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.feign.client; 2 | 3 | import com.sxzhongf.ad.common.vo.CommonResponse; 4 | import com.sxzhongf.ad.feign.client.vo.AdPlanGetRequestVO; 5 | import com.sxzhongf.ad.feign.client.vo.AdPlanVO; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * SponsorClientHystrix for TODO 12 | * 13 | * @author Isaac.Zhang | 若初 14 | * @since 2019/6/24 15 | */ 16 | @Component 17 | public class SponsorClientHystrix implements ISponsorFeignClient { 18 | @Override 19 | public CommonResponse> getAdPlansUseFeign(AdPlanGetRequestVO requestVO) { 20 | 21 | return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get plan error."); 22 | } 23 | 24 | @Override 25 | public CommonResponse getUsers(String username) { 26 | return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get user error."); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /mscx-ad-feign-sdk/src/main/java/com/sxzhongf/ad/feign/client/vo/AdPlanGetRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.feign.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * AdPlanGetRequestVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/21 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class AdPlanGetRequestVO { 19 | private Long userId; 20 | private List planIds; 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-feign-sdk/src/main/java/com/sxzhongf/ad/feign/client/vo/AdPlanVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.feign.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Date; 8 | 9 | /** 10 | * AdPlanVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/21 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class AdPlanVO { 19 | private Long planId; 20 | private Long userId; 21 | private String planName; 22 | private Integer planStatus; 23 | private Date startDate; 24 | private Date endDate; 25 | private Date createTime; 26 | private Date updateTime; 27 | } 28 | -------------------------------------------------------------------------------- /mscx-ad-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | com.sxzhongf 14 | mscx-ad-gateway 15 | 1.0-SNAPSHOT 16 | gateway网关提供 17 | 使用spring-cloud-gateway来提供服务网关实现 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-starter-gateway 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-actuator 27 | 28 | 29 | org.springframework.cloud 30 | spring-cloud-gateway-webflux 31 | 32 | 33 | 34 | org.springframework.cloud 35 | spring-cloud-starter-alibaba-nacos-discovery 36 | 0.9.0.RELEASE 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /mscx-ad-gateway/src/main/java/com/sxzhongf/ad/gateway/GatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.SpringCloudApplication; 6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | 9 | /** 10 | * GatewayApplication for spring-cloud-gateway网关启动类 11 | * {@link SpringCloudApplication} 是下面三个注解组合 12 | * 13 | * @author Isaac.Zhang 14 | * @see SpringBootApplication 15 | * @see EnableDiscoveryClient 16 | * @see EnableCircuitBreaker 17 | * @since 2019/6/13 18 | */ 19 | @SpringBootApplication 20 | @EnableDiscoveryClient 21 | public class GatewayApplication { 22 | 23 | public static void main(String[] args) { 24 | SpringApplication.run(GatewayApplication.class, args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /mscx-ad-gateway/src/main/java/com/sxzhongf/ad/gateway/filter/AccessLogFilter.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.cloud.gateway.filter.GatewayFilter; 5 | import org.springframework.cloud.gateway.filter.GatewayFilterChain; 6 | import org.springframework.core.Ordered; 7 | import org.springframework.stereotype.Component; 8 | import org.springframework.web.server.ServerWebExchange; 9 | import reactor.core.publisher.Mono; 10 | 11 | /** 12 | * AccessLogFilter for 实现请求调用前记录时间 13 | * 14 | * 在上面的代码中,Ordered中的int getOrder()方法是来给过滤器设定优先级别的,值越大则优先级越低。 15 | * 还有有一个filter(exchange,chain)方法,在该方法中,先记录了请求的开始时间, 16 | * 并保存在ServerWebExchange中,此处是一个“pre”类型的过滤器, 17 | * 然后再chain.filter的内部类中的run()方法中相当于"post"过滤器,在此处打印了请求所消耗的时间。 18 | * 然后将该过滤器注册到router中,代码如下: 19 | * 20 | * @author Isaac.Zhang 21 | * @since 2019/6/13 22 | */ 23 | @Slf4j 24 | @Component 25 | public class AccessLogFilter implements GatewayFilter,Ordered { 26 | 27 | @Override 28 | public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { 29 | exchange.getAttributes().put("api_request_time", System.currentTimeMillis()); 30 | return chain.filter(exchange).then( 31 | Mono.fromRunnable(() -> { 32 | Long startTime = exchange.getAttribute("api_request_time"); 33 | if (startTime != null) { 34 | log.info(exchange.getRequest().getURI().getRawPath() + ": " + (System.currentTimeMillis() - startTime) + "ms"); 35 | } 36 | }) 37 | ); 38 | } 39 | 40 | @Override 41 | public int getOrder() { 42 | return 0; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mscx-ad-gateway/src/main/java/com/sxzhongf/ad/gateway/filter/CORSFilter.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.cloud.gateway.filter.GatewayFilter; 5 | import org.springframework.cloud.gateway.filter.GatewayFilterChain; 6 | import org.springframework.http.HttpHeaders; 7 | import org.springframework.http.HttpMethod; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.server.reactive.ServerHttpRequest; 10 | import org.springframework.http.server.reactive.ServerHttpResponse; 11 | import org.springframework.stereotype.Component; 12 | import org.springframework.web.cors.reactive.CorsUtils; 13 | import org.springframework.web.server.ServerWebExchange; 14 | import org.springframework.web.server.WebFilter; 15 | import org.springframework.web.server.WebFilterChain; 16 | import reactor.core.publisher.Mono; 17 | 18 | /** 19 | * CORSFilter for 过滤CORS请求 20 | * 21 | * @author Isaac.Zhang 22 | * @since 2019/6/13 23 | */ 24 | @Slf4j 25 | @Component 26 | public class CORSFilter implements WebFilter { 27 | 28 | private static final String ALLOWED_HEADERS = "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN"; 29 | private static final String ALLOWED_METHODS = "GET, PUT, POST, DELETE, OPTIONS"; 30 | private static final String ALLOWED_ORIGIN = "*"; 31 | private static final String MAX_AGE = "3600"; 32 | 33 | /** 34 | * 通过自定义WebFilter, 配置CORS 35 | */ 36 | @Override 37 | public Mono filter(ServerWebExchange ctx, WebFilterChain chain) { 38 | ServerHttpRequest request = ctx.getRequest(); 39 | if (CorsUtils.isCorsRequest(request)) { 40 | ServerHttpResponse response = ctx.getResponse(); 41 | HttpHeaders headers = response.getHeaders(); 42 | headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN); 43 | headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS); 44 | headers.add("Access-Control-Max-Age", MAX_AGE); 45 | headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS); 46 | if (request.getMethod() == HttpMethod.OPTIONS) { 47 | response.setStatusCode(HttpStatus.OK); 48 | return Mono.empty(); 49 | } 50 | } 51 | return chain.filter(ctx); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /mscx-ad-gateway/src/main/java/com/sxzhongf/ad/gateway/filter/TokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway.filter; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import org.springframework.cloud.gateway.filter.GatewayFilterChain; 5 | import org.springframework.cloud.gateway.filter.GlobalFilter; 6 | import org.springframework.core.Ordered; 7 | import org.springframework.http.HttpStatus; 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.web.server.ServerWebExchange; 10 | import reactor.core.publisher.Mono; 11 | 12 | /** 13 | * TokenFilter for 全局token校验过滤器 14 | * 15 | * @author Isaac.Zhang 16 | * @since 2019/6/13 17 | */ 18 | @Slf4j 19 | @Component 20 | public class TokenFilter implements GlobalFilter, Ordered { 21 | 22 | @Override 23 | public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { 24 | String token = exchange.getRequest().getQueryParams().getFirst("token"); 25 | if (token == null || token.isEmpty()) { 26 | log.info("token is empty..."); 27 | exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); 28 | return exchange.getResponse().setComplete(); 29 | } 30 | return chain.filter(exchange); 31 | } 32 | 33 | @Override 34 | public int getOrder() { 35 | return Ordered.HIGHEST_PRECEDENCE - 1; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /mscx-ad-gateway/src/main/java/com/sxzhongf/ad/gateway/route/GatewayRoutes.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway.route; 2 | 3 | import com.sxzhongf.ad.gateway.filter.AccessLogFilter; 4 | import lombok.extern.slf4j.Slf4j; 5 | import org.springframework.cloud.gateway.route.RouteLocator; 6 | import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | /** 10 | * GatewayRoutes for TODO 11 | * 12 | * @author Isaac.Zhang 13 | * @since 2019/6/13 14 | */ 15 | @Slf4j 16 | @Configuration 17 | public class GatewayRoutes { 18 | 19 | /** 20 | * 通过Fluent API配置的其他路由断言 21 | * 等价于配置文件yml中的 22 | * {code} 23 | * cloud: 24 | * gateway: 25 | * routes: 26 | * - id: service_to_zuul_gateway #自定义路由id 27 | * uri: ad-gateway-zuul:1111 28 | * predicate: 29 | * - Path=/api-zuul/** 30 | * {/code} 31 | */ 32 | public RouteLocator routeLocator(RouteLocatorBuilder builder) { 33 | return builder.routes() 34 | .route("zuul-gateway-to-spring-gateway", r -> r.host("**.yi23.net") 35 | .and() 36 | .header("X-Next-Url") 37 | .uri("ad-gateway-zuul:1111") 38 | .filters( 39 | new AccessLogFilter() //注册自定义filter 40 | ) 41 | ) 42 | .route(r -> r.host("**.yi23.net") 43 | .and() 44 | .query("url") 45 | .uri("http://sxzhongf.com")) 46 | .build(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /mscx-ad-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | #study from https://blog.csdn.net/forezp/article/details/85057268 2 | spring: 3 | application: 4 | name: ad-gateway 5 | cloud: 6 | gateway: 7 | routes: 8 | id: service_to_zuul_gateway #自定义路由id 9 | uri: ad-gateway-zuul:1111 10 | predicate: 11 | - Path=/api-zuul/** 12 | discovery: 13 | locator: 14 | enabled: true 15 | nacos: 16 | discovery: 17 | server-addr: 127.0.0.1:8848 18 | server: 19 | port: 2222 20 | #eureka: 21 | # instance: 22 | # hostname: ad-gateway 23 | # client: 24 | # service-url: 25 | # defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ 26 | management: 27 | endpoints: 28 | web: 29 | exposure: 30 | include: '*' 31 | # exclude: -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/AdSearchApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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.hystrix.EnableHystrix; 9 | import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard; 10 | import org.springframework.cloud.openfeign.EnableFeignClients; 11 | import org.springframework.context.annotation.Bean; 12 | import org.springframework.web.client.RestTemplate; 13 | 14 | /** 15 | * AdSearchApplication for 广告搜索服务启动类 16 | * 17 | * @author Isaac.Zhang | 若初 18 | * @since 2019/6/21 19 | */ 20 | @EnableFeignClients //启动Feign 客户端,为了访问其他微服务 21 | @EnableDiscoveryClient // 开启服务发现组件,在这里等同于 @EnableEurekaClient 22 | @EnableHystrix // 开启hystrix 断路器 23 | @EnableCircuitBreaker // 断路器 24 | @EnableHystrixDashboard // 开启hystrix 监控 25 | @SpringBootApplication 26 | public class AdSearchApplication { 27 | public static void main(String[] args) { 28 | SpringApplication.run(AdSearchApplication.class, args); 29 | } 30 | 31 | /** 32 | * 注册{@link RestTemplate}Bean 33 | * @return 34 | */ 35 | @Bean 36 | @LoadBalanced 37 | RestTemplate restTemplate(){ 38 | return new RestTemplate(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/client/ISponsorFeignClient.java: -------------------------------------------------------------------------------- 1 | //package com.sxzhongf.ad.client; 2 | // 3 | //import com.sxzhongf.ad.client.vo.AdPlanGetRequestVO; 4 | //import com.sxzhongf.ad.client.vo.AdPlanVO; 5 | //import com.sxzhongf.ad.common.vo.CommonResponse; 6 | //import org.springframework.cloud.openfeign.FeignClient; 7 | //import org.springframework.data.repository.query.Param; 8 | //import org.springframework.web.bind.annotation.RequestBody; 9 | //import org.springframework.web.bind.annotation.RequestMapping; 10 | //import org.springframework.web.bind.annotation.RequestMethod; 11 | //import org.springframework.web.bind.annotation.RequestParam; 12 | // 13 | //import java.util.List; 14 | // 15 | ///** 16 | // * ISponsorFeignClient for service using 17 | // * 18 | // * @author Isaac.Zhang | 若初 19 | // * @since 2019/6/21 20 | // */ 21 | //@FeignClient(value = "mscx-ad-sponsor", fallback = SponsorClientHystrix.class) 22 | //public interface ISponsorFeignClient { 23 | // @RequestMapping(value = "/ad-sponsor/plan/get", method = RequestMethod.POST) 24 | // CommonResponse> getAdPlansUseFeign(@RequestBody AdPlanGetRequestVO requestVO); 25 | // 26 | // @RequestMapping(value = "/ad-sponsor/user/get", method = RequestMethod.GET) 27 | // /** 28 | // * Feign 埋坑之 如果是Get请求,必须在所有参数前添加{@link RequestParam},不能使用{@link Param} 29 | // * 会被自动转发为POST请求。 30 | // */ 31 | // CommonResponse getUsers(@RequestParam(value = "username") String username); 32 | //} 33 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/client/SponsorClientHystrix.java: -------------------------------------------------------------------------------- 1 | //package com.sxzhongf.ad.client; 2 | // 3 | //import com.sxzhongf.ad.client.vo.AdPlanGetRequestVO; 4 | //import com.sxzhongf.ad.client.vo.AdPlanVO; 5 | //import com.sxzhongf.ad.common.vo.CommonResponse; 6 | //import org.springframework.stereotype.Component; 7 | // 8 | //import java.util.List; 9 | // 10 | ///** 11 | // * SponsorClientHystrix for TODO 12 | // * 13 | // * @author Isaac.Zhang | 若初 14 | // * @since 2019/6/24 15 | // */ 16 | //@Component 17 | //public class SponsorClientHystrix implements ISponsorFeignClient { 18 | // @Override 19 | // public CommonResponse> getAdPlansUseFeign(AdPlanGetRequestVO requestVO) { 20 | // 21 | // return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get plan error."); 22 | // } 23 | // 24 | // @Override 25 | // public CommonResponse getUsers(String username) { 26 | // return new CommonResponse<>(-1, "mscx-ad-sponsor feign & hystrix get user error."); 27 | // } 28 | //} 29 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/client/vo/AdPlanGetRequestVO.java: -------------------------------------------------------------------------------- 1 | //package com.sxzhongf.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 | // * AdPlanGetRequestVO for TODO 11 | // * 12 | // * @author Isaac.Zhang | 若初 13 | // * @since 2019/6/21 14 | // */ 15 | //@Data 16 | //@NoArgsConstructor 17 | //@AllArgsConstructor 18 | //public class AdPlanGetRequestVO { 19 | // private Long userId; 20 | // private List planIds; 21 | //} 22 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/client/vo/AdPlanVO.java: -------------------------------------------------------------------------------- 1 | //package com.sxzhongf.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 | // * AdPlanVO for TODO 11 | // * 12 | // * @author Isaac.Zhang | 若初 13 | // * @since 2019/6/21 14 | // */ 15 | //@Data 16 | //@AllArgsConstructor 17 | //@NoArgsConstructor 18 | //public class AdPlanVO { 19 | // private Long planId; 20 | // private Long userId; 21 | // private String planName; 22 | // private Integer planStatus; 23 | // private Date startDate; 24 | // private Date endDate; 25 | // private Date createTime; 26 | // private Date updateTime; 27 | //} 28 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/config/BinlogConfig.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.config; 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.stereotype.Component; 8 | 9 | /** 10 | * BinlogConfig for 定义监听Binlog的配置信息 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/27 14 | */ 15 | @Component 16 | @ConfigurationProperties(prefix = "adconf.mysql") 17 | @Data 18 | @AllArgsConstructor 19 | @NoArgsConstructor 20 | public class BinlogConfig { 21 | 22 | private String host; 23 | private Integer port; 24 | private String username; 25 | private String password; 26 | 27 | private String binlogName; 28 | private Long position; 29 | } 30 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/controller/SearchController.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; 5 | import com.sxzhongf.ad.common.annotation.IgnoreResponseAdvice; 6 | import com.sxzhongf.ad.common.vo.CommonResponse; 7 | import com.sxzhongf.ad.feign.client.vo.AdPlanGetRequestVO; 8 | import com.sxzhongf.ad.feign.client.vo.AdPlanVO; 9 | import com.sxzhongf.ad.search.ISearch; 10 | import com.sxzhongf.ad.search.vo.SearchRequest; 11 | import com.sxzhongf.ad.search.vo.SearchResponse; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.data.repository.query.Param; 15 | import org.springframework.web.bind.annotation.*; 16 | import org.springframework.web.client.RestTemplate; 17 | 18 | import java.util.List; 19 | 20 | /** 21 | * SearchController for search information controller 22 | * 23 | * @author Isaac.Zhang | 若初 24 | * @since 2019/6/21 25 | */ 26 | @RestController 27 | @Slf4j 28 | @RequestMapping(path = "/search") 29 | public class SearchController { 30 | 31 | private final RestTemplate restTemplate; 32 | 33 | private final ISearch search; 34 | 35 | @Autowired 36 | public SearchController(RestTemplate restTemplate, ISearch search) { 37 | this.restTemplate = restTemplate; 38 | this.search = search; 39 | } 40 | 41 | @PostMapping(path = "/plan/get-ribbon") 42 | @IgnoreResponseAdvice //如果打上这个标记,我们的统一拦截就会忽略掉它 43 | public CommonResponse> getAdPlansUseRibbon(@RequestBody AdPlanGetRequestVO requestVO) { 44 | log.info("ad-search::getAdPlansUseRibbon -> {}", JSON.toJSONString(requestVO)); 45 | return restTemplate.postForEntity( 46 | "http://mscx-ad-sponsor/ad-sponsor/plan/get", requestVO, CommonResponse.class 47 | ).getBody(); 48 | } 49 | 50 | @GetMapping(path = "/user/get") 51 | public CommonResponse getUsers(@Param(value = "username") String username) { 52 | log.info("ad-search::getUsers -> {}", JSON.toJSONString(username)); 53 | CommonResponse commonResponse = restTemplate.getForObject( 54 | "http://mscx-ad-sponsor/ad-sponsor/user/get?username={username}", CommonResponse.class, username 55 | ); 56 | 57 | return commonResponse; 58 | } 59 | 60 | @PostMapping("/fetchAd") 61 | public SearchResponse fetchAdCreative(@RequestBody SearchRequest request) { 62 | log.info("ad-serach: fetchAd ->{}", JSON.toJSONString(request)); 63 | return search.fetchAds(request); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/controller/SearchFeignController.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sxzhongf.ad.common.vo.CommonResponse; 5 | import com.sxzhongf.ad.feign.client.ISponsorFeignClient; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.data.repository.query.Param; 9 | import org.springframework.web.bind.annotation.GetMapping; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | /** 14 | * SearchFeignController for TODO 15 | * 16 | * @author Isaac.Zhang | 若初 17 | * @since 2019/6/21 18 | */ 19 | @RestController 20 | @Slf4j 21 | @RequestMapping(path = "/search-feign") 22 | public class SearchFeignController { 23 | 24 | /** 25 | * 注入我们自定义的FeignClient 26 | */ 27 | private final ISponsorFeignClient sponsorFeignClient; 28 | @Autowired 29 | public SearchFeignController(ISponsorFeignClient sponsorFeignClient) { 30 | this.sponsorFeignClient = sponsorFeignClient; 31 | } 32 | 33 | @GetMapping(path = "/user/get") 34 | public CommonResponse getUsers(@Param(value = "username") String username) { 35 | log.info("ad-search::getUsersFeign -> {}", JSON.toJSONString(username)); 36 | CommonResponse commonResponse = sponsorFeignClient.getUsers(username); 37 | return commonResponse; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/AdDataLevel.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * AdDataLevel for 广告数据层级 7 | * 8 | * @author Isaac.Zhang | 若初 9 | * @since 2019/6/27 10 | */ 11 | @Getter 12 | public enum AdDataLevel { 13 | 14 | LEVEL2("2", "level 2"), 15 | LEVEL3("3", "level 3"), 16 | LEVEL4("4", "level 4"); 17 | 18 | private String level; 19 | private String desc; 20 | 21 | AdDataLevel(String level, String desc) { 22 | this.level = level; 23 | this.desc = desc; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/CommonStatus.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * CommonStatus for 推广单元和推广创意的状态 8 | * 9 | * @author Isaac.Zhang | 若初 10 | * @since 2019/8/12 11 | */ 12 | @Getter 13 | @AllArgsConstructor 14 | public enum CommonStatus { 15 | VALID(1, "有效状态"), 16 | INVALID(0, "无效状态"); 17 | 18 | private Integer status; 19 | private String desc; 20 | } 21 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/IIndexAware.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index; 2 | 3 | /** 4 | * IIndexAware for 实现广告索引的增删改查 5 | * 6 | * @author Isaac.Zhang | 若初 7 | * @since 2019/6/24 8 | */ 9 | public interface IIndexAware { 10 | 11 | /** 12 | * 通过key 获取索引 13 | */ 14 | V get(K key); 15 | 16 | /** 17 | * 添加索引 18 | * @param key 19 | * @param value 20 | */ 21 | void add(K key, V value); 22 | 23 | /** 24 | * 更新索引 25 | */ 26 | void update(K key, V value); 27 | 28 | /** 29 | * 删除索引 30 | */ 31 | void delete(K key, V value); 32 | } 33 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/IndexDataTableUtils.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Map; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | /** 13 | * IndexDataTableUtils for 所有索引服务需要缓存的Java Bean 14 | * Spring中以Aware结尾的接口,表明我想要某某某, 15 | * 比如 XXXAware表明当前实现类想要XXX 16 | * {@link ApplicationContextAware} 表明当前类想要一个 ApplicationContext 17 | * 18 | * 使用方式: 19 | * 获取{@link com.sxzhongf.ad.index.creative.CreativeIndexAwareImpl}索引服务类 20 | * 如下: 21 | * {@code 22 | * IndexDataTableUtils.of(CreativeIndexAwareImpl.class) 23 | * } 24 | * @author Isaac.Zhang | 若初 25 | * @since 2019/6/25 26 | */ 27 | @Component 28 | public class IndexDataTableUtils implements ApplicationContextAware, PriorityOrdered { 29 | 30 | //注入ApplicationContext 31 | private static ApplicationContext applicationContext; 32 | 33 | /** 34 | * 定义用于保存所有Index的Map 35 | * Class标示我们的索引类 36 | */ 37 | private static final Map dataTableMap = new ConcurrentHashMap<>(); 38 | 39 | @Override 40 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 41 | IndexDataTableUtils.applicationContext = applicationContext; 42 | } 43 | 44 | /** 45 | * 获取索引服务缓存 46 | */ 47 | public static T of(Class klass) { 48 | T instance = (T) dataTableMap.get(klass); 49 | //如果获取到索引bean,直接返回当前bean 50 | if (null != instance) { 51 | return instance; 52 | } 53 | //首次获取索引bean为空,写入Map 54 | dataTableMap.put(klass, bean(klass)); 55 | return (T) dataTableMap.get(klass); 56 | } 57 | 58 | /** 59 | * 获取Spring 容器中的Bean对象 60 | */ 61 | private static T bean(String beanName) { 62 | return (T) applicationContext.getBean(beanName); 63 | } 64 | 65 | /** 66 | * 获取Spring 容器中的Bean对象 67 | */ 68 | private static T bean(Class klass) { 69 | return (T) applicationContext.getBean(klass); 70 | } 71 | 72 | @Override 73 | public int getOrder() { 74 | return PriorityOrdered.HIGHEST_PRECEDENCE; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/adplan/AdPlanIndexAwareImpl.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.adplan; 2 | 3 | import com.sxzhongf.ad.index.IIndexAware; 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 | * AdPlanIndexAwareImpl for 推广计划索引实现类 12 | * 13 | * @author Isaac.Zhang | 若初 14 | * @since 2019/6/24 15 | */ 16 | @Slf4j 17 | @Component 18 | public class AdPlanIndexAwareImpl implements IIndexAware { 19 | 20 | private static Map planIndexObjectMap; 21 | 22 | /** 23 | * 为了防止多线程造成的线程不安全问题,我们不能使用hashmap,需要实现ConcurrentHashMap 24 | */ 25 | static { 26 | planIndexObjectMap = new ConcurrentHashMap<>(); 27 | } 28 | 29 | @Override 30 | public AdPlanIndexObject get(Long key) { 31 | return planIndexObjectMap.get(key); 32 | } 33 | 34 | @Override 35 | public void add(Long key, AdPlanIndexObject value) { 36 | 37 | log.info("AdPlanIndexAwareImpl before add::{}", planIndexObjectMap); 38 | planIndexObjectMap.put(key, value); 39 | log.info("AdPlanIndexAwareImpl after add::{}", planIndexObjectMap); 40 | } 41 | 42 | @Override 43 | public void update(Long key, AdPlanIndexObject value) { 44 | 45 | log.info("AdPlanIndexAwareImpl before update::{}", planIndexObjectMap); 46 | 47 | //查询当前的索引信息,如果不存在,直接新增索引信息 48 | AdPlanIndexObject oldObj = planIndexObjectMap.get(key); 49 | if (null == oldObj) { 50 | planIndexObjectMap.put(key, value); 51 | } else { 52 | oldObj.update(value); 53 | } 54 | 55 | log.info("AdPlanIndexAwareImpl after update::{}", planIndexObjectMap); 56 | } 57 | 58 | @Override 59 | public void delete(Long key, AdPlanIndexObject value) { 60 | 61 | log.info("AdPlanIndexAwareImpl before delete::{}", planIndexObjectMap); 62 | planIndexObjectMap.remove(key); 63 | log.info("AdPlanIndexAwareImpl after delete::{}", planIndexObjectMap); 64 | 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/adplan/AdPlanIndexObject.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * AdPlanIndexObject for 推广计划索引对象 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/24 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class AdPlanIndexObject { 19 | 20 | private Long planId; 21 | private Long userId; 22 | private Integer planStatus; 23 | private Date startDate; 24 | private Date endDate; 25 | 26 | public void update(AdPlanIndexObject newObject) { 27 | 28 | if (null != newObject.getPlanId()) { 29 | this.planId = newObject.getPlanId(); 30 | } 31 | if (null != newObject.getUserId()) { 32 | this.userId = newObject.getUserId(); 33 | } 34 | if (null != newObject.getPlanStatus()) { 35 | this.planStatus = newObject.getPlanStatus(); 36 | } 37 | if (null != newObject.getStartDate()) { 38 | this.startDate = newObject.getStartDate(); 39 | } 40 | if (null != newObject.getEndDate()) { 41 | this.endDate = newObject.getEndDate(); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/adunit/AdUnitConstants.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.adunit; 2 | 3 | /** 4 | * AdUnitConstants for TODO 5 | * 6 | * @author Isaac.Zhang | 若初 7 | * @since 2019/8/10 8 | */ 9 | 10 | public class AdUnitConstants { 11 | 12 | public static class PositionType { 13 | //App启动时展示的、展示时间短暂的全屏化广告形式。 14 | public static final int KAIPING = 1; 15 | //电影开始之前的广告 16 | public static final int TIEPIAN = 2; 17 | //电影播放中途广告 18 | public static final int TIEPIAN_MIDDLE = 4; 19 | //暂停视频时候播放的广告 20 | public static final int TIEPIAN_PAUSE = 8; 21 | //视频播放完 22 | public static final int TIEPIAN_POST = 16; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/adunit/AdUnitIndexAwareImpl.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.adunit; 2 | 3 | import com.sxzhongf.ad.index.IIndexAware; 4 | import com.sxzhongf.ad.index.adplan.AdPlanIndexObject; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.springframework.stereotype.Component; 7 | import org.springframework.util.CollectionUtils; 8 | 9 | import java.util.*; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | /** 13 | * AdUnitIndexAwareImpl for 推广单元索引实现类 14 | * 15 | * @author Isaac.Zhang | 若初 16 | * @since 2019/6/24 17 | */ 18 | @Slf4j 19 | @Component 20 | public class AdUnitIndexAwareImpl implements IIndexAware { 21 | 22 | private static Map objectMap; 23 | 24 | /** 25 | * 为了防止多线程造成的线程不安全问题,我们不能使用hashmap,需要实现ConcurrentHashMap 26 | */ 27 | static { 28 | objectMap = new ConcurrentHashMap<>(); 29 | } 30 | 31 | /** 32 | * 过滤当前是否存在满足positionType的UnitIds 33 | */ 34 | public Set match(Integer positionType) { 35 | Set adUnitIds = new HashSet<>(); 36 | objectMap.forEach((k, v) -> { 37 | if (AdUnitIndexObject.isAdSlotType(positionType, v.getPositionType())) { 38 | adUnitIds.add(k); 39 | } 40 | }); 41 | return adUnitIds; 42 | } 43 | 44 | /** 45 | * 根据UnitIds查询AdUnit list 46 | */ 47 | public List fetch(Collection adUnitIds) { 48 | if (CollectionUtils.isEmpty(adUnitIds)) { 49 | return Collections.EMPTY_LIST; 50 | } 51 | List result = new ArrayList<>(); 52 | adUnitIds.forEach(id -> { 53 | AdUnitIndexObject object = get(id); 54 | if (null == object) { 55 | log.error("AdUnitIndexObject does not found:{}", id); 56 | return; 57 | } 58 | result.add(object); 59 | }); 60 | 61 | return result; 62 | } 63 | 64 | @Override 65 | public AdUnitIndexObject get(Long key) { 66 | return objectMap.get(key); 67 | } 68 | 69 | @Override 70 | public void add(Long key, AdUnitIndexObject value) { 71 | 72 | log.info("AdUnitIndexAwareImpl before add::{}", objectMap); 73 | objectMap.put(key, value); 74 | log.info("AdUnitIndexAwareImpl after add::{}", objectMap); 75 | } 76 | 77 | @Override 78 | public void update(Long key, AdUnitIndexObject value) { 79 | log.info("AdUnitIndexAwareImpl before update::{}", objectMap); 80 | 81 | AdUnitIndexObject oldObj = objectMap.get(key); 82 | if (null == oldObj) { 83 | objectMap.put(key, value); 84 | } else { 85 | oldObj.update(value); 86 | } 87 | 88 | log.info("AdUnitIndexAwareImpl after update::{}", objectMap); 89 | } 90 | 91 | @Override 92 | public void delete(Long key, AdUnitIndexObject value) { 93 | log.info("AdUnitIndexAwareImpl before delete::{}", objectMap); 94 | objectMap.remove(key); 95 | log.info("AdUnitIndexAwareImpl after delete::{}", objectMap); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/adunit/AdUnitIndexObject.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.adunit; 2 | 3 | import com.sxzhongf.ad.index.adplan.AdPlanIndexObject; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * AdUnitIndexObject for TODO 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/6/24 13 | */ 14 | @Data 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | public class AdUnitIndexObject { 18 | 19 | private Long unitId; 20 | private Long planId; 21 | private Integer unitStatus; 22 | private Integer positionType; 23 | 24 | private AdPlanIndexObject adPlanIndexObject; 25 | 26 | void update(AdUnitIndexObject newObject) { 27 | if (null != newObject.getUnitId()) { 28 | this.unitId = newObject.getUnitId(); 29 | } 30 | if (null != newObject.getPlanId()) { 31 | this.planId = newObject.getPlanId(); 32 | } 33 | if (null != newObject.getUnitStatus()) { 34 | this.unitStatus = newObject.getUnitStatus(); 35 | } 36 | if (null != newObject.getPositionType()) { 37 | this.positionType = newObject.getPositionType(); 38 | } 39 | if (null != newObject.getAdPlanIndexObject()) { 40 | this.adPlanIndexObject = newObject.getAdPlanIndexObject(); 41 | } 42 | } 43 | 44 | public static boolean isAdSlotType(int adSlotType, int positionType) { 45 | switch (adSlotType) { 46 | case AdUnitConstants.PositionType.KAIPING: 47 | return isKaiPing(positionType); 48 | case AdUnitConstants.PositionType.TIEPIAN: 49 | return isTiePian(positionType); 50 | case AdUnitConstants.PositionType.TIEPIAN_MIDDLE: 51 | return isTiePianMiddle(positionType); 52 | case AdUnitConstants.PositionType.TIEPIAN_PAUSE: 53 | return isTiePianPause(positionType); 54 | case AdUnitConstants.PositionType.TIEPIAN_POST: 55 | return isTiePianPost(positionType); 56 | default: 57 | return false; 58 | } 59 | } 60 | 61 | /** 62 | * 与运算,低位取等,高位补零。 63 | * 如果 > 0,则为开屏 64 | */ 65 | private static boolean isKaiPing(int positionType) { 66 | return (positionType & AdUnitConstants.PositionType.KAIPING) > 0; 67 | } 68 | 69 | /** 70 | * ? & 0000 0100 71 | * 如果为 positionType 1 72 | * 0000 0001 73 | * 0000 0100 74 | * 0000 0000 < 0 75 | * 如果为 positionType 2 76 | * 0000 0010 77 | * 0000 0100 78 | * 0000 0000 < 0 79 | * 如果为 positionType 8 80 | * 0000 1000 81 | * 0000 0100 82 | * 0000 0000 < 0 83 | * 如果为 positionType 16 84 | * 0001 0000 85 | * 0000 0100 86 | * 0000 0000 < 0 87 | */ 88 | private static boolean isTiePianMiddle(int positionType) { 89 | return (positionType & AdUnitConstants.PositionType.TIEPIAN_MIDDLE) > 0; 90 | } 91 | 92 | private static boolean isTiePianPause(int positionType) { 93 | return (positionType & AdUnitConstants.PositionType.TIEPIAN_PAUSE) > 0; 94 | } 95 | 96 | private static boolean isTiePianPost(int positionType) { 97 | return (positionType & AdUnitConstants.PositionType.TIEPIAN_POST) > 0; 98 | } 99 | 100 | private static boolean isTiePian(int positionType) { 101 | return (positionType & AdUnitConstants.PositionType.TIEPIAN) > 0; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/creative/CreativeIndexAwareImpl.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.creative; 2 | 3 | import com.sxzhongf.ad.index.IIndexAware; 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 | * CreativeIndexAwareImpl for 创意索引实现类 13 | * 14 | * @author Isaac.Zhang | 若初 15 | * @since 2019/6/25 16 | */ 17 | @Slf4j 18 | @Component 19 | public class CreativeIndexAwareImpl implements IIndexAware { 20 | 21 | //正向索引对象 22 | private static Map objectMap; 23 | 24 | static { 25 | objectMap = new ConcurrentHashMap<>(); 26 | } 27 | 28 | /** 29 | * 根据ids获取创意list 30 | */ 31 | public List fetch(Collection ids) { 32 | if (CollectionUtils.isEmpty(ids)) return Collections.emptyList(); 33 | List result = new ArrayList<>(); 34 | 35 | for (Long id : ids) { 36 | CreativeIndexObject object = get(id); 37 | if (null != object) 38 | result.add(object); 39 | } 40 | 41 | return result; 42 | } 43 | 44 | @Override 45 | public CreativeIndexObject get(Long key) { 46 | return objectMap.get(key); 47 | } 48 | 49 | @Override 50 | public void add(Long key, CreativeIndexObject value) { 51 | log.info("CreativeIndexAwareImpl:: before add :{}", objectMap); 52 | objectMap.put(key, value); 53 | log.info("CreativeIndexAwareImpl:: after add :{}", objectMap); 54 | } 55 | 56 | @Override 57 | public void update(Long key, CreativeIndexObject value) { 58 | log.info("CreativeIndexAwareImpl:: before update :{}", objectMap); 59 | 60 | CreativeIndexObject oldObject = objectMap.get(key); 61 | if (null == oldObject) { 62 | objectMap.put(key, value); 63 | } else { 64 | oldObject.update(value); 65 | } 66 | 67 | log.info("CreativeIndexAwareImpl:: after update :{}", objectMap); 68 | 69 | } 70 | 71 | @Override 72 | public void delete(Long key, CreativeIndexObject value) { 73 | log.info("CreativeIndexAwareImpl:: before add :{}", objectMap); 74 | objectMap.remove(key); 75 | log.info("CreativeIndexAwareImpl:: after add :{}", objectMap); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/creative/CreativeIndexObject.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.creative; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * CreativeIndexObject for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class CreativeIndexObject { 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 | public void update(CreativeIndexObject newObject) { 28 | 29 | if (null != newObject.getAdId()) { 30 | this.adId = newObject.getAdId(); 31 | } 32 | if (null != newObject.getName()) { 33 | this.name = newObject.getName(); 34 | } 35 | if (null != newObject.getType()) { 36 | this.type = newObject.getType(); 37 | } 38 | if (null != newObject.getMaterialType()) { 39 | this.materialType = newObject.getMaterialType(); 40 | } 41 | if (null != newObject.getHeight()) { 42 | this.height = newObject.getHeight(); 43 | } 44 | if (null != newObject.getWidth()) { 45 | this.width = newObject.getWidth(); 46 | } 47 | if (null != newObject.getAuditStatus()) { 48 | this.auditStatus = newObject.getAuditStatus(); 49 | } 50 | if (null != newObject.getAdUrl()) { 51 | this.adUrl = newObject.getAdUrl(); 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/creative_relation_unit/CreativeRelationUnitIndexObject.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.creative_relation_unit; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * CreativeRelationUnitIndexObject for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/25 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class CreativeRelationUnitIndexObject { 17 | /** 18 | * 创意/广告ID 19 | */ 20 | private Long adId; 21 | /** 22 | * 推广单元ID 23 | */ 24 | private Long unitId; 25 | } 26 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/district/UnitDistrictIndexObject.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.district; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * UnitDistrictIndexObject for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/24 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class UnitDistrictIndexObject { 17 | private Long unitId; 18 | private String province; 19 | private String city; 20 | 21 | //Map> 22 | //Map的key为 province-city 23 | } 24 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/hobby/UnitHobbyIndexAwareImpl.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.hobby; 2 | 3 | import com.sxzhongf.ad.index.IIndexAware; 4 | import com.sxzhongf.ad.utils.CommonUtils; 5 | import lombok.extern.slf4j.Slf4j; 6 | import org.apache.commons.collections4.CollectionUtils; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.Set; 12 | import java.util.concurrent.ConcurrentHashMap; 13 | import java.util.concurrent.ConcurrentSkipListSet; 14 | 15 | /** 16 | * UnitHobbyIndexAwareImpl for 推广单元<->兴趣索引实现类 17 | * 18 | * @author Isaac.Zhang | 若初 19 | * @since 2019/6/24 20 | */ 21 | @Slf4j 22 | @Component 23 | public class UnitHobbyIndexAwareImpl implements IIndexAware> { 24 | 25 | //反向索引,根据兴趣标签查询关联的 unit ids 26 | private static Map> hobbyRelationUnitsMap; 27 | private static Map> unitRelationHobbiesMap; 28 | 29 | static { 30 | hobbyRelationUnitsMap = new ConcurrentHashMap<>(); 31 | unitRelationHobbiesMap = new ConcurrentHashMap<>(); 32 | } 33 | 34 | @Override 35 | public Set get(String key) { 36 | return hobbyRelationUnitsMap.get(key); 37 | } 38 | 39 | @Override 40 | public void add(String key, Set value) { 41 | log.info("UnitHobbyIndexAwareImpl::unitRelationHobbiesMap, before add :{}", unitRelationHobbiesMap); 42 | //获取兴趣标签对应的推广单元id Set 43 | Set unitIdSet = CommonUtils.getOrCreate( 44 | key, hobbyRelationUnitsMap, ConcurrentSkipListSet::new 45 | ); 46 | unitIdSet.addAll(value); 47 | 48 | // 循环添加 每个兴趣标签对应的 关键词Set 49 | for (Long hobbyId : value) { 50 | Set hobbySet = CommonUtils.getOrCreate( 51 | hobbyId, unitRelationHobbiesMap, ConcurrentSkipListSet::new 52 | ); 53 | hobbySet.add(key); 54 | } 55 | log.info("UnitHobbyIndexAwareImpl::unitRelationHobbiesMap, after add :{}", unitRelationHobbiesMap); 56 | 57 | } 58 | 59 | @Override 60 | public void update(String key, Set value) { 61 | log.info("UnitHobbyIndexAwareImpl::unitRelationHobbiesMap, can not support update,因为会遍历Set,直接删除后重新添加"); 62 | } 63 | 64 | @Override 65 | public void delete(String key, Set value) { 66 | log.info("UnitHobbyIndexAwareImpl::unitRelationHobbiesMap, before delete :{}", unitRelationHobbiesMap); 67 | //根据key获取全量的 推广单元ids,然后移除部分或者全部(value) 68 | Set unitIds = CommonUtils.getOrCreate(key, hobbyRelationUnitsMap, ConcurrentSkipListSet::new); 69 | unitIds.removeAll(value); 70 | 71 | for (Long unitId : value) { 72 | //根据UnitId获取hobby Set 73 | Set hobbySet = CommonUtils.getOrCreate(unitId, unitRelationHobbiesMap, ConcurrentSkipListSet::new); 74 | hobbySet.remove(key); 75 | } 76 | log.info("UnitHobbyIndexAwareImpl::unitRelationHobbiesMap, after delete :{}", unitRelationHobbiesMap); 77 | 78 | } 79 | 80 | /** 81 | * 查看索引中是否存在当前推广单元和关键词信息 82 | */ 83 | public boolean match(Long unitId, List unitHobbies) { 84 | //判断当前索引中是否存在当前推广计划 85 | if (unitRelationHobbiesMap.containsKey(unitId) 86 | && CollectionUtils.isNotEmpty(unitRelationHobbiesMap.get(unitId))) { 87 | Set unitHobbiesSet = unitRelationHobbiesMap.get(unitId); 88 | 89 | //当切仅当unitHobbies unitHobbiesSet 的子集合的时候返回true 90 | return CollectionUtils.isSubCollection(unitHobbies, unitHobbiesSet); 91 | } 92 | 93 | return false; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/hobby/UnitHobbyIndexObject.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.hobby; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * UnitHobbyIndexObject for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/24 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class UnitHobbyIndexObject { 17 | private Long unitId; 18 | private String hobbyTag; 19 | } 20 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/index/keyword/UnitKeywordIndexObject.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.index.keyword; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * UnitKeywordIndexObject for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/24 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class UnitKeywordIndexObject { 17 | private Long unitId; 18 | private String keyword; 19 | } 20 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/CustomBinlogClient.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.mysql; 2 | 3 | import com.github.shyiko.mysql.binlog.BinaryLogClient; 4 | import com.sxzhongf.ad.config.BinlogConfig; 5 | import com.sxzhongf.ad.mysql.listener.AggregationListener; 6 | import lombok.extern.slf4j.Slf4j; 7 | import org.apache.commons.lang.StringUtils; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.io.IOException; 12 | 13 | /** 14 | * CustomBinlogClient for 自定义Binlog Client 15 | * 16 | * @author Isaac.Zhang | 若初 17 | * @since 2019/6/27 18 | */ 19 | @Slf4j 20 | @Component 21 | public class CustomBinlogClient { 22 | 23 | private BinaryLogClient client; 24 | 25 | private final BinlogConfig config; 26 | private final AggregationListener listener; 27 | 28 | @Autowired 29 | public CustomBinlogClient(BinlogConfig config, AggregationListener listener) { 30 | this.config = config; 31 | this.listener = listener; 32 | } 33 | 34 | public void connect() { 35 | new Thread(() -> { 36 | client = new BinaryLogClient( 37 | config.getHost(), 38 | config.getPort(), 39 | config.getUsername(), 40 | config.getPassword() 41 | ); 42 | 43 | if (!StringUtils.isEmpty(config.getBinlogName()) && !config.getPosition().equals(-1L)) { 44 | client.setBinlogFilename(config.getBinlogName()); 45 | client.setBinlogPosition(config.getPosition()); 46 | } 47 | 48 | try { 49 | log.info("connecting to mysql start..."); 50 | client.connect(); 51 | log.info("connecting to mysql done!"); 52 | } catch (IOException e) { 53 | e.printStackTrace(); 54 | } 55 | }).start(); 56 | } 57 | 58 | public void disconnect() { 59 | try { 60 | log.info("disconnect to mysql start..."); 61 | client.disconnect(); 62 | log.info("disconnect to mysql done!"); 63 | } catch (IOException e) { 64 | e.printStackTrace(); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/constant/OperationTypeEnum.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.mysql.constant; 2 | 3 | import com.github.shyiko.mysql.binlog.event.EventType; 4 | 5 | /** 6 | * OperationTypeEnum for TODO 7 | * 8 | * @author Isaac.Zhang | 若初 9 | * @since 2019/6/26 10 | */ 11 | public enum OperationTypeEnum { 12 | ADD, 13 | UPDATE, 14 | DELETE, 15 | OTHER; 16 | 17 | public static OperationTypeEnum convert(EventType type) { 18 | switch (type) { 19 | case EXT_WRITE_ROWS: 20 | return ADD; 21 | case EXT_UPDATE_ROWS: 22 | return UPDATE; 23 | case EXT_DELETE_ROWS: 24 | return DELETE; 25 | default: 26 | return OTHER; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/dto/BinlogRowData.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * BinlogRowData for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/26 14 | */ 15 | @Data 16 | public class BinlogRowData { 17 | 18 | private TableTemplate tableTemplate; 19 | 20 | private EventType eventType; 21 | 22 | private List> before; 23 | 24 | //只有update操作才会有 25 | private List> after; 26 | 27 | } 28 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/dto/BinlogTemplate.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * BinlogTemplate for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/26 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class BinlogTemplate { 19 | 20 | private String database; 21 | private List tableList; 22 | } 23 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/dto/JsonTable.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * JsonTable for 用于表示template.json中对应的表信息 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/26 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class JsonTable { 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 | @AllArgsConstructor 28 | @NoArgsConstructor 29 | public static class Column { 30 | private String column; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/dto/MysqlRowData.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.mysql.dto; 2 | 3 | import com.sxzhongf.ad.mysql.constant.OperationTypeEnum; 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 | * MysqlRowData for 简化{@link BinlogRowData} 以方便实现增量索引的实现 14 | * 15 | * @author Isaac.Zhang | 若初 16 | * @since 2019/6/27 17 | */ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public class MysqlRowData { 22 | 23 | //实现多数据的时候,需要传递数据库名称 24 | //private String database; 25 | 26 | private String tableName; 27 | private String level; 28 | private OperationTypeEnum operationTypeEnum; 29 | private List> fieldValueMap = new ArrayList<>(); 30 | } 31 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/dto/ParseCustomTemplate.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.mysql.dto; 2 | 3 | import com.sxzhongf.ad.mysql.constant.OperationTypeEnum; 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 | * ParseCustomTemplate for TODO 14 | * 15 | * @author Isaac.Zhang | 若初 16 | * @since 2019/6/26 17 | */ 18 | @Data 19 | public class ParseCustomTemplate { 20 | 21 | private String database; 22 | 23 | /** 24 | * key -> TableName 25 | * value -> {@link TableTemplate} 26 | */ 27 | private Map tableTemplateMap = new HashMap<>(); 28 | 29 | public static ParseCustomTemplate parse(BinlogTemplate _template) { 30 | ParseCustomTemplate template = new ParseCustomTemplate(); 31 | template.setDatabase(_template.getDatabase()); 32 | 33 | for (JsonTable jsonTable : _template.getTableList()) { 34 | String name = jsonTable.getTableName(); 35 | Integer level = jsonTable.getLevel(); 36 | 37 | TableTemplate tableTemplate = new TableTemplate(); 38 | tableTemplate.setTableName(name); 39 | tableTemplate.setLevel(level.toString()); 40 | template.tableTemplateMap.put(name, tableTemplate); 41 | 42 | //遍历操作类型对应的列信息 43 | Map> operationTypeListMap = tableTemplate.getOpTypeFieldSetMap(); 44 | 45 | for (JsonTable.Column column : jsonTable.getInsert()) { 46 | getAndCreateIfNeed( 47 | OperationTypeEnum.ADD, 48 | operationTypeListMap, 49 | ArrayList::new 50 | ).add(column.getColumn()); 51 | } 52 | 53 | for (JsonTable.Column column : jsonTable.getUpdate()) { 54 | getAndCreateIfNeed( 55 | OperationTypeEnum.UPDATE, 56 | operationTypeListMap, 57 | ArrayList::new 58 | ).add(column.getColumn()); 59 | } 60 | 61 | for (JsonTable.Column column : jsonTable.getDelete()) { 62 | getAndCreateIfNeed( 63 | OperationTypeEnum.DELETE, 64 | operationTypeListMap, 65 | ArrayList::new 66 | ).add(column.getColumn()); 67 | } 68 | } 69 | 70 | return template; 71 | } 72 | 73 | /** 74 | * 从Map中获取对象,如果不存在,创建一个 75 | */ 76 | private static R getAndCreateIfNeed(T key, Map map, Supplier factory) { 77 | return map.computeIfAbsent(key, k -> factory.get()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/dto/TableTemplate.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.mysql.dto; 2 | 3 | import com.sxzhongf.ad.mysql.constant.OperationTypeEnum; 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 | * TableTemplate for Binlog日志中 字段索引 -> 字段名称 的一个转换映射 14 | * 15 | * @author Isaac.Zhang | 若初 16 | * @since 2019/6/26 17 | */ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | public class TableTemplate { 22 | private String tableName; 23 | private String level; 24 | 25 | //操作类型 -> 多列 26 | private Map> opTypeFieldSetMap = new HashMap<>(); 27 | 28 | /** 29 | * Binlog日志中 字段索引 -> 字段名称 的一个转换映射 30 | * 因为binlog中不会显示更新的列名是什么,它只会展示字段的索引,因此我们需要实现一次转换 31 | */ 32 | private Map posMap = new HashMap<>(); 33 | } 34 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/listener/Ilistener.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.mysql.listener; 2 | 3 | import com.sxzhongf.ad.mysql.dto.BinlogRowData; 4 | 5 | /** 6 | * Ilistener for 为了后续扩展不同的实现 7 | * 8 | * @author Isaac.Zhang | 若初 9 | * @since 2019/6/26 10 | */ 11 | public interface Ilistener { 12 | 13 | void register(); 14 | 15 | void onEvent(BinlogRowData eventData); 16 | } 17 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/mysql/listener/IncrementListener.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.mysql.listener; 2 | 3 | import com.github.shyiko.mysql.binlog.event.EventType; 4 | import com.sxzhongf.ad.mysql.constant.Constant; 5 | import com.sxzhongf.ad.mysql.constant.OperationTypeEnum; 6 | import com.sxzhongf.ad.mysql.dto.BinlogRowData; 7 | import com.sxzhongf.ad.mysql.dto.MysqlRowData; 8 | import com.sxzhongf.ad.mysql.dto.TableTemplate; 9 | import com.sxzhongf.ad.sender.ISender; 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 | * IncrementListener for 增量数据实现监听 22 | * 23 | * @author Isaac.Zhang | 若初 24 | * @since 2019/6/27 25 | */ 26 | @Slf4j 27 | @Component 28 | public class IncrementListener implements Ilistener { 29 | 30 | private final AggregationListener aggregationListener; 31 | 32 | @Autowired 33 | public IncrementListener(AggregationListener aggregationListener) { 34 | this.aggregationListener = aggregationListener; 35 | } 36 | 37 | //根据名称选择要注入的投递方式 38 | @Resource(name = "indexSender") 39 | private ISender sender; 40 | 41 | /** 42 | * 标注为 {@link PostConstruct}, 43 | * 即表示在服务启动,Bean完成初始化之后,立刻初始化 44 | */ 45 | @Override 46 | @PostConstruct 47 | public void register() { 48 | log.info("IncrementListener register db and table info."); 49 | Constant.table2db.forEach((tb, db) -> aggregationListener.register(db, tb, this)); 50 | } 51 | 52 | @Override 53 | public void onEvent(BinlogRowData eventData) { 54 | TableTemplate table = eventData.getTableTemplate(); 55 | EventType eventType = eventData.getEventType(); 56 | 57 | //包装成最后需要投递的数据 58 | MysqlRowData rowData = new MysqlRowData(); 59 | rowData.setTableName(table.getTableName()); 60 | rowData.setLevel(eventData.getTableTemplate().getLevel()); 61 | //将EventType转为OperationTypeEnum 62 | OperationTypeEnum operationType = OperationTypeEnum.convert(eventType); 63 | rowData.setOperationTypeEnum(operationType); 64 | 65 | //获取模版中该操作对应的字段列表 66 | List fieldList = table.getOpTypeFieldSetMap().get(operationType); 67 | if (null == fieldList) { 68 | log.warn("{} not support for {}.", operationType, table.getTableName()); 69 | return; 70 | } 71 | 72 | for (Map afterMap : eventData.getAfter()) { 73 | Map _afterMap = new HashMap<>(); 74 | for (Map.Entry entry : afterMap.entrySet()) { 75 | String colName = entry.getKey(); 76 | String colValue = entry.getValue(); 77 | 78 | _afterMap.put(colName, colValue); 79 | } 80 | 81 | rowData.getFieldValueMap().add(_afterMap); 82 | } 83 | sender.sender(rowData); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/runner/BinlogRunner.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.runner; 2 | 3 | import com.sxzhongf.ad.mysql.CustomBinlogClient; 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 | * BinlogRunner for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/27 14 | */ 15 | @Slf4j 16 | @Component 17 | public class BinlogRunner implements CommandLineRunner { 18 | 19 | private final CustomBinlogClient binlogClient; 20 | 21 | @Autowired 22 | public BinlogRunner(CustomBinlogClient binlogClient) { 23 | this.binlogClient = binlogClient; 24 | } 25 | 26 | @Override 27 | public void run(String... args) throws Exception { 28 | log.info("BinlogRunner is running..."); 29 | binlogClient.connect(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/ISearch.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search; 2 | 3 | import com.sxzhongf.ad.search.vo.SearchRequest; 4 | import com.sxzhongf.ad.search.vo.SearchResponse; 5 | 6 | /** 7 | * ISearch for 请求接口, 8 | * 根据广告请求对象,获取广告响应信息 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/7/1 12 | */ 13 | //@FunctionalInterface 14 | public interface ISearch { 15 | 16 | /** 17 | * 根据请求返回广告结果 18 | */ 19 | SearchResponse fetchAds(SearchRequest request); 20 | } 21 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/SearchRequest.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search.vo; 2 | 3 | import com.sxzhongf.ad.search.vo.feature.DistrictFeature; 4 | import com.sxzhongf.ad.search.vo.feature.FeatureRelation; 5 | import com.sxzhongf.ad.search.vo.feature.HobbyFeatrue; 6 | import com.sxzhongf.ad.search.vo.feature.KeywordFeature; 7 | import com.sxzhongf.ad.search.vo.media.AdSlot; 8 | import com.sxzhongf.ad.search.vo.media.App; 9 | import com.sxzhongf.ad.search.vo.media.Device; 10 | import com.sxzhongf.ad.search.vo.media.Geo; 11 | import lombok.AllArgsConstructor; 12 | import lombok.Builder; 13 | import lombok.Data; 14 | import lombok.NoArgsConstructor; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * SearchRequest for TODO 20 | * 21 | * @author Isaac.Zhang | 若初 22 | * @since 2019/7/1 23 | */ 24 | @Data 25 | @Builder 26 | @NoArgsConstructor 27 | @AllArgsConstructor 28 | public class SearchRequest { 29 | 30 | //媒体方请求标示 31 | private String mediaId; 32 | 33 | //请求基本信息 34 | private RequestInfo requestInfo; 35 | 36 | //匹配信息 37 | private FeatureInfo featureInfo; 38 | 39 | 40 | @Data 41 | @Builder 42 | @NoArgsConstructor 43 | @AllArgsConstructor 44 | public static class RequestInfo { 45 | private String requestId; 46 | 47 | private List adSlots; 48 | private App app; 49 | private Geo geo; 50 | private Device device; 51 | } 52 | 53 | @Data 54 | @Builder 55 | @NoArgsConstructor 56 | @AllArgsConstructor 57 | public static class FeatureInfo { 58 | 59 | private KeywordFeature keywordFeature; 60 | private DistrictFeature districtFeature; 61 | private HobbyFeatrue hobbyFeatrue; 62 | 63 | private FeatureRelation relation = FeatureRelation.AND; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/SearchResponse.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search.vo; 2 | 3 | import com.sxzhongf.ad.index.creative.CreativeIndexObject; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Builder; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Arrays; 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | /** 15 | * SearchResponse for 检索API响应对象 16 | * 17 | * @author Isaac.Zhang | 若初 18 | * @since 2019/8/10 19 | */ 20 | @Data 21 | @Builder 22 | @NoArgsConstructor 23 | @AllArgsConstructor 24 | public class SearchResponse { 25 | 26 | //一个广告位,可以展示多个广告 27 | //Map key为广告位 AdSlot#adSlotCode 28 | public Map> adSlotRelationAds = new HashMap<>(); 29 | 30 | @Data 31 | @Builder 32 | @NoArgsConstructor 33 | @AllArgsConstructor 34 | public static class Creative { 35 | 36 | private Long adId; 37 | private String adUrl; 38 | private Integer width; 39 | private Integer height; 40 | private Integer type; 41 | private Integer materialType; 42 | 43 | //展示监控url 44 | private List showMonitorUrl = Arrays.asList("www.life-runner.com", "www.babydy.cn"); 45 | //点击监控url 46 | private List clickMonitorUrl = Arrays.asList("www.life-runner.com", "www.babydy.cn"); 47 | } 48 | 49 | /** 50 | * 我们的检索服务针对的是内存中的索引检索,那么我们就需要一个转换方法 51 | */ 52 | public static Creative convert(CreativeIndexObject object) { 53 | 54 | return Creative.builder() 55 | .adId(object.getAdId()) 56 | .adUrl(object.getAdUrl()) 57 | .width(object.getWidth()) 58 | .height(object.getHeight()) 59 | .type(object.getType()) 60 | .materialType(object.getMaterialType()) 61 | .build(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/feature/DistrictFeature.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * DistrictFeature for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/7/2 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class DistrictFeature { 19 | 20 | private List provinceAndCities; 21 | 22 | @Data 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | public static class ProvinceAndCity { 26 | private String province; 27 | private String city; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/feature/FeatureRelation.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search.vo.feature; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * FeatureRelation for TODO 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/7/2 13 | */ 14 | @Getter 15 | public enum FeatureRelation { 16 | OR, 17 | AND 18 | } 19 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/feature/HobbyFeatrue.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * HobbyFeatrue for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/7/2 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class HobbyFeatrue { 19 | private List hobbys; 20 | } 21 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/feature/KeywordFeature.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * KeywordFeature for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/7/2 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class KeywordFeature { 19 | private List keywords; 20 | } 21 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/media/AdSlot.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * AdSlot for 广告位 12 | * 13 | * @author Isaac.Zhang | 若初 14 | * @since 2019/7/1 15 | */ 16 | @Data 17 | @Builder 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class AdSlot { 21 | 22 | //广告位编码 23 | private String adSlotCode; 24 | 25 | //流量类型 26 | private Integer positionType; 27 | 28 | //广告位宽和高 29 | private Integer height; 30 | private Integer width; 31 | 32 | //广告位物料类型:图片/视频等 33 | private List type; 34 | 35 | //最低出价 36 | private Integer minCpm; 37 | } 38 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/media/App.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * App for 广告应用 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/7/1 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class App { 19 | 20 | /** 21 | * 应用编码 22 | */ 23 | private String appCode; 24 | 25 | /** 26 | * 应用名称 27 | */ 28 | private String appName; 29 | 30 | /** 31 | * 应用包的名称 32 | */ 33 | private String packageName; 34 | 35 | /* 36 | * 对应的请求页面名称 37 | */ 38 | private String activityName; 39 | } 40 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/media/Device.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Device for TODO 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/7/2 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class Device { 19 | 20 | private String deviceCode; 21 | 22 | /** 23 | * 设备device mac地址 24 | */ 25 | private String deviceMacAddr; 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 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/search/vo/media/Geo.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.search.vo.media; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * Geo for 地理位置信息 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/7/1 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class Geo { 19 | 20 | /** 21 | * 纬度 22 | */ 23 | private Float latitude; 24 | 25 | /** 26 | * 经度 27 | */ 28 | private Float longitude; 29 | 30 | private String city; 31 | private String province; 32 | } 33 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/sender/ISender.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.sender; 2 | 3 | import com.sxzhongf.ad.mysql.dto.MysqlRowData; 4 | 5 | /** 6 | * ISender for 投递增量数据 方法定义接口 7 | * 8 | * @author Isaac.Zhang | 若初 9 | * @since 2019/6/27 10 | */ 11 | public interface ISender { 12 | 13 | void sender(MysqlRowData rowData); 14 | } 15 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/sender/kafka/KafkaSender.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.sender.kafka; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sxzhongf.ad.mysql.dto.MysqlRowData; 5 | import com.sxzhongf.ad.sender.ISender; 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 | * KafkaSender for 投递Binlog增量数据到kafka消息队列 17 | * 18 | * @author Isaac.Zhang | 若初 19 | * @since 2019/7/1 20 | */ 21 | @Component(value = "kafkaSender") 22 | public class KafkaSender implements ISender { 23 | 24 | @Value("${adconf.kafka.topic}") 25 | private String topic; 26 | 27 | // @Autowired 28 | // private KafkaTemplate kafkaTemplate; 29 | 30 | /** 31 | * 发送数据到kafka队列 32 | */ 33 | @Override 34 | public void sender(MysqlRowData rowData) { 35 | // kafkaTemplate.send( 36 | // topic, JSON.toJSONString(rowData) 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 kafkaMsg = Optional.ofNullable(record.value()); 46 | // if (kafkaMsg.isPresent()) { 47 | // Object message = kafkaMsg.get(); 48 | // MysqlRowData rowData = JSON.parseObject( 49 | // message.toString(), 50 | // MysqlRowData.class 51 | // ); 52 | // System.out.println("kafka process MysqlRowData: " + JSON.toJSONString(rowData)); 53 | //// sender.sender(); 54 | // } 55 | // 56 | // } 57 | } 58 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/service/BinlogServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * BinlogServiceTest for 测试Mysql binlog 监控 13 | * {@code 14 | * Mysql8 连接提示 Client does not support authentication protocol requested by server; consider upgrading MySQL client 解决方法 15 | * USE mysql; 16 | * ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'; 17 | * FLUSH PRIVILEGES; 18 | * } 19 | * 20 | * @author Isaac.Zhang | 若初 21 | * @since 2019/6/26 22 | */ 23 | public class BinlogServiceTest { 24 | 25 | /** 26 | * --------Update----------- 27 | * UpdateRowsEventData{tableId=90, includedColumnsBeforeUpdate={0, 1, 2, 3, 4, 5, 6, 7}, includedColumns={0, 1, 2, 3, 4, 5, 6, 7}, rows=[ 28 | * {before=[11, 10, Test Bin Log, 1, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019], after=[11, 10, zhangpan TestTable Binlog, 1, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019, Tue Jun 25 08:00:00 CST 2019]} 29 | * ]} 30 | * 31 | * --------Insert----------- 32 | * WriteRowsEventData{tableId=91, includedColumns={0, 1, 2, 3, 4, 5, 6, 7}, rows=[ 33 | * [10, 11, ad unit TestTable binlog, 1, 0, 1236.7655, Thu Jun 27 08:00:00 CST 2019, Thu Jun 27 08:00:00 CST 2019] 34 | * ]} 35 | */ 36 | 37 | public static void main(String[] args) throws IOException { 38 | 39 | // //构造BinaryLogClient,填充mysql链接信息 40 | BinaryLogClient client = new BinaryLogClient("127.0.0.1", 3306, 41 | "root", "12345678" 42 | ); 43 | 44 | //设置需要读取的Binlog的文件以及位置,否则,client会从"头"开始读取Binlog并监听 45 | // client.setBinlogFilename("binlog.000035"); 46 | // client.setBinlogPosition(); 47 | 48 | //给客户端注册监听器,实现对Binlog的监听和解析 49 | //event 就是监听到的Binlog变化信息,event包含header & data 两部分 50 | client.registerEventListener(event -> { 51 | EventData data = event.getData(); 52 | if (data instanceof UpdateRowsEventData) { 53 | System.out.println("--------Update-----------"); 54 | System.out.println(data.toString()); 55 | } else if (data instanceof WriteRowsEventData) { 56 | System.out.println("--------Insert-----------"); 57 | System.out.println(data.toString()); 58 | } else if (data instanceof DeleteRowsEventData) { 59 | System.out.println("--------Delete-----------"); 60 | System.out.println(data.toString()); 61 | } 62 | }); 63 | 64 | client.connect(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/java/com/sxzhongf/ad/utils/CommonUtils.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.utils; 2 | 3 | import java.util.Map; 4 | import java.util.function.Supplier; 5 | 6 | /** 7 | * CommonUtils for TODO 8 | * 9 | * @author Isaac.Zhang | 若初 10 | * @since 2019/6/24 11 | */ 12 | public class CommonUtils { 13 | 14 | /** 15 | * 如果根据当前key在当前map中查询不到结果, 16 | * 使用factory创建一个新的对象 17 | */ 18 | public static V getOrCreate(K key, Map map, Supplier factory) { 19 | return map.computeIfAbsent(key, k -> factory.get()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-search/src/main/resources/MySQL BinLog.md: -------------------------------------------------------------------------------- 1 | # Mysql Binlog 2 | ## 概念 3 | ### 什么是binlog? 4 | > BinLog是Mysql 维护的一种二进制日志,主要是用来记录对mysql数据更新或者潜在发生更新的SQL 5 | > 语句,并以"事物"的形式保存在磁盘文件中 6 | 7 | ### 主要用途 8 | - 复制:Mysql的Master-Slave协议,让Slave 可以通过监听Binlog实现数据复制(同步),达到数据一致性的目的。 9 | - 数据恢复: 通过mysql binlog 工具恢复数据 10 | - 增量备份 11 | ###支持的格式 12 | - ROW 13 | > 仅保存记录被修改细节,不记录SQL语句上下文相关信息。 14 | > 能非常清晰的记录下每一行数据的修改细节,不需要记录上下文相关信息,因此不会发生某些特定情况下的 15 | > procedure、function、及trigger的调用触发无法被正确复制的问题,任何情况都可以被复制,切能加快从 16 | > 从库重放日志的效率,保证从库数据的一致性 17 | - STATEMENT 18 | > 每一条会修改数据的SQL都会记录在Binlog中,只需要记录执行语句的细节和上下文环境,避免了记录每一行的 19 | > 变化,在一些修改记录较多的情况下,相比ROW类型能大大减少Binlog的日志量,节约IO,提高性能,还可以 20 | > 用于实时的还原,同时主从版本可以不一样,从服务器版本可以比主服务器版本高 21 | - MIXED 22 | > 以上两种类型的混合使用,经过上述比对,可以发现各有优势,如能根据SQL语句取舍可能会有更好的性能和效果, 23 | > MIXED便是以上两种类型的结合。 24 | 25 | ### 常用命令 26 | 27 | | SQl语句 | 语句含义| 28 | | ---- | ----| 29 | |SHOW MASTER LOGS;|查看所有binlog的日志列表| 30 | |SHOW MASTER STATUS;| 查看最后一个Binlog日志的编号名称,以及最后一个事件结束的位置(pos)| 31 | |FLUSH LOGS;| 刷新Binlog, 此刻开始产生一个新编号的binlog日志文件| 32 | |RESET MASTER;|清空所有binlog| 33 | |SHOW BINLOG EVENTS;|查看第一个binlog日志| 34 | |SHOW BINLOG EVENTS IN 'binlog.000035';|查看指定binlog| 35 | |SHOW BINLOG EVENTS IN 'binlog.000035' FROM 100;|从指定位置开始,查看| 36 | |SHOW BINLOG EVENTS IN '' FROM 100 LIMIT 2;|从指定位置开始,限制查询的条数| 37 | |SHOW BINLOG EVENTS IN '' FROM 100 LIMIT 1,2;|从指定位置开始,带有偏移| 38 | 39 | ### Binlog的Event类型 40 | MySQL Binlog Event 官方提供类型36种,常用的如下: 41 | 42 | |Event Type | 事件 | 重要程度| 43 | | ---- | ---- | ---- | 44 | |QUERY| 与数据无关的操作,如begin,drop table,truncate table等|了解即可| 45 | |XID|标记事物提交|了解即可| 46 | |TABLE_MAP|记录下一个操作所对应的表信息,存储了数据库名和表名|非常重要| 47 | |WRITE_ROWS|插入数据|非常重要| 48 | |UPDATE_ROWS|更新数据|非常重要| 49 | |DELETE_ROWS|删除数据|非常重要| 50 | 最好的方式是在数据库中创建一张测试表,然后对表进行增删改查操作,然后监控Binlog变化。 51 | 52 | ## 说明 53 | 对于MYSQL Binlog,我们可以不用过分追究Binlog里面到底包含了什么,对于应用的话,我们最重要的是要搞清楚, 54 | Binlog的Event:每个Event都包含header 和data两个部分。 55 | - header 56 | > 提供了Event的创建时间,哪个服务器等信息 57 | - data 58 | > 提供的是针对该Event的具体信息,如具体数据的修改 59 | 60 | 我们对Binlog的解析,即为对Event的解析 61 | - Binlog 的EventType(需要注意,不同版本的mysql,EventType可能会不同) 62 | - Binlog 中并不会打印数据表的列名 -------------------------------------------------------------------------------- /mscx-ad-search/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7001 3 | servlet: 4 | context-path: /ad-search #http请求的根路径(请求前缀,在handle的mapping之前,需要127.0.0.1/ad-search/XXXX) 5 | spring: 6 | application: 7 | name: mscx-ad-search 8 | jpa: 9 | show-sql: true #执行时是否打印sql语句,方便调试 10 | hibernate: 11 | ddl-auto: none 12 | properties: 13 | hibernate.format_sql: true 14 | open-in-view: false #控制是否在懒加载时,有可能会找不到bean报错 15 | datasource: 16 | username: root 17 | url: jdbc:mysql://127.0.0.1:3306/advertisement?useSSL=false&autoReconnect=true 18 | password: 12345678 19 | tomcat: 20 | max-active: 4 #最大连接数 21 | min-idle: 2 #最小空闲连接数 22 | initial-size: 2 #默认初始化连接数 23 | eureka: 24 | client: 25 | service-url: 26 | defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ 27 | feign: 28 | hystrix: 29 | enabled: true 30 | management: 31 | endpoints: 32 | web: 33 | exposure: 34 | include: "*" 35 | 36 | 37 | adconf: 38 | mysql: 39 | host: 127.0.0.1 40 | port: 3306 41 | username: root 42 | password: 12345678 43 | binlogName: "" 44 | position: -1 # 从当前位置开始监听 45 | kafka: 46 | topic: ad-search-mysql-data -------------------------------------------------------------------------------- /mscx-ad-search/src/main/resources/index-note.md: -------------------------------------------------------------------------------- 1 | # 广告数据索引设计 2 | 设计索引的目的是为了加快索引速度,将原始数据抽象,规划出合理的字段,在内存中构建广告数据索引。 3 | 记住,并不是所有的数据都需要放在索引中。 4 | ## 正向索引 5 | 核心思想是通过一个键(通常为主键)找到一个对象,切这种关系是确定的,即唯一键对应到唯一的对象。 6 | - 推广计划 7 | - 推广单元 8 | - 创意 9 | 10 | ## 倒排索引 11 | 核心思想是通过内容去确定包含关系的对象 12 | - 创意与推广单元的关联对象 13 | - 推广单元地域限制 14 | - 推广单元兴趣限制 15 | - 推广单元关键词限制 16 | 17 | ## 广告数据索引的维护 18 | 核心思想是保证检索服务中的索引是完整的 19 | - 全量索引 20 | - 增量索引 21 | 22 | # Question 23 | ## #1 24 | > 索引数据的存储与操作使用的是ConcurrentHashMap、ConcurrentSkipListSet,能否使用 25 | > HashMap、HashSet替换呢?为什么? 26 | ```html 27 | 不能. 28 | 用HashMap和HashSet在高并发的情况下会有线程安全问题, 29 | 相比之下ConcurrentHashMap和ConcurrentSkipListSet是线程安全的类. 30 | ``` 31 | 32 | ## #2 33 | > IndexDataTableUtils.java 的作用是什么? 34 | ```html 35 | 主要是在使用bean的时候,不需要繁琐的注入。 36 | 正常情况下,都需要Autowired或者Resource注入。如果使用到的bean太多的话, 37 | 也是个苦力活。所以说DataTable.java通过获取spring上下文, 38 | 里面的of方法实现了往dataTableMap中存放相应的bean, 39 | 再加上条件判断也不需要频繁的getBean(),这样方便我们使用, 40 | 只需要注入IndexDataTableUtils,调用of方法就可以取到相应的bean. 41 | ``` 42 | 43 | ## #3 44 | > 如果广告数据太多,内存中放不下,你会怎么做? 45 | ```html 46 | 广告数据如果在 JVM 中放不下了,可以考虑基于内存的存储工具,例如 Redis 等。 47 | ``` 48 | -------------------------------------------------------------------------------- /mscx-ad-search/src/test/java/com/sxzhongf/ad/AdSearchApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.cloud.client.loadbalancer.LoadBalanced; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.web.client.RestTemplate; 9 | 10 | /** 11 | * AdSearchApplication for search 服务测试用例启动程序 12 | * 13 | * @author Isaac.Zhang | 若初 14 | * @since 2019/8/16 15 | */ 16 | @SpringBootApplication 17 | public class AdSearchApplication { 18 | 19 | public static void main(String[] args) { 20 | SpringApplication.run(AdSearchApplication.class, args); 21 | } 22 | 23 | @Bean 24 | @LoadBalanced 25 | RestTemplate restTemplate(){ 26 | return new RestTemplate(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /mscx-ad-search/src/test/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7001 3 | servlet: 4 | context-path: /ad-search #http请求的根路径(请求前缀,在handle的mapping之前,需要127.0.0.1/ad-search/XXXX) 5 | spring: 6 | application: 7 | name: mscx-ad-search 8 | jpa: 9 | show-sql: true #执行时是否打印sql语句,方便调试 10 | hibernate: 11 | ddl-auto: none 12 | properties: 13 | hibernate.format_sql: true 14 | open-in-view: false #控制是否在懒加载时,有可能会找不到bean报错 15 | datasource: 16 | username: root 17 | url: jdbc:mysql://127.0.0.1:3306/advertisement?useSSL=false&autoReconnect=true 18 | password: 12345678 19 | tomcat: 20 | max-active: 4 #最大连接数 21 | min-idle: 2 #最小空闲连接数 22 | initial-size: 2 #默认初始化连接数 23 | eureka: 24 | client: 25 | service-url: 26 | defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ 27 | enabled: false 28 | feign: 29 | hystrix: 30 | enabled: true 31 | management: 32 | endpoints: 33 | web: 34 | exposure: 35 | include: "*" 36 | 37 | 38 | adconf: 39 | mysql: 40 | host: 127.0.0.1 41 | port: 3306 42 | username: root 43 | password: 12345678 44 | binlogName: "" 45 | position: -1 # 从当前位置开始监听 46 | kafka: 47 | topic: ad-search-mysql-data -------------------------------------------------------------------------------- /mscx-ad-sponsor/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | jar 12 | 13 | com.sxzhongf 14 | mscx-ad-sponsor 15 | 1.0-SNAPSHOT 16 | ad-sponsor 17 | 广告投放系统 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-actuator 27 | 28 | 29 | org.springframework.cloud 30 | spring-cloud-starter-eureka 31 | 1.2.7.RELEASE 32 | 33 | 34 | 35 | org.springframework.cloud 36 | spring-cloud-starter-hystrix 37 | 1.2.7.RELEASE 38 | 39 | 40 | org.springframework.cloud 41 | spring-cloud-starter-openfeign 42 | 43 | 44 | 45 | org.springframework.cloud 46 | spring-cloud-starter-ribbon 47 | 1.2.7.RELEASE 48 | 49 | 50 | org.springframework.boot 51 | spring-boot-starter-data-jpa 52 | 53 | 54 | mysql 55 | mysql-connector-java 56 | runtime 57 | 58 | 59 | 60 | 61 | 62 | 63 | com.sxzhongf 64 | mscx-ad-common 65 | 1.0-SNAPSHOT 66 | 67 | 68 | 69 | 70 | 71 | 72 | org.springframework.boot 73 | spring-boot-maven-plugin 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/SponsorApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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.openfeign.EnableFeignClients; 8 | 9 | /** 10 | * SponsorApplication for 广告赞助商/投递服务启动类 11 | * 添加注解{@link EnableFeignClients}之后,当前微服务就可以调用别的微服务, 12 | * 但是当前服务是广告提供,不需要调用别的微服务,在此只是为了在dashboard中监控 13 | * 14 | * {@link EnableCircuitBreaker} 也是为了dashboard监控 15 | * 16 | * @author Isaac.Zhang 17 | * @since 2019/6/15 18 | */ 19 | @EnableDiscoveryClient 20 | @EnableCircuitBreaker 21 | @EnableFeignClients 22 | @SpringBootApplication 23 | public class SponsorApplication { 24 | 25 | public static void main(String[] args) { 26 | SpringApplication.run(SponsorApplication.class, args); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/CreativeRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import com.sxzhongf.ad.constant.CommonStatus; 4 | import com.sxzhongf.ad.entity.AdCreative; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.util.Date; 10 | 11 | /** 12 | * CreativeRequestVO for TODO 13 | * 14 | * @author Isaac.Zhang | 若初 15 | * @since 2019/6/20 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | public class CreativeRequestVO { 21 | 22 | private String name; 23 | private Integer type; 24 | private Integer materialType; 25 | private Integer height; 26 | private Integer width; 27 | private Long size; 28 | private Long duration; 29 | private Long userId; 30 | private String url; 31 | 32 | public AdCreative convertToEntity() { 33 | AdCreative model = new AdCreative(); 34 | model.setName(name); 35 | model.setType(type); 36 | model.setMaterialType(materialType); 37 | model.setHeight(height); 38 | model.setWidth(width); 39 | model.setDuration(duration); 40 | model.setAuditStatus(CommonStatus.VALID.getStatus()); 41 | model.setUserId(userId); 42 | model.setUrl(url); 43 | model.setCreateTime(new Date()); 44 | model.setUpdateTime(model.getCreateTime()); 45 | 46 | return model; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/CreativeResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * CreativeResponseVO for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/20 12 | */ 13 | @Data 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | public class CreativeResponseVO { 17 | private Long creativeId; 18 | private String name; 19 | } 20 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/CreativeUnitRelationshipRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * CreativeUnitRelationshipRequestVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/21 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class CreativeUnitRelationshipRequestVO { 19 | 20 | private Collection creativeUnitItemVO; 21 | 22 | @Data 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | public static class CreativeUnitItemVO { 26 | private Long creativeId; 27 | private Long unitId; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/CreativeUnitRelationshipResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * CreativeUnitRelationshipResponseVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/21 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class CreativeUnitRelationshipResponseVO { 19 | private Collection ids; 20 | } 21 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/PlanGetRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.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 | /** 11 | * PlanGetRequestVO for TODO 12 | * 13 | * @author Isaac.Zhang | 若初 14 | * @since 2019/6/19 15 | */ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | public class PlanGetRequestVO { 20 | private Long userId; 21 | private List planIds; 22 | 23 | public boolean validate() { 24 | return userId != null && !CollectionUtils.isEmpty(planIds); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/PlanRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.apache.commons.lang.StringUtils; 7 | 8 | /** 9 | * PlanRequestVO for TODO 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/6/19 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class PlanRequestVO { 18 | 19 | private Long planId; 20 | private Long userId; 21 | private String planName; 22 | private String startDate; 23 | private String endDate; 24 | 25 | public boolean createValidate() { 26 | return userId != null 27 | && !StringUtils.isEmpty(planName) 28 | && StringUtils.isEmpty(startDate) 29 | && StringUtils.isEmpty(endDate); 30 | } 31 | 32 | public boolean updateOrDeleteValidate() { 33 | return userId != null && planId != null; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/PlanResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | /** 8 | * PlanResponseVO for TODO 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/19 12 | */ 13 | @Data 14 | @AllArgsConstructor 15 | @NoArgsConstructor 16 | public class PlanResponseVO { 17 | private Long planId; 18 | private String planName; 19 | } 20 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitDistrictRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * UnitDistrictRequestVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/20 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UnitDistrictRequestVO { 19 | 20 | private List unitDistrictList; 21 | 22 | /** 23 | * 允许批量操作 24 | */ 25 | @Data 26 | @NoArgsConstructor 27 | @AllArgsConstructor 28 | public static class UnitDistrict { 29 | private Long unitId; 30 | private String province; 31 | private String city; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitDistrictResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * UnitDistrictResponseVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/20 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UnitDistrictResponseVO { 19 | 20 | private Collection districtIds; 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitHobbyRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * UnitKeywordRequestVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/20 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UnitHobbyRequestVO { 19 | 20 | private List unitHobbyList; 21 | 22 | /** 23 | * 允许批量操作 24 | */ 25 | @Data 26 | @NoArgsConstructor 27 | @AllArgsConstructor 28 | public static class UnitHobby { 29 | private Long unitId; 30 | private String hobbyTag; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitHobbyResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * UnitHobbyResponseVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/20 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UnitHobbyResponseVO { 19 | 20 | private Collection hobbyIds; 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitKeywordRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * UnitKeywordRequestVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/20 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UnitKeywordRequestVO { 19 | 20 | private List unitKeywordList; 21 | /** 22 | * 允许批量操作 23 | */ 24 | @Data 25 | @NoArgsConstructor 26 | @AllArgsConstructor 27 | public static class UnitKeyword { 28 | private Long unitId; 29 | private String keyword; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitKeywordResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import java.util.Collection; 8 | 9 | /** 10 | * UnitKeywordResponseVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/20 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UnitKeywordResponseVO { 19 | 20 | private Collection keywordIds; 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | import org.apache.commons.lang.StringUtils; 8 | 9 | /** 10 | * UnitRequestVO for TODO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/20 14 | */ 15 | @Data 16 | @Builder 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | public class UnitRequestVO { 20 | 21 | private Long planId; 22 | 23 | private String unitName; 24 | 25 | private Integer positionType; 26 | 27 | private Long budgetFee; 28 | 29 | public boolean creteValidate() { 30 | return null != planId 31 | && !StringUtils.isEmpty(unitName) 32 | && null != positionType 33 | && null != budgetFee; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UnitResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * UnitResponseVO for TODO 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/6/20 13 | */ 14 | @Data 15 | @Builder 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class UnitResponseVO { 19 | private Long unitId; 20 | private String unitName; 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UserRequestVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.client.vo; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.apache.commons.lang.StringUtils; 7 | 8 | /** 9 | * UserRequestVO for 创建用户请求对象VO 10 | * 11 | * @author Isaac.Zhang | 若初 12 | * @since 2019/6/19 13 | */ 14 | @Data 15 | @AllArgsConstructor 16 | @NoArgsConstructor 17 | public class UserRequestVO { 18 | 19 | private String userName; 20 | 21 | public boolean validate() { 22 | return !StringUtils.isEmpty(userName); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/client/vo/UserResponseVO.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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 | * UserResponseVO for 用户响应VO 11 | * 12 | * @author Isaac.Zhang | 若初 13 | * @since 2019/6/19 14 | */ 15 | @Data 16 | @AllArgsConstructor 17 | @NoArgsConstructor 18 | public class UserResponseVO { 19 | private Long userId; 20 | private String userName; 21 | private String token; 22 | private Date createTime; 23 | private Date updateTime; 24 | } 25 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/constant/CommonStatus.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.constant; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * CommonStatus for 通用状态枚举 7 | * 8 | * @author Isaac.Zhang 9 | * @since 2019/6/15 10 | */ 11 | @Getter 12 | public enum CommonStatus { 13 | VALID(1, "有效"), 14 | INVALID(0, "无效状态"); 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 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/constant/Constants.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.constant; 2 | 3 | /** 4 | * Constants for TODO 5 | * 6 | * @author Isaac.Zhang | 若初 7 | * @since 2019/6/19 8 | */ 9 | public class Constants { 10 | 11 | /** 12 | * 通用错误信息异常类 13 | */ 14 | public static class ErrorMessage { 15 | public static final String REQUEST_PARAM_ERROR = "请求参数异常"; 16 | public static final String USER_EXIST = "用户已存在"; 17 | public static final String USER_NOT_EXIST = "用户不存在"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/constant/CreativeMaterielType.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.constant; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * CreativeMaterielType for 创意物料类型 7 | * 8 | * @author Isaac.Zhang 9 | * @since 2019/6/19 10 | */ 11 | @Getter 12 | public enum CreativeMaterielType { 13 | 14 | JPG(1, "jpg"), 15 | BMP(2, "bmp"), 16 | 17 | MP4(3, "mp4"), 18 | AVI(4, "avi"), 19 | 20 | TXT(5, "txt"); 21 | 22 | private int code; 23 | private String desc; 24 | 25 | CreativeMaterielType(int code, String desc) { 26 | this.code = code; 27 | this.desc = desc; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/constant/CreativeType.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.constant; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * CreativeType for 创意类型 7 | * 8 | * @author Isaac.Zhang 9 | * @since 2019/6/19 10 | */ 11 | @Getter 12 | public enum CreativeType { 13 | IMAGE(1, "图片"), 14 | VIDEO(2, "视频"), 15 | TXT(3, "文本"); 16 | 17 | private int code; 18 | private String desc; 19 | 20 | CreativeType(int code, String desc) { 21 | this.code = code; 22 | this.desc = desc; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/controller/CreativeController.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sxzhongf.ad.common.exception.AdException; 5 | import com.sxzhongf.ad.service.ICreativeService; 6 | import com.sxzhongf.ad.client.vo.CreativeRequestVO; 7 | import com.sxzhongf.ad.client.vo.CreativeResponseVO; 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.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * CreativeController for 创意controller 17 | * 18 | * @author Isaac.Zhang | 若初 19 | * @since 2019/6/21 20 | */ 21 | @Slf4j 22 | @RestController 23 | @RequestMapping("/creative") 24 | public class CreativeController { 25 | 26 | @Autowired 27 | private ICreativeService creativeService; 28 | 29 | @PostMapping("/create") 30 | public CreativeResponseVO createCreative(@RequestBody CreativeRequestVO requestVO) throws AdException { 31 | log.info("Ad-Sponsor::CreativeController -> createCreative {}", JSON.toJSONString(requestVO)); 32 | return creativeService.createCreative(requestVO); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/controller/PlanController.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sxzhongf.ad.common.annotation.IgnoreResponseAdvice; 5 | import com.sxzhongf.ad.common.exception.AdException; 6 | import com.sxzhongf.ad.common.vo.CommonResponse; 7 | import com.sxzhongf.ad.entity.AdPlan; 8 | import com.sxzhongf.ad.service.IPlanService; 9 | import com.sxzhongf.ad.client.vo.PlanGetRequestVO; 10 | import com.sxzhongf.ad.client.vo.PlanRequestVO; 11 | import com.sxzhongf.ad.client.vo.PlanResponseVO; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.web.bind.annotation.*; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * PlanController for 推广计划controller 20 | * 21 | * @author Isaac.Zhang | 若初 22 | * @since 2019/6/21 23 | */ 24 | @RestController 25 | @Slf4j 26 | @RequestMapping(path = "/plan") 27 | public class PlanController { 28 | 29 | @Autowired 30 | private IPlanService planService; 31 | 32 | @IgnoreResponseAdvice 33 | @GetMapping(path = "/get") 34 | public CommonResponse> getAdPlanByPlanIds(@RequestBody PlanGetRequestVO requestVO) throws AdException { 35 | log.info("Ad-sponsor: getAdPlanByPlanIds->{}", JSON.toJSONString(requestVO)); 36 | List planList = planService.getAdPlanByPlanIds(requestVO); 37 | log.info("Ad-sponsor: getAdPlanByPlanIds result->{}", JSON.toJSONString(planList)); 38 | 39 | return new CommonResponse<>(planList); 40 | } 41 | 42 | @PostMapping(value = "/create") 43 | public PlanResponseVO createPlan(@RequestBody PlanRequestVO requestVO) throws AdException { 44 | log.info("Ad-sponsor: createPlan->{}", JSON.toJSONString(requestVO)); 45 | return planService.createPlan(requestVO); 46 | } 47 | 48 | @PostMapping(value = "/update") 49 | public PlanResponseVO updatePlan(@RequestBody PlanRequestVO requestVO) throws AdException { 50 | log.info("Ad-sponsor: updatePlan->{}", JSON.toJSONString(requestVO)); 51 | return planService.updatePlan(requestVO); 52 | } 53 | 54 | @IgnoreResponseAdvice 55 | @PostMapping(value = "/delete") 56 | public CommonResponse deletePlan(@RequestBody PlanRequestVO requestVO) throws AdException { 57 | log.info("Ad-sponsor: deletePlan->{}", JSON.toJSONString(requestVO)); 58 | planService.deletePlan(requestVO); 59 | return new CommonResponse(); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/controller/UnitController.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sxzhongf.ad.common.exception.AdException; 5 | import com.sxzhongf.ad.service.IUnitService; 6 | import com.sxzhongf.ad.service.IUserService; 7 | import com.sxzhongf.ad.client.vo.*; 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.RequestMapping; 13 | import org.springframework.web.bind.annotation.RestController; 14 | 15 | /** 16 | * UnitController for 推广单元controller 17 | * 18 | * @author Isaac.Zhang | 若初 19 | * @since 2019/6/21 20 | */ 21 | @Slf4j 22 | @RestController 23 | @RequestMapping(path = "/unit") 24 | public class UnitController { 25 | 26 | private final IUnitService unitService; 27 | 28 | @Autowired 29 | public UnitController(IUnitService unitService) { 30 | this.unitService = unitService; 31 | } 32 | 33 | @PostMapping(path = "/create") 34 | public UnitResponseVO createUnit(@RequestBody UnitRequestVO requestVO) throws AdException { 35 | log.info("Ad-sponsor::UnitController createUnit->{}", JSON.toJSONString(requestVO)); 36 | 37 | return unitService.createUnit(requestVO); 38 | } 39 | 40 | /** 41 | * 创建推广单元-关键字 42 | */ 43 | @PostMapping(value = "/keyword/create") 44 | public UnitKeywordResponseVO createUnitKeyword(@RequestBody UnitKeywordRequestVO requestVO) throws AdException { 45 | 46 | log.info("Ad-sponsor::UnitController createUnitKeyword->{}", JSON.toJSONString(requestVO)); 47 | return unitService.createUnitKeyword(requestVO); 48 | } 49 | 50 | /** 51 | * 创建推广单元-爱好 52 | */ 53 | @PostMapping(path = "/hobby/create") 54 | public UnitHobbyResponseVO createUnitHobby(@RequestBody UnitHobbyRequestVO requestVO) throws AdException { 55 | 56 | log.info("Ad-sponsor::UnitController createUnitHobby->{}", JSON.toJSONString(requestVO)); 57 | return unitService.createUnitHobby(requestVO); 58 | } 59 | 60 | /** 61 | * 创建推广单元-地域 62 | */ 63 | @PostMapping(path = "/district/create") 64 | public UnitDistrictResponseVO createUnitDistrict(@RequestBody UnitDistrictRequestVO requestVO) throws AdException { 65 | 66 | log.info("Ad-sponsor::UnitController createUnitDistrict->{}", JSON.toJSONString(requestVO)); 67 | return unitService.createUnitDistrict(requestVO); 68 | } 69 | 70 | /** 71 | * 插入创意和推广单元关系表数据 72 | */ 73 | @PostMapping("/creative-unit/create") 74 | public CreativeUnitRelationshipResponseVO createCreativeUnitRelationship(CreativeUnitRelationshipRequestVO requestVO) 75 | throws AdException { 76 | 77 | log.info("Ad-sponsor::UnitController createCreativeUnitRelationship->{}", JSON.toJSONString(requestVO)); 78 | return unitService.createCreativeUnitRelationship(requestVO); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/controller/UserController.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.controller; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sxzhongf.ad.common.exception.AdException; 5 | import com.sxzhongf.ad.common.vo.CommonResponse; 6 | import com.sxzhongf.ad.service.IUserService; 7 | import com.sxzhongf.ad.client.vo.UserRequestVO; 8 | import com.sxzhongf.ad.client.vo.UserResponseVO; 9 | import feign.Param; 10 | import lombok.extern.slf4j.Slf4j; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | /** 15 | * UserController for 用户controller 16 | * 17 | * @author Isaac.Zhang | 若初 18 | * @since 2019/6/21 19 | */ 20 | @RestController 21 | @Slf4j 22 | @RequestMapping("/user") 23 | public class UserController { 24 | @Autowired 25 | private IUserService userService; 26 | 27 | @PostMapping(path = "/create") 28 | public UserResponseVO createUser(@RequestBody UserRequestVO requestVO) throws AdException { 29 | log.info("ad-sponsor: createUser -> {}", JSON.toJSONString(requestVO)); 30 | return userService.createUser(requestVO); 31 | } 32 | 33 | @GetMapping(path = "/get") 34 | public CommonResponse getUserList(@Param(value = "username") String username) throws AdException { 35 | log.info("ad-sponsor: getUserList -> {}", JSON.toJSONString(username)); 36 | return new CommonResponse(userService.findAllByUserName(username)); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/AdPlanRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao; 2 | 3 | import com.sxzhongf.ad.entity.AdPlan; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * AdPlanRepository for 广告计划数据库操作类 10 | * 11 | * @author Isaac.Zhang 12 | * @since 2019/6/19 13 | */ 14 | public interface AdPlanRepository extends JpaRepository { 15 | 16 | AdPlan findByPlanIdAndUserId(Long planId, Long userId); 17 | 18 | List findAllByPlanIdAndUserId(List planIds, Long userId); 19 | 20 | AdPlan findByUserIdAndPlanName(Long userId, String planName); 21 | 22 | List findAllByPlanStatus(Integer status); 23 | } 24 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/AdUnitRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao; 2 | 3 | import com.sxzhongf.ad.entity.AdUnit; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * AdUnitRepository for 广告单元数据库操作类 10 | * 11 | * @author Isaac.Zhang 12 | * @since 2019/6/19 13 | */ 14 | public interface AdUnitRepository extends JpaRepository { 15 | 16 | AdUnit findByPlanIdAndUnitName(Long planId, String unitName); 17 | 18 | List findAllByUnitStatus(Integer unitStatus); 19 | } -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/AdUserRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao; 2 | 3 | import com.sxzhongf.ad.entity.AdUser; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * AdUserRepository for 用户数据库操作接口 10 | * 11 | * @author Isaac.Zhang 12 | * @since 2019/6/19 13 | */ 14 | public interface AdUserRepository extends JpaRepository { 15 | 16 | /** 17 | * 根据用户名称获取用户 18 | * 19 | * @param username 名称 20 | * @return 用户对象 21 | */ 22 | AdUser findByUserName(String username); 23 | 24 | List findAllByUserName(String userName); 25 | } 26 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/CreativeRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao; 2 | 3 | import com.sxzhongf.ad.entity.AdCreative; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * CreativeRepository for 创意表数据库操作类 8 | * 9 | * @author Isaac.Zhang 10 | * @since 2019/6/19 11 | */ 12 | public interface CreativeRepository extends JpaRepository { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/unit_condition/AdUnitDistrictRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao.unit_condition; 2 | 3 | import com.sxzhongf.ad.entity.unit_condition.AdUnitDistrict; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * AdUnitDistrictRepository for 推广单元维度之地域维度 8 | * 9 | * @author Isaac.Zhang 10 | * @since 2019/6/19 11 | */ 12 | public interface AdUnitDistrictRepository extends JpaRepository { 13 | } 14 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/unit_condition/AdUnitHobbyRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao.unit_condition; 2 | 3 | import com.sxzhongf.ad.entity.unit_condition.AdUnitHobby; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * AdUnitHobbyRepository for 推广单元维度之兴趣维度 8 | * 9 | * @author Isaac.Zhang 10 | * @since 2019/6/19 11 | */ 12 | public interface AdUnitHobbyRepository extends JpaRepository { 13 | } 14 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/unit_condition/AdUnitKeywordRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao.unit_condition; 2 | 3 | import com.sxzhongf.ad.entity.unit_condition.AdUnitKeyword; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * AdUnitKeywordRepository for 推广单元维度之关键词维度 8 | * 9 | * @author Isaac.Zhang 10 | * @since 2019/6/19 11 | */ 12 | public interface AdUnitKeywordRepository extends JpaRepository { 13 | } 14 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/dao/unit_condition/RelationshipCreativeUnitRepository.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.dao.unit_condition; 2 | 3 | import com.sxzhongf.ad.entity.unit_condition.RelationshipCreativeUnit; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | 6 | /** 7 | * RelationshipCreativeUnitRepository for 关系表操作类 8 | * 9 | * @author Isaac.Zhang 10 | * @since 2019/6/19 11 | */ 12 | public interface RelationshipCreativeUnitRepository extends JpaRepository { 13 | } 14 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/AdCreative.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.*; 8 | import java.util.Date; 9 | 10 | /** 11 | * AdCreative for 广告创意表 12 | * 13 | * @author Isaac.Zhang 14 | * @since 2019/6/19 15 | */ 16 | @Data 17 | @AllArgsConstructor 18 | @NoArgsConstructor 19 | @Entity 20 | @Table(name = "ad_creative") 21 | public class AdCreative { 22 | 23 | @Id 24 | @GeneratedValue(strategy = GenerationType.IDENTITY) 25 | @Column(name = "creative_id") 26 | private Long creativeId; 27 | 28 | @Basic 29 | @Column(name = "name", nullable = false) 30 | private String name; 31 | 32 | /** 33 | * 创意类型:标示当前创意是视频/图片等等 34 | */ 35 | @Basic 36 | @Column(name = "type", nullable = false) 37 | private Integer type; 38 | 39 | /** 40 | * 物料的类型,比如图片可以是 bmp,jpge等等 41 | */ 42 | @Basic 43 | @Column(name = "material_type", nullable = false) 44 | private Integer materialType; 45 | 46 | /** 47 | * 物料的高度 48 | */ 49 | @Basic 50 | @Column(name = "height", nullable = false) 51 | private Integer height; 52 | 53 | /** 54 | * 物料的宽度 55 | */ 56 | @Basic 57 | @Column(name = "width", nullable = false) 58 | private Integer width; 59 | 60 | /** 61 | * 物料的大小,单位可以是kb,byte 62 | */ 63 | @Basic 64 | @Column(name = "size", nullable = false) 65 | private Integer size; 66 | 67 | /** 68 | * 持续时长,只有视频不为0 69 | */ 70 | @Basic 71 | @Column(name = "duration", nullable = false) 72 | private Long duration; 73 | 74 | /** 75 | * 审核状态 76 | */ 77 | @Basic 78 | @Column(name = "audit_status", nullable = false) 79 | private Integer auditStatus; 80 | 81 | @Basic 82 | @Column(name = "user_id", nullable = false) 83 | private Long userId; 84 | 85 | /** 86 | * 物料存储地址 87 | */ 88 | @Basic 89 | @Column(name = "url", nullable = false) 90 | private String url; 91 | 92 | @Basic 93 | @Column(name = "create_time", nullable = false) 94 | private Date createTime; 95 | 96 | @Basic 97 | @Column(name = "update_time", nullable = false) 98 | private Date updateTime; 99 | 100 | public AdCreative(String name, Integer type, Integer materielType, 101 | Integer height, Integer width, Integer size, Long duration, 102 | Integer auditStatus, Long userId, String url) { 103 | this.name = name; 104 | this.type = type; 105 | this.materialType = materielType; 106 | this.height = height; 107 | this.width = width; 108 | this.size = size; 109 | this.duration = duration; 110 | this.auditStatus = auditStatus; 111 | this.userId = userId; 112 | this.url = url; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/AdPlan.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity; 2 | 3 | import com.sxzhongf.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 | /** 12 | * AdPlan for 推广计划表 13 | * 14 | * @author Isaac.Zhang 15 | * @since 2019/6/15 16 | */ 17 | @Data 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @Entity 21 | @Table(name = "ad_plan") 22 | public class AdPlan { 23 | 24 | @Id 25 | @GeneratedValue(strategy = GenerationType.IDENTITY) 26 | @Column(name = "plan_id", nullable = false) 27 | private Long planId; 28 | 29 | @Basic 30 | @Column(name = "user_id", nullable = false) 31 | private Long userId; 32 | 33 | @Basic 34 | @Column(name = "plan_name", nullable = false) 35 | private String planName; 36 | 37 | @Basic 38 | @Column(name = "plan_status", nullable = false) 39 | private Integer planStatus; 40 | 41 | @Basic 42 | @Column(name = "start_date", nullable = false) 43 | private Date startDate; 44 | 45 | @Basic 46 | @Column(name = "end_date", nullable = false) 47 | private Date endDate; 48 | 49 | @Basic 50 | @Column(name = "create_time", nullable = false) 51 | private Date createTime; 52 | 53 | @Basic 54 | @Column(name = "update_time", nullable = false) 55 | private Date updateTime; 56 | 57 | public AdPlan(Long userId, String planName, Date startDate, Date endDate) { 58 | this.userId = userId; 59 | this.planName = planName; 60 | this.planStatus = CommonStatus.VALID.getStatus(); 61 | this.startDate = startDate; 62 | this.endDate = endDate; 63 | this.createTime = new Date(); 64 | this.updateTime = this.createTime; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/AdUnit.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity; 2 | 3 | import com.sxzhongf.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 | /** 12 | * AdUnit for 广告推广单元 13 | * 14 | * @author Isaac.Zhang 15 | * @see 16 | * @since 2019/6/15 17 | */ 18 | @Data 19 | @NoArgsConstructor 20 | @AllArgsConstructor 21 | @Entity 22 | @Table(name = "ad_unit") 23 | public class AdUnit { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | @Column(name = "unit_id", nullable = false) 28 | private Long unitId; 29 | 30 | @Basic 31 | @Column(name = "plan_id", nullable = false) 32 | private Long planId; 33 | 34 | @Basic 35 | @Column(name = "unit_name", nullable = false) 36 | private String unitName; 37 | 38 | @Basic 39 | @Column(name = "unit_status", nullable = false) 40 | private Integer unitStatus; 41 | 42 | /** 43 | * 广告位类型(开屏广告、贴片(贴着电影开头)、中贴、暂停贴...) 44 | */ 45 | @Basic 46 | @Column(name = "position_type", nullable = false) 47 | private Integer positionType; 48 | 49 | @Basic 50 | @Column(name = "budget_fee", nullable = false) 51 | private Long budgetFee; 52 | 53 | @Basic 54 | @Column(name = "create_time", nullable = false) 55 | private Date createTime; 56 | 57 | @Basic 58 | @Column(name = "update_time", nullable = false) 59 | private Date updateTime; 60 | 61 | public AdUnit(Long planId, String unitName, Integer positionType, Long budgetFee) { 62 | this.planId = planId; 63 | this.unitName = unitName; 64 | this.unitStatus = CommonStatus.VALID.getStatus(); 65 | this.positionType = positionType; 66 | this.budgetFee = budgetFee; 67 | this.createTime = new Date(); 68 | this.updateTime = this.createTime; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/AdUser.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity; 2 | 3 | import com.sxzhongf.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 | /** 12 | * AdUser for 数据库ad_user表对应的实体类 13 | * {@link Basic} 标示为数据库的字段信息,如果需要一个不属于数据库的字段,标注为 {@link Transient} 14 | * 15 | * @author Isaac.Zhang 16 | * @since 2019/6/15 17 | */ 18 | @Data 19 | @AllArgsConstructor 20 | @NoArgsConstructor 21 | @Entity 22 | @Table(name = "ad_user") 23 | public class AdUser { 24 | 25 | @Id 26 | @GeneratedValue(strategy = GenerationType.IDENTITY) 27 | @Column(name = "user_id", nullable = false) 28 | private Long userId; 29 | 30 | @Basic 31 | @Column(name = "user_name", nullable = false) 32 | private String userName; 33 | 34 | @Basic 35 | @Column(name = "token", nullable = false) 36 | private String token; 37 | 38 | @Basic 39 | @Column(name = "user_status", nullable = false) 40 | private Integer userStatus; 41 | 42 | @Basic 43 | @Column(name = "create_time", nullable = false) 44 | private Date createTime; 45 | 46 | @Basic 47 | @Column(name = "update_time", nullable = false) 48 | private Date updateTime; 49 | 50 | /** 51 | * 创建用户时所需的必填字段 52 | * 53 | * @param user_name 用户名称 54 | * @param token token 55 | */ 56 | public AdUser(String user_name, String token) { 57 | this.userName = user_name; 58 | this.token = token; 59 | this.userStatus = CommonStatus.VALID.getStatus(); 60 | this.createTime = new Date(); 61 | this.updateTime = this.createTime; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/unit_condition/AdUnitDistrict.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * AdUnitDistrict for 推广单元对应的维度之地域维度 11 | * 12 | * @author Isaac.Zhang 13 | * @since 2019/6/19 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Entity 19 | @Table(name = "ad_unit_district") 20 | public class AdUnitDistrict { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | @Column(name = "district_id", nullable = false) 25 | private Long districtId; 26 | 27 | @Basic 28 | @Column(name = "unit_id", nullable = false) 29 | private Long unitId; 30 | 31 | @Basic 32 | @Column(name = "province", nullable = false) 33 | private String province; 34 | 35 | @Basic 36 | @Column(name = "city", nullable = false) 37 | private String city; 38 | 39 | public AdUnitDistrict(Long unitId, String province, String city) { 40 | this.unitId = unitId; 41 | this.province = province; 42 | this.city = city; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/unit_condition/AdUnitHobby.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * AdUnitHobby for 推广单元对应的维度之兴趣维度 11 | * 12 | * @author Isaac.Zhang 13 | * @since 2019/6/19 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Entity 19 | @Table(name = "ad_unit_hobby") 20 | public class AdUnitHobby { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | @Column(name = "hobby_id", nullable = false) 25 | private Long hobbyId; 26 | 27 | @Basic 28 | @Column(name = "unit_id", nullable = false) 29 | private Long unitId; 30 | 31 | @Basic 32 | @Column(name = "hobby_tag", nullable = false) 33 | private String hobbyTag; 34 | 35 | 36 | public AdUnitHobby(Long unitId, String hobbyTag) { 37 | this.unitId = unitId; 38 | this.hobbyTag = hobbyTag; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/unit_condition/AdUnitKeyword.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * AdUnitKeyword for 推广单元对应的维度之关键词维度 11 | * 12 | * @author Isaac.Zhang 13 | * @since 2019/6/19 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Entity 19 | @Table(name = "ad_unit_keyword") 20 | public class AdUnitKeyword { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | @Column(name = "keyword_id", nullable = false) 25 | private Long keywordId; 26 | 27 | @Basic 28 | @Column(name = "unit_id", nullable = false) 29 | private Long unitId; 30 | 31 | @Basic 32 | @Column(name = "keyword", nullable = false) 33 | private String keyword; 34 | 35 | 36 | public AdUnitKeyword(Long unitId, String keyword) { 37 | this.unitId = unitId; 38 | this.keyword = keyword; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/entity/unit_condition/RelationshipCreativeUnit.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.entity.unit_condition; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | 7 | import javax.persistence.*; 8 | 9 | /** 10 | * RelationshipCreativeUnit for 创意 & 推广单元 关联关系表 11 | * 12 | * @author Isaac.Zhang 13 | * @since 2019/6/19 14 | */ 15 | @Data 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | @Entity 19 | @Table(name = "relationship_creative_unit") 20 | public class RelationshipCreativeUnit { 21 | 22 | @Id 23 | @GeneratedValue(strategy = GenerationType.IDENTITY) 24 | @Column(name = "id", nullable = false) 25 | private Long id; 26 | 27 | @Basic 28 | @Column(name = "unit_id", nullable = false) 29 | private Long unitId; 30 | 31 | @Basic 32 | @Column(name = "creative_id", nullable = false) 33 | private Long creativeId; 34 | 35 | public RelationshipCreativeUnit(Long unitId, Long creativeId) { 36 | this.unitId = unitId; 37 | this.creativeId = creativeId; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/service/ICreativeService.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | import com.sxzhongf.ad.common.exception.AdException; 4 | import com.sxzhongf.ad.client.vo.CreativeRequestVO; 5 | import com.sxzhongf.ad.client.vo.CreativeResponseVO; 6 | 7 | /** 8 | * ICreativeService for 创意service interface 9 | * 10 | * @author Isaac.Zhang | 若初 11 | * @since 2019/6/20 12 | */ 13 | public interface ICreativeService { 14 | /** 15 | * 新增创意 16 | */ 17 | CreativeResponseVO createCreative(CreativeRequestVO requestVO) throws AdException; 18 | } 19 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/service/IPlanService.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | import com.sxzhongf.ad.common.exception.AdException; 4 | import com.sxzhongf.ad.entity.AdPlan; 5 | import com.sxzhongf.ad.client.vo.PlanGetRequestVO; 6 | import com.sxzhongf.ad.client.vo.PlanRequestVO; 7 | import com.sxzhongf.ad.client.vo.PlanResponseVO; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * IPlanService for 推广计划service 接口 13 | * 14 | * @author Isaac.Zhang | 若初 15 | * @since 2019/6/19 16 | */ 17 | public interface IPlanService { 18 | 19 | /** 20 | * 创建推广计划 21 | */ 22 | PlanResponseVO createPlan(PlanRequestVO planRequestVO) throws AdException; 23 | 24 | /** 25 | * 获取推广计划 26 | */ 27 | List getAdPlanByPlanIds(PlanGetRequestVO planGetRequestVO) throws AdException; 28 | 29 | /** 30 | * 更新推广计划 31 | */ 32 | PlanResponseVO updatePlan(PlanRequestVO planRequestVO) throws AdException; 33 | 34 | /** 35 | * 删除推广计划 36 | */ 37 | void deletePlan(PlanRequestVO planRequestVO) throws AdException; 38 | } 39 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/service/IUnitService.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | import com.sxzhongf.ad.common.exception.AdException; 4 | import com.sxzhongf.ad.client.vo.*; 5 | 6 | /** 7 | * IUnitService for 推广单元service 8 | * 9 | * @author Isaac.Zhang | 若初 10 | * @since 2019/6/20 11 | */ 12 | public interface IUnitService { 13 | /** 14 | * 创建推广单元 15 | */ 16 | UnitResponseVO createUnit(UnitRequestVO unitRequestVO) throws AdException; 17 | 18 | /** 19 | * 创建推广单元-关键字 20 | */ 21 | UnitKeywordResponseVO createUnitKeyword(UnitKeywordRequestVO requestVO) throws AdException; 22 | 23 | /** 24 | * 创建推广单元-爱好 25 | */ 26 | UnitHobbyResponseVO createUnitHobby(UnitHobbyRequestVO requestVO) throws AdException; 27 | 28 | /** 29 | * 创建推广单元-地域 30 | */ 31 | UnitDistrictResponseVO createUnitDistrict(UnitDistrictRequestVO requestVO) throws AdException; 32 | 33 | /** 34 | * 插入创意和推广单元关系表数据 35 | */ 36 | CreativeUnitRelationshipResponseVO createCreativeUnitRelationship(CreativeUnitRelationshipRequestVO requestVO) throws AdException; 37 | } 38 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/service/IUserService.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | import com.sxzhongf.ad.common.exception.AdException; 4 | import com.sxzhongf.ad.client.vo.UserRequestVO; 5 | import com.sxzhongf.ad.client.vo.UserResponseVO; 6 | import com.sxzhongf.ad.entity.AdUser; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * IUserService for 用户service 12 | * 13 | * @author Isaac.Zhang | 若初 14 | * @since 2019/6/19 15 | */ 16 | public interface IUserService { 17 | 18 | /** 19 | * 创建用户接口 20 | * 21 | * @param userRequestVO {@link UserRequestVO} 22 | * @return {@link UserResponseVO} 23 | * @throws AdException 错误 24 | */ 25 | UserResponseVO createUser(UserRequestVO userRequestVO) throws AdException; 26 | 27 | List findAllByUserName(String userName); 28 | } 29 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/service/impl/CreativeServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service.impl; 2 | 3 | import com.sxzhongf.ad.common.exception.AdException; 4 | import com.sxzhongf.ad.dao.CreativeRepository; 5 | import com.sxzhongf.ad.entity.AdCreative; 6 | import com.sxzhongf.ad.service.ICreativeService; 7 | import com.sxzhongf.ad.client.vo.CreativeRequestVO; 8 | import com.sxzhongf.ad.client.vo.CreativeResponseVO; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.stereotype.Service; 12 | 13 | /** 14 | * CreativeServiceImpl for 创意service 15 | * 16 | * @author Isaac.Zhang | 若初 17 | * @since 2019/6/20 18 | */ 19 | @Slf4j 20 | @Service 21 | public class CreativeServiceImpl implements ICreativeService { 22 | 23 | private final CreativeRepository creativeRepository; 24 | 25 | @Autowired 26 | public CreativeServiceImpl(CreativeRepository creativeRepository) { 27 | this.creativeRepository = creativeRepository; 28 | } 29 | 30 | @Override 31 | public CreativeResponseVO createCreative(CreativeRequestVO requestVO) throws AdException { 32 | //TODO: validate params 33 | 34 | AdCreative creative = creativeRepository.save( 35 | requestVO.convertToEntity() 36 | ); 37 | 38 | return new CreativeResponseVO(creative.getCreativeId(), creative.getName()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/java/com/sxzhongf/ad/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service.impl; 2 | 3 | import com.sxzhongf.ad.common.exception.AdException; 4 | import com.sxzhongf.ad.common.utils.CommonUtils; 5 | import com.sxzhongf.ad.common.vo.CommonResponse; 6 | import com.sxzhongf.ad.constant.Constants; 7 | import com.sxzhongf.ad.dao.AdUserRepository; 8 | import com.sxzhongf.ad.entity.AdUser; 9 | import com.sxzhongf.ad.service.IUserService; 10 | import com.sxzhongf.ad.client.vo.UserRequestVO; 11 | import com.sxzhongf.ad.client.vo.UserResponseVO; 12 | import lombok.extern.slf4j.Slf4j; 13 | import org.springframework.beans.factory.annotation.Autowired; 14 | import org.springframework.stereotype.Service; 15 | 16 | import javax.transaction.Transactional; 17 | import java.util.List; 18 | 19 | /** 20 | * UserServiceImpl for 用户service 21 | * 22 | * @author Isaac.Zhang | 若初 23 | * @since 2019/6/19 24 | */ 25 | @Slf4j 26 | @Service 27 | public class UserServiceImpl implements IUserService { 28 | 29 | private final AdUserRepository userRepository; 30 | 31 | @Autowired 32 | public UserServiceImpl(AdUserRepository userRepository) { 33 | this.userRepository = userRepository; 34 | } 35 | 36 | /** 37 | * 创建用户 38 | * 39 | * @param userRequestVO {@link UserRequestVO} 40 | * @return result {@link UserResponseVO} 41 | * @since 2019/6/19 9:08 PM 42 | */ 43 | @Override 44 | @Transactional 45 | public UserResponseVO createUser(UserRequestVO userRequestVO) throws AdException { 46 | if (!userRequestVO.validate()) { 47 | log.error("Request params error: {}", userRequestVO); 48 | throw new AdException(Constants.ErrorMessage.REQUEST_PARAM_ERROR); 49 | } 50 | //查重 51 | AdUser existUser = userRepository.findByUserName(userRequestVO.getUserName()); 52 | if (existUser != null) { 53 | log.error("{} user is not exist.", userRequestVO.getUserName()); 54 | throw new AdException(Constants.ErrorMessage.USER_EXIST); 55 | } 56 | AdUser user = userRepository.save(new AdUser(userRequestVO.getUserName(), CommonUtils.md5(userRequestVO.getUserName()))); 57 | log.info("current user is : {}", user); 58 | return new UserResponseVO(user.getUserId(), user.getUserName(), user.getToken(), 59 | user.getCreateTime(), user.getUpdateTime()); 60 | } 61 | 62 | @Override 63 | public List findAllByUserName(String userName) { 64 | return userRepository.findAllByUserName(userName); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 7000 3 | servlet: 4 | context-path: /ad-sponsor #http请求的根路径(请求前缀,在handle的mapping之前,需要127.0.0.1/ad-sponsor/XXXX) 5 | spring: 6 | application: 7 | name: mscx-ad-sponsor 8 | jpa: 9 | show-sql: true #执行时是否打印sql语句,方便调试 10 | hibernate: 11 | ddl-auto: none 12 | properties: 13 | hibernate.format_sql: true 14 | open-in-view: false #控制是否在懒加载时,有可能会找不到bean报错 15 | datasource: 16 | username: root 17 | url: jdbc:mysql://127.0.0.1:3306/advertisement?useSSL=false&autoReconnect=true 18 | password: 12345678 19 | tomcat: 20 | max-active: 4 #最大连接数 21 | min-idle: 2 #最小空闲连接数 22 | initial-size: 2 #默认初始化连接数 23 | eureka: 24 | client: 25 | service-url: 26 | defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ 27 | instance: 28 | prefer-ip-address: false 29 | 30 | 31 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/test/java/com/sxzhongf/ad/SponsorApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.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.openfeign.EnableFeignClients; 8 | 9 | /** 10 | * SponsorApplication for Unit Test 11 | * @author Isaac.Zhang 12 | * @since 2019/6/15 13 | */ 14 | 15 | @SpringBootApplication 16 | public class SponsorApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(SponsorApplication.class, args); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/test/java/com/sxzhongf/ad/service/AdPlanServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | import com.sxzhongf.ad.SponsorApplication; 4 | import com.sxzhongf.ad.client.vo.PlanGetRequestVO; 5 | import com.sxzhongf.ad.common.exception.AdException; 6 | import com.sxzhongf.ad.entity.AdPlan; 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 java.util.Arrays; 14 | import java.util.List; 15 | import java.util.stream.Stream; 16 | 17 | /** 18 | * AdPlanServiceTest for 推广计划单元测试 19 | * 20 | * @author Isaac.Zhang | 若初 21 | * @since 2019/8/16 22 | */ 23 | @RunWith(SpringRunner.class) 24 | @SpringBootTest( 25 | classes = {SponsorApplication.class}, 26 | webEnvironment = SpringBootTest.WebEnvironment.NONE 27 | ) 28 | public class AdPlanServiceTest { 29 | 30 | @Autowired 31 | private IPlanService planService; 32 | 33 | @Test 34 | public void testGetAdPlanByPlanIds() throws AdException { 35 | 36 | List adPlanByPlanIds = planService.getAdPlanByPlanIds(new PlanGetRequestVO(10L, Arrays.asList(10L))); 37 | assert adPlanByPlanIds.size() == 1; 38 | assert adPlanByPlanIds.get(0).getPlanId() == 10L; 39 | 40 | Stream.of(adPlanByPlanIds).forEach(System.out::println); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/test/java/com/sxzhongf/ad/service/AdUnitServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | import com.sxzhongf.ad.SponsorApplication; 4 | import com.sxzhongf.ad.client.vo.UnitRequestVO; 5 | import com.sxzhongf.ad.client.vo.UnitResponseVO; 6 | import com.sxzhongf.ad.common.exception.AdException; 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 | import org.springframework.transaction.annotation.Transactional; 13 | 14 | /** 15 | * AdUnitServiceTest for 推广单元测试用例 16 | * 17 | * @author Isaac.Zhang | 若初 18 | * @since 2019/8/16 19 | */ 20 | @RunWith(SpringRunner.class) 21 | @SpringBootTest( 22 | classes = {SponsorApplication.class}, 23 | webEnvironment = SpringBootTest.WebEnvironment.NONE) 24 | public class AdUnitServiceTest { 25 | 26 | @Autowired 27 | private IUnitService unitService; 28 | 29 | @Test 30 | @Transactional 31 | public void testCreateUnit() throws AdException { 32 | 33 | UnitResponseVO unit = unitService.createUnit( 34 | new UnitRequestVO().builder() 35 | .planId(10L) 36 | .positionType(1) 37 | .budgetFee(100L) 38 | .unitName("test-unit-name") 39 | .build()); 40 | assert unit.getUnitName().equals("test-unit-name"); 41 | System.out.println("测试推广单元:" + unit); 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /mscx-ad-sponsor/src/test/java/com/sxzhongf/ad/service/UserServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.service; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import com.sxzhongf.ad.SponsorApplication; 5 | import com.sxzhongf.ad.common.exception.AdException; 6 | import com.sxzhongf.ad.client.vo.UserRequestVO; 7 | import com.sxzhongf.ad.client.vo.UserResponseVO; 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 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | /** 16 | * UserServiceTest for TODO 17 | * 18 | * @author Isaac.Zhang | 若初 19 | * @since 2019/6/21 20 | */ 21 | @RunWith(SpringRunner.class) 22 | @SpringBootTest( 23 | classes = {SponsorApplication.class}, 24 | webEnvironment = SpringBootTest.WebEnvironment.NONE 25 | ) 26 | public class UserServiceTest { 27 | 28 | @Autowired 29 | private IUserService userService; 30 | 31 | @Test 32 | // @Transactional 33 | public void testCreateUser() throws AdException { 34 | UserRequestVO userRequestVO = new UserRequestVO("Isaac Zhang"); 35 | 36 | UserResponseVO responseVO = userService.createUser(userRequestVO); 37 | 38 | assert responseVO.getUserName() == "Isaac Zhang"; 39 | 40 | System.out.printf("创建用户: %s", JSON.toJSONString(responseVO)); 41 | 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /mscx-ad-zuul/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | mscx-ad 7 | com.sxzhongf 8 | 1.0-SNAPSHOT 9 | ../pom.xml 10 | 11 | 4.0.0 12 | jar 13 | 14 | com.sxzhongf 15 | mscx-ad-zuul 16 | 1.0-SNAPSHOT 17 | zuul网关提供 18 | 使用zuul来提供服务网关实现 19 | 20 | 21 | 22 | org.springframework.cloud 23 | spring-cloud-starter-netflix-zuul 24 | 25 | 26 | org.springframework.cloud 27 | spring-cloud-starter-netflix-eureka-client 28 | 29 | 30 | 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-maven-plugin 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /mscx-ad-zuul/src/main/java/com/sxzhongf/ad/gateway/GatewayApplication.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.SpringCloudApplication; 6 | import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; 7 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 8 | import org.springframework.cloud.netflix.zuul.EnableZuulProxy; 9 | import org.springframework.scheduling.annotation.EnableScheduling; 10 | import org.springframework.scheduling.annotation.Scheduled; 11 | 12 | /** 13 | * GatewayApplication for zuul网关启动类 14 | * {@link SpringCloudApplication} 是下面三个注解组合 15 | * 16 | * @author Isaac.Zhang 17 | * @see SpringBootApplication 18 | * @see EnableDiscoveryClient 19 | * @see EnableCircuitBreaker 20 | * @since 2019/6/13 21 | */ 22 | @SpringCloudApplication 23 | @EnableZuulProxy 24 | //@EnableScheduling 25 | public class GatewayApplication { 26 | 27 | public static void main(String[] args) { 28 | SpringApplication.run(GatewayApplication.class, args); 29 | } 30 | 31 | @Scheduled(fixedRate = 2000) 32 | private void print(){ 33 | System.out.println("hello scheduled."); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mscx-ad-zuul/src/main/java/com/sxzhongf/ad/gateway/filter/AccessLogFilter.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway.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 | * AccessLogFilter for 记录服务请求结束时间,配合{@link PreRequestFilter}计算整个调用请求链路消耗时间 14 | * 15 | * @author Isaac.Zhang 16 | * @since 2019/6/13 17 | */ 18 | @Slf4j 19 | @Component 20 | public class AccessLogFilter extends ZuulFilter { 21 | 22 | @Override 23 | public String filterType() { 24 | return FilterConstants.POST_TYPE; 25 | } 26 | 27 | @Override 28 | public int filterOrder() { 29 | //需要最后一个执行的filter 30 | return FilterConstants.SEND_RESPONSE_FILTER_ORDER - 1; 31 | } 32 | 33 | @Override 34 | public boolean shouldFilter() { 35 | return true; 36 | } 37 | 38 | @Override 39 | public Object run() throws ZuulException { 40 | RequestContext requestContext = RequestContext.getCurrentContext(); 41 | HttpServletRequest request = requestContext.getRequest(); 42 | log.info("Request \"{}\" spent : {} ms.", request.getRequestURI(), 43 | (System.currentTimeMillis() - Long.valueOf(requestContext.get("api_request_time").toString()))); 44 | return null; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /mscx-ad-zuul/src/main/java/com/sxzhongf/ad/gateway/filter/PreRequestFilter.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway.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 | /** 11 | * PreRequestFilter for 自定义{@link ZuulFilter},记录服务请求进入时间 12 | * 13 | * @author Isaac.Zhang 14 | * @since 2019/6/13 15 | */ 16 | @Slf4j 17 | @Component 18 | public class PreRequestFilter extends ZuulFilter { 19 | @Override 20 | public String filterType() { 21 | // pre filter 22 | return FilterConstants.PRE_TYPE; 23 | } 24 | 25 | @Override 26 | public int filterOrder() { 27 | return 0; 28 | } 29 | 30 | @Override 31 | public boolean shouldFilter() { 32 | return true; 33 | } 34 | 35 | @Override 36 | public Object run() throws ZuulException { 37 | //获取当前请求的请求上下文 38 | RequestContext requestContext = RequestContext.getCurrentContext(); 39 | //记录请求进入时间 40 | requestContext.set("api_request_time", System.currentTimeMillis()); 41 | return null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /mscx-ad-zuul/src/main/java/com/sxzhongf/ad/gateway/filter/ValidateTokenFilter.java: -------------------------------------------------------------------------------- 1 | package com.sxzhongf.ad.gateway.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 | * ValidateTokenFilter for 服务token校验 14 | * 15 | * @author Isaac.Zhang 16 | * @see 17 | * @since 2019/6/13 18 | */ 19 | @Slf4j 20 | @Component 21 | public class ValidateTokenFilter extends ZuulFilter { 22 | @Override 23 | public String filterType() { 24 | return FilterConstants.PRE_TYPE; 25 | } 26 | 27 | @Override 28 | public int filterOrder() { 29 | return 1; 30 | } 31 | 32 | @Override 33 | public boolean shouldFilter() { 34 | return true; 35 | } 36 | 37 | @Override 38 | public Object run() throws ZuulException { 39 | RequestContext ctx = RequestContext.getCurrentContext(); 40 | HttpServletRequest request = ctx.getRequest(); 41 | 42 | log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString())); 43 | 44 | Object accessToken = request.getHeader("accessToken"); //.getParameter("accessToken"); 45 | if (accessToken == null) { 46 | log.warn("access token is empty"); 47 | ctx.setSendZuulResponse(false); 48 | ctx.setResponseStatusCode(401); 49 | // ctx.setResponseBody(body)对返回body内容进行编辑 50 | return null; 51 | } 52 | log.info("access token ok"); 53 | return null; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /mscx-ad-zuul/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: ad-gateway-zuul 4 | server: 5 | port: 1111 6 | eureka: 7 | client: 8 | service-url: 9 | defaultZone: http://server1:7777/eureka/,http://server2:8888/eureka/,http://server3:9999/eureka/ 10 | instance: 11 | hostname: ad-gateway-zuul 12 | prefer-ip-address: false 13 | zuul: 14 | # ignored-services: '*' # 过滤所有请求,除了下面routes中声明过的服务 15 | routes: 16 | sponsor: #在路由中自定义服务路由名称 17 | path: /ad-sponsor/** 18 | serviceId: mscx-ad-sponsor #微服务name 19 | strip-prefix: false 20 | search: #在路由中自定义服务路由名称 21 | path: /ad-search/** 22 | serviceId: mscx-ad-search #微服务name 23 | strip-prefix: false 24 | prefix: /gateway/api 25 | strip-prefix: true #不对 prefix: /gateway/api 设置的路径进行截取,默认转发会截取掉配置的前缀 26 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | pom 7 | 8 | mscx-ad-discovery 9 | mscx-ad-zuul 10 | mscx-ad-gateway 11 | mscx-ad-common 12 | 13 | mscx-ad-feign-sdk 14 | mscx-ad-search 15 | mscx-ad-sponsor 16 | kafka-demo 17 | mscx-ad-dashboard 18 | 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-parent 23 | 2.1.5.RELEASE 24 | 25 | 26 | 27 | com.sxzhongf 28 | mscx-ad 29 | 1.0-SNAPSHOT 30 | 分布式广告系统 31 | 基于Spring Cloud Alibaba 实现的分布式广告系统 32 | 33 | 34 | 1.8 35 | Greenwich.SR2 36 | 37 | 38 | 39 | 40 | org.projectlombok 41 | lombok 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-starter-test 46 | test 47 | 48 | 49 | 50 | 51 | 52 | 53 | org.springframework.cloud 54 | spring-cloud-dependencies 55 | ${spring-cloud.version} 56 | pom 57 | import 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | spring-milestones 66 | Spring Milestones 67 | https://repo.spring.io/milestone 68 | 69 | false 70 | 71 | 72 | 73 | alibaba-milestones 74 | ali Milestones 75 | http://maven.aliyun.com/nexus/content/groups/public/ 76 | 77 | false 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | --------------------------------------------------------------------------------