前言

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相关推荐

  1. SpringBoot整合阿里云OSS文件上传、下载、查看、删除

    SpringBoot整合阿里云OSS文件上传.下载.查看.删除 该项目源码地址:https://github.com/ggb2312/springboot-integration-examples ( ...

  2. MinIO入门-02 SpringBoot 整合MinIO并实现文件上传

    SpringBoot 整合MinIO并实现文件上传 1.依赖 <!-- https://mvnrepository.com/artifact/io.minio/minio --> < ...

  3. springboot整合minio,实现文件上传与下载,且支持链接永久访问

    1.minio部署 1.1 拉取镜像 docker pull minio/minio 1.2 创建数据目录 mkdir -p /home/guanz/minio mkdir -p /home/guan ...

  4. SpringBoot(24) 整合七牛云实现文件上传

    一.前言 本文将基于springboot2.1.8.RELEASE整合七牛云实现文件上传 本文参考 https://www.keppel.fun/articles/2019/02/27/1551262 ...

  5. SpringBoot整合FFmpeg进行视频分片上传(Linux)

    SpringBoot整合FFmpeg进行视频分片上传 分片上传的核心思路: 分片上传到意义: 分片上传的原理: 准备工作: 一:下载.解压 代码展示: pom文件 yml配置 工具类 controll ...

  6. 腾讯云cos对象存储服务文件上传api就是一个大坑

    一.介绍 对象存储服务(Cloud Object Service)是基于腾讯多年海量服务经验,对外提供的可靠.安全.易用的海量存储服务.提供多样化接入方式,以及全国部署的上传加速集群,可以无缝衔接CD ...

  7. spring boot 整合web开发之文件上传、静态资源访问、异常处理、返回JSON数据

    目录 springboot 整合web开发 返回json数据 静态资源访问 文件上传 全局异常 1.返回json数据 springboot默认的是jackson-databind做为json处理器.也 ...

  8. SpringMVC整合fastdfs-client-java实现web文件上传下载

    为什么80%的码农都做不了架构师?>>>    版权声明:本文为博主原创文章,转载请标明出处(http://blog.csdn.net/wlwlwlwl015)Thanks. 目录( ...

  9. SpringBoot集成FastDFS依赖实现文件上传

    前言 对FastDFS文件系统安装后的使用. FastDFS的安装请参考这篇:https://www.cnblogs.com/niceyoo/p/13511082.html 本文环境:IDEA + J ...

最新文章

  1. android 文件名 标题,有什么方法可以让Android的默认浏览器识别Content-Disposition:attachment下载中的非ASCII文件名?...
  2. MongoDB删除数据
  3. Keras蚂蚁金服大赛实战——自然语言处理技术
  4. 用记事本打造简易计算器
  5. Python安装时import matplotlib.pyplot as plt报错
  6. Android获取手机型号
  7. Spring系列缓存注解@Cacheable @CacheEvit @CachePut 使用姿势介绍
  8. TE(泰科)什么是超频?如何实现CPU超频?CPU超频无法进入系统怎么办?
  9. PyTorch grad 与 Optimizer(params) 区别
  10. Onenote实用笔记
  11. vue项目 添加全局水印或某个指定页面水印 源码
  12. 怎么样配置阿里云的CDN-可以加速网站访问速度
  13. 计算机专业用什么轴的键盘,机械键盘什么轴好
  14. 交互设计师必须知道的五大交互设计流程
  15. 电路版设计的先期工作
  16. 【MD5】快速实现MD5加密解密(盐值)
  17. 晾衣服,西北大学集训队选拔赛(重现赛)
  18. 西门子界面精美触摸屏+WINCC程序模板 西门子触摸屏程序模板
  19. Flutter中的Scaffold
  20. 在Adobe Illustrator中创建漂亮的冬季场景

热门文章

  1. vscode安装旧版本插件_2020 我在使用VScode时安装的插件(针对前端开花推荐)
  2. java 枚举放那个包,java枚举,包装类,math使用
  3. 攻击需要成本吗_石子厂成本大概多少?开一个石子厂都需要哪些设备,价格高吗 ?...
  4. 我的计算机用户账户logo,UserAccountControl
  5. c语言制作贪吃小白入门,小白入门——easyx界面版“贪吃蛇”的C语言实现(详细)...
  6. 单选不生效为什么_“我这么努力刷题,为什么还是考不过税务师?”
  7. 项目入口_住宅小区入口就该这么设计,说得好仔细!
  8. VB 两种方法实现热键
  9. Win2003 R2 with SP2的MSDN版所有版本http下载,已收集全
  10. AI版“大家来找茬”上线,究竟谁是真人,谁是GAN生成的假脸?