Loading...

springboot整合Dubbo与Feign的实现 (无注册中心)_java

一,SpringBoot 整合 Dubbo

1.1 服务提供者

1.1.1 核心依赖

<!-- dubbo依赖 -->          <dependency>              <groupId>org.apache.dubbo</groupId>              <artifactId>dubbo-spring-boot-starter</artifactId>              <version>3.0.5</version>          </dependency>

1.1.2 核心配置

server:    port: 8081  spring:    application:      name: provide-api     dubbo:    registry:      address: N/A # 表示无注册中心    protocol:      name: dubbo # 提供者协议      port: 18081 # 提供者dubbo端口      host: 127.0.0.1 # 服务提供者所在机器地址    scan:      base-packages: com.paycools.service # 提供者需要交由dubbo管理的扫描包路径    application:      name: provide-server # 提供者服务名   

1.1.3 服务提供者代码结构

1.1.4 服务提供者暴露的API(DubboDemoServiceImpl)

package com.jxz.service.impl;     import com.jxz.service.IDubboDemoService;  import com.jxz.service.vo.User;  import lombok.extern.slf4j.Slf4j;  import org.apache.dubbo.config.annotation.DubboService;  import org.springframework.stereotype.Service;     import java.util.ArrayList;  import java.util.List;     /**   * @author jiangXueZhi   * @data 2022/4/1   */  @Service // spring 的注解  @DubboService // dubbo 提供者的注解  @Slf4j  public class DubboDemoServiceImpl implements IDubboDemoService {      /**       * 用于测试 dubbo 的rpc 远程过程调用是否成功       */      @Override      public String dubboTest() {          log.info("###########  服务提供者成功提供API响应");          return "服务提供者成功提供API响应";      }         /**       * 用于测试 dubbo 的rpc 远程过程调用携带参数与返回值是否正常       */      @Override      public List<User> dubboVoTest(Integer aa) {          if (aa == 1) {              List<User> list = new ArrayList<>(3);              list.add(new User().setName("张三").setAge(18));              list.add(new User().setName("李四").setAge(5));              log.info("###########  服务提供者成功提供API响应,参数为{}, 返回值为{}", aa, list);              return list;          }          log.info("###########  服务提供者成功提供API响应,参数为{}, 返回值为{}", aa, null);          return null;      }  }

1.1.5 服务提供者端的对象(User)

一定要实现序列化!!!

package com.jxz.service.vo;     import lombok.Data;  import lombok.experimental.Accessors;     import java.io.Serializable;     /**   * @author jiangXueZhi   * @data 2022/4/2   */  @Data  @Accessors(chain = true)  public class User implements Serializable { // 一定要序列化,因为dubbo传输数据以二进制的方式      private String name;      private int age;  }

1.2 服务消费者

1.2.1 核心依赖

与提供者端一样

<!-- dubbo依赖 -->          <dependency>              <groupId>org.apache.dubbo</groupId>              <artifactId>dubbo-spring-boot-starter</artifactId>              <version>3.0.5</version>          </dependency>

1.2.2 核心配置

server:    port: 8082  spring:    application:      name: consumer-api     dubbo:    registry:      address: N/A # 表示无注册中心    #scan: # 作为提供者时使用      #base-packages: com.paycools.service # 扫描包的路径    protocol:      name: dubbo      port: 18082      host: 127.0.0.1    application:      name: consumer-server     # 自定义配置--因无注册中心,则需指定服务提供者地址  provide:    host: "dubbo://127.0.0.1:18081"      

1.2.3 服务消费者代码结构

注意,本文中的 UserDemo 完全可以不需要,

可以直接在Controller中注入 IDubboDemoService

1.2.4 服务消费者调用服务提供者

controller

package com.jxz.controller;     import com.jxz.service.UserDemo;  import org.springframework.web.bind.annotation.PathVariable;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestMethod;  import org.springframework.web.bind.annotation.RestController;     import javax.annotation.Resource;     /**   * @author jiangXueZhi   * @data 2022/4/1   */  @RequestMapping("/api")  @RestController  public class DemoTestController {      @Resource      private UserDemo userDemo;         @RequestMapping(value = "/demoTest", method = RequestMethod.GET)      public String demoTest() {          return userDemo.demoTest();      }         @RequestMapping(value = "/demoVoTest/{aa}", method = RequestMethod.GET)      public String demoVoTest(@PathVariable("aa") Integer aa) {          return userDemo.demoVoTest(aa);      }  }

userDemo(可省去此类,而直接调用提供者API)

package com.jxz.service;     import org.apache.dubbo.config.annotation.DubboReference;  import org.springframework.stereotype.Service;     /**   * @author jiangXueZhi   * @data 2022/4/1   */  @Service  public class UserDemo {         @DubboReference(check = false, url = "${provide.host}") // 无注册中心时的参数配置      IDubboDemoService iDubboDemoService;         public String demoTest() {          return "###  服务消费者成功拿到提供者的API响应:" + iDubboDemoService.dubboTest();      }         public String demoVoTest(Integer aa) {          return "### <带参数以及对象返回值> 服务消费者成功拿到提供者的API响应:" + iDubboDemoService.dubboVoTest(aa);      }  }

IDubboDemoService 

包的路径与名称必须与服务提供者端的保持一致!!!并且无需实现

package com.jxz.service;     import com.paycools.service.pojo.User;     import java.util.List;     public interface IDubboDemoService {      String dubboTest();         List<User> dubboVoTest(Integer aa);  }

User

package com.jxz.service.pojo;     import lombok.Data;     import java.io.Serializable;     /**   * @author jiangXueZhi   * @data 2022/4/2   */  @Data  public class User implements Serializable { // 必须实现序列化      private String name;      private int age;  }

1.3 调用示例

1.3.1 消费者入口(测试是否导通)

1.3.1.1 服务提供者端日志打印

2022-04-06 11:27:03.047  INFO 12284 --- [:18081-thread-6] c.p.service.impl.DubboDemoServiceImpl    : ###########  服务提供者成功提供API响应

1.3.2 消费者入口(测试携带参数与返回值)

1.3.2.1 服务提供者端日志打印

2022-04-06 11:30:46.489  INFO 12284 --- [:18081-thread-9] c.p.service.impl.DubboDemoServiceImpl    : ###########  服务提供者成功提供API响应,参数为0, 返回值为null

2022-04-06 11:30:58.910  INFO 12284 --- [18081-thread-10] c.p.service.impl.DubboDemoServiceImpl    : ###########  服务提供者成功提供API响应,参数为1, 返回值为[User(name=张三, age=18), User(name=李四, age=5)]

1.4 小结

a.  dubbo 服务提供者暴露的API,在服务消费者中必须保持包名与文件名一致

b.  dubbo 服务消费者在注入API时,要用到  @DubboReference 注解

c.  dubbo 基于TCP传输协议,其对象都必须实现序列化

二, SpringBoot 整合 Feign

2.1 服务提供者

使用feign 的方式时,服务提供者无需任何特殊处理,仅正常启动程序即可

2.1.1 服务提供者基础配置 

server:    port: 8083     spring:    application:      name: provide-server    profiles:      active: dev   

2.1.2 服务提供者代码结构 

2.2 服务消费者

2.2.1 服务消费者代码结构

2.2.2 核心依赖

<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->          <dependency>              <groupId>org.springframework.cloud</groupId>              <artifactId>spring-cloud-starter-openfeign</artifactId>              <version>3.1.1</version>          </dependency>

2.2.3 核心配置

server:    port: 8084  spring:    application:      name: consumer-server        # 自定义配置,因无注册中心,需直接指定服务提供者  provider:    application-name: provide-server    host: http://127.0.0.1:8083

2.2.4 启动类注解 

package com.jxz;     import org.springframework.boot.SpringApplication;  import org.springframework.boot.autoconfigure.SpringBootApplication;  import org.springframework.cloud.openfeign.EnableFeignClients;     @SpringBootApplication  @EnableFeignClients  public class FeignConsumerDemoApplication {         public static void main(String[] args) {          SpringApplication.run(FeignConsumerDemoApplication.class, args);          System.out.println("服务消费者启动成功...");      }     }

2.2.5 在消费者端中声明提供者端的API

package com.paycools.service;     import com.paycools.pojo.User;  import org.springframework.cloud.openfeign.FeignClient;  import org.springframework.web.bind.annotation.PathVariable;  import org.springframework.web.bind.annotation.RequestMapping;     import java.util.List;     @FeignClient(value = "${provider.application-name}", url = "${provider.host}") // 因无注册中心,需直接指定其url  public interface IProvideService {         @RequestMapping("/api/provide/getProvideResponse")      String getProvideResponse();         @RequestMapping("/api/provide/getProvideVoResponse/{id}")      List<User> getProvideVoResponse(@PathVariable("id") Integer id);  }

2.2.6 在消费者端中调用提供者端的API

package com.jxz.controller;     import com.jxz.service.IProvideService;  import lombok.extern.slf4j.Slf4j;  import org.springframework.web.bind.annotation.PathVariable;  import org.springframework.web.bind.annotation.RequestMapping;  import org.springframework.web.bind.annotation.RequestMethod;  import org.springframework.web.bind.annotation.RestController;     import javax.annotation.Resource;     /**   * @author jiangXueZhi   * @data 2022/4/2   */  @RestController  @RequestMapping("/api/consumer")  @Slf4j  public class ConsumerDemoController {         @Resource      private IProvideService iProvideService;         @RequestMapping("/getProvideResponse")      public String getProvideResponse() {          log.info("服务消费者,成功调用服务提供者API");          return "服务消费者端," + iProvideService.getProvideResponse();      }         @RequestMapping(value = "/getProvideVoResponse/{id}", method = RequestMethod.GET)      public String getProvideVoResponse(@PathVariable("id") Integer id) {          log.info("服务消费者,成功调用服务提供者API");          return "服务消费者端," + iProvideService.getProvideVoResponse(id);      }  }

2.3 调用示例

2.3.1 测试是否导通

2.3.1.1 服务提供者端的日志打印

2022-04-06 11:56:46.472  INFO 4724 --- [nio-8083-exec-1] com.paycools.controller.UserController   : 服务提供者, 成功通过feign的方式提供服务

2.3.1.2 服务消费者端的日志打印

2022-04-06 11:56:46.399  INFO 3352 --- [nio-8084-exec-2] c.p.controller.ConsumerDemoController    : 服务消费者,成功调用服务提供者API

2.3.2 测试携带参数与获取返回值是否正常

2.3.2.1 服务提供者端的日志打印

2022-04-06 12:01:14.588  INFO 4724 --- [nio-8083-exec-8] com.paycools.controller.UserController   : 服务提供者, <带有参数与返回值>成功通过feign的方式提供服务, 参数为0,响应为null
2022-04-06 12:02:51.754  INFO 4724 --- [nio-8083-exec-5] com.paycools.controller.UserController   : 服务提供者, <带有参数与返回值>成功通过feign的方式提供服务, 参数为1,响应为[User(id=1, name=王五, age=19), User(id=1, name=赵六, age=15)]

2.3.2.2 服务消费者端的日志打印

2022-04-06 12:01:14.579  INFO 3352 --- [nio-8084-exec-3] c.p.controller.ConsumerDemoController    : 服务消费者,成功调用服务提供者API
2022-04-06 12:02:51.751  INFO 3352 --- [nio-8084-exec-8] c.p.controller.ConsumerDemoController    : 服务消费者,成功调用服务提供者API

2.4 小结

a. 服务提供者无需特殊操作

b. 服务消费者端启动类声明注解

c. 服务消费者端声明服务提供者的API,然后调用时与本地API无异