javascript
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:
改一下包名,打包選項這里可以jar可以war,選jar的話可以在build的時候再生成war.
這里用的是模板引擎Thymeleaf,選擇spring web與Thymeleaf.
最后點擊finish.
4 新建包
4個包,service,properties,controller,exception.
5 exception
處理兩個異常,分別是存儲異常與存儲文件找不到異常.
5.1 StorageException
package5.2 StorageFileNotFoundException
package這個構造函數中的cause是引起這個異常的異常,允許空值,如果是空值則表示這個引起這個異常的異常不存在或者未知.
6 properties
新建StorageProperties.java,設定存儲文件的位置,就是location的值,可以使用"../../"這樣的值,什么也不加的話會在項目路徑下新建文件夾,若有同名的文件夾會被刪除再重新創建.
注意一下權限的問題,后面部署到Tomcat上面時可能會因為沒有寫權限而不能寫入文件,要確保文件夾擁有寫權限.
package這里使用@ConfigurationProperties會報紅,提示沒有@EnableConfigurationProperties:
可以先不管,后面會在Main類中添加@EnableConfigurationProperties(StorageProperties.class).
7 service
先加一個StorageService接口:
package然后新建一個FileSystemStorageService實現該接口:
package7.1 init
@Override使用java.nio.file.Files.createDirectories()創建存儲目錄,可以建立多級目錄.
7.2 deleteAll
@Override使用工具類FileSystemUtils的方法遞歸刪除文件與文件夾.參數是一個File. 下面是方法源碼:
public首先判斷根是否為空,不為空的話判斷是否是目錄,不是目錄的話直接刪除,是目錄的話,利用listFiles()獲取所有文件及文件夾,判斷是否為空并進行遞歸刪除.
7.3 load
@OverridePath.resolve(String)返回相對于this的路徑,具體來說,等于執行
cd rootLocation返回pwd的值.
7.4 loadAll
@OverrideFiles.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
@OverridegetOriginalFilename()獲取文件原名字,然后通過StringUtils.cleanPath()將其標準化,.處理掉"."與"..",然后判斷文件是否為空與是否包含相對路徑,沒有的話利用Files.copy()進行復制,resolve獲取filename相對于rootLocation的值,復制選項是REPLACE_EXISTING. StandardCopyOption有三個可選值: - ATOMIC_MOVE:原子性的移動操作,一般在移動文件或目錄時使用. - COPY_ATTRIBUTES:復制屬性,可以保留源文件或源目錄的屬性. - REPLACE_EXISTING:替換已存在的文件.
8 controller
新建FileUploadController.
package8.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主要有以下方法:
ModeladdAttribute()添加一個變量,對于兩個參數的,使用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,然后添加請求頭.
HttpHeaderscontent_disposition表示文件是直接在瀏覽器打開還是下載,attachment表示是要下載,文件名為file.getFilename().
8.3 handleFileUpload
@PostMapping@PostMapping()與@GetMapping()類似,只不過方法不是GET而是POST.@RequestParam表示請求參數,里面的是請求參數的名字,使用MultipartFile來處理文件上傳. RedirectAttributes是用于重定向使用的,可以附帶參數,RedirectAttributes有兩種帶參的形式:
addAttributeaddAttribute()相當于直接在重定向的地址添加
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生效,如果沒有這一行會報紅:
@Bean標注在方法上,等價于spring的xml配置文件的<bean>,注冊bean對象. CommandLineRunner接口用于應用初始化后去執行一段代碼邏輯,這段代碼在整個應用周期只執行一次.
10 application.properties
這里可以設置一些環境配置屬性,Spring Boot允許準備多個配置文件,在部署時可以指定那個配置文件覆蓋默認的application.properties.這里是有關上傳文件的設置:
默認如下:
springenabled表示允許上傳,file-size-threshold表示上傳文件超過一定長度就先寫入臨時文件,單位MB或KB,location是臨時文件存放目錄,不設定的話使用web服務器提供的臨時目錄.max-file-size表示單個文件最大長度,默認1MB,max-request-size為單次HTTP請求上傳的最大長度,默認10MB,resolve-lazily表示文件和參數被訪問的時候再解析成文件.
在這里只需把max-size調大一點即可.
11 測試
這是在本地進行的測試.直接在IDE上點擊運行應用,然后打開瀏覽器輸入:
localhost:12 打包部署到Tomcat上
Spring Boot通常打成jar包或war包,這里部署到Tomcat上的是打成war包.
12.1 改變打包方式
pom.xml中,<packaing>改成war:
12.2 去除Tomcat依賴
Spring Boot默認自帶了一個嵌入式的Tomcat,需要把Tomcat依賴方式改為provided. pom.xml中,在<dependencies>添加:
<dependency>12.3 修改Main類
修改Main類,讓其繼承SpringBootServletInitializer,重載configure(),同時main()保持不變.
@SpringBootApplication12.4 路徑問題
這個很重要,設置不當的話就無法訪問了,主要就是四個路徑: - action:
- @GetMapping
- @PostMapping
- redirect
12.4.1 action
這個是絕對路徑,要加上/war項目名.
/war項目名/上傳路徑名比如這里war項目名是kr,上傳路徑名是upload.
12.4.2 @GetMapping
這個是相對路徑,相對于當前項目的路徑,不用加上/war項目名.
/上傳路徑名這里是upload.
12.4.3 @PostMapping
與@GetMapping一樣,上傳路徑名.
/上傳路徑名12.4.4 redirect
這個是返回的重定向的路徑名,相對路徑,與上兩個一樣,也是上傳路徑名.
/上傳路徑名12.5 設置打包名字
在<build>中添加<finalName>,指定打包出來的war名,注意這個要與上面的war項目名一樣,這里設置的是kr.
12.6 Maven打包
運行
mvn即可打包,對于IDEA,可以在IDEA右側欄的Maven中,打開Lifecycle,選擇package:
12.7 打包完成
打包后的war默認放在target下,名字默認為<artifactId>+<version>.
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
總結
以上是生活随笔為你收集整理的springboot urlresource_Spring Boot上传文件+部署到Tomcat的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 运算符_详解Java表达式与运
- 下一篇: python写一个路径选择app_dja