OpenFeign中动态URl

1

 1、依赖引入

 <!--客户端依赖-->
    <dependencies>
        <!--由于使用了lombok减缓模型对象的编写,所以需要添加该依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <!-- 因为使用web进行测试,所以需要引入Web依赖-->
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <dependency>
            <!-- 使用openfeign,所以必须引入该依赖-->
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>
    </dependencies>


 <!--服务端依赖-->
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>runtime</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <!--使用json序列化,所以添加该依赖-->
        <dependency>
            <artifactId>fastjson</artifactId>
            <groupId>com.alibaba</groupId>
            <version>1.2.62</version>
        </dependency>
        <!--由于使用了lombok减缓模型对象的编写,所以需要添加该依赖-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>


2、服务端代码

@RestController
@RequestMapping("server")
public class ServerController {
    @GetMapping("get")
    public String getFunc(@RequestParam(value = "name") String name) {
        return "get --- " + name;
    }

    @PostMapping("post")
    public Student PostFunc(@RequestParam(value = "remark") String remark, @RequestBody Student student) {
        student.setRemark(remark);
        return student;
    }


    @PutMapping("put")
    public Student putFunc(@RequestParam(value = "remark") String remark, @RequestBody Student student) {
        student.setRemark(remark);
        return student;
    }

    @DeleteMapping("delete")
    public String deleteFunc(@RequestParam(value = "remark") String name) {
        return "delete --- " + name;
    }


    @PostMapping("path/{remark}")
    public Student pathFunc(@PathVariable(value = "remark") String remark, @RequestBody Student student) {
        student.setRemark(remark);
        return student;
    }
}

3、定义客户端Feign接口,在客户端中使用两种方式进行调用测试

3.1通过SpringBoot自动注入Feign对象,不改变调用服务器地址创建。该接口定义如下:

import com.mnyc.model.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
//为了能看清楚自动创建对象和SpringBoot创建对象的区别,因此这个地方需要设置url
//这样Feign就不会去创建负载均衡的底层调用对象,然后就和自己自定url的对象基本相同了
@FeignClient(name = "feign", url = "http://localhost:8080/server")
public interface FeignServerrClient {
    @GetMapping("/get")
    String getMethod(@RequestParam(value = "name", required = true) String name);

    @PostMapping("/post")
    String postMethod(@RequestParam("remark") String remark, User user);

    @PutMapping("/put")
    String putMethod(@RequestParam("remark") String remark, User user);

    @DeleteMapping("/delete")
    String deleteMethod(@RequestParam("remark") String remark);

    @PostMapping("/path/{remark}")
    String pathMethod(@PathVariable("remark") String remark, User user);
}

3.2 不指定服务地址,在调用的时候动态指定调用地址


import com.mnyc.model.User;
import feign.Param;
import feign.RequestLine;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import java.net.URI;

@FeignClient(name = "test")
public interface FeignTestClient {
    //在其他的一些博客中说的在Feign接口上使用@RequestLine,如果使用@RequestLine
    //应该是需要配合对应的decoder、encoder、contract,但是我没有找到正确的方式
    // 配置正确合适的decoder、encoder、contract,然后通过和SpirngBoot自动创建
    // 的Feign对象进行对比,然后在自己创建客户端的时候设置decoder、encoder、
    // contract三个核心对象与SpringBoot创建的相同,所以在客户端Feign的接口中使
    // 用完全和不动态修改地址的Feign接口相同
    @GetMapping("/get")
    String getMethod(@RequestParam(value = "name", required = true) String name);

    @PostMapping("/post")
    String postMethod(@RequestParam("remark") String remark, User user);

    @PutMapping("/put")
    String putMethod(@RequestParam("remark") String remark, User user);

    @DeleteMapping("/delete")
    String deleteMethod(@RequestParam("remark") String remark);

    @PostMapping("/path/{remark}")
    String pathMethod(@PathVariable("remark") String remark, User user);
}

4、为了方便测试,每个调用服务端的Feign都使用单独的服务类进行管理

4.1使用固定服务地址方式调用服务类


import com.mnyc.http.FeignServerrClient;
import com.mnyc.model.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class FeignServerService {
    @Autowired
    FeignServerrClient feignServerrClient;
    String flag = "FeignClient";

    public void get() {
        try {
            String result = "";
            result = feignServerrClient.getMethod(flag);
            log.info("Feign ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void post() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            result = feignServerrClient.postMethod(flag, user);
            log.info("Feign ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void put() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            result = feignServerrClient.putMethod(flag, user);
            log.info("Feign ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void delete() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            result = feignServerrClient.deleteMethod(flag);
            log.info("Feign ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void path() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            result = feignServerrClient.pathMethod(flag,user);
            log.info("Feign ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

4.2使用动态URL方式调用服务端的服务类

import com.mnyc.http.FeignTestClient;
import com.mnyc.model.User;
import feign.Feign;
import feign.form.spring.SpringFormEncoder;
import feign.optionals.OptionalDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.cloud.openfeign.support.SpringEncoder;
import org.springframework.cloud.openfeign.support.SpringMvcContract;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Service;

@Slf4j
@Service
//网上说的需要在调用的地方导入该配置类,最后我屏蔽掉该代码好像也可以
@Import(FeignClientsConfiguration.class)
public class FeignTestService {

    @Autowired
    ObjectFactory<HttpMessageConverters> messageConverters;
    String flag = "TestClient";

    private FeignTestClient createFeignClient() {
        OptionalDecoder decoder = new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(messageConverters)));
        SpringEncoder springEncoder = new SpringEncoder(messageConverters);
        SpringFormEncoder encoder = new SpringFormEncoder(springEncoder);
        SpringMvcContract contract = new SpringMvcContract();
        FeignTestClient feignTestClient = Feign.builder()
                .decoder(decoder)
                .encoder(encoder)
                .contract(contract)
                //这个地方的Url可以根据每次调用的时候进行改变
                .target(FeignTestClient.class, "http://localhost:8080/server");//传入url
        return feignTestClient;
    }


    public void get() {
        try {
            FeignTestClient feignClient = createFeignClient();
            String result = feignClient.getMethod(flag);
            log.info("TEST ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    public void post() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            FeignTestClient feignClient = createFeignClient();
            result = feignClient.postMethod(flag, user);
            log.info("TEST ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void put() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            FeignTestClient feignClient = createFeignClient();
            result = feignClient.putMethod(flag, user);
            log.info("TEST ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void delete() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            FeignTestClient feignClient = createFeignClient();
            result = feignClient.deleteMethod(flag);
            log.info("TEST ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public void path() {
        try {
            String result = "";
            User user = new User();
            user.setName("name");
            user.setAge(100);
            FeignTestClient feignClient = createFeignClient();
            result = feignClient.pathMethod(flag, user);
            log.info("TEST ========= " + result);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

5、核心

5.1 在使用lombok对模型进行标注的时候,因为在controller中有对应模型作为输入参数,所以该模型上必须添加“@NoArgsConstructor”注解

5.2Feign核心部分

 private FeignTestClient createFeignClient() {
        //1、在创建Feign客户端的时候最核心的对象是decoder、encoder、contract
        //通过跟踪源码与SpringBoot自动创建的Feign对象比较,设置decoder、encoder、
        //contract为SpringBoot中自动创建对象相同,然后定义Feign接口的时候,
        //各种参数的注解和方法的注解就可以和不动态修改url的相同了
        //decoder解码器,对返回的结果进行解码
        OptionalDecoder decoder = new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(messageConverters)));
        //encoder编码器,对输入的数据进行编码
        SpringEncoder springEncoder = new SpringEncoder(messageConverters);
        SpringFormEncoder encoder = new SpringFormEncoder(springEncoder);
        //该对象是将接口进行解析,方便生成最后调用的网络对象HttpurlConnection
        SpringMvcContract contract = new SpringMvcContract();
        FeignTestClient feignTestClient = Feign.builder()
                .decoder(decoder)
                .encoder(encoder)
                .contract(contract)
                //这个地方的Url可以根据每次调用的时候进行改变
                .target(FeignTestClient.class, "http://localhost:8080/server");//传入url
        return feignTestClient;
    }

 DEMO下载地址:https://download.csdn.net/download/wangdaoyin2010/21138515

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值