欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

feign調(diào)用中文參數(shù)被encode編譯的問(wèn)題

 更新時(shí)間:2022年03月07日 08:38:42   作者:珍惜當(dāng)下668  
這篇文章主要介紹了feign調(diào)用中文參數(shù)被encode編譯的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

Feign調(diào)用中文參數(shù)被encode編譯

原因

在實(shí)現(xiàn)一個(gè)feign調(diào)用時(shí)使用了Post請(qǐng)求,并且拼接url參數(shù),name傳值為中文時(shí)被encode轉(zhuǎn)譯,且最終接取數(shù)據(jù)之前未被decode轉(zhuǎn)譯回,問(wèn)題探索:

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中接到的中文參數(shù)被URIEncode轉(zhuǎn)譯了

測(cè)試 被轉(zhuǎn)譯成:%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那么會(huì)被使用encodeValueIfNotEncoded都encode轉(zhuǎn)譯,但是不會(huì)走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中,則不會(huì)被encode轉(zhuǎn)譯

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

綜合上述的調(diào)試,如果在Post中拼接參數(shù)那么會(huì)被encode轉(zhuǎn)譯,且不會(huì)被decode轉(zhuǎn)譯,如果使用body傳參,那么不會(huì)出現(xiàn)轉(zhuǎn)譯問(wèn)題,如果必須使用拼接傳參,那么可以使用方法

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

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

記錄今天遇到的feign多參數(shù)問(wèn)題

1.Post方式

錯(cuò)誤寫法示例如下:

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

錯(cuò)誤原因:

fegin中可以有多個(gè)@RequestParam,但只能有不超過(guò)一個(gè)@RequestBody,@RequestBody用來(lái)修飾對(duì)象,但是既有@RequestBody也有@RequestParam,

那么參數(shù)就要放在請(qǐng)求的Url中,@RequestBody修飾的就要放在提交對(duì)象中。

注意?。。?用來(lái)處理@RequestBody Content-Type 為 application/json,application/xml編碼的內(nèi)容

正確寫法示例如下:

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

2.Get方式

錯(cuò)誤寫法示例如下:

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

錯(cuò)誤原因:

異常原因:當(dāng)使用Feign時(shí),如果發(fā)送的是get請(qǐng)求,那么需要在請(qǐng)求參數(shù)前加上@RequestParam注解修飾,Controller里面可以不加該注解修飾,@RequestParam可以修飾多個(gè),@RequestParam是用來(lái)修飾參數(shù),不能用來(lái)修飾整個(gè)對(duì)象。

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

正確寫法示例如下:

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

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java動(dòng)態(tài)代理實(shí)現(xiàn)代碼

    java動(dòng)態(tài)代理實(shí)現(xiàn)代碼

    這篇文章主要介紹了java 動(dòng)態(tài)代理的的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下,希望能給你帶來(lái)幫助
    2021-07-07
  • 淺談在springboot中使用定時(shí)任務(wù)的方式

    淺談在springboot中使用定時(shí)任務(wù)的方式

    今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著在springboot中使用定時(shí)任務(wù)的方式展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Spring?Boot項(xiàng)目抵御XSS攻擊實(shí)戰(zhàn)過(guò)程

    Spring?Boot項(xiàng)目抵御XSS攻擊實(shí)戰(zhàn)過(guò)程

    XSS攻擊又稱跨站腳本攻擊,通常指利用網(wǎng)頁(yè)開發(fā)時(shí)留下的漏洞,通過(guò)巧妙的方法注入惡意指令代碼到網(wǎng)頁(yè),使用戶加載并執(zhí)行攻擊者惡意制造的網(wǎng)頁(yè)程序,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot項(xiàng)目抵御XSS攻擊的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • Dubbo本地調(diào)試的幾種方式總結(jié)

    Dubbo本地調(diào)試的幾種方式總結(jié)

    dubbo服務(wù)方啟動(dòng)時(shí)需要加載的東西太多,如果跑單元測(cè)試把服務(wù)開啟會(huì)浪費(fèi)不少時(shí)間,而且單元測(cè)試沒(méi)法保持服務(wù)一直開啟的狀態(tài),這篇文章主要給大家介紹了關(guān)于Dubbo本地調(diào)試的幾種方式,需要的朋友可以參考下
    2022-11-11
  • SWT(JFace) 打印功能

    SWT(JFace) 打印功能

    SWT(JFace)體驗(yàn)之打印功能
    2009-06-06
  • java多線程處理執(zhí)行solr創(chuàng)建索引示例

    java多線程處理執(zhí)行solr創(chuàng)建索引示例

    這篇文章主要介紹了java多線程處理執(zhí)行solr創(chuàng)建索引示例,需要的朋友可以參考下
    2014-02-02
  • Java如何導(dǎo)出數(shù)據(jù)庫(kù)中的所有數(shù)據(jù)表到指定文件夾

    Java如何導(dǎo)出數(shù)據(jù)庫(kù)中的所有數(shù)據(jù)表到指定文件夾

    這篇文章主要介紹了Java導(dǎo)出數(shù)據(jù)庫(kù)中的所有數(shù)據(jù)表到指定文件夾,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • 用Java程序判斷是否是閏年的簡(jiǎn)單實(shí)例

    用Java程序判斷是否是閏年的簡(jiǎn)單實(shí)例

    下面小編就為大家?guī)?lái)一篇用Java程序判斷是否是閏年的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-06-06
  • Maven的pom.xml文件結(jié)構(gòu)中的build

    Maven的pom.xml文件結(jié)構(gòu)中的build

    本文主要介紹了Maven的pom.xml文件結(jié)構(gòu)中的build,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • AsyncHttpClient IOExceptionFilter異常過(guò)濾器

    AsyncHttpClient IOExceptionFilter異常過(guò)濾器

    這篇文章主要為大家介紹了AsyncHttpClient IOExceptionFilter異常過(guò)濾器代碼流程解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12

最新評(píng)論