需求场景:

  用户调用微服务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. Spring Cloud Alibaba Nacos 入门

    概览 阿里巴巴在2018年7月份发布Nacos, Nacos是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台.并表示在6-8个月完成到生产可用的0.8版本,目前版本是0.9版本. Na ...

  2. ES10特性详解

    摘要: 最新的JS特性. ES10 还只是一个草案.但是除了 Object.fromEntries 之外,Chrome 的大多数功能都已经实现了,为什么不早点开始探索呢?当所有浏览器都开始支持它时,你 ...

  3. Dynamics 365新特性介绍:在视图中显示图片和提示

    关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复242或者20161230可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...

  4. 控制台程序(C#)不弹出认证窗口连接到Dynamics CRM Online的Web API

    摘要: 本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复271或者20180602可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyon ...

  5. Odoo POS会员积分当钱用如何设置?

    问题提问 设定积分规则1元积1分.而后每1积分可以当1分钱用,POS中能处理吗? 解决方案 1) 设定服务类型产品“积分”,其单价为0.01,收入科目为“销售费用” 2) 设定积分计划:积分规则是,订 ...

  6. vue父子组件之间传值

    vue父子组件进行传值 vue中的父子组件,什么是父组件什么是子组件呢?就跟html标签一样,谁包裹着谁谁就是父组件,被包裹的元素就是子组件. 父组件向子组件传值 下面用的script引入的方式,那种 ...

  7. CAP理论和Base理论

    CAP理论 Consistency(一致性), 数据一致更新,所有数据变动都是同步的 Availability(可用性), 好的响应性能 Partition tolerance(分区容错性) 可靠性, ...

  8. XPath Helper的安装与使用

    摘要 : XPath Helper可以支持在网页点击元素生成xpath,整个抓取使用了xpath.正则表达式.消息中间件.多线程调度框架的chrome插件. xpath:是一门XML和HTML文档中查 ...

  9. 【PAT】B1016 部分A+B

    水题 以字符和字符串形式储存输入,比较,计算出两个个数的D的个数,用for循环拼成P,相加得出结果 #include<stdio.h> int main(){ char A[20],DA, ...

  10. SQL NOT NULL 约束

    SQL NOT NULL 约束 NOT NULL 约束强制列不接受 NULL 值. NOT NULL 约束强制字段始终包含值.这意味着,如果不向字段添加值,就无法插入新记录或者更新记录. 下面的 SQ ...