SpringBoot整合Jersey2.x实现文件上传API
前言
SpringBoot的官方文档中关于Jersey的介绍并不是很全面: 27.3 JAX-RS and Jersey,SpringBoot-Sample项目里面也只有非常基础的代码,对于一些复杂的常用需求,这个文档给不了任何帮助。
为了使用Jersey提供的Restful API完成文件上传功能,今天我花了不少时间查阅文档资料,遇到了一些问题,然后不断地踩坑尝试,其中一些坑还是参照Stack Overflow的解决方案,甚至是框架官方文档的说明而碰到的。主要问题就是,SpringBoot和Jersey的官方文档没有给出更详细的内容,Stack Overflow针对的问题很片面,不能适用于所有的情况,所以我打算将搭建项目的过程从头到尾写下来,以便有一个方便参照的教程。
项目搭建
我使用了Spring发布的Spring Tool Suit(STS)来创建项目,因为这个IDE使用SpringBoot十分方便,可以在创建项目时引入一些技术栈。
我使用的Java版本是JDK 8,后面会用到CURL这个命令行工具来测试相关的接口,大家可以先准备好,以便学习过程连贯。
这个项目命名为demo-app
,默认包为org.demo
,我在创建时仅添加了Jersey的支持,SpringBoot版本是1.5.10。
如果没有STS,也可以用Eclipse创建一个Maven项目,Pom文件配置如下:
<?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>org.demo</groupId><artifactId>demo-app</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>1.5.10.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jersey</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
项目创建完成后,需要添加一个jersey-media-multipart
的依赖,在pom中dependencies
标签中添加:
<dependency><groupId>org.glassfish.jersey.media</groupId><artifactId>jersey-media-multipart</artifactId>
</dependency>
这个依赖不需要版本号,因为在spring-boot-starter-parent
中已经定义了版本,我们只需要添加一个dependency在具体项目中即可。
编写代码
项目创建好时,已经存在一个带有main方法的入口类DemoAppApplication
,我们不需要改动它。
Jersey的官方文档中将Restful API调用的入口称作Resources
,而在SpringBoot的示例代码中将其命名为Endpoint
,其实指的是同一个东西。因为使用了SpringBoot,为了风格统一我使用了Endpoint
的命名规则,这不是强制的,大家也可以自定义命名规则。但建议从这两者中选择一种,以便大家方便理解。
首先增加一个HelloEndpoint
类:
package org.demo;import java.io.IOException;
import java.io.InputStream;import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.springframework.stereotype.Component;@Component
@Path("/file")
public class FileUploadEndpoint {@POST@Consumes(MediaType.MULTIPART_FORM_DATA)public String upload(@FormDataParam("file") InputStream fis,@FormDataParam("file") FormDataContentDisposition fileDisposition) {ByteArrayOutputStream baos = new ByteArrayOutputStream();try {IOUtils.copy(fis, baos);String content = new String(baos.toByteArray());return content;} catch (IOException e) {e.printStackTrace();}return null;}
}
它十分类似于SpringMVC的Controller
,但是拥有更规范更严格的REST风格,而且它不能像SpringMVC一样通过返回一个视图名称指向某个视图。
其次是JerseyConfig
类:
package org.demo;import javax.ws.rs.ApplicationPath;import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;@Component
@ApplicationPath("/rest/demo")
public class JerseyConfig extends ResourceConfig {public JerseyConfig() {register(MultiPartFeature.class);register(FileUploadEndpoint.class);}}
至此,一个文件上传的服务端接口已经编写完成。关于表单页面这里不多做说明,因为这个项目不是一个Web项目,而是Web Service的服务端,不能在项目中直接访问静态Web资源。也不建议使用特殊方法满足这种需要,我们应当保持项目的纯净。
需要注意@ApplicationPath
这个注解,它决定了所有Endpoint
的基础路径。
运行测试
下面我们来测试一下这个Restful API是否能正常工作,运行DemoAppApplication
,等待项目部署。
接下来准备使用CURL测试,CURL可以到官网下载操作系统对应的版本。创建一个demo.txt
文件保存到任意目录,文件内容写入Test my restful api with curl.
,使用英文是为了避免CMD命令行中的中文出现乱码的情况,这里不用过多在意,我们只要关注结果。
进入demo.txt
文件所在的目录,按住Shift
打开CMD或者PowerShell(Linux系统下打开终端定位到该目录),执行:curl -X POST -F "file=@demo.txt" http://localhost:8080/rest/demo/file
如果得到Test my restful api with curl.
的回显,说明Restful API部署成功,并且能够接收上传的文件。
注意问题
在实现利用Jersey完成文件上传的过程中,我遇到的一些问题需要大家特别关注:
- SpringBoot没有默认添加
jersey-media-multipart
依赖,仅预先定义了需要的版本,如果未引入这个包,将无法使用@FormDataParam
注解和Multipart相关的类,无法对Multipart内容进行解析; JerseyConfig
中需要注册MultiPartFeature.class
,否则会出现报错,无法正确注入文件输入流对象。报错的时机根据是否延迟加载决定,如果application.properties定义了spring.jersey.servlet.load-on-startup=1
,会在项目启动时报错;否则会在首次上传文件,初始化FileUploadEndpoint
时报错。- 关于
FileUploadEndpoint.upload()
方法,有些文档和教程中,fileDisposition
对象使用了ContentDisposition
类来定义,尽管它是FormDataContentDisposition
的父类,但仍然会报错,原因未知。建议直接使用FormDataContentDisposition
SpringBoot整合Jersey2.x实现文件上传API相关推荐
- SpringBoot整合阿里云OSS文件上传、下载、查看、删除
SpringBoot整合阿里云OSS文件上传.下载.查看.删除 该项目源码地址:https://github.com/ggb2312/springboot-integration-examples ( ...
- MinIO入门-02 SpringBoot 整合MinIO并实现文件上传
SpringBoot 整合MinIO并实现文件上传 1.依赖 <!-- https://mvnrepository.com/artifact/io.minio/minio --> < ...
- springboot整合minio,实现文件上传与下载,且支持链接永久访问
1.minio部署 1.1 拉取镜像 docker pull minio/minio 1.2 创建数据目录 mkdir -p /home/guanz/minio mkdir -p /home/guan ...
- SpringBoot(24) 整合七牛云实现文件上传
一.前言 本文将基于springboot2.1.8.RELEASE整合七牛云实现文件上传 本文参考 https://www.keppel.fun/articles/2019/02/27/1551262 ...
- SpringBoot整合FFmpeg进行视频分片上传(Linux)
SpringBoot整合FFmpeg进行视频分片上传 分片上传的核心思路: 分片上传到意义: 分片上传的原理: 准备工作: 一:下载.解压 代码展示: pom文件 yml配置 工具类 controll ...
- 腾讯云cos对象存储服务文件上传api就是一个大坑
一.介绍 对象存储服务(Cloud Object Service)是基于腾讯多年海量服务经验,对外提供的可靠.安全.易用的海量存储服务.提供多样化接入方式,以及全国部署的上传加速集群,可以无缝衔接CD ...
- spring boot 整合web开发之文件上传、静态资源访问、异常处理、返回JSON数据
目录 springboot 整合web开发 返回json数据 静态资源访问 文件上传 全局异常 1.返回json数据 springboot默认的是jackson-databind做为json处理器.也 ...
- SpringMVC整合fastdfs-client-java实现web文件上传下载
为什么80%的码农都做不了架构师?>>> 版权声明:本文为博主原创文章,转载请标明出处(http://blog.csdn.net/wlwlwlwl015)Thanks. 目录( ...
- SpringBoot集成FastDFS依赖实现文件上传
前言 对FastDFS文件系统安装后的使用. FastDFS的安装请参考这篇:https://www.cnblogs.com/niceyoo/p/13511082.html 本文环境:IDEA + J ...
最新文章
- android 文件名 标题,有什么方法可以让Android的默认浏览器识别Content-Disposition:attachment下载中的非ASCII文件名?...
- MongoDB删除数据
- Keras蚂蚁金服大赛实战——自然语言处理技术
- 用记事本打造简易计算器
- Python安装时import matplotlib.pyplot as plt报错
- Android获取手机型号
- Spring系列缓存注解@Cacheable @CacheEvit @CachePut 使用姿势介绍
- TE(泰科)什么是超频?如何实现CPU超频?CPU超频无法进入系统怎么办?
- PyTorch grad 与 Optimizer(params) 区别
- Onenote实用笔记
- vue项目 添加全局水印或某个指定页面水印 源码
- 怎么样配置阿里云的CDN-可以加速网站访问速度
- 计算机专业用什么轴的键盘,机械键盘什么轴好
- 交互设计师必须知道的五大交互设计流程
- 电路版设计的先期工作
- 【MD5】快速实现MD5加密解密(盐值)
- 晾衣服,西北大学集训队选拔赛(重现赛)
- 西门子界面精美触摸屏+WINCC程序模板 西门子触摸屏程序模板
- Flutter中的Scaffold
- 在Adobe Illustrator中创建漂亮的冬季场景
热门文章
- vscode安装旧版本插件_2020 我在使用VScode时安装的插件(针对前端开花推荐)
- java 枚举放那个包,java枚举,包装类,math使用
- 攻击需要成本吗_石子厂成本大概多少?开一个石子厂都需要哪些设备,价格高吗 ?...
- 我的计算机用户账户logo,UserAccountControl
- c语言制作贪吃小白入门,小白入门——easyx界面版“贪吃蛇”的C语言实现(详细)...
- 单选不生效为什么_“我这么努力刷题,为什么还是考不过税务师?”
- 项目入口_住宅小区入口就该这么设计,说得好仔细!
- VB 两种方法实现热键
- Win2003 R2 with SP2的MSDN版所有版本http下载,已收集全
- AI版“大家来找茬”上线,究竟谁是真人,谁是GAN生成的假脸?