java - 使用 Json 请求部分假装多部分
问题描述
我在一项服务中有 Feign 客户,使用一种方法
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
MyDto uploadDocument(@RequestPart("file") MultipartFile file,
@RequestPart("myDto") String myDto);
我在另一个服务中有一个控制器
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<MyDto> uploadDocument(@RequestParam("file") MultipartFile file,
@RequestPart("myDto") MyDto myDto) {
.... some code here
}
我面临的问题是 Feign 发送 myDto 与 Content-type : text/plain 我有 HttpMediaTypeNotSupportedException
是否可以@RequestPart("myDto") String myDto
使用 Content-type 发送: application/json ?
预期的原始请求:
----------------------------boundary
Content-Disposition: form-data; name="file"; filename="fileName"
<file>
----------------------------boundary
Content-Disposition: form-data; name="myDto"
**Content-Type: application/json**
{"myDto": ""}
当前原始请求:
----------------------------boundary
Content-Disposition: form-data; name="file"; filename="fileName"
<file>
----------------------------boundary
Content-Disposition: form-data; name="myDto"
**Content-Type: text/plain**
{"myDto": ""}
解决方案
通过替换 feign-form PojoWriter 设法解决了这个问题。默认情况下,它将对象的每个字段序列化为单独的部分。
@Bean
public Encoder feignEncoder () {
return new MyFormEncoder(objectMapper, new SpringEncoder(messageConverters));
}
public class MyFormEncoder extends SpringFormEncoder {
/**
* Constructor with specified delegate encoder.
*
* @param delegate delegate encoder, if this encoder couldn't encode object.
*/
public MyFormEncoder(ObjectMapper objectMapper, Encoder delegate) {
super(delegate);
val processor = (MultipartFormContentProcessor) getContentProcessor(MULTIPART);
processor.addFirstWriter(new MyPojoWriter(objectMapper));
}
}
@FieldDefaults(level = PRIVATE, makeFinal = true)
public class MyPojoWriter extends AbstractWriter {
private ObjectMapper objectMapper;
public MyPojoWriter(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public boolean isApplicable(Object object) {
return isUserPojo(object);
}
@Override
protected void write(Output output, String key, Object value) throws EncodeException {
var data = "";
try {
data = objectMapper.writeValueAsString(value);
} catch (JsonProcessingException e) {
}
val string = new StringBuilder()
.append("Content-Disposition: form-data; name=\"").append(key).append('"').append(CRLF)
.append("Content-Type: application/json; charset=").append(output.getCharset().name()).append(CRLF)
.append(CRLF)
.append(data)
.toString();
output.write(string);
}
private boolean isUserPojo(@NonNull Object object) {
val type = object.getClass();
val typePackage = type.getPackage();
return typePackage != null && typePackage.getName().startsWith("com.my-package.");
}
}
推荐阅读
- python - 如何按照我在 Maya 中选择的顺序列出顶点?
- css - 为什么我的移动版页面有空白空间?
- typescript - 在 sinon 中,当没有函数时,如何监视通过“* as”导入的模块
- php - Laravel 管理全局设置
- javascript - 图片库 - 移动设备优化
- python - python拼字游戏分数计算
- c - redis cygwin 在本地 pc 上运行,与 redis-cli 连接会给出无法在 127.0.0.1:6668 连接到 Redis:名称或服务未知
- c# - 用于缓存来自 Web 服务调用的数据并在后台更新的模式或库
- git - 将自定义行附加到范围内的精选提交
- postgresql - PostgreSQL 查询每运行五次/六次就非常慢