Python 官方文档:入门教程 => 点击学习
目录Feign调用中文参数被encode编译原因记录今天遇到的feign多参数问题1.Post方式2.Get方式Feign调用中文参数被encode编译 原因 在实现一个feign调
在实现一个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的方法
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的扩展方法。
错误写法示例如下:
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);
错误写法示例如下:
@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);
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。
--结束END--
本文标题: feign调用中文参数被encode编译的问题
本文链接: https://lsjlt.com/news/141486.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0