JavaWeb學習筆記——第十一天

zgg1h發表於2024-04-01

SpringBootWeb案例(二)

新增員工

實現

  • EmpController:
@PostMapping
public Result add(@RequestBody Emp emp) {
    log.info("新增員工:{}", emp);
    empService.add(emp);
    return Result.success();
}
  • EmpService:
void add(Emp emp);
  • EmpServiceImpl:
@Override
public void add(Emp emp) {
    emp.setCreateTime(LocalDateTime.now());
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.add(emp);
}
  • EmpMapper:
@Insert("insert into emp (username, name, gender, image, job, entrydate, dept_id, create_time, " + 
        "update_time) values (#{username}, #{name}, #{gender}, #{image}, #{job}, #{entrydate}, #{deptId}," + 
        " #{createTime}, #{updateTime});")
void add(Emp emp);

檔案上傳

簡介

  • 檔案上傳是指將本地圖片、影片、音訊等檔案上傳到伺服器,供其他使用者瀏覽或下載的過程。
  • 檔案上傳在專案中應用非常廣泛,我們經常發微博、發微信朋友圈都用到了檔案上傳功能。

前端頁面三要素

  • 表單項型別必須為file。
  • 表單提交方式必須為post。
  • 表單的編碼型別必須為multipart/form-data。
<form action="/upload" method="post" enctype="multipart/form-data">
    姓名: <input type="text" name="username"><br>
    年齡: <input type="text" name="age"><br>
    頭像: <input type="file" name="image"><br>
    <input type="submit" value="提交">
</form>

服務端接收檔案

@RestController
public class UploadController {
    @PostMapping("/upload")
    public Result upload(String username , Integer age, @RequestParam("image") MultipartFile file) {
        return Result.success();
    }
}
  • 使用MultipartFile型別來接收上傳的檔案。
  • 形參名要和表單項的名字相同,如果不相同,則要使用@RequestParam("表單項名稱")註解將形參名對映為表單項名稱。

注意事項

接收到的檔案會在本地以臨時檔案的形式儲存,程式結束後,臨時檔案會消失。所以,要把臨時檔案儲存下來才能永久儲存。

本地儲存

在服務端,接收到上傳上來的檔案之後,將檔案儲存在本地伺服器磁碟中。

程式程式碼

@RestController
public class UploadController {
    @PostMapping("/upload")
    public Result upload(MultipartFile image) throws IOException {
        //獲取原始檔名
        String originalFilename = image.getOriginalFilename();
        //構建新的檔名,使用uuid生成不重複的檔名,並拼接上原始檔案的字尾
        String newFileName = UUID.randomUUID().toString()+originalFilename.substring(originalFilename.lastIndexOf("."));
        //將檔案儲存在伺服器端 E:/images/ 目錄下
        image.transferTo(new File("E:/images/"+newFileName));
        return Result.success();
    }
}

MultipartFile類的常用方法

方法 說明
String getOriginalFilename() 獲取原始檔名
void transferTo(File dest) 將接收的檔案轉存到磁碟檔案中
long getSize() 獲取檔案的大小,單位:位元組
byte[] getBytes() 獲取檔案內容的位元組陣列
InputStream getInputStream() 獲取接收到的檔案內容的輸入流

上傳檔案大小限制配置

在SpringBoot中,檔案上傳,預設單個檔案允許最大大小為 1M。如果需要上傳大檔案,可以在application.properties檔案中進行如下配置:

#配置單個檔案最大上傳大小
spring.servlet.multipart.max-file-size=10MB
#配置單個請求最大上傳大小(一次請求可以上傳多個檔案)
spring.servlet.multipart.max-request-size=100MB

本地儲存的問題

  • 如果儲存在本地,瀏覽器無法直接訪問。
  • 如果磁碟滿了,伺服器不便於擴容。
  • 如果磁碟損壞,資料會丟失,造成很大的損失。
解決方案
  • 方案一:專案組自己搭建一套檔案儲存服務。
  • 方案二:使用現成的雲端儲存服務。

雲端儲存(阿里雲OSS)

  • 阿里雲是阿里巴巴集團旗下全球領先的雲端計算公司,也是國內最大的雲服務提供商 。
  • 阿里雲物件儲存OSS(Object Storage Service),是一款海量、安全、低成本、高可靠的雲端儲存服務。使用OSS,您可以透過網路隨時儲存和呼叫包括文字、圖片、音訊和影片等在內的各種檔案。

第三方服務使用的通用思路

  1. 準備工作:註冊登入等。
  2. 參照官方SDK編寫入門程式。(SDK:Software Development Kit 的縮寫,軟體開發工具包,包括輔助軟體開發的依賴(jar包)、程式碼示例等,都可以叫做SDK)
  3. 整合使用。

阿里雲OSS-使用步驟

  1. 註冊阿里雲。(需要實名認證)
  2. 充值。(可以不做)
  3. 開通物件儲存服務。(OSS)
  4. 建立bucket。(Bucket:即儲存空間,是使用者用於儲存物件(Object,就是檔案)的容器,所有的物件都必須隸屬於某個儲存空間)
  5. 獲取AccessKey。(秘鑰)
  6. 參照官方SDK編寫入門程式。
  7. 案例整合OSS。

阿里雲OSS-整合

  • 引入阿里雲OSS上傳檔案工具類(由官方的示例程式碼改造而來):
package com.zgg1h.utils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;

/**
 * 阿里雲 OSS 工具類
 */
@Component
public class AliOSSUtils {

    private String endpoint = ""; //修改成自己的endpoint
    private String accessKeyId = ""; //修改成自己的accessKeyId
    private String accessKeySecret = ""; //修改成自己的accessKeySecret
    private String bucketName = ""; //修改成自己的bucketName

    /**
     * 實現上傳圖片到OSS
     */
    public String upload(MultipartFile file) throws IOException {
        // 獲取上傳的檔案的輸入流
        InputStream inputStream = file.getInputStream();

        // 避免檔案覆蓋
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

        //上傳檔案到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);

        //檔案訪問路徑
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
        // 關閉ossClient
        ossClient.shutdown();
        return url;// 把上傳到oss的路徑返回
    }

}
  • 上傳圖片介面開發:
import com.zgg1h.pojo.Result;
import com.zgg1h.utils.AliOSSUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
public class UploadController {
    @Autowired
    private AliOSSUtils aliOSSUtils;
    @PostMapping("/upload")
    public Result upload(MultipartFile image) throws Exception {
        String url = aliOSSUtils.upload(image); //呼叫阿里雲OSS工具類,將上傳上來的檔案存入阿里雲
        return Result.success(url); //將圖片上傳完成後的url返回,用於瀏覽器回顯展示
    }
}

資料回顯

實現

  • EmpController:
@GetMapping("/{id}")
public Result getById(@PathVariable Integer id) {
    log.info("根據id查詢員工,id:{}", id);
    Emp emp = empService.getById(id);
    return Result.success(emp);
}
  • EmpService:
Emp getById(Integer id);
  • EmpServiceImpl:
@Override
public Emp getById(Integer id) {
    Emp emp = empMapper.getById(id);
    return emp;
}
  • EmpMapper:
@Select("select * from emp where id = #{id}")
Emp getById(Integer id);

修改員工

實現

  • EmpController:
@PutMapping
public Result update(@RequestBody Emp emp) {
    log.info("根據id更新員工資料:{}", emp);
    empService.update(emp);
    return Result.success();
}
  • EmpService:
void update(Emp emp);
  • EmpServiceImpl:
@Override
public void update(Emp emp) {
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.update(emp);
}
  • EmpMapper:
void update(Emp emp);
  • EmpMapper.xml:
<update id="update">
    update emp
    <set>
        <if test="username != null and username != ''">
            username = #{username},
        </if>
        <if test="password != null and password != ''">
            password = #{password},
        </if>
        <if test="name != null and name != ''">
            name = #{name},
        </if>
        <if test="gender != null">
            gender = #{gender},
        </if>
        <if test="image != null and username != ''">
            image = #{image},
        </if>
        <if test="updateTime != null">
            update_time = #{updateTime}
        </if>
    </set>
    where id = #{id}
</update>

配置檔案

引數配置化

  • 可以將配置資訊寫入配置檔案application.properties中:
#阿里雲oss配置資訊
aliyun.oss.endpoint=your endpoint
aliyun.oss.accessKeyId=your accessKeyId
aliyun.oss.accessKeySecret=your accessKeySecret
aliyun.oss.bucketName=your bucketName
  • 在需要賦值的地方使用@Value註解進行外部配置的屬性注入,具體用法為: @Value("${配置檔案中的key}")
@Value("${aliyun.oss.endpoint}")
private String endpoint;
@Value("${aliyun.oss.accessKeyId}")
private String accessKeyId;
@Value("${aliyun.oss.accessKeySecret}")
private String accessKeySecret;
@Value("${aliyun.oss.bucketName}")
private String bucketName;

yml配置檔案

  • SpringBoot提供了多種屬性配置方式:.properties,.yml,和.yaml。

常見配置檔案格式對比

  • XML(springboot配置檔案不支援xml,這裡只做比較):
<server>
	<port>8080</port>
	<address>127.0.0.1</address>
</server>

優點:層次結構清晰;缺點:語法臃腫。

  • properties:
server.port=8080
server.address=127.0.0.1

優點:語法簡潔;缺點:層次結構不清晰。

  • yml/yaml:
server:
   port: 8080
   address: 127.0.0.1

優點:語法簡潔,層次結構清晰,以資料為中心。

yml基本語法

  • 大小寫敏感。
  • 數值前邊必須有空格,作為分隔符。
  • 使用縮排表示層級關係,縮排時,不允許使用Tab鍵,只能用空格。(IDEA中會自動將Tab轉換為空格)
  • 縮排的空格數目不重要,只要相同層級的元素左側對齊即可。
  • 表示註釋,從這個字元一直到行尾,都會被解析器忽略。

yml資料格式

  • 物件/Map集合:
user:
   name: zhangsan
   age: 18
   password: 123456
  • 陣列/List/Set集合:
#注意:-之後必須有空格
hobby:
  - java
  - game
  - sport

@ConfigurationProperties

  • @ConfigurationProperties與@Value類似,都是用來注入外部配置的屬性的。
  • @ConfigurationProperties可以批次的將外部的屬性配置注入到bean物件的屬性中,而@Value註解只能一個一個的進行外部屬性的注入。

@ConfigurationProperties的使用步驟

  1. 新建一個實體類,其屬性為想要注入的屬性,且名稱要與配置檔案保持一致。
public class AliOSSProperties {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
}
  1. 為其加上@Component註解和@ConfigurationProperties註解,其中@ConfigurationProperties的引數prefix的值是想要注入的屬性名的共同字首。
@Data
@Component
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliOSSProperties {
    private String endpoint;
    private String accessKeyId;
    private String accessKeySecret;
    private String bucketName;
}
  1. 在使用這些引數的類中建立這個實體類物件並加上@Autowired註解,並呼叫該物件的get方法獲取注入後的變數。
//AliOSSUtils類內
@Autowired
private AliOSSProperties aliOSSProperties;

//upload方法內
String endpoint = aliOSSProperties.getEndpoint();
String accessKeyId = aliOSSProperties.getAccessKeyId();
String accessKeySecret = aliOSSProperties.getAccessKeySecret();
String bucketName = aliOSSProperties.getBucketName();

spring-boot-configuration-processor依賴(可選,不影響程式執行)

新增了這一項依賴後,在properties和yml/yaml檔案中可以自動識別被@ConfigurationProperties標識的bean物件,然後在配置檔案中配置時就會自動提示與這個bean物件的屬性名相對應的配置項的名字。

引入依賴的程式碼
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

相關文章