需求场景:

  用户调用微服务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. 使用 Lombok 优雅编码

    一.介绍和使用 Lombok 是一个 java 库,能以简单的注解形式来简化 java 代码,提高开发人员的开发效率. 常见使用在开发过程中需要写的 javabean,往往开发需要花时间去添加相应的 ...

  2. USSD 杂记

    Android Oreo允许应用程序读取来自运营商的USSD消息. 利用emoney执行话费充值,需要执行USSD代码,尝试编写apk执行ussd代码进行充值. 尝试在Android8的系统上进行US ...

  3. Dvna for Owasp top 10 2017

    简介: DVNA(Damn Vulnerable Node Application),它是一款由Node.js打造的知名WEB漏洞测试平台,或许有些朋友已经使用过.它是用来给使用Node的WEB开发人 ...

  4. ArcGIS 网络分析[3] 发布NAServer到ArcGIS for Server(以Server 10.4为例)

    前阵子对ArcGIS API For JavaScript的网络分析有兴趣,但是不知道其数据是如何获取的. 查阅API知道,AJS的网络分析只有三个功能:最短路径(RouteTask).最近设施点(C ...

  5. Android开发中如何使用RecyclerView

    介绍 在Android应用程序中,只要您想显示数据列表,就可以使用 RecyclerView . 早期的Android提供 ListView 了同样的东西. RecyclerView 可以被认为是一个 ...

  6. 解决vs启动出现“cannot find one or more components .Please reinstall the application”

    参考下文: https://blog.csdn.net/novice_growth/article/details/71627395

  7. Bootstrap -- 按钮样式与使用

    Bootstrap -- 按钮样式与使用 1. 可用于<a>, <button>, 或 <input> 元素的按钮样式 按钮样式使用: <!DOCTYPE h ...

  8. Redis操作集合,有序集合

    Set操作,Set集合就是不允许重复的列表 sadd(name,values) 1 # name对应的集合中添加元素 scard(name) 1 获取name对应的集合中元素个数 sdiff(keys ...

  9. (十一)Updating Documents

    In addition to being able to index and replace documents, we can also update documents. Note though ...

  10. 理解OSI参考模型(转)

    文章转自 https://www.cnblogs.com/evablogs/p/6709707.html 一个视频网站上不小心搜到网络知识的视频,突然以前大学的没有真正接受的知识点,一下子豁然开朗,赶 ...