在RPC框架中,服务调用一般是服务的暴露接口,并提供客户端API,客户端在添加依赖后,即可像本地方法一样调用远程服务,SpringCloud也提供了类似需求,而在此之前,使用的是RestTemplate调用,这种调用方式不是很直观
目的
- 学会使用Feigh声明式服务调用
准备工作
需要4个项目: eureka-server:服务注册中心 user-service-feigh-api:服务API,客户端依赖,user-service-feigh-impl:服务实现放 ,user-service-client:服务消费方
- 提供一个供服务方和消费方共用的api接口 user-service-feigh-api
- 提供一个增删改查的用户服务 user-service-feigh-impl
- 体统一个调用user-srvice的客户端 user-service-client
Eureka服务中心搭建
参考Eureka服务治理
服务提供方
新建项目:
user-service-api
该项目仅仅提供服务API,并不需要启动,服务提供方和服务消费方都依赖该项目,实际情况下,该项目应该写在user-service-feigh-impl中,通过不同的打包方式将该项目打包出来,由各个服务方调用
添加依赖
org.springframework.cloud
spring-cloud-starter-feign
提供API
只有接口,没有实现
@FeignClient("USER-SERVICE")
public interface UserService {
@RequestMapping("add-user")
String addUser();
@RequestMapping("list-user")
List listUser();
@RequestMapping("delete-user")
boolean deleteUser();
@RequestMapping("update-user")
String updateUser();
}
public class User {
private int id;
private String name;
private int age;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
启动
不需要启动,由user-service-feigh-impl和user-service依赖
服务实现方
新建项目:
user-service-feigh-impl
添加依赖
org.springframework.cloud
spring-cloud-starter-eureka
cn.liuyiyou.springcloud
user-service-feigh-api
0.0.1-SNAPSHOT
配置文件
#服务命名
spring.application.name=user-service
#指定服务注册中心地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka
server.port=8080
启动类
@EnableDiscoveryClient
@SpringBootApplication
public class UserServiceFeighApiApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceFeighApiApplication.class, args);
}
}
服务实现类
注意:
- 实现了UserService接口,确保声明的服务都有其实现方法
- 包所在的名字是service,但是写的方式好像是controller,这是因为采用的是http方式进行调用
package cn.liuyiou.cloud.service;
import cn.liuyiou.cloud.model.User;
import com.google.common.collect.Lists;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 该注解必须是 @RestController 不能是@Service
*/
@RestController
public class UserServiceImpl implements UserService {
@Override
public String addUser() {
return "add User Has Been Called";
}
@Override
public List listUser() {
return Lists.newArrayList(new User() {{
setId(1);
setAge(18);
setName("lyy");
}}, new User() {{
setId(2);
setAge(18);
setName("yi");
}}, new User() {{
setId(1);
setAge(18);
setName("you");
}});
}
@Override
public boolean deleteUser() {
return true;
}
@Override
public String updateUser() {
return "update User Has Been Called";
}
}
启动
观察是否注册到服务中心中了
服务调用方
新建项目
user-service-client
添加依赖
因为只是调用方,该依赖可以不添加
org.springframework.cloud
spring-cloud-starter-eureka
配置文件
因为只是调用方,该配置可以不添加
#服务命名
spring.application.name=hello-service
#指定服务注册中心地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka
server.port=10000
#需要启动eureka-server后启动,再看 http://localhost:1111/ 会发现hello-service已经注册到服务中心中去了
添加注释
因为只是调用方,该@EnableDiscoveryClient
可以不添加
注意
:
因为UserService是单独编译一个jar包,所以在使用@EnableFeignClients注解时需要指定basePackages的值,否则报错:
Consider defining a bean of type 'cn.liuyiou.cloud.service.api.Service' in your configuration.
/**
* 因为UserService是单独编译一个jar包,所以在使用@EnableFeignClients注解时需要指定basePackages的值,否则报错
* Consider defining a bean of type 'cn.liuyiou.cloud.service.api.Service' in your configuration.
*/
@EnableFeignClients(basePackages = "cn.liuyiou.cloud.service.api")
@SpringBootApplication
@EnableDiscoveryClient
public class UserServiceClientApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceClientApplication.class, args);
}
}
调用服务
package cn.liuyiou.cloud.controller;
import cn.liuyiou.cloud.model.User;
import cn.liuyiou.cloud.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.PostConstruct;
import java.util.List;
@RestController
public class UserController {
private Logger logger = LoggerFactory.getLogger(UserController.class);
@Autowired
private UserService userService;
public UserController() {
logger.info("userservice In Construct {}", userService);
}
@PostConstruct
public void printService(){
logger.info("userservice In PostConstruct::{}", userService);
}
@RequestMapping("/add-user")
public String saveUser() {
return userService.addUser();
}
@RequestMapping("/list-user")
public List getUser() {
logger.info("userservice In Method ::{}", userService);
List userList = userService.listUser();
return userList;
}
@RequestMapping("/edit-user")
public String editUser() {
return userService.updateUser();
}
@RequestMapping("/delete-user")
public Boolean deleteUser() {
return userService.deleteUser();
}
}
启动
- userservice In Construct null
- userservice In PostConstruct::HardCodedTarget(type=UserService, name=USER-SERVICE, url=http://USER-SERVICE)
- userservice In Method ::HardCodedTarget(type=UserService, name=USER-SERVICE, url=http://USER-SERVICE)
访问 : http://localhost:8081/list-user
[{"id":1,"name":"lyy","age":18},{"id":2,"name":"yi","age":18},{"id":1,"name":"you","age":18}]
API和IMP合二为一
具体的目录规范需要自己定义
cn.liuyiyou.springcloud
user-service-api
0.0.2-SNAPSHOT
jar
user-service-api
org.apache.maven.plugins
maven-jar-plugin
3.0.2
cn/liuyiyou/cloud/model/**/*.class
cn/liuyiyou/cloud/service/api/**/*.class
客户端依赖修改成 0.0.2
参考资料
Spring Cloud入门教程(三):声明式服务调用(Feign)
Spring Cloud 声明式服务调用 Feign