微服务架构中,一般存在2种服务,一种是消费服务,一种是提供服务,消费服务在 SpringCloud-feign 声明式服务调用 这一篇文章中已讲过,本章我们主要讲解提供服务
不论是什么服务,都需要注册中心,可以参考 SpringCloud-eureka构建简单注册中心或SpringCloud-eureka高可用注册中心,启动注册中心后, 消费服务和提供服务才能注册。
下面创建一个Gradle工程,工程依赖如下(这里使用boot1.5.x):
dependencyManagement {
imports {
mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Edgware.SR4'
}
}
dependencies {
compile('org.springframework.boot:spring-boot-starter')
compile('org.springframework.boot:spring-boot-starter-web')
compile 'org.slf4j:slf4j-api:1.7.14'
compile('org.springframework.cloud:spring-cloud-starter-eureka')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
配置文件application.properties如下:
spring.application.name=hello-service
# 单机
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
server.port=8081
配置启动类,将启动服务配置为可发现的服务,如下:
@EnableDiscoveryClient
@SpringBootApplication
public class CloudApplication {
public static void main(String[] args) {
SpringApplication.run(CloudApplication.class, args);
}
}
接着,创建controller,定义相应在的服务接口,如下:
@RestController
public class HelloController {
private final Logger logger = LoggerFactory.getLogger(HelloController.class);
@Autowired
private DiscoveryClient client;
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public String hello() throws Exception {
ServiceInstance instance = client.getLocalServiceInstance();
logger.info("/hello, host:" + instance.getHost() + ", service_id:" + instance.getServiceId());
return "Hello World";
}
@RequestMapping(value = "/hello1", method = RequestMethod.GET)
public String hello(@RequestParam String name) {
ServiceInstance instance = client.getLocalServiceInstance();
logger.info("/hello1, host:" + instance.getHost() + ", service_id:" + instance.getServiceId());
return "Hello " + name;
}
@RequestMapping(value = "/hello2", method = RequestMethod.GET)
public User hello(@RequestHeader String name, @RequestHeader Integer age) {
ServiceInstance instance = client.getLocalServiceInstance();
logger.info("/hello2, host:" + instance.getHost() + ", service_id:" + instance.getServiceId());
return new User(name, age);
}
@RequestMapping(value = "/hello3", method = RequestMethod.POST)
public String hello(@RequestBody User user) {
ServiceInstance instance = client.getLocalServiceInstance();
logger.info("/hello3, host:" + instance.getHost() + ", service_id:" + instance.getServiceId());
return "Hello "+ user.getName() + ", " + user.getAge();
}
这样就可以被消费服务消费了,如restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class).getBody()
虽然实现了service的服务接口,但却有个问题,提供服务的接口不容易被消费服务知道,如何解决这个问题呢?
我们可以抽取一个通用的服务,将url写在这个服务上,如下:
@RequestMapping("/refactor")
public interface HelloService {
@RequestMapping(value = "/hello1", method = RequestMethod.GET)
String hello(@RequestParam("name") String name) ;
@RequestMapping(value = "/hello2", method = RequestMethod.GET)
User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);
@RequestMapping(value = "/hello3", method = RequestMethod.POST)
String hello(@RequestBody User user);
}
这个服务可以放在一个单独的工程内,受maven/gradle管理,这样就可以在消费端和提供端共享,下面看下新的controller如下:
@RestController
public class RefactorHelloController implements HelloService {
@Override
public String hello(@RequestParam("name") String name) {
return "Hello " + name;
}
@Override
public User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age) {
return new User(name, age);
}
@Override
public String hello(@RequestBody User user) {
return "Hello "+ user.getName() + ", " + user.getAge();
}
}
新的controller只需实现这个接口服务就可以了。
学习交流,请加群:64691032