写点什么

Docker 下 Java 文件上传服务三部曲之二:服务端开发

作者:程序员欣宸
  • 2022 年 5 月 20 日
  • 本文字数:4937 字

    阅读完需:约 16 分钟

Docker下Java文件上传服务三部曲之二:服务端开发

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


  • 《Docker 下 Java 文件上传服务三部曲》的主要内容是 Java 的文件上传服务实战,由三篇文章组成,内容分别如下:


  1. 准备工作(即本章),包括上传文件的客户端开发、创建 Tomcat 容器(支持在线部署),安装 wireshark;

  2. 服务端编码,创建三个应用,实战 SpringMVC、Apache fileupload 库,SpringBoot 三种场景下的文件上传服务;

  3. wireshark 抓包,分析文件上传服务过程中的传输详情;

实战环境

  • 整个环境由两台电脑组成,操作系统分别是 win10 和 ubuntu16,如下图:


  • 如上图,在 win10 电脑上运行一个 java 类,发起 POST 请求将文件提交到 ubuntu 电脑上的 Docker 容器中,该容器运行着上传文件的 web 服务,在 win10 电脑上安装有 wireshark,用来分析这个上传文件的 POST 请求;


注:客户端和服务端部署在不同的机器上,这样方便 wireshark 抓包,您也可以用 vmware 在 win10 上装一个 ubuntu 虚拟机,不过此时 wireshark 抓包前请注意选择正确的网卡(vmware 虚拟出的那个);


  • 开发环境的具体信息如下:

  1. 操作系统:win10,ubuntu16;

  2. JDK:1.8.0_151;

  3. maven:3.3.3;

  4. Docker 版本:17.03.2-ce;

  5. wireshark 版本:2.4.4;

源码下载

  • 上传文件的客户端源码,您可以在 GitHub 下载,地址和链接信息如下表所示:


  • 这个 git 项目中有多个目录,本次所需的资源放在 uploadfileclient,如下图红框所示:


本章内容列举

  • 本章的工作是为后面章节的文件服务的运行和验证做准备的,包含以下步骤:


  1. 在 win10 电脑上,安装 wireshark;

  2. 在 win10 电脑上,创建 maven 工程 uploadfileclient,里面有一个 java 类 UploadFileClient,后续所有上传文件的请求都是这个类的 main 方法完成的;

  3. 我们要验证 UploadFileClient.java 能不能正常工作(上传文件全靠它了),所以在 ubuntu 电脑上创建一个文件服务的 docker 容器,用于接收 UploadFileClient 类上传的文件;

  4. 在 win10 电脑上,运行 UploadFileClient.java 的 main 方法,看能否把文件上传到步骤 4 中搭建的文件服务器上;

  5. 下一章的文件服务应用会做成 war 包运行在 Tomcat 上,所以我们要在 Docker 下创建一个 Tomcat 容器,并且该容器支持在线部署 war 包;

安装 wireshark

  • 请在官网下载 wireshark 安装文件,地址:https://www.wireshark.org/#download

在 ubuntu 电脑上,创建一个文件服务的 Docker 容器

  • 在装好了 docker 的 ubuntu 电脑上运行以下命令,可以启动一个文件服务的容器:


docker run --name fileserver001 -p 8080:8080 -v /usr/local/work/fileupload/upload:/usr/Downloads -idt  bolingcavalry/springbootfileserver:0.0.1-SNAPSHOT
复制代码


  • 启动后,容器的/usr/Downloads 目录被映射到了 ubuntu 电脑的/usr/local/work/fileupload/upload 目录(此目录要确保存在),这样上传的文件就能通过这个目录导出到 ubuntu 电脑上,便于我们验证文件是否完好无损;


注:有关该容器的镜像的会在下一章详细说明,本章我们就直接拿来用吧,作为上传文件的服务端;


上传文件的客户端开发

  • 在 win10 电脑上创建一个 maven 工程,pom.xml 如下:


<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId> <artifactId>uploadfileclient</artifactId> <version>1.0-SNAPSHOT</version>
<!-- 指明编译源代码时使用的字符编码,maven编译的时候默认使用的GBK编码, 通过project.build.sourceEncoding属性设置字符编码,告诉maven这个项目使用UTF-8来编译 --> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
<dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.5</version> </dependency>
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.3.5</version> </dependency> </dependencies>
</project>
复制代码


  • 该工程只依赖了两个库:httpclient 和 httpmime;

  • 创建一个 java 类用来发起上传文件的请求,源码如下:


package com.bolingcavalry;
import org.apache.http.HttpEntity;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.ContentType;import org.apache.http.entity.mime.MultipartEntityBuilder;import org.apache.http.entity.mime.content.FileBody;import org.apache.http.entity.mime.content.StringBody;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.util.EntityUtils;
import java.io.File;import java.io.IOException;
/** * @Description : 上传文件的类,将本地文件POST到server * @Author : zq2599@gmail.com * @Date : 2018-02-24 18:12 */public class UploadFileClient {
/** * 文件服务的ULR */ private static final String POST_URL = "http://www.bolingcavalry.com:8088/springmvcfileserver/upload";
/** * 要上传的本地文件的完整路径加文件名 */ private static final String UPLOAD_FILE_FULLPATH = "D:\\temp\\201802\\21\\abc.zip";
public static void main(String[] args) throws Exception{ System.out.println("start upload"); CloseableHttpClient httpclient = HttpClients.createDefault(); try { HttpPost httppost = new HttpPost(POST_URL);
//基本的配置信息 RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000).build();
httppost.setConfig(requestConfig);
//要上传的文件 FileBody bin = new FileBody(new File(UPLOAD_FILE_FULLPATH));
//在POST中添加一个字符串请求参数 StringBody comment = new StringBody("This is comment", ContentType.TEXT_PLAIN);
HttpEntity reqEntity = MultipartEntityBuilder.create().addPart("file", bin).addPart("comment", comment).build();
httppost.setEntity(reqEntity);
System.out.println("executing request " + httppost.getRequestLine());
//发起POST CloseableHttpResponse response = httpclient.execute(httppost);
try {
HttpEntity resEntity = response.getEntity(); if (resEntity != null) { String responseEntityStr = EntityUtils.toString(response.getEntity()); System.out.println("response status : " + response.getStatusLine()); System.out.println("response content length: " + resEntity.getContentLength()); System.out.println("response entity str : " + responseEntityStr); } EntityUtils.consume(resEntity); } finally { response.close(); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } }
System.out.println("end upload"); }}
复制代码


  • 上面的代码,有以下三点需要注意:


  1. 利用 httpclient 的 API 可以发起 POST 请求,提交的二进制文件用 FileBody 对象处理,字符串用 StringBody 对象处理;

  2. 我的 ubuntu 电脑 IP 地址是 192.168.119.155,所以 POST_URL 的值是:http://192.168.119.155:8080/upload,请将此改为您的 ubuntu 电脑的 IP 地址;

  3. UPLOAD_FILE_FULLPATH 的值是要上传的文件在 win10 电脑上的路径;

验证 UploadFileClient 类上传文件的功能

  • 在 pom.xml 所在目录执行以下命令,即可编译并运行 UploadFileClient 类的 main 方法:


mvn clean compile -U exec:java -Dexec.mainClass="com.bolingcavalry.UploadFileClient"
复制代码


  • 上述命令执行时,会输出类似以下的信息:


[INFO][INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ uploadfileclient ---start uploadexecuting request POST http://192.168.119.155:8080/upload HTTP/1.1response status : HTTP/1.1 200response content length: 40response entity str : SpringBoot环境下,上传文件成功end upload[INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: 10.226 s[INFO] Finished at: 2018-02-25T00:00:13+08:00[INFO] Final Memory: 20M/181M[INFO] ------------------------------------------------------------------------
复制代码


**“SpringBoot 环境下,上传文件成功"**这一句是服务端接收文件成功后返回的信息;

在服务端验证上传成功

  • 在 ubuntu 电脑执行 docker logs fileserver001,能看到容器的日志,如下:


2018-02-24 16:00:13.077  INFO 1 --- [nio-8080-exec-5] c.b.s.controller.UploadController        : start upload, comment [This is comment]2018-02-24 16:00:13.079  INFO 1 --- [nio-8080-exec-5] c.b.s.controller.UploadController        : base save path [/tmp/tomcat-docbase.8533878395220260315.8080/WEB-INF/upload], original file name [abc.zip]2018-02-24 16:00:13.080  INFO 1 --- [nio-8080-exec-5] c.b.s.controller.UploadController        : real save path [/tmp/tomcat-docbase.8533878395220260315.8080/WEB-INF/upload/15/1], real file name [fba8a275-cfc0-4471-b4f7-21d2913450cb_abc.zip]2018-02-24 16:00:13.080  INFO 1 --- [nio-8080-exec-5] c.b.s.controller.UploadController        : save file success [/tmp/tomcat-docbase.8533878395220260315.8080/WEB-INF/upload/15/1/fba8a275-cfc0-4471-b4f7-21d2913450cb_abc.zip]
复制代码


  • 如上所示,上传的文件存放在文件夹:/tmp/tomcat-docbase.8533878395220260315.8080/WEB-INF/upload/15/1/

  • 执行命令 docker exec -it fileserver001 /bin/bash 进入容器,再将上述文件夹内的文件复制到/usr/Downloads 目录下,此文件就从 docker 容器被导出到 ubuntu 的/usr/local/work/fileupload/upload 目录下了,方便您验证该文件与上传的是否一致;

创建支持在线部署的 Tomcat 容器

  • 在 ubuntu 电脑上,执行以下命令即可创建 Tomcat 容器,并且该容器支持在线部署 war 包:


docker run --name tomcat006 -p 8088:8080 -v /usr/local/work/fileupload/upload:/usr/Downloads -idt  bolingcavalry/online_deploy_tomcat:0.0.1
复制代码


  • 这样文件服务的 maven 工程就可以直接在线部署到这个 tomcat 上去了,关于 Tomcat 在线部署的详情,请参照《实战 docker,编写 Dockerfile 定制 tomcat 镜像,实现 web 应用在线部署》

  • 至此,前期的准备工作已经完成,接下来的章节我们一起来开发和部署文件服务的 web 应用吧;

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

发布于: 2022 年 05 月 20 日阅读数: 17
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
Docker下Java文件上传服务三部曲之二:服务端开发_Java_程序员欣宸_InfoQ写作社区