当前位置: 首页 > news >正文

SpringBoot系列之基于Jersey实现文件上传API

前言

  • JAX-RS:JAX-RS是可以用可以用于实现RESTFul应用程序的JAVA API,给开发者提供了一系列的RESTFul注解
  • Jersey:是基于JAX-RX API的实现框架,用于实现RESTful Web 服务的开源框架。

JAX-RX常用的注解:

@javax.ws.rs.Path // 请求的资源类或资源方法的uri路径
@javax.ws.rs.GET //表示此方法响应HTTP GET请求。
@javax.ws.rs.POST // 表示此方法响应HTTP POST请求。
@javax.ws.rs.PUT // 通常用来更新数据,PUT操作
@javax.ws.rs.DELETE // 通常用来删除数据。
@javax.ws.rs.Produces //设置Http返回报文,报文体的内容类型
@javax.ws.rs.Consumes //客户端请求的MIME媒体类型
@javax.ws.rs.QueryParam // 一般是GET请求的参数,相当于SpringMVC框架的@RequestParam
@javax.ws.rs.FormParam // 媒体类型为”application/x-www-form-urlencoded” 的参数
@javax.ws.rs.PathParam // uri中指定的路径参数绑定到资源方法参数

开发环境

  • SpringBoot2.2.1.RELEASE
  • Jersey2.x
  • JDK1.8
  • Maven 3.2+

搭建一个SpringBoot项目

在IDEA里new一个project,这里使用Spring Initializer快速创建一个SpringBoot项目,Server url可以使用Spring官网的,也可以使用阿里的,然后点击Next
在这里插入图片描述

选择jdk版本,还有使用maven做jar管理
在这里插入图片描述
选择需要的jar,选择之后,生成的项目会自动加上maven配置
在这里插入图片描述
如果是自己搭建的项目,可以自己加上spring-boot-starter-jersey的maven配置

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jersey</artifactId>
</dependency>

点击Next会生成一个SpringBoot项目,注意也可以加上lombokhutool组件,方便开发项目

<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional>
</dependency>
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.11</version>
</dependency>

加上jersey-media-multipart,注意不要加上版本号,因为自己加的版本号可能会和spring-boot-starter-jersey版本冲突,不加上版本号,通过SpringBoot的版本仲裁机制,自动加载对应版本的jar,加上jersey-media-multipart依赖就可以使用@FormDataParam注解,上传文件一般都是要form-data方式

<dependency><groupId>org.glassfish.jersey.media</groupId><artifactId>jersey-media-multipart</artifactId>
</dependency>

项目代码实现

简单加一个返回结果的枚举类,方便返回参数

package com.example.springbootjersey.common;import lombok.Data;
import org.springframework.http.HttpStatus;@Data
public class ResultBean<T> {/*** 状态* */private int status;/*** 描述* */private String desc;/*** 数据返回* */private T data;public ResultBean(int status, String desc, T data) {this.status = status;this.desc = desc;this.data = data;}public ResultBean(T data) {this.status = HttpStatus.OK.value();this.desc = "处理成功";this.data = data;}public static <T> ResultBean<T> ok(T data) {return new ResultBean(data);}public static <T> ResultBean<T> ok() {return new ResultBean(null);}public static <T> ResultBean<T> badRequest(String desc,T data) {return new ResultBean(HttpStatus.BAD_REQUEST.value(), desc, data);}public static <T> ResultBean<T> badRequest(String desc) {return new ResultBean(HttpStatus.BAD_REQUEST.value(), desc, null);}public static <T> ResultBean serverError(String desc, T data){return new ResultBean(HttpStatus.INTERNAL_SERVER_ERROR.value(),"服务器内部异常:"+desc,data);}public static <T> ResultBean serverError(String desc){return new ResultBean(HttpStatus.INTERNAL_SERVER_ERROR.value(),"服务器内部异常:"+desc,null);}}

写一个文件上传的api接口

package com.example.springbootjersey.endpoint;import com.example.springbootjersey.common.ResultBean;
import com.example.springbootjersey.entity.FileUploadResult;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;import java.io.InputStream;public interface IFileServerClient {ResultBean<FileUploadResult> uploadFile(InputStream inputStream , FormDataContentDisposition fileDisposition);}

在SpringBoot里封装的Jersey使用Endpoint作为一个Resource,在JAX-RS项目里一般使用Resource,SpringBoot使用Endpoint,那项目也跟着命名,关键点,要先设置客户端传入的媒体类型,这里使用multipart/form-data方式,加上注解@Consumes(MediaType.MULTIPART_FORM_DATA)@FormDataParam定义传入的对象

package com.example.springbootjersey.endpoint;import com.example.springbootjersey.common.ResultBean;
import com.example.springbootjersey.entity.FileUploadResult;
import com.example.springbootjersey.manager.FileUploadHandler;
import lombok.extern.slf4j.Slf4j;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.io.InputStream;@Path("/api")
@Service
@Produces({MediaType.APPLICATION_JSON  , MediaType.APPLICATION_XML})
@Slf4j
public class FileServerEndpoint implements IFileServerClient {@Resourceprivate FileUploadHandler fileUploadHandler;@POST@Path("/v1/uploadFile")@Consumes(MediaType.MULTIPART_FORM_DATA)@Overridepublic ResultBean<FileUploadResult> uploadFile(@FormDataParam("file") InputStream inputStream,@FormDataParam("file") FormDataContentDisposition fileDisposition) {try {FileUploadResult result = fileUploadHandler.fileUpload(inputStream ,fileDisposition);return ResultBean.ok(result);} catch (Exception e) {log.error("exception:{}" , e);return ResultBean.badRequest("error" , null);}}
}

具体的业务实现,拿到对应的InputStream ,就可以创建文件,注意这个文件大小不能从FormDataContentDisposition 直接拿,里面的getSize方法拿到的是-1,可能是bug,所以从File里拿

package com.example.springbootjersey.manager;import cn.hutool.core.io.FileUtil;
import com.example.springbootjersey.entity.FileUploadResult;
import lombok.extern.slf4j.Slf4j;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.springframework.stereotype.Component;import java.io.File;
import java.io.IOException;
import java.io.InputStream;@Component
@Slf4j
public class FileUploadHandler {public FileUploadResult fileUpload(InputStream inputStream , FormDataContentDisposition fileDisposition) throws IOException {String fileName = fileDisposition.getFileName();String fileType = fileName.substring(fileName.lastIndexOf("."));File file = FileUtil.writeFromStream(inputStream, new File("D:/server/" + fileName));long length = file.length();log.info("fileName : [{}] , fileTye : [{}], size:[{}]" , fileName , fileType , length);return FileUploadResult.builder().fileName(fileName).fileUrl(file.getPath()).fileSize(length).fileType(fileType).build();}
}

配置类,注意要加上MultiPartFeature,也要注册,@ApplicationPath是定义应用的根路径,默认是/*

package com.example.springbootjersey.configuration;import com.example.springbootjersey.endpoint.FileServerEndpoint;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.context.annotation.Configuration;import javax.ws.rs.ApplicationPath;@Configuration
@ApplicationPath("/server")
public class JerseyConfig extends ResourceConfig{public JerseyConfig() {register(FileServerEndpoint.class);register(MultiPartFeature.class);}
}

写好代码,丢一个文件测试一下看看,在POST MAN里测试,注意要form-data方式
在这里插入图片描述

相关文章:

SpringBoot系列之基于Jersey实现文件上传API

前言 JAX-RS&#xff1a;JAX-RS是可以用可以用于实现RESTFul应用程序的JAVA API&#xff0c;给开发者提供了一系列的RESTFul注解Jersey&#xff1a;是基于JAX-RX API的实现框架&#xff0c;用于实现RESTful Web 服务的开源框架。 JAX-RX常用的注解&#xff1a; javax.ws.rs.Pa…...

【LangChain】Prompts之示例选择器

LangChain学习文档 【LangChain】向量存储(Vector stores)【LangChain】向量存储之FAISS【LangChain】Prompts之Prompt templates【LangChain】Prompts之自定义提示模板【LangChain】Prompts之示例选择器 概要 如果您有大量示例&#xff0c;您可能需要选择要包含在提示中的哪…...

Neo4j之CREATE基础

在 Neo4j 中&#xff0c;CREATE 语句用于创建节点、关系以及节点属性。 创建节点&#xff1a; CREATE (p:Person {name: John, age: 30});这个查询会创建一个具有 "Person" 标签的节点&#xff0c;节点属性包括 "name" 和 "age"。 创建带有关…...

Kali Hyper-V安装正常启动后 黑屏 只能进命令模式

问题: Hyper-V安装虚拟机Kali系统一切安装正常, 没有出现错误. 安装成功后重启,只能进入命令模式,tt1-tt6,进不去GUI桌面. 尝试: 一代二代虚拟硬盘都试过,同样问题,只能开进后进入命令模式,在命令模式下一切运行正常, 也修复过系统 GNOM等的,不管用. 以下为国外论坛给的建议,尝…...

【人工智能124种任务大集合】-集齐了自然语言处理(NLP),计算机视觉(CV),语音识别,多模态等任务

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下人工智能124种任务大集合&#xff0c;任务集合主要包括4大类&#xff1a;自然语言处理&#xff08;NLP&#xff09;、计算机视觉&#xff08;CV&#xff09;、语音识别、多模态任务。 我这里整理了124种应用场景任…...

IntelliJ IDEA快捷键大全

文章目录 1、构建/编译2、文本编辑3、光标操作4、文本选择5、代码折叠6、辅助编码7、上下文导航8、查找操作9、符号导航10、代码分析11、运行和调试12、代码重构13、全局 CVS 操作14、差异查看器15、工具窗口 本文参考了 IntelliJ IDEA 的官网&#xff0c;列举了IntelliJ IDEA&…...

阿里云轻量应用服务器_2核4G4M_2核2G3M_性能测评

阿里云轻量应用服务器2核2G3M带宽108元一年&#xff0c;系统盘为50GB高效云盘&#xff1b;轻量服务器2核4G4M带宽&#xff0c;60GB高效云盘297.98元12个月。目前轻量应用服务器只有2核2G和2核4G有活动&#xff0c;阿里云百科分享阿里云轻量应用服务器入口&#xff1a; 目录 阿…...

猿人学刷题系列(第一届比赛)——第二题( js 混淆 - 动态cookie 1)

题目&#xff1a;提取全部5页发布日热度的值&#xff0c;计算所有值的加和 地址&#xff1a;https://match.yuanrenxue.cn/match/2 思路分析 本题我们会简单说一下两种不同的方式去处理&#xff0c;一种是不还原混淆代码直接从源代码硬扣生成逻辑&#xff0c;另一种则是还原…...

ubuntu网络管理

主机-ip&#xff0c;service—port 分别查看/etc/hosts&#xff0c;/etc/host.conf&#xff1b;/etc/services&#xff0c;/etc/resolv.conf&#xff1b; 内核更新——linux-image-generic 6.2.0-24.24 非常抱歉&#xff0c;我误解了你的问题。如果你想更新已安装的内核版本…...

您可能并不需要单页应用程序

前端框架的迅速崛起&#xff0c;如React、Angel、Vue.js、Elm等&#xff0c;使得单页面应用程序&#xff08;Single Page Application&#xff09;在网络上无处不在。对于许多开发人员来说&#xff0c;这些已经成为他们“默认”工具集的一部分。当他们开始一个新项目时&#xf…...

基于低代码和数字孪生技术的电力运维平台设计

电力能源服务商在为用能企业提供线上服务的时候&#xff0c;不可避免要面对用能企业的各种个性化需求。如果这些需求和想法都要靠平台厂家研发人员来实现&#xff0c;那在周期、成本、效果上都将是无法满足服务运营需要的&#xff0c;这也是目前很多线上能源云平台应用效果不理…...

【Github】SourceTree技巧汇总

sourceTree登录github账户 会跳转到浏览器端 按照Git Flow 初始化仓库分支 克隆远程仓库到本地 推送变更到远程仓库 合并分支 可以看到目前的本地分支&#xff08;main、iOS_JS&#xff09;和远程分支&#xff08;origin/main、origin/HEAD、origin/iOS_JS&#xff09;目前所处…...

人工智能轨道交通行业周刊-第55期(2023.8.7-8.13)

本期关键词&#xff1a;北京智慧交通规划、成都数智化规划、关门车、集装箱标志、大模型隐私、视觉大模型 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交…...

向量数据库 Milvus Cloud Partition Key:租户数量多,单个租户数据少的三种解决方案

三种解决方案 这个问题提出的时候,Milvus 的最新版本是 2.2.8,我们做个角色互换,在当时站在这个用户的角度,留在我们面前的选择有这么几个: 为每个租户创建一个 collection 为每个租户创建一个 partition 创建一个租户名称的标量字段 接下来,我们依次分析下这三种方案的可…...

文本三剑客之grep命令和awk命令 1.0 版本

grep awk 1.grep命令1.1 基本格式1.2 常用选项 2.awk命令2.1 awk工作原理2.2 awk命令格式2.3 awk常用内置变量 1.grep命令 1.1 基本格式 grep [选项]… 查找条件 目标文件1.2 常用选项 选项功能 -m [ x ]匹配x次 后停止,x为具体数字-v取反 -i忽略字符大小写 -n显示匹配的 …...

【软件测试】Linux环境Ant调用Jmeter脚本并且生成测试报告(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 准备工作 需要在…...

MySQL的YEAR函数

MySQL的YEAR函数用于提取日期或日期时间值的年份部分。 语法&#xff1a; YEAR(date)参数&#xff1a; date&#xff1a;要提取年份的日期或日期时间值。 示例&#xff1a; SELECT YEAR(2023-08-09); -- 返回 2023SELECT YEAR(2023-08-09 14:16:20); -- 返回 2023注意事项…...

208、仿真-51单片机脉搏心率与心电报警Proteus仿真设计(程序+Proteus仿真+配套资料等)

毕设帮助、开题指导、技术解答(有偿)见文未 目录 一、硬件设计 二、设计功能 三、Proteus仿真图 四、程序源码 资料包括&#xff1a; 需要完整的资料可以点击下面的名片加下我&#xff0c;找我要资源压缩包的百度网盘下载地址及提取码。 方案选择 单片机的选择 方案一&a…...

787. 归并排序

文章目录 QuestionIdeasCode Question 给定你一个长度为 n 的整数数列。 请你使用归并排序对这个数列按照从小到大进行排序。 并将排好序的数列按顺序输出。 输入格式 输入共两行&#xff0c;第一行包含整数 n 。 第二行包含 n 个整数&#xff08;所有整数均在 1∼109 范围…...

【马蹄集】第二十二周——进位制与字符串专题

进位制与字符串专题 目录 MT2179 01操作MT2182 新十六进制MT2172 萨卡兹人MT2173 回文串等级MT2175 五彩斑斓的串 MT2179 01操作 难度&#xff1a;黄金    时间限制&#xff1a;1秒    占用内存&#xff1a;128M 题目描述 刚学二进制的小码哥对加减乘除还不熟&#xff0c;他…...

java 实现excel文件转pdf | 无水印 | 无限制

文章目录 目录 文章目录 前言 1.项目远程仓库配置 2.pom文件引入相关依赖 3.代码破解 二、Excel转PDF 1.代码实现 2.Aspose.License.xml 授权文件 总结 前言 java处理excel转pdf一直没找到什么好用的免费jar包工具,自己手写的难度,恐怕高级程序员花费一年的事件,也…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

vue3 daterange正则踩坑

<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

数据库正常,但后端收不到数据原因及解决

从代码和日志来看&#xff0c;后端SQL查询确实返回了数据&#xff0c;但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离&#xff0c;并且ai辅助开发的时候&#xff0c;很容易出现前后端变量名不一致情况&#xff0c;还不报错&#xff0c;只是单…...

【java】【服务器】线程上下文丢失 是指什么

目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失&#xff1f; 直观示例说明 为什么上下文如此重要&#xff1f; 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程&#xff0c;代码应该如何实现 推荐方案&#xff1a;使用 ManagedE…...