關於Feign在微服務間調用引用參數傳遞的問題

Feign默認不支持GET方式傳遞POJO,也不支持傳遞多個引用類型的參數!本文就是解決這兩個問題!

 

解決思路:

在微服務A端:將要傳遞的引用類型參數要麼以body方式傳遞,要麼以json串方式傳遞,在攔截器裏解析json串拆分爲更爲詳細的參數。

在微服務B端:按照SpringMVC支持寫法去寫,A端傳來的請求參數自動映射到B端實體屬性上!

 

解決問題的關鍵:是自定義Feign請求攔截器的實現

 

關鍵代碼如下:

/**
 * 處理Feign請求不支持Pojo的問題,以及參數爲json串的轉換處理!
 */
@AllArgsConstructor
@Configuration
public class FeignRequestInterceptor implements RequestInterceptor {
    private ObjectMapper objectMapper;

    @Override
    public void apply(RequestTemplate template) {

        if (template.method().equals("GET")) {
            try {
                Map<String, Collection<String>> queries = new HashMap<>();
                // 處理不帶註解的參數解析
                // feign 不支持 GET 方法傳 POJO, json body轉query
                if (template.requestBody().asBytes() != null) {
                    JsonNode jsonNode = objectMapper.readTree(template.requestBody().asBytes());
                    buildQuery(jsonNode, "", queries);
                }

                // 處理帶有@RequestParam前綴註解的參數解析,如果是json串則拆分處理
                Map<String, Collection<String>> entityParams = template.queries();
                if (entityParams.size() > 0) {
                    for (Map.Entry<String, Collection<String>> entry : entityParams.entrySet()) {
                        List<String> value = (List<String>) entry.getValue();
                        String strVal = value.get(0);
                        // 判斷是否是引用對象的的參數,例如:%7B%22code%22:%2218041CAB070-018%22%7D
//                        if (strVal.contains("%22") && strVal.contains("%7B") && strVal.contains("%7D")) { // 則認爲是引用類型
                        JsonNode tmpJsonNode = objectMapper.readTree(URLDecoder.decode(strVal, "UTF-8"));
                        buildQuery(tmpJsonNode, "", queries);
//                        }
                    }
                }

                template.queries(queries);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    ...省略其他的代碼....    
}  

 

解決不能傳遞POJO的問題:

下面這段代碼處理:支持有一個參數不寫@RequestParam,這樣這個引用參數自動映射爲body:即支持get傳遞POJO對象,例如分頁對象,攔截器攔截處理!

 Map<String, Collection<String>> queries = new HashMap<>();
                // 處理不帶註解的參數解析
                // feign 不支持 GET 方法傳 POJO, json body轉query
                if (template.requestBody().asBytes() != null) {
                    JsonNode jsonNode = objectMapper.readTree(template.requestBody().asBytes());
                    buildQuery(jsonNode, "", queries);
                }

例如,下面爲feign接口中定義的樣例:

  @GetMapping("/warninginfo/page")
 R getWarningInfoPage(Page page, @RequestParam("warningInfo") String warningInfoJsonString, @RequestHeader(SecurityConstants.FROM) String from);

此處的Page就會被攔截器處理,以便支持傳遞到B端!

 

解決傳遞多個引用對象參數到B端的問題:

下面的這段代碼處理帶有@RequestParam前綴註解的參數解析,如果是json串則拆分處理:

 // 處理帶有@RequestParam前綴註解的參數解析,如果是json串則拆分處理
                Map<String, Collection<String>> entityParams = template.queries();
                if (entityParams.size() > 0) {
                    for (Map.Entry<String, Collection<String>> entry : entityParams.entrySet()) {
                        List<String> value = (List<String>) entry.getValue();
                        String strVal = value.get(0);
                        // 判斷是否是引用對象的的參數,例如:%7B%22code%22:%2218041CAB070-018%22%7D
//                        if (strVal.contains("%22") && strVal.contains("%7B") && strVal.contains("%7D")) { // 則認爲是引用類型
                        JsonNode tmpJsonNode = objectMapper.readTree(URLDecoder.decode(strVal, "UTF-8"));
                        buildQuery(tmpJsonNode, "", queries);
//                        }
                    }
                }

在A端傳遞多個引用類型對象的json串,這樣就支持傳遞多個引用對象作爲參數了,攔截器會解析json串並拆分爲請求參數;

下面爲feign接口中定義的樣例,

@GetMapping("/warninginfo/page") 
R getWarningInfoPage(@RequestParam("page") String pageJsonString, @RequestParam("warningInfo") String warningInfoJsonString, @RequestHeader(SecurityConstants.FROM) String from)

 

 

B端按照SpringMVC支持的方式書寫即可:例如

@GetMapping("/page")
@Inner
public R getWarningInfoPage(Page page, WarningInfo warningInfo) {
    return super.getByPage(page, warningInfo);
}

 

攔截器代碼參見有道雲筆記地址:http://note.youdao.com/noteshare?id=576a6c4f11b25758a44fb09cb0632151

 

參考:

https://www.jianshu.com/p/085c11e5722f

https://github.com/spring-cloud/spring-cloud-netflix/issues/1253

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章