springboot urlresource_Spring Boot上传文件+部署到Tomcat

1 概述

Spring Boot上传文件,根据官方uploadfile示例修改的,可以打成war放到服务器上(笔者使用的是Tomcat).主要步骤是创建异常类,属性类,接口类与控制器类,最后进行少量修改打包部署到服务器上.

2 环境

  • win10
  • Tomcat 9.0.30
  • IDEA 2019.03
  • Spring boot 2.2.2 RELEASE

3 新建工程

选择spring initializer:

620769ee8d130bdff87dc1f5f64f88b2.png

改一下包名,打包选项这里可以jar可以war,选jar的话可以在build的时候再生成war.

d79fad73957d374c04c1dafb171dd62f.png

这里用的是模板引擎Thymeleaf,选择spring web与Thymeleaf.

f35a50b9d4cc0c8b4b4c3b4077da6758.png

e0cb2d81d153819b2fb44256d7f18883.png

最后点击finish.

4 新建包

4个包,service,properties,controller,exception.

b35b3000dbe3893c8e9a3ca0c5982a98.png

5 exception

处理两个异常,分别是存储异常与存储文件找不到异常.

1eb78f0b112f7c6bf3fb79c5ab4aa2de.png

5.1 StorageException

package 

5.2 StorageFileNotFoundException

package 

这个构造函数中的cause是引起这个异常的异常,允许空值,如果是空值则表示这个引起这个异常的异常不存在或者未知.

1fbd089a9b4c60d482f34cca5563276e.png

6 properties

新建StorageProperties.java,设定存储文件的位置,就是location的值,可以使用"../../"这样的值,什么也不加的话会在项目路径下新建文件夹,若有同名的文件夹会被删除再重新创建.

注意一下权限的问题,后面部署到Tomcat上面时可能会因为没有写权限而不能写入文件,要确保文件夹拥有写权限.

package 

这里使用@ConfigurationProperties会报红,提示没有@EnableConfigurationProperties:

343e260f1d3bec43c390555e9cb98d0b.png

可以先不管,后面会在Main类中添加@EnableConfigurationProperties(StorageProperties.class).

7 service

先加一个StorageService接口:

package 

然后新建一个FileSystemStorageService实现该接口:

package 

7.1 init

@Override

使用java.nio.file.Files.createDirectories()创建存储目录,可以建立多级目录.

7.2 deleteAll

@Override

使用工具类FileSystemUtils的方法递归删除文件与文件夹.参数是一个File. 下面是方法源码:

public 

首先判断根是否为空,不为空的话判断是否是目录,不是目录的话直接删除,是目录的话,利用listFiles()获取所有文件及文件夹,判断是否为空并进行递归删除.

7.3 load

@Override

Path.resolve(String)返回相对于this的路径,具体来说,等于执行

cd rootLocation

返回pwd的值.

7.4 loadAll

@Override

Files.walk遍历目录,返回一个Stream<Path>,返回的Stream包含打开的一个或多个目录的引用,会在Stream关闭时关闭,第二个参数1表示遍历的最大深度.

然后对这个Stream进行filter过滤,这里是把与rootLocation不相等的Path留下,注意是不相等,就是留下filter()中条件为真的Path,不是把条件为真的Path给"删去".

最后进行map,relativize返回参数相对于调用者的路径,这里是返回Stream中的每个Path相对于rootLocation的路径. 对于relativize,无论什么情况下:

Path 

都有

a

为真.

7.5 loadAsResource

@Override

这里的Resource是org.springframework.core.io.Resource,是一个接口,可以通过它访问各种资源,实现类有UrlResource,InputStreamResource等,这里利用Path.toUri()把file转换为Resource后,判断这个源是否存在或者是否可读并返回,否则抛出存储文件找不到异常.

7.6 store

@Override

getOriginalFilename()获取文件原名字,然后通过StringUtils.cleanPath()将其标准化,.处理掉"."与"..",然后判断文件是否为空与是否包含相对路径,没有的话利用Files.copy()进行复制,resolve获取filename相对于rootLocation的值,复制选项是REPLACE_EXISTING. StandardCopyOption有三个可选值: - ATOMIC_MOVE:原子性的移动操作,一般在移动文件或目录时使用. - COPY_ATTRIBUTES:复制属性,可以保留源文件或源目录的属性. - REPLACE_EXISTING:替换已存在的文件.

8 controller

新建FileUploadController.

73b14b39cb73907cc9bdb9362a87c490.png
package 

8.1 listUploadedFiles

@GetMapping

@GetMapping是@RequestMapping(method = RequestMethod.GET)的简化写法,将HTTP GET路径映射到特定的处理方法上. 方法的参数是spring MVC中的Model,Model实质上是一个Map,添加的key可以在视图中用${key}获取值,比如,这里添加了"files"作为key,则在视图中可用 ${files}获取值.

MvcUriComponentsBuilder可以为Controller指定uri,fromMethod简单地说就是会调用FileUploadController的serveFile(),参数是path.getFileName().toString(),由于serveFile()返回的是Stream<Path>,利用Stream的collect将其转换成List添加到model中,然后返回uploadForm,表示这是视图的名称,会到resource/templates下寻找.

这里说一下RequestMapping与Model:

8.1.1 RequestMapping

可以用@RequestMapping()来映射URL,可以映射到某个类或某个具体方法.@RequestMapping常用的有以下属性:

  • value:请求的URL路径,支持URL模板,正则表达式.
  • method:HTTP请求方法,如GET,POST,PUT,DELTE等.
  • consumes:允许的媒体类型,如consumes="application/json".对应于HTTP请求的Content-Type.
  • produces:相应的媒体类型,如produces="application/json",对于HTTP请求的Accept.
  • params:请求参数,如params="action=update". - headers:请求头.

Spring提供了简化的@RequestMapping,提供了新的注解来标识HTTP方法: - @GetMapping - @PostMapping - @PutMapping - ...

所以这里的@GetMapping是简化了的@RequestMapping.

8.1.2 Model

可以向Model添加视图所需要的变量,Model主要有以下方法:

Model 

addAttribute()添加一个变量,对于两个参数的,使用name作为变量名称,后面的是值,对于只有一个Object的,变量的名字就是类名字首字母小写后转为的java变量. addAttributes()添加多个变量,如果变量存在则覆盖,其中参数为Collection<?>的方法添加变量名时与addAttribute(Object)的命名规范类似. mergeAttributes()也是添加多个变量,不过变量已存在的话会忽略. containAttributte()判断是否存在变量.

8.2 serveFile

@GetMapping

这里的@GetMapping用来表示显示的用来供下载的文件名,@ResponseBody表示直接返回内容而不是视图名,因为默认返回的是视图名称,@ResponseBody对于String直接返回,否则默认使用Jackson进行序列化.

@PathVariable表示这是@GetMapping中的参数的值,可以省略,默认同名,就是形参的名字与GetMapping中的名字一样,从中取值赋给形参,通过filename加载资源后,作为ResponseEntity的请求体. ResponseEntity从HttpEntity继承而来,ResponseEntity.ok()是一个静态方法,表示构建一个状态为"ok"的ResponseEntity,然后添加请求头.

HttpHeaders

content_disposition表示文件是直接在浏览器打开还是下载,attachment表示是要下载,文件名为file.getFilename().

8.3 handleFileUpload

@PostMapping

@PostMapping()与@GetMapping()类似,只不过方法不是GET而是POST.@RequestParam表示请求参数,里面的是请求参数的名字,使用MultipartFile来处理文件上传. RedirectAttributes是用于重定向使用的,可以附带参数,RedirectAttributes有两种带参的形式:

addAttribute

addAttribute()相当于直接在重定向的地址添加

name

这样的形式,会将参数暴露在重定向的地址上.

而addFlashAttribute()隐藏了参数,只能在重定向的页面中获取参数的值,用到了session,session跳转到页面后就会删除对象. handleFileUpload首先保存文件,然后添加一个保存成功的信息,由于Controller中重定向可以返回以"redirect:"或以"forward:"为前缀的URI,因此返回"redirect:/",重定向到根.

8.4 handleStorageFileNotFound

@ExceptionHandler

@ExceptionHandler()注解会处理Controller层抛出的所有StorageFileNotFoundException类及其子类的异常,ResponseEntity.notFound()相当于返回404标识码.

9 main

package 

在原来的基础上添加

@EnableConfigurationProperties

@Bean

@EnableConfigurationProperties可以为带有@ConfigurationProperties注解的Bean提供有效的支持,将带有@Configuration注解的类注入为Spring的Bean,在这里是使StorageProperties的@ConfigurationProperties生效,如果没有这一行会报红:

ae56e2566f261351165869dc05b3858d.png

@Bean标注在方法上,等价于spring的xml配置文件的<bean>,注册bean对象. CommandLineRunner接口用于应用初始化后去执行一段代码逻辑,这段代码在整个应用周期只执行一次.

10 application.properties

这里可以设置一些环境配置属性,Spring Boot允许准备多个配置文件,在部署时可以指定那个配置文件覆盖默认的application.properties.这里是有关上传文件的设置:

2fb46f9e8d32dbbee1f4bd1c142bee9e.png

默认如下:

spring

enabled表示允许上传,file-size-threshold表示上传文件超过一定长度就先写入临时文件,单位MB或KB,location是临时文件存放目录,不设定的话使用web服务器提供的临时目录.max-file-size表示单个文件最大长度,默认1MB,max-request-size为单次HTTP请求上传的最大长度,默认10MB,resolve-lazily表示文件和参数被访问的时候再解析成文件.

在这里只需把max-size调大一点即可.

1a68dc193fce3f126fecf09b376dfcd2.png

11 测试

这是在本地进行的测试.直接在IDE上点击运行应用,然后打开浏览器输入:

localhost:

66f59f8136ae1a9131a0788d7d8d3e02.gif

12 打包部署到Tomcat上

Spring Boot通常打成jar包或war包,这里部署到Tomcat上的是打成war包.

12.1 改变打包方式

pom.xml中,<packaing>改成war:

0b83fc1a45366a6fdbed03992c61143c.png

12.2 去除Tomcat依赖

Spring Boot默认自带了一个嵌入式的Tomcat,需要把Tomcat依赖方式改为provided. pom.xml中,在<dependencies>添加:

<dependency>

12.3 修改Main类

修改Main类,让其继承SpringBootServletInitializer,重载configure(),同时main()保持不变.

@SpringBootApplication

12.4 路径问题

这个很重要,设置不当的话就无法访问了,主要就是四个路径: - action:

7f9f6b8eecefec4b88e5b054530f72ad.png
  • @GetMapping

b046eb4d236e9fdb115a7501a48ed026.png
  • @PostMapping

1250580fd33385412d0eb9b0dd815245.png
  • redirect

457ff5ff3a09571ef961896f838bf856.png

12.4.1 action

这个是绝对路径,要加上/war项目名.

/war项目名/上传路径名

6328d48fe5a6129b08b9b3d581bdb82c.png

比如这里war项目名是kr,上传路径名是upload.

12.4.2 @GetMapping

这个是相对路径,相对于当前项目的路径,不用加上/war项目名.

/上传路径名

a1932aa531cdd9de3cf2013ab3171381.png

这里是upload.

12.4.3 @PostMapping

与@GetMapping一样,上传路径名.

/上传路径名

c40a769a7d4781ae7d75c908acd605b8.png

12.4.4 redirect

这个是返回的重定向的路径名,相对路径,与上两个一样,也是上传路径名.

/上传路径名

cebbc9d646ec1310a2500c3393e107ad.png

12.5 设置打包名字

在<build>中添加<finalName>,指定打包出来的war名,注意这个要与上面的war项目名一样,这里设置的是kr.

c53e525d36dad586727f71bcf14068d6.png

12.6 Maven打包

运行

mvn 

即可打包,对于IDEA,可以在IDEA右侧栏的Maven中,打开Lifecycle,选择package:

4d6f5c5a2f1bbef23ef11b1eb0b00f74.png

12.7 打包完成

打包后的war默认放在target下,名字默认为<artifactId>+<version>.

9b0dfbe623838ece8fcd63bf89d51d42.png

352cca1112f380b1765aa2a0ee793d5c.png

12.8 上传到服务器

上传的话笔者用的是密钥认证的scp:

id_rsa kr.war username@ip:/usr/local/tomcat/webapps

放到服务器的Tomcat下的webapps目录.

12.9 开启Tomcat

进入到Tomcat目录的bin下:

cd /usr/local/tomcat/bin
./startup.sh

如果正在运行的话就不用启动了,因为会自动检测到webapps目录的变化,把新的war自动解包.

12.10 测试

略,与本地测试类似,不过要注意的是上传的文件夹是在tomcat/bin下,想要修改的话可以修改StorageProperties的location.

13 源码

github

码云

14 参考

1.ConfigurationProperties

2.CommandLineRunner

3.RedirectAttribute

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/552317.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

alc236黑苹果驱动_台式机黑苹果独显驱动

黑苹果安装离不开黑苹果驱动程序&#xff0c;常见的有网卡驱动、显卡驱动、声卡驱动、还有其他的一些常用的驱动程序&#xff0c;这里我们单独讲一下黑苹果上驱动英伟达GTX的独显驱动&#xff0c;即我们平常说的N卡&#xff0c;如果文章中介绍的有错误&#xff0c;或者您还有其…

c语言break在if中用法,break可用于什么语句 break语句可用于for语句和if语句中 对吗...

c语言中break语句的作用C语言中&#xff0c;break都可以用在什么地方&#xff1f;用到每一个语...break 一般是针对一个循环或者switch中的case,表示跳出当前的循环或选择&#xff0c;即在一个单层循环中&#xff0c;可以通过break 来跳出循环&#xff0c;在switch 中的case通过…

python简单实用案例_Python 21 Django 实用小案例1

8 9 10 {% csrf_token %}11 用户名&#xff1a;12 密码&#xff1a;13 验证码&#xff1a;14 15 16 17

c语言的一段程序,C语言第一个程序(入门)

1.文件类型(基本)c语言源文件 为.c 文件扩展名&#xff0c;例如 main.c 编译后将得到 a.out 文件 运行会得到 我们程序执行的结果2.hello world (第一个程序)#include --------------------> 引入标准库的信息main () { …

matlab table中的文字转string_MATLAB_GUI_教程(2)pushbutton

目录前言上期教程按钮介绍按钮(pushbutton)如何在窗口中创建一个按钮常用属性常用属性练习回调函数的编写规则设置回调函数&#xff1a;定义(编写)回调函数&#xff1a;NoteGUI中各个回调函数之间数据的传递setappdatagetappdata方法按钮的回调函数前言上期教程按钮介绍这个按钮…

python中类和对象_Python里的类和对象简介

---恢复内容开始--- Python里的类 对象属性方法&#xff1b; 对象的属性主要是指主要的特征和参量&#xff0c;而方法主要是指函数&#xff1b; 类是一个具有一定特征和方法的集合&#xff0c;而对象是类的一个&#xff1b;类和对象的关系就如同模具和用这个模具制作出的物品之…

r语言 fread函数参数_R语言 第4章 初级绘图(6)

分析数据间的关系散点矩阵图如果数据框是多维数据&#xff0c;那么plot函数将绘制出两两之间散点图组合成为散点矩阵图(matrix of scatterplots)。散点矩阵图将多个散点图组合起来&#xff0c;以便可以同时浏览多个二元变量关系&#xff0c;一定程度上克服了在平面上展示高维数…

android 渠道打包工具,Android渠道打包技术小结

导读本文对比了渠道4种渠道打包方式:与iOS的单一渠道(AppStore)不同&#xff0c;Android平台在国内的渠道多入牛毛。以我们的App为例&#xff0c;就有27个普通渠道(应用宝&#xff0c;百度&#xff0c;360这种)和更多的推广专用渠道。我们打包技术也经过了若干次的改进。1.利用…

机械臂中的四元素转为旋转矩阵_雅克比矩阵(上)雅克比推导

1、前言 回顾前面几期的内容&#xff0c;在第一期中介绍了机器人的正/逆运动学建模&#xff0c;正运动学解决的问题是如何从关节空间的关节变量描述操作空间的位姿&#xff0c;反之则是逆运动学的内容。将操作空间和关节的空间的关系用以下关系式进行表达。机器人正/逆运动…

DS1819 对应版本的FFMPEG_OpenCV开发笔记(七十):红胖子带你傻瓜式编译VS2017x64版本的openCV4...

若该文为原创文章&#xff0c;转载请注明出处本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/107837715各位读者&#xff0c;知识无穷而人力有穷&#xff0c;要么改需求&#xff0c;要么找专业人士&#xff0c;要么自己研究红胖子(红模仿)的博文…

用Android打出马奔跑的动画,一款非常好用的动画库Lottie

简介Lottie是Android和iOS的移动图书馆&#xff0c;用于解析Adobe After Effects动画&#xff0c;并以Bodymovin作为json导出&#xff0c;并在手机和网络上本机呈现。该项目在GitHub已经获得三个端累计3万的star。在Lottie社区提供了更多的动画下载。如果你是一个设计师还可以将…

全站仪和手机连接软件_全站仪各方面应用的原理、操作及计算,看这篇就对了!...

来源&#xff1a;豆丁施工版权归原作者所有全站仪是什么&#xff1f;全站仪&#xff0c;即全站型电子速测仪。它是随着计算机和电子测距技术的发展&#xff0c;近代电子科技与光学经纬仪结合的新一代既能测角又能测距的仪器&#xff0c;它是在电子经纬仪的基础上增加了电子测距…

C#session共享+redis_技术干货分享:基于SpringBoot+Redis的Session共享与单点登录

categories:架构author: mrzhoutags:SpringBootredissession单点登录基于SpringBootRedis的Session共享与单点登录前言使用Redis来实现Session共享&#xff0c;其实网上已经有很多例子了&#xff0c;这是确保在集群部署中最典型的redis使用场景。在SpringBoot项目中&#xff0c…

android 热修复视频,Android热修复

所谓热修复&#xff0c;简单来说就是不以下载新版本apk的方式来修改应用的bug&#xff0c;而是在应用启动后从服务器下拉补丁包实现动态修复bug。所以在应用出现bug后&#xff0c;我们只需要打一个补丁&#xff0c;用户无需下载安装新的版本。主要是针对一些紧急的bug的修复。常…

text 两端对齐 小程序_leetcode 68 文本左右对齐

给定一个单词数组和一个长度 maxWidth&#xff0c;重新排版单词&#xff0c;使其成为每行恰好有 maxWidth 个字符&#xff0c;且左右两端对齐的文本。你应该使用“贪心算法”来放置给定的单词&#xff1b;也就是说&#xff0c;尽可能多地往每行中放置单词。必要时可用空格 填…

for循环如果先--_乐字节Java循环:循环控制和嵌套循环

乐字节小乐上次讲完了Java反射&#xff0c;接下来小乐给大家讲述Java循环。循环有以下四部分&#xff1a;Java循环一、循环控制1. do..while直到型 ( 先执行后判断) &#xff0c;结构为:先执行循环体&#xff0c;后判断布尔表达式。循环体至少执行一次其流程图如下:2. for灵活的…

input框传值是怎么才能是整形_做了这些项目,到底多久才能化妆?

要说变美有两招最好用&#xff1a;一是化妆&#xff0c;二是整形。化妆能让长相普通的妹子变个大美妞&#xff0c;但程序繁琐的很&#xff0c;手残宝宝都表示好心累。整形就不一样了&#xff0c;不用左一层右一层的涂粉底神马的&#xff0c;绝对是手残党的福利&#xff0c;最最…

html纵向固定导航菜单代码,jQuery和css3响应式垂直固定导航菜单插件

这是一款非常实用的jQuery和css3响应式垂直固定导航菜单插件。当你的页面上有很多的内容&#xff0c;用户需要花费大量的时间才能找到他们想要的内容。这个垂直固定导航菜单插件能够为页面提供一个内容预览&#xff0c;使用户能非常轻松的找到他们需要的内容。HTML结构导航菜单…

单点登录 cas 设置回调地址_单点登录落地实现技术有哪些,有哪些流行的登录方案搭配?...

实现单点登录说到底就是要解决如何产生和存储那个信任&#xff0c;再就是其他系统如何验证这个信任的有效性&#xff0c;因此要点也就以下两个&#xff1a;1、存储信任 &#xff1b;2、服务器生产~验证信任 &#xff1b; 3、拿到服务器再次验证。单点登录的常见落地实现技术有哪…

python 长度queue_python:常见的数据结构

​ Python中常见的数据结构可以统称为容器。序列&#xff08;如列表和元组&#xff09;、映射&#xff08;如字典&#xff09;以及集合&#xff08;set&#xff09;是三类主要的容器。线性数据结构分类&#xff1a;栈(stack)--先进后出、 队列(queue)-先进先出、双端队列(deque…