上一篇文章《Spring Cloud Alibaba | Dubbo 與 Spring Cloud 完美結合》我們介紹了Dubbo Spring Cloud的基本使用,使用的服務中心為Spring Cloud Alibaba提供的Nacos,Dubbo內部提供了基於Dubbo的RPC調用,同時,Dubbo Spring Cloud在整合了Spring Cloud之后,可以直接提供HTTP接口,同Spring Cloud無縫銜接,直接支持Feign、RestTemplate等方式的遠程調用,在提供HTTP服務的同時可以提供Dubbo服務。Dubbo Spring Cloud支持HTTP遠程調用級大的方便了我們的對接外部系統,無需對Dubbo再做二次封裝。
1. 案例實戰
接下來,我們通過一個簡單的案例來介紹一下Dubbo Spring Cloud通過注解的方式是如何同時提供Dubbo服務和HTTP服務的。
1.1 創建父工程dubbo-spring-cloud-http
工程依賴pom.xml如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Cloud Nacos Service Discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
1.2 創建子工程dubbo_provider_web,服務提供方
工程依賴pom.xml如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/dubbo_provider_web/pom.xml
<dependencies>
<!-- API -->
<dependency>
<groupId>com.springcloud</groupId>
<artifactId>dubbo_api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Dubbo Spring Cloud Starter -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
</dependencies>
這里引入Dubbo Spring Cloud工具包和Dubbo API依賴包。
配置文件參考上一節配置,這里不再贅述。
接口實現類UserServiceI.java如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/dubbo_provider_web/src/main/java/com/springcloud/dubbo_provider_web/service/UserServiceI.java
@Service(version = "1.0.0")
@RestController
@Slf4j
public class UserServiceI implements UserService {
private Map<Long, UserModel> usersRepository = Maps.newHashMap();
@Override
@PostMapping("/save")
public UserModel save(@RequestBody UserModel user) {
return usersRepository.put(user.getId(), user);
}
@Override
@DeleteMapping("/remove")
public void remove(@RequestParam("id") Long userId) {
usersRepository.remove(userId);
}
@Override
@GetMapping("/findAll")
public Collection<UserModel> findAll() {
return usersRepository.values();
}
}
@Service
注解有很多有關服務的配置屬性,這里使用 version 定義當前接口版本,此處版本僅在 Dubbo 調用時生效, HTTP 調用無效,更多相關配置可以參考源碼org.apache.dubbo.config.annotation.Service
。
1.3 創建子工程 spring_cloud_consumer , web 服務消費方
工程依賴pom.xml如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/spring_cloud_consumer/pom.xml
<dependencies>
<!-- API -->
<dependency>
<groupId>com.springcloud</groupId>
<artifactId>dubbo_api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
配置文件application.yml如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/spring_cloud_consumer/src/main/resources/application.yml
server:
port: 8080
spring:
application:
name: spring-cloud-consumer-server
cloud:
nacos:
discovery:
server-addr: 192.168.44.129:8848
接口測試類UserController.java如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/spring_cloud_consumer/src/main/java/com/springcloud/spring_cloud_consumer/controller/UserController.java
@RestController
public class UserController {
@Autowired
UserRemote userRemote;
@Autowired
RestTemplate restTemplate;
@PostMapping("/saveByFeign")
public UserModel saveByFeign(@RequestBody UserModel user) {
return userRemote.save(user);
}
@DeleteMapping("/removeByFeign")
public void removeByFeign(@RequestParam("id") Long userId) {
userRemote.remove(userId);
}
@GetMapping("/findAllByFeign")
public Collection<UserModel> findAllByFeign() {
return userRemote.findAll();
}
@PostMapping("/saveByRestTemplate")
public UserModel saveByRestTemplate(@RequestBody UserModel user) {
return restTemplate.postForObject("http://dubbo-spring-cloud-provider-web/save/", user, UserModel.class);
}
@DeleteMapping("/removeByRestTemplate")
public void removeByRestTemplate(@RequestParam("id") Long userId) {
restTemplate.delete("http://dubbo-spring-cloud-provider-web/remove?id=" + userId);
}
@GetMapping("/findAllByRestTemplate")
public Collection<UserModel> findAllByRestTemplate() {
return restTemplate.getForObject("http://dubbo-spring-cloud-provider-web/findAll/", Collection.class);
}
}
共計三個測試接口,這里提供兩種測試方式,一種是通過Feign調用,另一種是通過RestTemplate調用。
SpringCloudConsumerApplication.java如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/spring_cloud_consumer/src/main/java/com/springcloud/spring_cloud_consumer/SpringCloudConsumerApplication.java
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class SpringCloudConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(SpringCloudConsumerApplication.class, args);
}
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
使用@EnableFeignClients
開啟Feign功能,將RestTemplate以Bean的形式注入Spring中。
1.4 創建子工程dubbo_consumer作為Dubbo服務的消費方
接口測試類UserController.java如下:
代碼清單:Alibaba/dubbo-spring-cloud-http/dubbo_consumer/src/main/java/com/springcloud/dubbo_consumer/controller/UserController.java
@RestController
public class UserController {
@Reference(version = "1.0.0")
UserService userService;
@PostMapping("/save")
public UserModel save(@RequestBody UserModel user) {
return userService.save(user);
}
@DeleteMapping("/remove")
public void remove(@RequestParam("id") Long userId) {
userService.remove(userId);
}
@GetMapping("/findAll")
public Collection<UserModel> findAll() {
return userService.findAll();
}
}
這里@Reference
注解需指明調用服務提供者接口的版本號,如果未指明版本號,將無法調用我們前面的服務提供者的接口。
2. 測試
我們使用測試工具PostMan進行測試,順次啟動三個子工程provider_web、spring_cloud_consumer和dubbo_consumer,首先測試組件Feign訪問,使用PostMan向:http://localhost:8080/saveByFeign 發送 POST 請求,如圖:
測試鏈接:http://localhost:8080/findAllByFeign ,如圖:
測試 RestTemplate 訪問,如圖:
至此,spring_cloud_consumer測試成功,下面繼續測試dubbo_consumer,如圖: