亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何解決feign調用中文參數被encode編譯的問題

發布時間:2022-03-07 09:40:23 來源:億速云 閱讀:1177 作者:小新 欄目:開發技術

這篇文章主要介紹如何解決feign調用中文參數被encode編譯的問題,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

Feign調用中文參數被encode編譯

原因

在實現一個feign調用時使用了Post請求,并且拼接url參數,name傳值為中文時被encode轉譯,且最終接取數據之前未被decode轉譯回,問題探索:

feign:

@FeignClient(name = "service-test")
public interface TestServiceApi {
    @PostMapping("/test/abc")
    public String getTestNo(@RequestParam("code") String code, @RequestParam("name") String name);
}

controller:

@RequestMapping("/test")
public interface TestController {
    @Autowired
    private TestService testService;
    @PostMapping("/abc")
    public String getTestNo(@RequestParam("code") String code, @RequestParam("name") String name) {
        return testService.query(code, name); 
    }    
}

在controller中接到的中文參數被URIEncode轉譯了

測試 被轉譯成:%E6%B5%8B%E8%AF%95

找到feign的入口類ReflectiveFeign中拼裝RequestTemplate的方法:

    @Override
    public RequestTemplate create(Object[] argv) {
      RequestTemplate mutable = new RequestTemplate(metadata.template());
      if (metadata.urlIndex() != null) {
        int urlIndex = metadata.urlIndex();
        checkArgument(argv[urlIndex] != null, "URI parameter %s was null", urlIndex);
        mutable.insert(0, String.valueOf(argv[urlIndex]));
      }
      Map<String, Object> varBuilder = new LinkedHashMap<String, Object>();
      for (Entry<Integer, Collection<String>> entry : metadata.indexToName().entrySet()) {
        int i = entry.getKey();
        Object value = argv[entry.getKey()];
        if (value != null) { // Null values are skipped.
          if (indexToExpander.containsKey(i)) {
            value = expandElements(indexToExpander.get(i), value);
          }
          for (String name : entry.getValue()) {
            varBuilder.put(name, value);
          }
        }
      }
      // 組裝template的方法
      RequestTemplate template = resolve(argv, mutable, varBuilder);
      if (metadata.queryMapIndex() != null) {
        // add query map parameters after initial resolve so that they take
        // precedence over any predefined values
        template = addQueryMapQueryParameters(argv, template);
      }
      if (metadata.headerMapIndex() != null) {
        template = addHeaderMapHeaders(argv, template);
      }
      return template;
    }

在RequestTemplate類中如果是拼接在url后的param那么會被使用encodeValueIfNotEncoded都encode轉譯,但是不會走decode的方法 

 /**
   * Resolves any template parameters in the requests path, query, or headers against the supplied
   * unencoded arguments. <br> <br><br><b>relationship to JAXRS 2.0</b><br> <br> This call is
   * similar to {@code javax.ws.rs.client.WebTarget.resolveTemplates(templateValues, true)} , except
   * that the template values apply to any part of the request, not just the URL
   */
  RequestTemplate resolve(Map<String, ?> unencoded, Map<String, Boolean> alreadyEncoded) {
    replaceQueryValues(unencoded, alreadyEncoded);
    Map<String, String> encoded = new LinkedHashMap<String, String>();
    for (Entry<String, ?> entry : unencoded.entrySet()) {
      final String key = entry.getKey();
      final Object objectValue = entry.getValue();
      String encodedValue = encodeValueIfNotEncoded(key, objectValue, alreadyEncoded);
      encoded.put(key, encodedValue);
    }
    String resolvedUrl = expand(url.toString(), encoded).replace("+", "%20");
    if (decodeSlash) {
      resolvedUrl = resolvedUrl.replace("%2F", "/");
    }
    url = new StringBuilder(resolvedUrl);
    Map<String, Collection<String>> resolvedHeaders = new LinkedHashMap<String, Collection<String>>();
    for (String field : headers.keySet()) {
      Collection<String> resolvedValues = new ArrayList<String>();
      for (String value : valuesOrEmpty(headers, field)) {
        String resolved = expand(value, unencoded);
        resolvedValues.add(resolved);
      }
      resolvedHeaders.put(field, resolvedValues);
    }
    headers.clear();
    headers.putAll(resolvedHeaders);
    if (bodyTemplate != null) {
      body(urlDecode(expand(bodyTemplate, encoded)));
    }
    return this;
  }

如果傳入的值在requestBody中,則不會被encode轉譯

    @Override
    public void encode(Object requestBody, Type bodyType, RequestTemplate request)
            throws EncodeException {
        // template.body(conversionService.convert(object, String.class));
        if (requestBody != null) {
            Class<?> requestType = requestBody.getClass();
            Collection<String> contentTypes = request.headers().get("Content-Type");
            MediaType requestContentType = null;
            if (contentTypes != null && !contentTypes.isEmpty()) {
                String type = contentTypes.iterator().next();
                requestContentType = MediaType.valueOf(type);
            }
            for (HttpMessageConverter<?> messageConverter : this.messageConverters
                    .getObject().getConverters()) {
                if (messageConverter.canWrite(requestType, requestContentType)) {
                    if (log.isDebugEnabled()) {
                        if (requestContentType != null) {
                            log.debug("Writing [" + requestBody + "] as \""
                                    + requestContentType + "\" using ["
                                    + messageConverter + "]");
                        }
                        else {
                            log.debug("Writing [" + requestBody + "] using ["
                                    + messageConverter + "]");
                        }
                    }
                    FeignOutputMessage outputMessage = new FeignOutputMessage(request);
                    try {
                        @SuppressWarnings("unchecked")
                        HttpMessageConverter<Object> copy = (HttpMessageConverter<Object>) messageConverter;
                        copy.write(requestBody, requestContentType, outputMessage);
                    }
                    catch (IOException ex) {
                        throw new EncodeException("Error converting request body", ex);
                    }
                    // clear headers
                    request.headers(null);
                    // converters can modify headers, so update the request
                    // with the modified headers
                    request.headers(getHeaders(outputMessage.getHeaders()));
                    // do not use charset for binary data
                    if (messageConverter instanceof ByteArrayHttpMessageConverter) {
                        request.body(outputMessage.getOutputStream().toByteArray(), null);
                    } else {
                        request.body(outputMessage.getOutputStream().toByteArray(), Charset.forName("UTF-8"));
                    }
                    return;
                }
            }
            String message = "Could not write request: no suitable HttpMessageConverter "
                    + "found for request type [" + requestType.getName() + "]";
            if (requestContentType != null) {
                message += " and content type [" + requestContentType + "]";
            }
            throw new EncodeException(message);
        }
    }

綜合上述的調試,如果在Post中拼接參數那么會被encode轉譯,且不會被decode轉譯,如果使用body傳參,那么不會出現轉譯問題,如果必須使用拼接傳參,那么可以使用方法

1. @RequestLine的注解自定義參數的格式,具體參考該注解的使用方式。

2.在Feign的RequestInterceptor將傳遞的值decode的擴展方法。

記錄今天遇到的feign多參數問題

1.Post方式

錯誤寫法示例如下:

public int save(@RequestBody final User u, @RequestBody final School s);

錯誤原因:

fegin中可以有多個@RequestParam,但只能有不超過一個@RequestBody,@RequestBody用來修飾對象,但是既有@RequestBody也有@RequestParam,

那么參數就要放在請求的Url中,@RequestBody修飾的就要放在提交對象中。

注意!!! 用來處理@RequestBody Content-Type 為 application/json,application/xml編碼的內容

正確寫法示例如下:

public int save(@RequestBody final Person p,@RequestParam("userId") String userId,@RequestParam("userTel") String userTel);

2.Get方式

錯誤寫法示例如下:

@RequestMapping(value="/test", method=RequestMethod.GET)  
Model test(final String name,  final int age);

錯誤原因:

異常原因:當使用Feign時,如果發送的是get請求,那么需要在請求參數前加上@RequestParam注解修飾,Controller里面可以不加該注解修飾,@RequestParam可以修飾多個,@RequestParam是用來修飾參數,不能用來修飾整個對象。

注意:@RequestParam Content-Type 為 application/x-www-form-urlencoded 而這種是默認的

正確寫法示例如下:

@GetMapping("/getSchoolDetail")
    public ResultMap getSchoolDetail(@RequestParam("kSchoolId") LongkSchoolId,
     @RequestParam("kSchoolYearId") Long kSchoolYearId);

以上是“如何解決feign調用中文參數被encode編譯的問題”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

瑞丽市| 丰原市| 孟州市| 金平| 牡丹江市| 平泉县| 凭祥市| 沙坪坝区| 乡宁县| 富源县| 齐河县| 紫阳县| 泗水县| 云南省| 九台市| 沙洋县| 米泉市| 固阳县| 枣阳市| 织金县| 乌审旗| 荔浦县| 镶黄旗| 崇明县| 温州市| 北票市| 班玛县| 延川县| 兴安县| 揭阳市| 伊川县| 栾城县| 临沧市| 安徽省| 同德县| 集安市| 富裕县| 新化县| 沧州市| 旌德县| 莎车县|