Spring Cloud Feign(声明式服务调用)(1)

版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37598011/article/details/82811468

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);
    }

}

猜你喜欢

转载自blog.csdn.net/qq_37598011/article/details/82811468