JavaWeb学习笔记——第十一天

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>
posted @ 2024-04-01 12:20  zgg1h  阅读(71)  评论(0)    收藏  举报