spring cloud实战与思考(三) 微服务之间通过fiegn上传一组文件(下)
需求场景:
用户调用微服务1的接口上传一组图片和对应的描述信息。微服务1处理后,再将这组图片上传给微服务2进行处理。各个微服务能区分开不同的图片进行不同处理。

上一篇博客已经讨论了在微服务之间传递一组图片和对应参数的解决方案。现在来看看如何对组内文件进行区分。当前项目中使用了“commons-fileupload”和“feign-form”两个库进行文件传输。

“commons-fileupload”库可以将http request转换成“MultipartHttpServletRequest”,最终能够获取到“MultipartFile”列表:
@RequestMapping(value="/psts/add/insertWithFiles", method = RequestMethod.POST)
public Object pastsAddTripInfo(HttpServletRequest request) {
//创建一个通用的多部分解析器
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext()); //转换成多部分request
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request; Map<String, MultipartFile> files = multiRequest.getFileMap(); for(Map.Entry<String, MultipartFile> entry : files.entrySet()) {
System.out.println("file key name: " + entry.getKey()); //文件对象名称
System.out.println("file original name: " + entry.getValue().getOriginalFilename()); //文件原始名称
System.out.println("file name: " + entry.getValue().getName()); //文件对象名称
}
}
“MultipartFile”的“getName()”能获取到form表单中指定的对象名称。对这个名称进行约定就能区分不同的文件。
选择文件:
<input type="file" name="file1" />
<br/><br/>
<input type="file" name="file2" />
<br/><br/>
<input type="submit" value="上传" />
使用文件对象名称,微服务1可以区分开组内的各文件。微服务1向微服务2上传一组文件的时候使用“feign-form”库。在上一篇微博中已经找到了解决方案。但是方案的“@RequestPart(value = "files") MultipartFile[] photoFiles”接口方式将这组文件的对象名称都限定为“files”。貌似微服务2只能用文件的原始名称“getOriginalFilename()”对文件进行区分。但是对文件名称进行约定不利于用户使用体验。
既然微服务1拥有文件的区分标识,即文件对象名称,并且文件原始名称在传输过程中保持不变。不妨在封装文件时使用“对象名称.原始名称”替换文件原始名称。这样即保留了文件原始名称信息,又加入了文件区分标识。只要小小的改动一下“feign-form”库中封装“MultipartFile[]”的接口,就能实现这个目的。
封装“MultipartFile[]”的类是“SpringManyMultipartFilesWriter”,它使用“SpringSingleMultipartFileWriter”做具体的封装工作。所以声明一个新类“FeignSpringSingleMultipartFileWriter”继承自“SpringSingleMultipartFileWriter”,然后修改其“write()”函数。
import feign.form.multipart.Output;
import feign.form.spring.SpringSingleMultipartFileWriter;
import org.springframework.web.multipart.MultipartFile; public class FeignSpringSingleMultipartFileWriter extends SpringSingleMultipartFileWriter {
public FeignSpringSingleMultipartFileWriter() {
} @Override
protected void write(Output output, String key, Object value) throws Exception {
MultipartFile file = (MultipartFile)value; //file.getName()就是文件区分标识
this.writeFileMetadata(output, key, file.getName()+"."+file.getOriginalFilename(), file.getContentType()); output.write(file.getBytes());
}
}
声明一个“FeignSpringManyMultipartFilesWriter”类,引用“FeignSpringSingleMultipartFileWriter”类:
import feign.form.multipart.AbstractWriter;
import feign.form.multipart.Output;
import org.springframework.web.multipart.MultipartFile; import java.util.Iterator; public class FeignSpringManyMultipartFilesWriter extends AbstractWriter {
//引用“FeignSpringSingleMultipartFileWriter”
private final FeignSpringSingleMultipartFileWriter fileWriter = new FeignSpringSingleMultipartFileWriter(); public FeignSpringManyMultipartFilesWriter() {
} public void write(Output output, String boundary, String key, Object value) throws Exception {
if (value instanceof MultipartFile[]) {
MultipartFile[] files = (MultipartFile[])((MultipartFile[])value);
MultipartFile[] var6 = files;
int var7 = files.length; for(int var8 = ; var8 < var7; ++var8) {
MultipartFile file = var6[var8];
this.fileWriter.write(output, boundary, key, file);
}
} else if (value instanceof Iterable) {
Iterable iterable = (Iterable)value;
Iterator var11 = iterable.iterator(); while(var11.hasNext()) {
Object file = var11.next();
this.fileWriter.write(output, boundary, key, file);
}
} } public boolean isApplicable(Object value) {
if (value == null) {
return false;
} else if (value instanceof MultipartFile[]) {
return true;
} else {
if (value instanceof Iterable) {
Iterable iterable = (Iterable)value;
Iterator iterator = iterable.iterator();
if (iterator.hasNext() && iterator.next() instanceof MultipartFile) {
return true;
}
} return false;
}
}
}
修改上一个博客中新增的“FeignSpringFormEncoder”类,在构造函数中使用“FeignSpringManyMultipartFilesWriter”替换原来的“SpringManyMultipartFilesWriter”类。
public class FeignSpringFormEncoder extends FormEncoder {
public FeignSpringFormEncoder() {
this(new Default());
}
public FeignSpringFormEncoder(Encoder delegate) {
super(delegate);
MultipartFormContentProcessor processor = (MultipartFormContentProcessor)this.getContentProcessor(ContentType.MULTIPART);
processor.addWriter(new SpringSingleMultipartFileWriter());
//使用新的封装类“FeignSpringManyMultipartFilesWriter”
processor.addWriter(new FeignSpringManyMultipartFilesWriter());
}
至此修改完毕,微服务2可以将区分标识从文件的原始名称中解析出来使用。不知道是否还有更简单的方式满足这个需求?
spring cloud实战与思考(三) 微服务之间通过fiegn上传一组文件(下)的更多相关文章
- spring cloud实战与思考(二) 微服务之间通过fiegn上传一组文件(上)
需求场景: 微服务之间调用接口一次性上传多个文件. 上传文件的同时附带其他参数. 多个文件能有效的区分开,以便进行不同处理. Spring cloud的微服务之间接口调用使用Feign.原装的Feig ...
- 基于Spring Cloud和Netflix OSS构建微服务,Part 2
在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...
- 今天介绍一下自己的开源项目,一款以spring cloud alibaba为核心的微服务架构项目,为给企业与个人提供一个零开发基础的微服务架构。
LaoCat-Spring-Cloud-Scaffold 一款以spring cloud alibab 为核心的微服务框架,主要目标为了提升自己的相关技术,也为了给企业与个人提供一个零开发基础的微服务 ...
- Spring Cloud(1):微服务简介
架构的演进: 1.十年前:用户->单一服务器->单一数据库(支持十万级用户) 2.五年前:用户->负载均衡器->多台服务器->缓存集群->主从数据库(支持百万级用户 ...
- spring cloud 入门,看一个微服务框架的「五脏六腑」
Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 注:Spring Boot 简单理解就是简化 Spring 项目的搭建.配置.组 ...
- 基于Spring Cloud和Netflix OSS 构建微服务-Part 1
前一篇文章<微服务操作模型>中,我们定义了微服务使用的操作模型.这篇文章中,我们将开始使用Spring Cloud和Netflix OSS实现这一模型,包含核心部分:服务发现(Servic ...
- SpringCloud(10)使用Spring Cloud OAuth2和JWT保护微服务
采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...
- 在IDEA编辑器中建立Spring Cloud的子项目包(构建微服务)
本文介绍在IDEA编辑器中建立Spring Cloud的子项目包 总共分为5个包: 外层使用maven quickstart建立,子modules直接选择了springboot
- 使用Spring Cloud OAuth2和JWT保护微服务
采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...
随机推荐
- 3 Redis 的常用五大数据类型
2016-12-21 14:54:20 该系列文章链接NoSQL 数据库简介Redis的安装及及一些杂项基础知识Redis 的常用五大数据类型(key,string,hash,list,set,zse ...
- 后端开发者的Vue学习之路(五)
目录 上节内容回顾 使用第三方组件库 如何发起请求 请求错误处理 请求带参 以get的方式带参: 以post的方式带参: 封装处理 请求的配置 axios实例 实现调用自定义函数来发起请求 抽取axi ...
- Android远程桌面助手之性能监测篇
<Android下获取FPS的几种方法>一文中提到了Gamebench工具,它不仅可以获取FPS,还可以获取CPU及内存占用率等系统状态信息.其局限性也非常明显,切换应用时需要重新选择监控 ...
- Android 使用Picasso加载网络图片等比例缩放
在做android图片加载的时候,由于手机屏幕受限,很多大图加载过来的时候,我们要求等比例缩放,比如按照固定的宽度,等比例缩放高度,使得图片的尺寸比例得到相应的缩放,但图片没有变形.显然按照andro ...
- 模拟ES6中的Promise实现,让原理一目了然
简介 Promise 对象用于延迟(deferred) 计算和异步(asynchronous )计算.一个Promise对象代表着一个还未完成,但预期将来会完成的操作.Promise 对象是一个返回值 ...
- Cygwin 编译 ffmpeg
1.在官网下载linux下的压缩包 https://ffmpeg.zeranoe.com/builds/source/ffmpeg/ffmpeg-3.2.4.tar.xz 2.进入cygwin,假定将 ...
- iOS MVVM架构总结
为什么使用MVVM iOS中,我们使用的大部分都是MVC架构.虽然MVC的层次明确,但是由于功能日益的增加.代码的维护,使得更多的代码被写在了Controller中,这样Controller就显得非常 ...
- 【PAT】B1018 锤子剪刀布
抄的柳婼小姐姐的,感觉三个数求最大那里用的真棒 #include <stdio.h> int main() { int N; scanf("%d", &N); ...
- Centos7.5 部署postfix邮件系统
1. Postfix 1.1 邮件服务的介绍 电子邮件是—种用电子手段提供信息交换的通信方式,是互联网应用最广的服务.通过网络的电子邮件系统,用户可以以非常低廉的价格(不管发送到哪里,都只需负担网费) ...
- 简单理解Java的反射
反射(reflect): JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功 ...