投放模块
数据表设计
- 用户账户
- 推广计划(与推广单元是一对多)
- 推广单元 (与创意是多对多)
- 创意
层级设计
最高层级: 用户账户
第二层级: 推广计划
第三层级: 推广单元
- 关键词推广单元
- 地域推广单元
- 兴趣推广单元
- 人群推广单元
创意: 文字创意,图片创意等等
用户表
用户账户(ad_user) | 含义 |
---|---|
username | 账户名称 |
token | 账户token |
user_status | 账号状态 |
create_time | 创建时间 |
update_time | 更新时间 |
推广计划表
推广计划(ad_plan) | 含义 |
---|---|
user_id | 标记当前记录所属用户 |
plan_name | 推广计划名称 |
plan_status | 推广计划状态 |
start_date | 推广计划开始时间 |
end_date | 推广计划结束时间 |
create_time | 创建时间 |
update_time | 更新时间 |
推广单元表
推广单元(ad_unit) | 含义 |
---|---|
plan_id | 关联推广计划id |
unit_name | 推广单元名称 |
unit_status | 推广单元状态 |
position_type | 广告位类型 |
budget | 预算 |
create_time | 创建时间 |
update_time | 更新时间 |
关键词推广单元
关键词限制(ad_unit_keyword) | 含义 |
---|---|
unit_id | 关联推广单元id |
keyword | 关键词 |
地域推广单元
关键词限制(ad_unit_district) | 含义 |
---|---|
unit_id | 关联推广单元id |
province | 省 |
city | 市 |
兴趣推广单元
关键词限制(ad_unit_it) | 含义 |
---|---|
unit_id | 关联推广单元id |
it_tag | 兴趣标签 |
创意表
创意(ad_creative) | 含义 |
---|---|
name | 创意名称 |
type | 物料类型 |
material_type | 物料子类型 |
height | 高度 |
width | 宽度 |
size | 尺寸 |
duration | 持续时长 |
audit_status | 审核状态 |
user_id | 标记当前所属用户 |
url | 物料地址 |
create_time | 创建时间 |
update_time | 更新时间 |
由于创意与推广单元是多对多关系,因此还要有一个创意与推广单元关联表。
创意与推广单元关联表
创意与推广单元关联(creative_unit) | 含义 |
---|---|
creative_id | 关联创意id |
unit_id | 关联推广单元id |
代码编写
编写配置文件
1 | server: |
定义数据表实体类(ad_user)
1 | import org.springframework.boot.SpringApplication; |
对应创建的数据库表
1 | -- 用户表 |
1 | import lombok.AllArgsConstructor; |
接下来编写ad_plan,ad_unit以及创意表,创意推广单元关联表对应的实体类,方式与上述代码基本一致。
定义数据表Dao接口(以AdUser实体类为例)
1 | import org.springframework.data.jpa.repository.JpaRepository; |
用户账户服务功能实现
用户创建需要提供创建用户的请求数据,还需要返回给广告主数据。
vo对象定义,即请求和响应
请求对象
1 |
|
响应对象
1 |
|
创建用户的接口实现
对于创建用户接口,创建了相应的请求对象和响应对象,方便管理实体类。
如果有其他功能的接口方法,则创建相对应的请求对象和响应对象。
1 | public interface IUserService { |
实现用户接口
使用内部类定义一些error信息
1 | public class Constants { |
1 | // service层 |
推广计划服务功能实现
同样的编写对应的vo 请求对象。应用于创建,更新以及删除推广计划的方法中。
1 |
|
创建获取推广计划的请求对象
1 |
|
响应对象的封装
1 |
|
创建推广计划服务的增删改查的接口
定义了请求的vo对象,方便序列化和反序列化。
1 | import java.util.List; |
将String属性转化成Date属性
1 | private static String[] parsePatterns = {"yyyy-MM-dd", "yyyy/MM/dd", "yyyy.MM.dd"}; |
实现推广计划服务接口
1 |
|
1 |
|
1 | private boolean isRelatedUnitExist(List |
java8特性
1 |
|
java8 stream().map().collect()用法
有一个集合:
1 | List |
现在想获取User的身份证号码;在后续的逻辑处理中要用;
常用的方法我们大家都知道,用for循环,
1 | List |
java8 之后:
1 | List |
解释下一这行代码:
users:一个实体类的集合,类型为List
User:实体类
getIdcard:实体类中的get方法,为获取User的idcard
stream()优点
无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
stream().map()方法的使用示例:
- 数组字母小写变大写
1 | List |
数组所有元素,按某种规律计算:
1
2
3List
num = Arrays.asList(1,2,3,4,5);
Listcollect1 = num.stream().map(n -> n * 2).collect(Collectors.toList());
System.out.println(collect1); //[2, 4, 6, 8, 10]
1 | 4j |
配置路由信息
1 | zuul: |
检索模块
1 | feign: |
1 | "eureka-client-ad-sponsor", (value = |
断路器
1 |
|
构建正向索引和倒排索引。
构建索引接口,对索引的增删改查
1 | public interface IndexAware<K, V> { |
不需要对数据库全部的字段建立索引,而且也不需要对全部的数据库表建立索引,比如用户表,不需要对广告主建立索引。
建立推广计划的索引属性planname不需要作为索引,定义索引对象
1 |
|
构建正向索引,通过id得到推广计划的索引对象
1 | 4j |
构建推广单元的索引对象
1 |
|
关键词推广单元的索引实现
其中,对推广单元的限制这种要使用倒排索引。
1 |
|