Mybatis 案例

news2024/11/28 0:45:28

文章目录

  • Mybatis 案例
  • 一、 准备工作
    • 1.1 数据库表
    • 1.2 Restfull规范
    • 1.3 封装结果类
    • 1.4 实体类
  • 二、部门管理
    • 2.1 查询全部部门信息
    • 2.2 删除部门
    • 2.3 新增部门
  • 三、员工管理
    • 3.1 分页查询
    • 3.2 分页查询 - PageHelper插件
    • 3.3 分页查询 - 条件查询
    • 3.4 批量删除员工
    • 3.5 新增员工
    • 3.6 修改员工
      • 3.6.1 查询回显
      • 3.6.2 修改员工
  • 四、文件上传
    • 4.0 html
    • 4.1 简介
    • 4.2 本地存储
    • 4.3 对象存储 OSS
      • 4.3.1 maven坐标
      • 4.3.2 简单上传
    • 4.4 案例集成OSS
      • 4.4.1 上传工具类
  • 五、 配置文件
    • 5.1 介绍
    • 5.2 @ConfigurationProperties

Mybatis 案例

一、 准备工作

前置知识:Mybatis - 基础

1.1 数据库表

-- 部门管理
create table dept(
 id int unsigned primary key auto_increment comment '主键ID',
 name varchar(10) not null unique comment '部门名称',
 create_time datetime not null comment '创建时间',
 update_time datetime not null comment '修改时间'
) comment '部门表';

-- 部门表测试数据
insert into dept (id, name, create_time, update_time) values(1,'学工
部',now(),now()),(2,'教研部',now(),now()),(3,'咨询部',now(),now()),
(4,'就业部',now(),now()),(5,'人事部',now(),now());
-- 员工管理(带约束)

create table emp (
 id int unsigned primary key auto_increment comment 'ID',
 username varchar(20) not null unique comment '用户名',
password varchar(32) default '123456' comment '密码',
 name varchar(10) not null comment '姓名',
 gender tinyint unsigned not null comment '性别, 说明: 1 男, 2 女',
 image varchar(300) comment '图像',
 job tinyint unsigned comment '职位, 说明: 1 班主任,2 讲师, 3 学工主
管, 4 教研主管, 5 咨询师',
 entrydate date comment '入职时间',
 dept_id int unsigned comment '部门ID',
 create_time datetime not null comment '创建时间',
 update_time datetime not null comment '修改时间'
) comment '员工表';

-- 员工表测试数据
INSERT INTO emp
 (id, username, password, name, gender, image, job,
entrydate,dept_id, create_time, update_time) VALUES
 (1,'jinyong','123456','金庸',1,'1.jpg',4,'2000-01-
01',2,now(),now()),
 (2,'zhangwuji','123456','张无忌',1,'2.jpg',2,'2015-01-
01',2,now(),now()),
 (3,'yangxiao','123456','杨逍',1,'3.jpg',2,'2008-05-
01',2,now(),now()),
 (4,'weiyixiao','123456','韦一笑',1,'4.jpg',2,'2007-01-
01',2,now(),now()),
 (5,'changyuchun','123456','常遇春',1,'5.jpg',2,'2012-12-
05',2,now(),now()),
 (6,'xiaozhao','123456','小昭',2,'6.jpg',3,'2013-09-
05',1,now(),now()),
 (7,'jixiaofu','123456','纪晓芙',2,'7.jpg',1,'2005-08-
01',1,now(),now()),
 (8,'zhouzhiruo','123456','周芷若',2,'8.jpg',1,'2014-11-
09',1,now(),now()),
 (9,'dingminjun','123456','丁敏君',2,'9.jpg',1,'2011-03-
11',1,now(),now()),
 (10,'zhaomin','123456','赵敏',2,'10.jpg',1,'2013-09-
05',1,now(),now()),
 (11,'luzhangke','123456','鹿杖客',1,'11.jpg',5,'2007-02-
01',3,now(),now()),
 (12,'hebiweng','123456','鹤笔翁',1,'12.jpg',5,'2008-08-
18',3,now(),now()),
 (13,'fangdongbai','123456','方东白',1,'13.jpg',5,'2012-11-
01',3,now(),now()),
 (14,'zhangsanfeng','123456','张三丰',1,'14.jpg',2,'2002-08-
01',2,now(),now()),
 (15,'yulianzhou','123456','俞莲舟',1,'15.jpg',2,'2011-05-
01',2,now(),now()),
 (16,'songyuanqiao','123456','宋远桥',1,'16.jpg',2,'2007-01-
01',2,now(),now()),
 (17,'chenyouliang','123456','陈友谅',1,'17.jpg',NULL,'2015-03-
21',NULL,now(),now());

1.2 Restfull规范

Controller层开发、请求与响应、RESTful开发规范_springboot控制层代码规范_

1.3 封装结果类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {
    private Integer code;//响应码,1 代表成功; 0 代表失败
    private String msg; //响应信息 描述字符串
    private Object data; //返回的数据

    //增删改 成功响应
    public static Result success() {
        return new Result(1, "success", null);
    }

    //查询 成功响应
    public static Result success(Object data) {
        return new Result(1, "success", data);
    }

    //失败响应
    public static Result error(String msg) {
        return new Result(0, msg, null);
    }
}

1.4 实体类

剩余的实体类都在 “mybatis-基础”中添加了

/*部门类*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Dept {
    private Integer id;
    private String name;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
}

二、部门管理

2.1 查询全部部门信息

SQL

@Mapper
public interface DeptMapper {
    @Select("select * from dept")
    List<Dept> list();
}

测试接口:

@GetMapping("/depts")
public Result list() {
    log.info("查询全部数据");

   List<Dept> deptList =  deptService.list();
    return Result.success(deptList);
}

返回结果:

{
    "code": 1,
    "msg": "success",
    "data": [
        {
            "id": 1,
            "name": "学工部",
            "createTime": "2023-05-13T11:16:16",
            "updateTime": "2023-05-13T11:16:16"
        },
        {
            "id": 2,
            "name": "教研部",
            "createTime": "2023-05-13T11:16:16",
            "updateTime": "2023-05-13T11:16:16"
        },
        {
            "id": 3,
            "name": "咨询部",
            "createTime": "2023-05-13T11:16:16",
            "updateTime": "2023-05-13T11:16:16"
        },
        {
            "id": 4,
            "name": "就业部",
            "createTime": "2023-05-13T11:16:16",
            "updateTime": "2023-05-13T11:16:16"
        },
        {
            "id": 5,
            "name": "人事部",
            "createTime": "2023-05-13T11:16:16",
            "updateTime": "2023-05-13T11:16:16"
        }
    ]
}

2.2 删除部门

SQL

    @Delete("delete from dept where id= #{id}")
    void deleteById(Integer id);

接口

@DeleteMapping("/depts/{id}")
public Result delete(@PathVariable Integer id) {
    log.info("根据Id删除部门:{}", id);
    deptService.deleteById(id);
    return Result.success();
}

2.3 新增部门

SQL

    @Insert("insert  into dept(name,create_time,update_time) value (#{name},#{createTime},#{updateTime})")
    void add(Dept dept);

接口

@PostMapping("/depts")
public Result add(@RequestBody Dept dept) {
    deptService.add(dept);
    return Result.success();
}

三、员工管理

3.1 分页查询

SQL语句

起始索引与页码、查询返回的记录数有关系

--  分页查询语法
--  参数1: 起始索引 = (页码-1)*每页展示的记录数
--  参数2: 查询返回的记录数
--  含义: 从第一条记录开始查询,一共查询五条记录
select * from emp LIMIT 0,5

实体类封装分页查询的结果

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PageBean {
    private Long total; //总记录数
    private List rows;  //当前页数数据列表
}

请求参数

image-20230514151904945

SQL语句

        @Select("select count(*) from emp")
        public Long count();//查询总记录数

        @Select("select * from emp limit #{start},#{pageSize}")
        public List<Emp> page(Integer start,Integer pageSize); //分页查询获取列表数据

接口代码

    @GetMapping("/emps")
    public Result page(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize) {
        log.info("分页查询,参数:{},{}", page, pageSize);
//      调用Service分页查询
        PageBean pageBean = empService.page(page,pageSize);
        return Result.success(pageBean);
    }

业务实现

    @Override
    public PageBean page(Integer page, Integer pageSize) {
//      TODO 获取总记录数
        Long count = empMapper.count();
//      TODO 获取分页数据
        Integer start = (page-1)*pageSize;

        List<Emp> empList = empMapper.page(start, pageSize);

        PageBean pageBean = new PageBean(count,empList);

        return pageBean;
    }

3.2 分页查询 - PageHelper插件

**两种方式对比:**所有的操作都是分页插件帮我们实现的,我们只需要正常的执行查询操作即可

image-20230514172606165

Maven坐标

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.6</version>
</dependency>

SQL

@Select("select * from emp")
public List<Emp> list();

业务层

    @Override
    public PageBean page(Integer page, Integer pageSize) {
//     TODO  设置分页参数
        PageHelper.startPage(page,pageSize);
//     TODO  执行查询
        List<Emp> list = empMapper.list();
        Page<Emp> p = (Page<Emp>)list;

//     TODO  封装PageBean
        PageBean pageBean = new PageBean(p.getTotal(),p.getResult());

        return pageBean;
    }

日志输出

仔细观察,就会发现插件所调用的方法就是 3.1 我们手写的SQL语句,只不过插件帮我们完成了而已。

> Preparing: SELECT count(0) FROM emp
> Parameters:
<
Columns: count(0)
<
Row: 16
<== Total: 1
> Preparing: select * from emp LIMIT ?
> Parameters: 5(Integer)
<
Columns: id, username, password, name, gender, image, job, entrydate, dept_id, create_time, update_time
<
Row: 4, weiyixiao, 123456, 韦一笑, 1, 4.jpg, 2, 2007-01-01, 2, 2023-05-13 11:16:16, 2023-05-13 11:16:16
<== Row: 5, changyuchun, 123456, 常遇春, 1, 5.jpg, 2, 2012-12-05, 2, 2023-05-13 11:16:16, 2023-05-13 11:16:16
<== Row: 6, xiaozhao, 123456, 小昭, 2, 6.jpg, 3, 2013-09-05, 1, 2023-05-13 11:16:16, 2023-05-13 11:16:16
<== Row: 7, jixiaofu, 123456, 纪晓芙, 2, 7.jpg, 1, 2005-08-01, 1, 2023-05-13 11:16:16, 2023-05-13 11:16:16
<== Row: 8, zhouzhiruo, 123456, 周芷若, 2, 8.jpg, 1, 2014-11-09, 1, 2023-05-13 11:16:16, 2023-05-13 11:16:16
<== Total: 5

3.3 分页查询 - 条件查询

image-20230514151904945

接口

//    @DateTimeFormat注解指定前端传输过来的日期格式
    @GetMapping("/emps")
    public Result page(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer pageSize,
                       String name, Short gender,
                       @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd")  LocalDate end) {
        log.info("分页查询,参数:{},{},{},{},{},{}", page, pageSize,name,gender,begin,end);
//      调用Service分页查询
        PageBean pageBean = empService.page(page,pageSize,name,gender,begin,end);
        return Result.success(pageBean);
    }

SQL - XML 映射文件

public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);
<mapper namespace="com.zhangjingqi.mapper.EmpMapper">
    <select id="list" resultType="com.zhangjingqi.pojo.Emp">
        select *
        from emp
        <where>
            <if test="name !=null and name!=''">
                name like concat('%',#{name},'%')
            </if>
            <if test="gender !=null">
                and gender =#{gender}
            </if>
            <if test="begin !=null and end!=null">
                and entrydate between #{begin} and #{end}
            </if>
        </where>
        order by update_time desc
    </select>
</mapper>

业务代码

    @Override
    public PageBean page(Integer page, Integer pageSize, String name, Short gender,LocalDate begin, LocalDate end) {
//     TODO  设置分页参数
        PageHelper.startPage(page,pageSize);
//     TODO  执行查询
        List<Emp> list = empMapper.list(name,  gender,  begin,  end);
        Page<Emp> p = (Page<Emp>)list;

//     TODO  封装PageBean
        PageBean pageBean = new PageBean(p.getTotal(),p.getResult());

        return pageBean;
    }

3.4 批量删除员工

接口

@DeleteMapping("/{ids}")
public Result delete(@PathVariable List<Integer> ids) {
    log.info("批量删除操作,ids:{}",ids);
    empService.delete(ids);
    return Result.success();
}

业务逻辑

@Override
public void delete(List<Integer> ids) {
 empMapper.delete( ids);
}

SQL

    void delete(@Param("ids") List<Integer> ids);

XML文件映射

<delete id="delete">
    delete
    from emp
    <where>
        id in
        <foreach collection="ids" item="id" separator="," open="(" close=")">
            #{id}
        </foreach>
    </where>
</delete>

参考资料:mybatis中foreach collection三种用法-腾讯云开发者社区-腾讯云 (tencent.com)

再详细讲解一下foreach标签中的collection参数

collection : 指定要遍历的集合或数组,可以是 List、Set、Array、Map 等类型。遍历操作会把元素依次添加到 SQL 语句中。

  • 在 MyBatis 中,<foreach> 标签的 collection 属性可以有三种用法:

    1. *Java 集合和数组方式

    可以将一个 Java 集合或数组传入方法作为参数,MyBatis 会自动将其转换为 Map 类型,其中 collection 属性指定为参数的名称。下面是使用集合方式的示例:

    <select id="getUsersByIds" parameterType="map" resultType="User">
        SELECT *
        FROM user
        WHERE id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>
    

    在该示例中,ids 是传入方法的 List 类型参数的名称,在 SQL 语句中用 #{id} 获取集合中的每个元素。

    ​ 下面这种方式也是

        void delete(@Param("ids") List<Integer> ids);
    
    <delete id="delete">
        delete
        from emp
        <where>
            id in
            <foreach collection="ids" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </where>
    </delete>
    
    1. 嵌套 SQL 语句方式

    除了直接使用集合参数方式,还可以在 <foreach> 标签的 collection 属性中直接编写 SQL 语句或调用已定义的 mapper,返回指定列表数据作为集合参数。下面是使用 SQL 语句方式的示例:

    <select id="getUsersByAge" parameterType="int" resultType="User">
        SELECT *
        FROM user
        WHERE age IN
        <foreach collection="select id from age_table where age = #{age}" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>
    

    在该示例中,使用 SQL 语句方式获取年龄等于某个值的用户 ID 列表,后面进行 in 查询。

    1. 数组方式

    可以将一个简单的 Java 数组传递给一个方法,下面是使用数组方式的示例:

    <select id="getUsersByIds" parameterType="array" resultType="User">
        SELECT *
        FROM user
        WHERE id IN
        <foreach collection="array" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>
    

    在该示例中,Mapper 方法接收的参数为简单的数组,直接在 SQL 中使用 [?]占位符,并将 array 作为 collection 传入即可。

3.5 新增员工

接口

@PostMapping
public Result save(@RequestBody Emp emp){

    empService.save(emp);

    return Result.success();
}

SQL

@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})")
public void insert(Emp emp);

业务层

@Override
public void save(Emp emp) {
    emp.setUpdateTime(LocalDateTime.now());
    emp.setCreateTime(LocalDateTime.now());

    empMapper.insert(emp);
}

3.6 修改员工

3.6.1 查询回显

接口

@GetMapping("/emps/{id}")
public Result getById(@PathVariable Integer id){
    log.info("根据ID查询员工信息:id{}",id);
    Emp emp = empService.getById(id);
    return Result.success(emp);
}

SQL

@Select("select * from emp where id=#{id}")
public Emp getById(Integer id);

3.6.2 修改员工

接口

@PutMapping
public Result update(@RequestBody Emp emp){
    log.info("更新员工信息");
    empService.update(emp);
    return Result.success();
}

业务实现

@Override
public void update(Emp emp) {
    emp.setUpdateTime(LocalDateTime.now());
    empMapper.update(emp);
}

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 image != ''">
            image = #{image},
        </if>
        <if test="job != null">
            job = #{job},
        </if>
        <if test="entrydate != null">
            entrydate = #{entrydate},
        </if>
        <if test="deptId != null">
            dept_id = #{deptId},
        </if>
        <if test="updateTime != null">
            update_time = #{updateTime}
        </if>
    </set>
    where id = #{id}
</update>

四、文件上传

4.0 html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>上传文件</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data" >
    姓名:<input type="text" name="username">
    年龄:<input type="text" name="age">
    头像:<input type="file" name="image">
    <input type="submit" value="提交">
</form>
</body>
</html>

4.1 简介

  • 文件上传,指将本地图片、视频、音频等文件上传到服务器,供其他用户浏览或下载的过程。

这是之前做的文件上传下载的笔记,但是是保存到本地的,知识点挺详细的

Springboot——文件的上传与下载(reggie)_

4.2 本地存储

  • 开发中基本不用这种方式。如果将文件存储在服务器磁盘当中,前端是没有办法直接访问的

  • 如果说服务器中上传了大量的文件占满了磁盘,服务器是不容易扩容的

  • 假如服务器的磁盘坏了,里面存储的所有数据全部丢失

接口

    @PostMapping("/upload")
    public Result upload(String username, Integer age, MultipartFile image) throws IOException {
//      MultipartFile 介绍文件
//      TODO 文件的name(表单项中的名字),filename已经封装在MultipartFile中
        String originalFilename = image.getOriginalFilename();  // 文件原始名

//      TODO 构造唯一文件名(不能重复) - 采用uuid  通用唯一识别码,长度固定字符串,是不会重复的
        int index = originalFilename.lastIndexOf("."); //最后一个点的坐标

        String imageType = originalFilename.substring(index); //ru .jpg

        String imageName = UUID.randomUUID().toString()+imageType;
        log.info("新文件名:{}",imageName);
//        将文件存储在磁盘目录当中  E:\Note\SpringBootWeb\Note\image
//        image.transferTo(new File("E:/Note/SpringBootWeb/Note/image/"+originalFilename));
//        但是我们一般不使用文件原始名进行存储,因为用户A存储照片的名称为1.jpg,用户B存储照片的名称为1.jpg,那这样用户B的图片将用户A的图片覆盖了

//        TODO 将文件存储在磁盘目录当中  E:\Note\SpringBootWeb\Note\image
        image.transferTo(new File("E:/Note/SpringBootWeb/Note/image/"+imageName));
        return Result.success();
    }

请求

image-20230515122926584

当我们上传一个比较大的文件(超过1M)时,服务端就会出现异常

org.apache.tomcat.util.http.fileupload.impl.FileSizeLimitExceededException: The field image exceeds its maximum permitted size of 1048576 bytes.
at org.apache.tomcat.util.http.fileupload.impl.FileItemStreamImpl$1.raiseError(FileItemStreamImpl.java:117) ~[tomcat-embed-core-9.0.74.jar:9.0.74]
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.checkLimit(LimitedInputStream.java:76) ~[tomcat-embed-core-9.0.74.jar:9.0.74]
at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:135) ~[tomcat-embed-core-9.0.74.jar:9.0.74]

解决方案

spring:
  servlet:
    multipart:
#     配置单个文件最大上传大小
      max-file-size: 10MB
#     配置单个请求最大上传大小(一次请求可以上传多个文件)
      max-request-size: 100MB

MultipartFile类常用方法

image-20230515124555636

4.3 对象存储 OSS

文件上传-阿里云OSS-准备

帮助文档: https://oss.console.aliyun.com/sdk

​ https://help.aliyun.com/document_detail/32007.html?spm=a2c4g.52834.0.0.663862a9UbH61y

可以通过网络随时存储和调用包括文本、图片、音频和视频在内的各种文件

SDK:软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK

Bucket:存储空间是用户用于存储对象(Object,就是文件)的容器,所有的对象都必须隶属于某个存储空间

4.3.1 maven坐标

因为我使用的java8,只需要引用这个坐标,如果是java9及其以上版本,需要在帮助文档中复制其他的

<dependency>
    <groupId>com.aliyun.oss</groupId>
    <artifactId>aliyun-sdk-oss</artifactId>
    <version>3.15.1</version>
</dependency>

4.3.2 简单上传

帮助文档: https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.84778.0.0.12271cc87u9r8x

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
//      TODO 我在华北2,所以用北京
        String endpoint = "https://oss-cn-beijing.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "LTAI5t6aEYHiGAqeJ28Pz2mR";
        String accessKeySecret = "自己写自己的,不要用我的我没钱";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "picture-typora-zhangjingqi";
        // 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
        String objectName = "1.jpg"; //最终在OSS中叫什么名字

//      填写本地文件的完整路径,例如D:/exampledir/exampleobject.txt
//      如果没有指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件流
        String filePath = "E:\\Note\\SpringBootWeb\\Note\\image\\0bf39d2621167df89780626b602cfad.jpg";

// 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            InputStream inputStream = new FileInputStream(filePath);
            // 创建PutObjectRequest对象。
            PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, inputStream);
            // 设置该属性可以返回response。如果不设置,则返回的response为空。
            putObjectRequest.setProcess("true");
            // 创建PutObject请求。
            PutObjectResult result = ossClient.putObject(putObjectRequest);
            // 如果上传成功,则返回200。
            System.out.println(result.getResponse().getStatusCode());
        }catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}

4.4 案例集成OSS

  • 上传员工的图像并保存起来

  • 将上传的图像进行展示

流程

image-20230515140126085

接口

    @Autowired
    private AliOSSUtils aliOSSUtils;

    @PostMapping("/upload")
    public Result upload(MultipartFile image) throws IOException {

        log.info("文件上传,文件名:{}", image.getOriginalFilename());
//      调用阿里云OOS工具类进行上传
        String url = aliOSSUtils.upload(image);
        log.info("文件上传完成,url:{}",url);

        return Result.success(url);
    }

4.4.1 上传工具类

/**
 * 阿里云 OSS 工具类
 */
@Component
public class AliOSSUtils {

    private String endpoint = "https://oss-cn-beijing.aliyuncs.com";
    private String accessKeyId = "LTAI5t6aEYHiGAqeJ28Pz2mR";
    private String accessKeySecret = "Dm4H7Lbq9NpDDmIEsC1mCX8U694C7b";
    private String bucketName = "picture-typora-zhangjingqi";

    /**
     * 实现上传图片到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);

        //文件访问路径  比如 https://picture-typora-zhangjingqi.oss-cn-beijing.aliyuncs.com/1.jpg
//         相当于把bucketName拼接在http://后面,把文件名字拼接在aliyuncs.com/ 后面
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
        // 关闭ossClient
        ossClient.shutdown();
        return url;// 把上传到oss的路径返回
    }

}

五、 配置文件

5.1 介绍

之前笔记

读取yaml配置文件中的基本数据+字符串_yaml配置字符串数组

springboot—YAML文件中读取Map集合并带有转义字符(问题记录)_yaml文件map

# 对象/Map集合
user:
  name: zhangsan
  age: 18
  password: 123456

# 数组/List/Set集合
hobby:
  - java
  - game
  - sport

5.2 @ConfigurationProperties

前提是类中的属性名与yaml文件中属性名保持一致才能将yaml文件属性名对应的值自动填充到类中的属性名

prefix:表示前缀

image-20230515153553960

  • @Value注解只能一个一个的进行外部属性注入
  • @ConfigurationProperties可以批量的将外部属性配置注入到bean对象的属性中

添加依赖 - 可添加也可不添加

我们可以添加下面的依赖,不添加也能使用,只不过Idea会有提示。添加之后会方便我们后续的开发。

在properties或者yaml配置文件中会提示@ConfigurationProperties注解所在类中的属性。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

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

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

相关文章

蓝桥杯模块学习3——蜂鸣器与继电器

第一章 硬件部分 1.1 电路的组成部分 1.1.1 译码器和锁存器 具体可回顾之前LED灯的文章&#xff1a; https://blog.csdn.net/weixin_63568691/article/details/130660096 1.1.2 ULN2003达林顿管 原理图&#xff1a; 功能&#xff1a; &#xff08;1&#xff09;改变电路特性…

使用Spring初始化器创建Spring Boot项目

注&#xff1a;初始化向导需要联网创建Spring Boot项目 new project 项目创建完成 resources 文件夹中目录结构&#xff1a; static &#xff1a;保存所有的静态资文件&#xff0c; js css images templates &#xff1a;保存所有的模板页面&#xff08;Spring Boot默认j…

python3 爬虫相关学习1:安装requests模块

目录 1 安装前&#xff1a;避免python2 python3 引起的问题 2 如何安装python3 2.1 直接上python3 官网下载 2.2 或者windows的话&#xff0c;microsoft store 里也可以下载 2.3 查看python版本 3 安装requests模块 3.1 很可能安装requests模块之前会遇到报错&#xff…

linux0.12-8-11-vsprintf.c

[383页] 1、 这一小节可以不看代码如何实现&#xff0c;因为标准的C库函数&#xff1b; 2、 等自己看完的这本书&#xff0c;有兴趣过来研究研究也是可以的。 8-11 vsprintf.c程序 8-11-1 功能描述 该程序主要包括vsprintf(),用于对参数产生格式化的输出。由于该函数是C函数…

SOME/IP 草稿

SOME/IP 名词解释 SOME/IP 全称是 Scalable service-Oriented MiddlewarE over IP。也就是基于 IP 协议的面向服务的可扩展性通信中间件协议。 面向服务 SOA基于 IP 协议之上的通信协议中间件 SOME/IP 功能 服务发现 (Service Discovery)远程服务调用 &#xff08;RPC,rem…

React面试题汇总 --2

1. 何为 redux &#xff0c;解决什么问题 操作流程 使用场景 优缺点 &#xff1f; Redux使用详解(一) Redux的核心思想与基本使用__聪明勇敢有力气的博客-CSDN博客Redux使用详解(一) Redux的核心思想与基本使用https://blog.csdn.net/weixin_65402230/article/details/128193…

全免费开源-国内搭建ChatGPT个人镜像站与维护全攻略

全免费开源-国内搭建ChatGPT个人镜像站与维护全攻略 准备阶段部署网站腾讯云注册与解析添加API和密码更换域名的配置多密码管理密码更换密码批量生成 本教程收集于&#xff1a;AIGC从入门到精通教程汇总 全免费开源&#xff0c;仅需一个域名就可以部署国内的ChatGPT镜像版本。…

ConvTranspose2d 的简单例子理解

文章目录 参考基础概念简单例子&#xff1a; stride2step1step2step3 参考 逆卷积的详细解释ConvTranspose2d&#xff08;fractionally-strided convolutions)nn.ConvTranspose2d的参数output_padding的作用 基础概念 逆卷积&#xff0c;也叫反卷积或者转置卷积&#xff0c;…

故障分析 | OceanBase 频繁更新数据后读性能下降的排查

本文摘要 本文分析并复现了 OceanBase 频繁更新数据后读性能下降现象的原因&#xff0c;并给出了性能改善建议。 背景 测试在做 OceanBase 纯读性能压测的时候&#xff0c;发现对数据做过更新操作后&#xff0c;读性能会有较为明显的下降。具体复现步骤如下。 复现方式 环…

部门新来一00后,给我卷崩溃了...

2022年已经结束结束了&#xff0c;最近内卷严重&#xff0c;各种跳槽裁员&#xff0c;相信很多小伙伴也在准备今年的金三银四的面试计划。 在此展示一套学习笔记 / 面试手册&#xff0c;年后跳槽的朋友可以好好刷一刷&#xff0c;还是挺有必要的&#xff0c;它几乎涵盖了所有的…

NFT数字藏品平台

在 NFT &#xff08;非同质化代币&#xff09;发行和交易中&#xff0c;数字藏品交易平台&#xff08;以下简称“交易平台”&#xff09;的运营模式和法律地位至关重要。本文对数字藏品交易平台的运营方式进行梳理&#xff0c;并对其中可能存在的法律风险进行分析。 2021年以来…

NFS服务器搭建(案例)

目录标题 第一个问题1.安装软件包2.进入配置文件进行定义&#xff0c;并创建对应的资源文件3.客户端进行挂载&#xff0c;并查看挂载信息&#xff0c;修改挂载权限4.客户端查看挂载的信息 第二个问题1.服务端配置文件进行定义&#xff0c;并创建对应资源文件2.客户端进行挂载3.…

电子邮件是最有效的营销方式吗?解析邮件营销的优势和劣势

互联网的快速发展&#xff0c;使得新媒体营销、短视频营销、微信营销等新型营销方式渗入到大家的生活中。很多人会认为邮件营销已经落后。但事实上&#xff0c;邮件营销仍然有着广泛的市场需求&#xff0c;特别是对于出海或者做跨境电商的企业来讲&#xff0c;邮件营销仍然发挥…

深度学习笔记(续)——数值稳定性、模型初始化与激活函数

深度学习笔记[续]——数值稳定性、模型初始化与激活函数 引言回顾&#xff1a;没有激活函数参与&#xff0c;输入输出分布的变化情况 Xavier \text{Xavier} Xavier方法 存在激活函数的情况假设激活函数是线性函数激活函数的底层逻辑 总结 引言 继续上一节介绍激活函数在神经网…

Google IO 2023推出Android Studio官方AI工具Studio Bot

Google推出Android Studio官方AI工具Studio Bot Studio Bot 简介 在2023 Google I/O大会上&#xff0c;Google 宣布在 Android Studio 中推出了一款名为 Studio Bot 的新 AI 功能&#xff0c;它将为开发者提供更高效、智能的开发体验。Studio Bot 是一个基于机器学习的助手&a…

想要快速进入车载测试?这份车载面试题集锦送给你,建议收藏!

1.道路测试流程 测试场地 1.测试场地有哪些&#xff1f; 对于一些要求不太高/简单的测试场景可以找一些封闭的场地&#xff0c;如断头路或者是城市所在地当地政府提供的诸如智能网联专用道路之类的测试道路&#xff0c;对于复杂或相对要求高一些的测试场景可以到专业的国家智…

【运维杂谈】如何将ios镜像挂载到Linux系统中?

本期我们实现将CentOS7.9系统镜像挂载到Linux系统当中&#xff0c;首先明确什么是挂载&#xff0c;我理解的挂载就是把系统镜像与Linux操作系统建立直接的联系&#xff0c;将镜像的顶级目录连接到Linux根目录下的某一目录中&#xff0c;就好比我们Windows系统插入一张光盘&…

C++学习记录——이십삼 哈希表

文章目录 1、unordered_map unordered_set2、哈希表1、闭散列2、开散列&#xff08;拉链法/哈希桶&#xff09;继续优化 3、封装unordered和迭代器 1、unordered_map unordered_set C11提供&#xff0c;功能和map、set完全类似&#xff0c;不过它们底层实现是红黑树&#xff0…

JDBC~

文章目录 JDBCJDBC API详解DriverManagerConnectionStatementResultSetPreparedStatementPreparedStatement原理 JDBC JDBC就是使用JAVA语言操作关系型数据库的一套API JDBC是java处理数据库的接口 JDBC API详解 DriverManager 驱动管理类: 注册驱动&#xff0c;获取数据库连接…

Cplex的数据类型结构及基本语法功能

本序列将会重开一门新的序列----数学求解器cplex,文章不做简单介绍&#xff0c;不灌水&#xff0c;直接给大家进行讲述如何上手实操&#xff0c;并有针对性的给出相应案例分析。 OPL编程 OPL是ILOG团队为运筹学专家量身定制的一种优化建模语言&#xff0c;语法相对简单&#x…