此博客用于个人学习,来源于网上,对知识点进行一个整理。
1. 创意服务功能实现:
1.1 定义响应格式:
由于要进行数据的交互,所以需要定义一个 Request 和 Response 的响应格式,本次暂不考虑验证的事情。在 Request 中,需要定义一个方法用于将 request 对象转化为实体类对象。
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreativeRequest {
private String name;
private Integer type;
private Integer materialType;
private Integer height;
private Integer width;
private Long size;
private Integer duration;
private Long userId;
private String url;
/**
* 将请求对象转化为实体类对象
* @return
*/
public Creative convertToEntity(){
Creative creative = new Creative();
creative.setName(name);
creative.setType(type);
creative.setMaterialType(materialType);
creative.setHeight(height);
creative.setWidth(width);
creative.setSize(size);
creative.setDuration(duration);
creative.setAuditStatus(CommonStatus.VALID.getStatus());
creative.setUserId(userId);
creative.setUrl(url);
creative.setCreateTime(new Date());
creative.setUpdateTime(creative.getCreateTime());
return creative;
}
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreativeResponse {
private Long id;
private String name;
}
1.2 核心逻辑 Service:
前面构造的类都是为了核心的逻辑而建立的,以创建创意方法为例。首先,先定义一个 Service 接口,如下:
public interface ICreativeService {
/**
* 创建一个新创意
* @param request
* @return
* @throws AdException
*/
CreativeResponse creatCreative(CreativeRequest request) throws AdException;
}
然后,实现该接口。
@Service
public class CreativeServiceImpl implements ICreativeService {
private final CreativeRepository creativeRepository;
@Autowired
public CreativeServiceImpl(CreativeRepository creativeRepository) {
this.creativeRepository = creativeRepository;
}
/**
* 创建一个新创意
* @param request
* @return
* @throws AdException
*/
@Override
public CreativeResponse creatCreative(CreativeRequest request) throws AdException{
Creative creative = creativeRepository.save(
request.convertToEntity()
);
return new CreativeResponse(creative.getId(),creative.getName());
}
}
2. 创意与推广单元关联服务功能实现:
由于推广单元与创意是多对多关系,需要在推广单元的 Service 层中添加与创意的关联方法。
2.1 定义响应格式:
请求:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreativeUnitRequest {
private List<CreativeUnitItem> unitItems;
@Data
@AllArgsConstructor
@NoArgsConstructor
public static class CreativeUnitItem{
private Long creativeId;
private Long unitId;
}
}
响应:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class CreativeUnitResponse {
private List<Long> ids;
}
2.2 核心逻辑 Service:
Service 接口:前四个方法是之前就定义的,第五个方法才是与创意的关联方法。
public interface IAdUnitService {
AdUnitResponse createUnit(AdUnitRequest request) throws AdException;
AdUnitKeywordResponse createUnitKeyword(AdUnitKeywordRequest request) throws AdException;
AdUnitItResponse createUnitIt(AdUnitItRequest request) throws AdException;
AdUnitDistrictResponse createUnitDistrict(AdUnitDistrictRequest request) throws AdException;
CreativeUnitResponse createCreativeUnit(CreativeUnitRequest request) throws AdException;
}
Service:添加创意 ID 的验证方法,并且实现刚才定义的创建方法。
@Service
public class AdUnitServiceImpl implements IAdUnitService {
private final AdPlanRepository planRepository;
private final AdUnitRepository unitRepository;
private final AdUnitKeyWordRepository unitKeyWordRepository;
private final AdUnitItRepository unitItRepository;
private final AdUnitDistrictRepository unitDistrictRepository;
private final CreativeRepository creativeRepository;
private final CreativeUnitRepository creativeUnitRepository;
@Autowired
public AdUnitServiceImpl(AdPlanRepository planRepository, AdUnitRepository unitRepository,
AdUnitKeyWordRepository unitKeyWordRepository, AdUnitItRepository unitItRepository,
AdUnitDistrictRepository unitDistrictRepository, CreativeRepository creativeRepository, CreativeUnitRepository creativeUnitRepository) {
this.planRepository = planRepository;
this.unitRepository = unitRepository;
this.unitKeyWordRepository = unitKeyWordRepository;
this.unitItRepository = unitItRepository;
this.unitDistrictRepository = unitDistrictRepository;
this.creativeRepository = creativeRepository;
this.creativeUnitRepository = creativeUnitRepository;
}
@Override
public AdUnitResponse createUnit(AdUnitRequest request) throws AdException {
if (!request.createValidate()){
throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
}
Optional<AdPlan> adPlan = planRepository.findById(request.getPlanId());
if (!adPlan.isPresent()){
throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD);
}
AdUnit oldAdUnit = unitRepository.findByPlanIdAndUnitName(
request.getPlanId(),request.getUnitName()
);
if (oldAdUnit != null){
throw new AdException(Constants.ErrorMsg.SAME_NAME_UNIT_ERROR);
}
AdUnit newAdUnit = unitRepository.save(
new AdUnit(request.getPlanId(),request.getUnitName(),request.getPositionType(),request.getBudget())
);
return new AdUnitResponse(newAdUnit.getId(),newAdUnit.getUnitName());
}
@Override
public AdUnitKeywordResponse createUnitKeyword(AdUnitKeywordRequest request) throws AdException {
List<Long> unitIds = request.getUnitKeywords().stream().map(AdUnitKeywordRequest.UnitKeyword::getUnitId).collect(Collectors.toList());
if (!isRelatedUnitExist(unitIds)){
throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
}
List<Long> ids = Collections.emptyList();
List<AdUnitKeyword> unitKeywords = new ArrayList<>();
if (!CollectionUtils.isEmpty(request.getUnitKeywords())){
request.getUnitKeywords().forEach(i -> unitKeywords.add(
new AdUnitKeyword(i.getUnitId(),i.getKeyword())
));
ids = unitKeyWordRepository.saveAll(unitKeywords).stream().map(AdUnitKeyword::getId).collect(Collectors.toList());
}
return new AdUnitKeywordResponse(ids);
}
@Override
public AdUnitItResponse createUnitIt(AdUnitItRequest request) throws AdException {
List<Long> unitIds = request.getUnitIts().stream().map(AdUnitItRequest.UnitIt::getUnitId).collect(Collectors.toList());
if (!isRelatedUnitExist(unitIds)){
throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
}
List<AdUnitIt> unitIts = new ArrayList<>();
request.getUnitIts().forEach(i -> unitIts.add(
new AdUnitIt(i.getUnitId(),i.getItTag())
));
List<Long> ids = unitItRepository.saveAll(unitIts).stream().map(AdUnitIt::getId).collect(Collectors.toList());
return new AdUnitItResponse(ids);
}
@Override
public AdUnitDistrictResponse createUnitDistrict(AdUnitDistrictRequest request) throws AdException {
List<Long> unitIds = request.getUnitDistricts().stream().map(AdUnitDistrictRequest.UnitDistrict::getUnitId).collect(Collectors.toList());
if (!isRelatedUnitExist(unitIds)){
throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
}
List<AdUnitDistrict> unitDistricts = new ArrayList<>();
request.getUnitDistricts().forEach(d -> unitDistricts.add(
new AdUnitDistrict(d.getUnitId(),d.getProvince(),d.getCity())
));
List<Long> ids = unitDistrictRepository.saveAll(unitDistricts).stream().map(AdUnitDistrict::getId).collect(Collectors.toList());
return new AdUnitDistrictResponse(ids);
}
@Override
public CreativeUnitResponse createCreativeUnit(CreativeUnitRequest request) throws AdException {
List<Long> unitIds = request.getUnitItems().stream().map(CreativeUnitRequest.CreativeUnitItem::getUnitId).collect(Collectors.toList());
List<Long> creativeIds = request.getUnitItems().stream().map(CreativeUnitRequest.CreativeUnitItem::getCreativeId).collect(Collectors.toList());
if (!(isRelatedUnitExist(unitIds) && isRelatedCreativeUnit(creativeIds))){
throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
}
List<CreativeUnit> creativeUnits = new ArrayList<>();
request.getUnitItems().forEach(i -> creativeUnits.add(
new CreativeUnit(i.getCreativeId(),i.getUnitId())
));
List<Long> ids = creativeUnitRepository.saveAll(creativeUnits).stream().map(CreativeUnit::getId).collect(Collectors.toList());
return new CreativeUnitResponse(ids);
}
/**
* 对输入的 ID 进行校验
* @param unitIds
* @return
*/
private boolean isRelatedUnitExist(List<Long> unitIds){
if (CollectionUtils.isEmpty(unitIds)){
return false;
}
return unitRepository.findAllById(unitIds).size() == new HashSet<>(unitIds).size();
}
/**
* 对输入的创意 ID 进行校验
* @param creativeIds
* @return
*/
private boolean isRelatedCreativeUnit(List<Long> creativeIds){
if (CollectionUtils.isEmpty(creativeIds)){
return false;
}
return creativeRepository.findAllById(creativeIds).size() == new HashSet<>(creativeIds).size();
}
}
3. 服务 Controller 的编写:
3.1 用户 Controller:
由于需要考虑到其中有 JSON 格式的数据,于是定义 @RestController 注解,以及考虑到日志的情况,添加 @Slf4j 的注解。由于之前用户的 service 中只有定义创建方法,于是 Controller 中也是只需要实现一个方法即可。
@RestController
@Slf4j
public class UserOPController {
private final IUserService userService;
@Autowired
public UserOPController(IUserService userService) {
this.userService = userService;
}
@PostMapping("/create/user")
public CreateUserResponse createUser(@RequestBody CreateUserRequest request) throws AdException {
log.info("ad-sponsor: createUser -> {}", JSON.toJSONString(request));
return userService.createUser(request);
}
}
3.2 推广计划 Controller:
由于之前推广计划的 service 中定义了增删改查四个方法,于是 Controller 中也是需要实现四个方法,同样的这里需要注意到的就是推广计划的响应数据有两种,一种对应查询方法,另外一种对应剩下三种方法。
@Slf4j
@RestController
public class AdPlanOPController {
private final IAdPlanService adPlanService;
@Autowired
public AdPlanOPController(IAdPlanService adPlanService) {
this.adPlanService = adPlanService;
}
@PostMapping("/create/adPlan")
public AdPlanResponse createAdPlan(@RequestBody AdPlanRequest request) throws AdException{
log.info("ad-sponsor: createAdPlan -> {}", JSON.toJSONString(request));
return adPlanService.createAdPlan(request);
}
@PostMapping("/get/adPlan")
public List<AdPlan> getAdPlanByIds(@RequestBody AdPlanGetRequest request) throws AdException{
log.info("ad-sponsor: getAdPlanIds -> {}",JSON.toJSONString(request));
return adPlanService.getAdPlanByIds(request);
}
@PostMapping("/update/adPlan")
public AdPlanResponse updateAdPlan(@RequestBody AdPlanRequest request) throws AdException{
log.info("ad-sponsor: updateAdPlan -> {}",JSON.toJSONString(request));
return adPlanService.updateAdPlan(request);
}
@DeleteMapping("/delete/adPlan")
public void deleteAdPlan(@RequestBody AdPlanRequest request) throws AdException{
log.info("ad-sponsor: deleteAdPlan -> {}",JSON.toJSONString(request));
adPlanService.deleteAdPlan(request);
}
}
3.3 推广单元 Controller:
由于之前推广单元的 service 中定义了本身的创建方法,与三个限制相关联的创建方法,与创意相关联的创建方法,于是 Controller 中也是需要实现这五个方法。
@Slf4j
@RestController
public class AdUnitOPController {
private final IAdUnitService adUnitService;
@Autowired
public AdUnitOPController(IAdUnitService adUnitService) {
this.adUnitService = adUnitService;
}
@PostMapping("/create/adUnit")
public AdUnitResponse createUnit(@RequestBody AdUnitRequest request) throws AdException {
log.info("ad-sponsor: createUnit -> {}",JSON.toJSONString(request));
return adUnitService.createUnit(request);
}
@PostMapping("/create/unitKeyword")
public AdUnitKeywordResponse createUnitKeyword(@RequestBody AdUnitKeywordRequest request) throws AdException {
log.info("ad-sponsor: createUnitKeyword -> {}",JSON.toJSONString(request));
return adUnitService.createUnitKeyword(request);
}
@PostMapping("/create/unitIt")
public AdUnitItResponse createUnitIt(@RequestBody AdUnitItRequest request) throws AdException {
log.info("ad-sponsor: createUnitIt -> {}",JSON.toJSONString(request));
return adUnitService.createUnitIt(request);
}
@PostMapping("/create/unitDistrict")
public AdUnitDistrictResponse createUnitDistrict(@RequestBody AdUnitDistrictRequest request) throws AdException {
log.info("ad-sponsor: createUnitDistrict -> {}",JSON.toJSONString(request));
return adUnitService.createUnitDistrict(request);
}
@PostMapping("/create/creativeUnit")
public CreativeUnitResponse createCreativeUnit(@RequestBody CreativeUnitRequest request) throws AdException {
log.info("ad-sponsor: createCreativeUnit -> {}",JSON.toJSONString(request));
return adUnitService.createCreativeUnit(request);
}
}
3.4 创意 Controller:
同样也是实现 service 的方法。
@Slf4j
@RestController
public class CreativeOPController {
private final ICreativeService creativeService;
@Autowired
public CreativeOPController(ICreativeService creativeService) {
this.creativeService = creativeService;
}
@PostMapping("/create/creative")
public CreativeResponse createCreative(@RequestBody CreativeRequest request) throws AdException {
log.info("ad-sponsor: createCreative -> {}", JSON.toJSONString(request));
return creativeService.createCreative(request);
}
}
4. 添加网关配置:
到现在为止,广告投放系统实现完成,于是在网关进行配置,实现请求的转发。
zuul:
prefix: /imooc
routes:
sponsor:
path: /ad-sponsor/**
serviceId: eureka-client-ad-sponsor
strip-prefix: false #不跳过前缀