转载

Feign动态设置Header,地址和参数

最近在使用Feign,总结了一下使用经验

普通调用

配置client 接口类NormalFeginClient

@FeignClient(name = "NormalFeignClient", url = "localhost:9004/check")
public interface NormalFeginClient {
    @GetMapping("userValidGet")
    Response normalGet(@RequestParam("userId") String userId, @RequestParam("userName") String userName);

    @GetMapping("userValidGet")
    Response mapGet(@HeaderMap Map<String, Object> headerMap, @SpringQueryMap Map<String, Object> requestMap);

    @GetMapping("userValidGet")
    Response pojoGet(@HeaderMap Map<String, Object> headerMap, @SpringQueryMap User user);

    @PostMapping("testAspectUserValidPost")
    Response normalPost(@RequestBody Map<String, Object> request);

    @PostMapping("testAspectUserValidPost")
    Response pojoPost(@HeaderMap Map<String, Object> headerMap, @SpringQueryMap User user);
}

在controller中调用

@GetMapping(value = "/thirdService")
    public Response requestThirdService(HttpServletRequest req) {
        String message = "test   Jpa     Message";
        String result = "test   Jpa     Result";

        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("a", "A");
        headerMap.put("a1", "A1");

        Map<String, Object> requestMap = new HashMap<>();
        requestMap.put("userId", "A");
        requestMap.put("userName", "zero");

        User user = new User();
        user.setUserId("A");
        user.setUserName("zero");

        feign.Response requestResult1 = normalFeginClient.normalGet("A", "zero");

        feign.Response requestResult2 = normalFeginClient.mapGet(headerMap, requestMap);

        feign.Response requestResult3 = normalFeginClient.pojoGet(headerMap, user);

        feign.Response requestResult4 = normalFeginClient.normalPost(requestMap);

        feign.Response requestResult5 = normalFeginClient.pojoPost(headerMap, user);

        System.out.println(FeignUtil.feignResponseBody(requestResult1));
        System.out.println(FeignUtil.feignResponseBody(requestResult2));
        System.out.println(FeignUtil.feignResponseBody(requestResult3));
        System.out.println(FeignUtil.feignResponseBody(requestResult4));
        System.out.println(FeignUtil.feignResponseBody(requestResult5));
        return Response.ok(message).setData(result);
    }

返回结果

{"code":"ok","data":"Hello zero","requestid":"d56b56a443a64b69b2b9cb22a9761532"}
{"timestamp":"2020-04-13T09:52:57.842+0000","status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/check/userValidGet"}
{"timestamp":"2020-04-13T09:52:57.848+0000","status":405,"error":"Method Not Allowed","message":"Request method 'POST' not supported","path":"/check/userValidGet"}
{"code":"ok","data":"Hello null","requestid":"b27fdf522c2943f6b750ecb770db0aa1"}
{"code":"ok","data":"Hello null","requestid":"c50a2333b2ba4840ab77215fa1fc4ae9"}

在上面的调用中我们发现以这种方式调用有很多问题,调用地址无法动态修改,Get只要加上@HeaderMap就会被识别为POST方式调用,为了解决这些问题,有了以下方法

自定义调用

配置client 接口类CustomerFeignClient

注解使用 @RequestLine,参数里应按指定格式

@QueryMap参数定义名称-值对(或POJO)的映射,展开后成为字符串,可以用于Get方式传递参数

@FeignClient(name = "CustomerFeignClient")
public interface CustomerFeignClient {

    @RequestLine("GET")
    Response get(URI baseUri, @HeaderMap Map<String, Object> headerMap, @QueryMap Map<String, Object> requestMap);

    @RequestLine("POST")
    Response post(URI baseUri, @HeaderMap Map<String, Object> headerMap, @RequestBody Map<String, Object> request);
}

修改Feign配置

有两点需要注意

  1. import feign配置类,FeignClientsConfiguration.class,如果没有自定义参数和编解码器就使用FeignClientsConfiguration默认的
  2. 在CustomerFeignConfig构造函数中用 @Autowired 引入自定义参数和编解码器
package com.mantis.brac.common.feign;

import com.mantis.brac.common.exception.BracBusinessException;
import com.mantis.brac.common.http.RequestEnum;
import feign.Feign;
import feign.Response;
import feign.Target;
import feign.codec.Decoder;
import feign.codec.Encoder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.openfeign.FeignClientsConfiguration;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;

@Component
@Import(FeignClientsConfiguration.class)
public class CustomerFeignConfig {

    private CustomerFeignClient bracFeignClient;
    private String uri;
    private RequestEnum requestType;
    private Map<String, Object> header;
    private Map<String, Object> request;
    
    /**
     * 在构造函数中用 @Autowired 引入自定义参数和编解码器
     * @param encoder
     * @param decoder
     */
    @Autowired
    public CustomerFeignConfig(Encoder encoder, Decoder decoder) {
        bracFeignClient = Feign.builder().encoder(encoder).decoder(decoder)
                .target(Target.EmptyTarget.create(CustomerFeignClient.class));
    }

    public CustomerFeignConfig get() {
        this.setRequestType(RequestEnum.GET);
        return this;
    }

    public CustomerFeignConfig post() {
        this.setRequestType(RequestEnum.POST);
        return this;
    }

    /**
     * 执行调用方法
     *
     * @return
     */
    public Response execute() {
        switch (getRequestType()) {
            case GET:
                return bracFeignClient.get(findUri(getUri()), getHeader(), getRequest());
            case POST:
                return bracFeignClient.post(findUri(getUri()), getHeader(), getRequest());
            default:
                throw new BracBusinessException("请选择调用方式!");
        }
    }



    public String getUri() {
        return uri;
    }

    public CustomerFeignConfig setUri(String uri) {
        if (uri == null) {
            throw new BracBusinessException("uri == null");
        } else {
            this.uri = uri;
        }
        return this;
    }

    public Map<String, Object> getRequest() {
        return request;
    }

    public CustomerFeignConfig setRequest(Map<String, Object> request) {
        this.request = request;
        return this;
    }

    public RequestEnum getRequestType() {
        return requestType;
    }

    public void setRequestType(RequestEnum requestType) {
        this.requestType = requestType;
    }

    public Map<String, Object> getHeader() {
        return header;
    }

    public CustomerFeignConfig setHeader(Map<String, Object> header) {
        this.header = header;
        return this;
    }

    /**
     * 获取请求URI
     *
     * @param uri
     * @return
     */
    private URI findUri(String uri) {
        try {
            return new URI(uri);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        throw new BracBusinessException("获取请求地址失败!");
    }

}

在controller中调用

@Autowired
CustomerFeignConfig customerFeignConfig;    

@PostMapping(value = "/lookup/customer/thirdService")
    public Response postQueryThirdService(HttpServletRequest req) {
        String message = "Message";
        String result = "Result";
        StringBuilder reqJson = JsonUtil.getJson(req);
        Map<String, Object> headerMap = new HashMap<>();
        headerMap.put("a", "A");
        headerMap.put("a1", "A1");

        Map<String, Object> requestMap = new HashMap<>();
        requestMap.put("userId", "A");
        requestMap.put("userName", "zero");
        feign.Response requestResult1 = customerFeignConfig.setHeader(headerMap).setUri("http://localhost:9004/check/userValidGet").setRequest(requestMap).get().execute();
        feign.Response requestResult2 = customerFeignConfig.setHeader(headerMap).setUri("http://localhost:9004/check/testAspectUserValidPost").setRequest(requestMap).post().execute();
        System.out.println(FeignUtil.feignResponseBody(requestResult1));
        System.out.println(FeignUtil.feignResponseBody(requestResult2));
        return Response.ok(message).setData(result);
    }

返回结果

我们可以发现数据请求参数和Header正常传递

Feign动态设置Header,地址和参数

Feign动态设置Header,地址和参数

返回结果也可以正常拿到

{"code":"ok","data":"Hello zero","requestid":"3afdaf854b0946edb5b035c09198081e"}
{"code":"ok","data":"Hello null","requestid":"6b4ec0b79ab94e67b182ac9fae9adf7c"}

Git地址

git@github.com:A-mantis/brac-project-service.git
原文  https://segmentfault.com/a/1190000022359063
正文到此结束
Loading...