需求场景:

  用户调用微服务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上传一组文件(下)的更多相关文章

  1. spring cloud实战与思考(二) 微服务之间通过fiegn上传一组文件(上)

    需求场景: 微服务之间调用接口一次性上传多个文件. 上传文件的同时附带其他参数. 多个文件能有效的区分开,以便进行不同处理. Spring cloud的微服务之间接口调用使用Feign.原装的Feig ...

  2. 基于Spring Cloud和Netflix OSS构建微服务,Part 2

    在上一篇文章中,我们已使用Spring Cloud和Netflix OSS中的核心组件,如Eureka.Ribbon和Zuul,部分实现了操作模型(operations model),允许单独部署的微 ...

  3. 今天介绍一下自己的开源项目,一款以spring cloud alibaba为核心的微服务架构项目,为给企业与个人提供一个零开发基础的微服务架构。

    LaoCat-Spring-Cloud-Scaffold 一款以spring cloud alibab 为核心的微服务框架,主要目标为了提升自己的相关技术,也为了给企业与个人提供一个零开发基础的微服务 ...

  4. Spring Cloud(1):微服务简介

    架构的演进: 1.十年前:用户->单一服务器->单一数据库(支持十万级用户) 2.五年前:用户->负载均衡器->多台服务器->缓存集群->主从数据库(支持百万级用户 ...

  5. spring cloud 入门,看一个微服务框架的「五脏六腑」

    Spring Cloud 是一个基于 Spring Boot 实现的微服务框架,它包含了实现微服务架构所需的各种组件. 注:Spring Boot 简单理解就是简化 Spring 项目的搭建.配置.组 ...

  6. 基于Spring Cloud和Netflix OSS 构建微服务-Part 1

    前一篇文章<微服务操作模型>中,我们定义了微服务使用的操作模型.这篇文章中,我们将开始使用Spring Cloud和Netflix OSS实现这一模型,包含核心部分:服务发现(Servic ...

  7. SpringCloud(10)使用Spring Cloud OAuth2和JWT保护微服务

    采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...

  8. 在IDEA编辑器中建立Spring Cloud的子项目包(构建微服务)

    本文介绍在IDEA编辑器中建立Spring Cloud的子项目包 总共分为5个包: 外层使用maven quickstart建立,子modules直接选择了springboot

  9. 使用Spring Cloud OAuth2和JWT保护微服务

    采用Spring Security AOuth2 和 JWT 的方式,避免每次请求都需要远程调度 Uaa 服务.采用Spring Security OAuth2 和 JWT 的方式,Uaa 服务只验证 ...

随机推荐

  1. 2018.12/17 function 的闭包

    1.闭包:函数在调用的时候会形成一个私有的作用域,对内部变量起到保护的作用,这就是闭包. 2.变量销毁: 1.人为销毁  var a=12; a=null 2.自然销毁  函数调用完成之后 浏览器会自 ...

  2. 一文搞懂TCP与UDP的区别

    摘要:计算机网络基础 引言 网络协议是每个前端工程师都必须要掌握的知识,TCP/IP 中有两个具有代表性的传输层协议,分别是 TCP 和 UDP,本文将介绍下这两者以及它们之间的区别. 一.TCP/I ...

  3. ArcGIS API for JavaScript:Layer之间那点儿事

    先来看一个模型: |–TiledMapServiceLayer  |       |–ArcGISTiledMapServiceLayer  |–DynamicLayer  |       |–Dyn ...

  4. 查看系统cpu性能top和多核cpu使用性能

    1.使用top查看系统当前负载情况. 在显示过程 按P会按照cpu使用率排序,按M会按照内存占用率排序. 2.多核CPU上,每个核的使用率,使用 mpstat mpstat -P ALL 1 10 - ...

  5. (简单)华为荣耀4A SCL-TL00的usb调试模式在哪里打开的方法

    就在我们使用PC通过数据线连接上安卓手机的时候,如果手机没有开启Usb调试模式,PC则没办法成功检测到我们的手机,有时候,我们使用的一些功能强大的App好比之前我们使用的一个App引号精灵,老版本就需 ...

  6. Git:五、操作远程仓库

    0.一般流程 1)自己新写:GitHub创建有README的库 -> clone到本地 2)修改已有:GitHub上fork别人的仓库 -> clone自己账号下的库到本地 1.创建库 右 ...

  7. javaweb学习--jsp

    阅读电子书<Java Web从入门到精通>密码:461c,学习JavaWeb基础知识.由于本人已有html基础,所以直接略过前面部分,进入jsp学习 jsp页面添加库引用,引入项目文件 引 ...

  8. jQuery如何制作动画

    下面为一组图片(四张)展示 1 2 3 4 页面代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN& ...

  9. PHP程序污点型漏洞静态检测方法

    这篇文献,作者针对基于PHP语言开发的web应用程序产生的污点型漏洞,提出了一种静态代码分析检测的方法.       先解释一下什么叫污点型漏洞,由于对于用户的输入没有进行有效的过滤,使其进入敏感函数 ...

  10. Postman安装与使用

    Postman一款非常流行的API调试工具.其实,开发人员用的更多.因为测试人员做接口测试会有更多选择,例如Jmeter.soapUI等.不过,对于开发过程中去调试接口,Postman确实足够的简单方 ...