Spring Cloud Feign(声明式服务调用)(1)
Spring Cloud Feign它基于Netflix Feign实现,整合了Spring Cloud Ribbon与Spring Cloud Hystrix,除了提供这两者的强大功能,它还提供了一种声明式的Web服务客户端定义方式。
1.下面首先创建一个Spring Boot基础工程取名为feign-consumer并在其pom.xml文件中加入spring-cloud-starter-eureka和spring-cloud-starter-feign依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>feign-consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>feign-consumer</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.在主类上添加@EnableFeignClients注解开启Spring Cloud Feign的支持功能:
@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
public class FeignConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(FeignConsumerApplication.class, args);
}
}
3.定义HelloService接口,通过@FeignClient注解指定服务名来绑定服务,然后使用Spring MVC的注解来绑定具体该服务提供的REST接口。
@FeignClient("hello-service")//用于绑定名为hello-service服务
public interface HelloService {
@RequestMapping("/hello")
public String hello(String id);
}
4.最后创建一个控制器来实现对Feign客户端的调用。使用@AutoWired直接注入HelloService实例,并在该控制器中直接调用hello-service服务发起的/hello接口的调用。
@RestController
public class ConsumerController {
@Autowired
HelloService helloService;
@GetMapping("/feign-consumer")
public String helloConsumer(String id){
return helloService.hello(id);
}
}
5.修改application.properties文件:
spring.application.name=feign-consumer
server.port=9001
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
不过此时是没有参数绑定能力的所以没有打印id。
参数绑定
首先扩展一下服务提供者(hello-service)。
@RestController
public class HelloController {
private final Logger logger=Logger.getLogger(getClass());
@RequestMapping("/hello")
public String index() throws InterruptedException {
// int sleepTime=new Random().nextInt(3000);
// logger.info("sleep:"+sleepTime);
// Thread.sleep(sleepTime);
logger.info(new Date());
return "Hello"+new Date()+"---"+new Random().nextInt();
}
@RequestMapping(value = "/hello1", method = RequestMethod.GET)
public String hello1(@RequestParam String name) {
return "hello " + name + "!";
}
@RequestMapping(value = "/hello2", method = RequestMethod.GET)
public Map<String,Object> hello2(@RequestHeader String name, @RequestHeader String author, @RequestHeader Integer price) throws UnsupportedEncodingException {
Map<String,Object> map = new HashMap<String,Object>();
map.put("name",URLDecoder.decode(name));
map.put("author",URLDecoder.decode(author));
return map;
}
@RequestMapping(value = "/hello3", method = RequestMethod.POST)
public String hello3(@RequestBody Map<String,Object> book) {
return "书名为:" + book.get("name") + ";作者为:" + book.get("author");
}
@RequestMapping(value = "/hello4", method = RequestMethod.POST)
public String hello4(@RequestBody User user) {
return "用户名:" + user.getName() + ";年龄为:" + user.getAge();
}
}
User类:
public class User {
private String name;
private Integer age;
public User(){}
public User(String name, Integer age){
this.name=name;
this.age=age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
然后在feign-consumer中也创建逾期一样的User类。
然后再HelloService接口中新增上述接口的绑定:
@FeignClient("hello-service")//用于绑定名为hello-service服务
public interface HelloService {
@RequestMapping("/hello")
public String hello();
@RequestMapping(value = "/hello1", method = RequestMethod.GET)
String hello(@RequestParam("name") String name);
@RequestMapping(value = "/hello2", method = RequestMethod.GET)
Map<String,Object> hello(@RequestHeader("name") String name, @RequestHeader("author") String author, @RequestHeader("price") Integer price);
@RequestMapping(value = "/hello3", method = RequestMethod.POST)
String hello(@RequestBody Map<String,Object> book);
@RequestMapping(value = "/hello4", method = RequestMethod.POST)
String hello(@RequestBody User user);
}
这里需要注意在绑定参数时,@RequestParam,@RequestHeader等可以指定参数名称的注解的value参数不能少。在Feign中绑定参数必须通过value来指定具体的参数名不然会抛出IlleglStateException异常,value属性不能为空。
最后控制器新增上述接口:
@RestController
public class ConsumerController {
@Autowired
HelloService helloService;
@GetMapping("/feign-consumer")
public String helloConsumer(){
return helloService.hello();
}
@RequestMapping("/hello1")
public String hello1() {
return helloService.hello("张三");
}
@RequestMapping(value = "/hello2")
public Map<String,Object> hello2() throws UnsupportedEncodingException {
Map<String,Object> book = helloService.hello(URLEncoder.encode("三国演义","UTF-8"), URLEncoder.encode("罗贯中","UTF-8"), 33);
System.out.println(book);
return book;
}
@RequestMapping("/hello3")
public String hello3() {
Map<String,Object> book = new HashMap<String,Object>();
book.put("name","三国演义");
book.put("author","罗贯中");
return helloService.hello(book);
}
@RequestMapping("/hello4")
public String hello4() {
User user=new User("刘德华",99);
return helloService.hello(user);
}
}
还没有评论,来说两句吧...