资讯专栏INFORMATION COLUMN

SpringBoot整合Jersey2.x实现文件上传API

andot / 587人阅读

摘要:的官方文档中将调用的入口称作,而在的示例代码中将其命名为,其实指的是同一个东西。其次是类至此,一个文件上传的服务端接口已经编写完成。

前言

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文件配置如下:



    4.0.0
    org.demo
    demo-app
    0.0.1-SNAPSHOT
    jar
    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.10.RELEASE
         
    

    
        UTF-8
        UTF-8
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-jersey
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

项目创建完成后,需要添加一个jersey-media-multipart的依赖,在pom中dependencies标签中添加:


    org.glassfish.jersey.media
    jersey-media-multipart

这个依赖不需要版本号,因为在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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68428.html

相关文章

  • SpringBoot 整合 阿里云OSS 存储服务,快来免费搭建一个自己的图床

    摘要:笔主很早就开始用阿里云存储服务当做自己的图床了。阿里云对象存储文档,本篇文章会介绍到整合阿里云存储服务实现文件上传下载以及简单的查看。 Github 地址:https://github.com/Snailclimb/springboot-integration-examples(SpringBoot和其他常用技术的整合,可能是你遇到的讲解最详细的学习案例,力争新手也能看懂并且能够在看完...

    邹强 评论0 收藏0
  • 两年了,我写了这些干货!

    摘要:开公众号差不多两年了,有不少原创教程,当原创越来越多时,大家搜索起来就很不方便,因此做了一个索引帮助大家快速找到需要的文章系列处理登录请求前后端分离一使用完美处理权限问题前后端分离二使用完美处理权限问题前后端分离三中密码加盐与中异常统一处理 开公众号差不多两年了,有不少原创教程,当原创越来越多时,大家搜索起来就很不方便,因此做了一个索引帮助大家快速找到需要的文章! Spring Boo...

    huayeluoliuhen 评论0 收藏0
  • moquette改造笔记(一):整合SpringBoot

    摘要:整合到本文更加注重代码实践,对于配置相关的知识会一笔带过,不做过多的详解。笔者是上传到私服,然后通过导入。接口是预留给开发者根据不同事件处理业务逻辑的接口。改造笔记二优化逻辑 Moquette简介 Mqtt作为物联网比较流行的协议现在已经被大范围使用,其中也有很多开源的MQTT BROKEN。Moquette是用java基于netty实现的轻量级的MQTT BROKEN. Moquet...

    young.li 评论0 收藏0
  • Java3y文章目录导航

    摘要:前言由于写的文章已经是有点多了,为了自己和大家的检索方便,于是我就做了这么一个博客导航。 前言 由于写的文章已经是有点多了,为了自己和大家的检索方便,于是我就做了这么一个博客导航。 由于更新比较频繁,因此隔一段时间才会更新目录导航哦~想要获取最新原创的技术文章欢迎关注我的公众号:Java3y Java3y文章目录导航 Java基础 泛型就这么简单 注解就这么简单 Druid数据库连接池...

    KevinYan 评论0 收藏0

发表评论

0条评论

andot

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<