截至目前,还剩eureka client和openfeign两个工程没有整合,但这两个工程本来就应该是一个工程。
想一想,eureka client作为微服务的客户端,是真正的微服务业务处理模块;而openfeign工程作为服务间调用的例子,本就应该应用在微服务模块上,所以本章的内容不是单纯移植,而是创建两个服务模块service1和service2实现模块间调用。
理论上所有的业务模块应该有大量通用的依赖,所以可以再建立一层子模块关系,如下图所示,在工程下创建microservices模块,在microservices模块下创建service1和service2模块。
microservices build.gradle
subprojects {
dependencies {
// --- Spring boot dependencies ---
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
// --- Other dependencies ---
// 要想使用lombok,两个依赖必须同时存在
annotationProcessor 'org.projectlombok:lombok'
compileOnly 'org.projectlombok:lombok'
}
}
service1 build.gradle
version = '0.0.1-SNAPSHOT'
service2 build.gradle
version = '0.0.1-SNAPSHOT'
service1 application.yml
server:
port: 9101
spring:
application:
name: service1
eureka:
client:
serviceUrl:
defaultZone: http://admin:123456@localhost:9000/eureka/
service2 application.yml
server:
port: 9102
spring:
application:
name: service2
eureka:
client:
serviceUrl:
defaultZone: http://admin:123456@localhost:9000/eureka/
Service1Application
package com.hao1st.service1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@SpringBootApplication
public class Service1Application {
public static void main(String[] args) {
SpringApplication.run(Service1Application.class, args);
}
}
Service2Application
package com.hao1st.service2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@SpringBootApplication
public class Service2Application {
public static void main(String[] args) {
SpringApplication.run(Service2Application.class, args);
}
}
service1 IndexDemoController
package com.hao1st.service1.biz.indexdemo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class IndexDemoController {
/**
* 浏览器访问
* @return
*/
@GetMapping("/index")
public String index(){
return "您访问的是service1的index";
}
/**
* rpc访问
* @return
*/
@PostMapping("/pindex")
public String postIndex() {
return "您访问的是service1的postIndex";
}
}
service2 IndexDemoController
package com.hao1st.service2.biz.indexdemo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class IndexDemoController {
/**
* 浏览器访问
* @return
*/
@GetMapping("/index")
public String index(){
return "您访问的是service2的index";
}
/**
* rpc访问
* @return
*/
@PostMapping("/pindex")
public String postIndex() {
return "您访问的是service2的postIndex";
}
}
到此,service1和service2的对外api创建完毕。我们可以依次启动eureka、gateway、service1、service2,启动完毕后访问eureka控制面板localhost:9000查看服务注册状态,服务列表中应包含gateway、service1和service2三个服务,如下图:
接下来分别测试service1和service是否畅通,访问localhost:9001/SERVICE1/index,localhost:9001/SERVICE2/index两个地址,可以看到如下内容:
接下来,编写rpc调用代码,注意,下面所有代码都在service1里。
先看文件结构,如下图,只需新建两个文件,一个用于外部访问的controller,一个用于调用service2的接口。
Service2Rpc
package com.hao1st.service1.rpc;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
// 指定要调用的模块,value即配置文件中的spring.application.name
@FeignClient(value="service2")
public interface Service2Rpc {
// api路径
@PostMapping("/pindex")
String rpcService2();
}
RpcController
package com.hao1st.service1.biz.rpcdemo.controller;
import com.hao1st.service1.biz.rpcdemo.rpc.Service2Rpc;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/rpc")
public class RpcController {
@Resource
private Service2Rpc service2Rpc;
@GetMapping("/invoke")
public String rpcService2() {
// 调用接口访问service2
return service2Rpc.rpcService2();
}
}
这样就OK了,访问service1的/rpc/invoke就可以调用到service2的内容,如下图:
同理,service2调用service1也是同样的逻辑。