基于 SpringCloud 微服务架构的广告系统(第二部分:广告投放、微服务调用与断路器)

目录

广告系统架构图

四、sponsor模块(广告投放)

sponsor模块(广告投放)介绍图

数据库对应的实体类 (例子)

Dao接口实现 (例子)

service实现(例子)

controller 控制层(例子)

sponsor(广告投放)示意图(单个-例子)

五、Feign与Ribbon微服务相互访问(RPC)与hystrix断路器使用

Ribbon+Hystrix方式

Feign方式


第一部分:eureka、zuul、通用模块(不讲代码实现,下载代码自己看。)

这不是一个完整的广告系统,主要涉及两方面  广告检索 、广告投放 ,这两个方面我感觉是最重要的,但是也使用Kafka的消息传递,为剩下的曝光见监测、 报表 、扣费 这三个部分留下了接口。

第二部分:主要会介绍广告投放、hystrix断路器。打算随便介绍一下,也就是MVC架构设计模式,Model层数据的操作,数据库实体类对象等;Controller层控制层对外提供服务(跳转),对内访问Model层;没有用户ui等,都是后端接口,所以,也就没有view层了。 

广告系统架构图

基于 SpringCloud 微服务架构的广告系统(第二部分:广告投放、微服务调用与断路器)_第1张图片 简略的广告系统架构图

 所使用到的技术

JDK   、Kafka 、MySQL 

框架 SpringCloud: Finchley.RELEASE   、Spring  、Spring Data JPA 、Spring boot 

源码 : github https://github.com/yingyingqiqi/luoweiying-ad-spring-cloud/tree/master

四、sponsor模块(广告投放)

sponsor模块(广告投放)介绍图

基于 SpringCloud 微服务架构的广告系统(第二部分:广告投放、微服务调用与断路器)_第2张图片

maven坐标(简化版)

artifactId>spring-boot-starter-web            //web功能
spring-cloud-starter-netflix-eureka-client    //euraka客户端
spring-boot-starter-data-jpa      //jpa规范+hibernate+spring jdbc
mysql-connector-java            //驱动
commons-codec                    //apache工具类

这里介绍一下spring data jpa: 很久以前,数据库的持久层有一套标准--ORM(对象关系映射,就是把数据库映射成对象),一些第三方公司根据这个标准,做了一些ORM框架,如:hibernate、TopLink等,sun整合了第三方框架,推出一套JPA规范,spring data jpa是在这个jpa规范+hibernate+jdbc再次的封装,越封装、越难理解底层代码,但是对于广告投放这个项目,对数据库的性能要求不高,后面会介绍。

一些介绍可以看这里  spring data jpa 详解    SpringData JPA 官方文档

配置(不用看)

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8000/eureka
server:
  port: 7000
  servlet:
    path: /ad-sponsor
spring:
  application:
    name: eureka-client-ad-sponsor
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
    properties:
      hibernate.format_sql: true
    open-in-view: false
  datasource:
    url: jdbc:mysql://ip:3306/ad_data?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&useSSL=false
    username: 
    password: 
    tomcat:
      max-active: 40
      min-idle: 20
      initial-size: 4

数据库对应的实体类 (例子)

package cn.luoweiying.entity;
@Entity                    //标记为实体类
@Table(name = "ad_plan")    //与数据库对应的表名
public class AdPlan {

    @Id          //主键
    @GeneratedValue(strategy = GenerationType.IDENTITY)    //主键序号方式
    @Column(name = "id", nullable = false)                 //对应列名
    private Long id;

    @Column(name = "user_id", nullable = false)            //对应列名
    private Long userId;

详细的hibernate注解 可以看官方文档, 也可以看 JPA注解详解

Dao接口实现 (例子)

public interface AdPlanRepository extends JpaRepository {

    AdPlan findByIdAndUserId(Long id, Long userId);       //跟spl类似,不用写sql语句

    List findAllByIdInAndUserId(List ids, Long userId);

接口继承Repository ,就可以在自己的dao接口定义方法,只用写关键字,不用写sql语句,每个关键字有特定意思,不用写dao接口的实现,自动实现了。

继承JpaRepository类并添加泛型,会自动实现一些方法,此步骤也可以作为如何定义方法的回想线索。

spring支持的自定义关键字查询 ,可以查看 Appendix C: Repository query keywords   SpringDataJPA自定义关键字查询

vo对象, 方法间传递的对象(例子)

public class AdPlanRequest {

    private Long id;
    private Long userId;
    private String planName;
    private String startDate;
    private String endDate;

    public boolean createValidate() {            //检查方法是否为空
        return userId != null && !StringUtils.isEmpty(planName)
  && !StringUtils.isEmpty(startDate)&& !StringUtils.isEmpty(endDate);
    }
public class AdPlanResponse {

    private Long id;
    private String planName;
}

这些vo对象,方法间相互调用,传递的对象,相当于一个数据结构,dao--service--controller调用更加清晰明了。

service接口定义(例子)

public interface IAdplanService {
  
    AdPlanResponse createAdPlan(AdPlanRequest request) throws AdException;//创建推广计划

    List getAdPlanByIds(AdPlanGetRequest request) throws AdException;//获取推广单元

service实现(例子)

@Service
public class AdPlanServiceImpl implements IAdplanService {
    @Autowired
    AdPlanRepository adPlanRepository;
   @Transactional
    public AdPlanResponse createAdPlan(AdPlanRequest request) throws AdException {
        if (!request.createValidate())throw new AdException(CodeMsg.REQUEST_PARAM_ERROR);
        
        Optional adUser = adUserRepository.findById(request.getUserId());
        if (!adUser.isPresent()) throw new AdException(CodeMsg.CAN_NOT_FIND_RECORD);//确保关联的User不存在

        AdPlan oldPlan = adPlanRepository.findByUserIdAndPlanName(request.getUserId(), request.getPlanName());
        if (oldPlan != null)  throw new AdException(CodeMsg.SAME_NAME_UNIT_ERROR);//同名推广计划

        AdPlan newPlan = adPlanRepository.save(new AdPlan(request.getUserId(), request.getPlanName(),
    CommonUtils.parseStringDate(request.getStartDate()),CommonUtils.parseStringDate(request.getEndDate())
        ));
        return new AdPlanResponse(newPlan.getId(),newPlan.getPlanName());

controller 控制层(例子)

@Slf4j
@RestController             //==responsebody+controller
public class AdPlanOPController {
    @Autowired
    AdPlanServiceImpl adPlanService;
    @PostMapping("/create/adPlan")
    public AdPlanResponse createAdPlan(@RequestBody AdPlanRequest request) throws AdException {
        log.info("ad-sponsor:creatAdPlan: -> {}", JSON.toJSON(request));
        return adPlanService.createAdPlan(request);
    }

sponsor(广告投放)示意图(单个-例子)

基于 SpringCloud 微服务架构的广告系统(第二部分:广告投放、微服务调用与断路器)_第3张图片

这只是单个访问的接口的例子,全部的太多了,下载源码自己看吧。

五、Feign与Ribbon微服务相互访问(RPC)与hystrix断路器使用

基于 SpringCloud 微服务架构的广告系统(第二部分:广告投放、微服务调用与断路器)_第4张图片 hystrix短路器介绍

这个项目没真正使用到微服务相互访问,并不需要调用,检索系统提供给媒体方,但是这个模块没有写,也就不需要调用了。

这里简单讲一下微服务相互访问的方式。

微服务相互访问,通讯的协议应该是"http",目前有两种常用的调用:

1.ribbon+spring restTemplate  

2.feign(ribbon+hystrix) 声明式接口的形式

这两种也就是对 apache httpClient 的封装,方便微服务的使用吧。

Ribbon+Hystrix方式

坐标(简化)

spring-cloud-starter-netflix-ribbon
artifactId>spring-cloud-starter-netflix-hystrix//断路器

配置eureka

(第一部分有)

注入 RestTemplate 

@EnableEurekaClient //@EnableDiscoveryClient其他服务注册中心
@EnableHystrix  //内部有@EnableCircuitBreaker
@SpringBootApplication
public class SearchApplication {
    public static void main(String[] args) {SpringApplication.run(SearchApplication.class, args);}
    //基于Ribbon实现微服务调用
    @Bean
    @LoadBalanced  //开启默认Ribbon
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

服务调用

@HystrixCommand(fallbackMethod = "这里有断路器-例子")   //使用断路器
@PostMapping("/getAdPlansByRibbon")            //Spring MVC 的controller
public CommonResponse> getAdPlansByRibbon(@RequestBody AdPlanGetRequest request) {
    return restTemplate.postForEntity("http://eureka-client-ad-sponsor/ad-sponsor/get/adPlan",
        request, CommonResponse.class).getBody();}

Feign方式

坐标(简版)   feign引入ribbon+hystrix等

spring-cloud-starter-netflix-hystrix

配置eureka

(第一部分有)

启动类加上@EnableFeignClients

实现服务调用

@FeignClient(value = "eureka-client-ad-sponsor",fallback = SponsorClientHystrix.class)
public interface SponsorClient {
    @RequestMapping(value = "/ad-sponsor/get/adPlan",method = RequestMethod.POST)
    List getAdPlans(@RequestBody AdPlanGetRequest request) throws AdException;
}

声明式的接口,外部直接调用方法就可以了,这个加了一个断路器SponsorClientHystrix

@Component
public class SponsorClientHystrix implements SponsorClient {
    @Override
    public List getAdPlans(AdPlanGetRequest request) throws AdException {
        throw new AdException(CodeMsg.EUREKA_CLIENT_AD_SPONSOR_ERROR);}

 

 

 

你可能感兴趣的:(学习总结,SpringBoot,完整项目)