springboot整合mybatis-plus及mybatis-plus分页插件的使用

news2024/11/15 20:04:28

springboot整合mybatis-plus及mybatis-plus分页插件的使用

  • 1. mybatis-plus?
  • 2. 引入依赖
  • 3. 编写配置文件
  • 4. 编写sql表
  • 5. mapper层
    • 5.1 mybatis-plus做了什么?及创建mapper接口
    • 5.2 baseMapper源码
  • 6. service层及controller层
    • 6.1 service层
    • 6.2 controller层
      • 6.2.1 page对象
  • 7. 分页插件的使用
  • 8. 数据显示html页面
  • 9. 项目结构及整合测试
    • 9.1 项目结构
    • 9.2 运行测试
  • 总结

1. mybatis-plus?

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

在这里插入图片描述

mybatis-plus官网: https://baomidou.com/pages/24112f/

2. 引入依赖

引入mybatis-plus的第三方stater以及数据源:

        <!--    mybatis-plus stater    -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
        <!--   druid数据源     -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.17</version>
        </dependency>
        <!--     mysql驱动   -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

3. 编写配置文件

在application.yaml中配置数据源的相关配置:

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/phpdemo?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

4. 编写sql表

编写测试用例的sql表:

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` bigint(0) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '姓名',
  `age` int(0) NULL DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NULL DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'Jone', 18, 'test1@baomidou.com');
INSERT INTO `user` VALUES (2, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `user` VALUES (3, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `user` VALUES (5, 'Billie', 24, 'test5@baomidou.com');
INSERT INTO `user` VALUES (6, '叶秋', 18, 'robindebug@163.com');
INSERT INTO `user` VALUES (7, '张三', 49, 'zhangsan@126.com');

SET FOREIGN_KEY_CHECKS = 1;

5. mapper层

5.1 mybatis-plus做了什么?及创建mapper接口

在springboot中使用mybatis-plus创建mapper接口,可以通过继承baseMapper类来快速生成常用的sql(baseMapper类为我们提供了很便捷的sql,懒人必备哈哈哈)

mapper接口:

package com.robin.boot.mapper;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.robin.boot.bean.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * 使用mapper接口继承BaseMapper的方式,可以快速获得常用的sql
 * 无须编写mapper.xml文件
 */
@Mapper
public interface UserMapper extends BaseMapper<User> {

}

注意mybatis-plus为我们自动配置了以下内容:

  • MybatisPlusAutoConfiguration 配置类,MybatisPlusProperties 配置项绑定。mybatis-plus:xxx 就是对mybatis-plus的定制
  • SqlSessionFactory 自动配置好。底层是容器中默认的数据源
  • mapperLocations 自动配置好的。有默认值。classpath*:/mapper/**/*.xml;任意包的类路径下的所有mapper文件夹下任意路径下的所有
    xml都是sql映射文件。 建议以后sql映射文件,放在 mapper下
  • 容器中也自动配置好了 SqlSessionTemplate
  • @Mapper 标注的接口也会被自动扫描;

相比mybatis的整合,这次我们连创建xml也不需要了,它已经自动默认好了。

5.2 baseMapper源码

baseMapper源码:

/*
 * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * https://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.baomidou.mybatisplus.core.mapper;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import org.apache.ibatis.annotations.Param;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * Mapper 继承该接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
 * <p>这个 Mapper 支持 id 泛型</p>
 *
 * @author hubin
 * @since 2016-01-23
 */
public interface BaseMapper<T> extends Mapper<T> {

    /**
     * 插入一条记录
     *
     * @param entity 实体对象
     */
    int insert(T entity);

    /**
     * 根据 ID 删除
     *
     * @param id 主键ID
     */
    int deleteById(Serializable id);

    /**
     * 根据 columnMap 条件,删除记录
     *
     * @param columnMap 表字段 map 对象
     */
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    /**
     * 根据 entity 条件,删除记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int delete(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 删除(根据ID 批量删除)
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

    /**
     * 根据 ID 修改
     *
     * @param entity 实体对象
     */
    int updateById(@Param(Constants.ENTITY) T entity);

    /**
     * 根据 whereEntity 条件,更新记录
     *
     * @param entity        实体对象 (set 条件值,可以为 null)
     * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
     */
    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);

    /**
     * 根据 ID 查询
     *
     * @param id 主键ID
     */
    T selectById(Serializable id);

    /**
     * 查询(根据ID 批量查询)
     *
     * @param idList 主键ID列表(不能为 null 以及 empty)
     */
    List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

    /**
     * 查询(根据 columnMap 条件)
     *
     * @param columnMap 表字段 map 对象
     */
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

    /**
     * 根据 entity 条件,查询一条记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询总记录数
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 entity 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录
     * <p>注意: 只返回第一个字段的值</p>
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 entity 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件(可以为 RowBounds.DEFAULT)
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

    /**
     * 根据 Wrapper 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件
     * @param queryWrapper 实体对象封装操作类
     */
    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
}

baseMapper中为我们提供了很多常用的sql方法,只要通过mapper接口继承该接口即可"开箱即用"。

6. service层及controller层

6.1 service层

service层接口:

package com.robin.boot.service;


import com.baomidou.mybatisplus.extension.service.IService;
import com.robin.boot.bean.User;

public interface UserService extends IService<User> {

}

serviceImpl实现类:

package com.robin.boot.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.robin.boot.bean.User;
import com.robin.boot.mapper.UserMapper;
import com.robin.boot.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

}

6.2 controller层

编写controller及请求映射处理:

package com.robin.boot.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.robin.boot.bean.User;
import com.robin.boot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserController {

    @Autowired
    UserService userService;


    // 分页查询用户
    @GetMapping("/showUser")
    public String dynamic_table(@RequestParam(value = "pn",defaultValue = "1")Integer pn, Model model){
        // 分页查询
        Page<User> userPage = new Page<>(pn,3);
        // 分页查询结果
        IPage<User> page = userService.page(userPage,null);
        model.addAttribute("users",page);
        return "show";
    }

    // 单个用户删除
    @GetMapping("/user/delete/{id}")
    public String deleteUser(@PathVariable("id") Long id,
                             @RequestParam(value = "pn",defaultValue = "1") Integer pn){
        userService.removeById(id);
        return "redirect:/showUser?pn="+pn;
    }
}

6.2.1 page对象

在这里插入图片描述

7. 分页插件的使用

我们查看其官网介绍: https://baomidou.com/pages/2976a3/#mybatisplusinterceptor

MybatisPlusInterceptor是核心插件,目前代理了 Executor#query 和 Executor#update 和 StatementHandler#prepare 方法。

mybatis-plus中的所有插件都是基于InnerInterceptor这个接口来实现插件功能。
在这里插入图片描述
官方提供的分页插件参考配置文件如下:

@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
}

创建config包我们自定义配置类,使用mybatis-plus的插件:

package com.robin.boot.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisConfig {

    /**
     * mybatis-plus 分页插件
     * @return
     */
    @Bean
    public MybatisPlusInterceptor paginationInnerInterceptor(){
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
        return mybatisPlusInterceptor;
    }

}

8. 数据显示html页面

使用thymeleaf模板引擎来获取数据和数据遍历,以及视图渲染:

show.html:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>用户数据显示页面</title>
    <style>
        table,tr,td{
            border: 1px solid deepskyblue;
        }
        table{
            margin: 0 auto;
        }
        h3{
            text-align: center;
        }
        .recordsBar{
            text-align: center;
        }
        a{
            color: black;
        }
        .active>a{
            color: red;
        }
    </style>
</head>
<body>
    <h3>用户信息</h3>
    <hr>
    <table>
       <tr>
           <td>id</td>
           <td>姓名</td>
           <td>年龄</td>
           <td>邮箱</td>
           <td>操作</td>
       </tr>
        <tr th:each="user:${users.records}">
           <td th:text="${user.id}">xxxx</td>
           <td th:text="${user.name}">xxxx</td>
           <td th:text="${user.age}">xxxx</td>
           <td th:text="${user.email}">xxxx</td>
           <td><a th:href="@{/user/delete/{id}(id=${user.id},pn=${users.current})}">删除</a></td>
        </tr>
    </table>
    <hr>
    <div class="recordsBar">
        <span>当前第 [[${users.current}]] 页</span>
        <span>共 [[${users.pages}]] 页</span>
        <span>总记录数 [[${users.total}]] 条</span>
        <span th:class="${num == users.current ?'active':''}" th:each="num : ${#numbers.sequence(1,users.pages)}">
            <a th:href="@{/showUser(pn=${num})}" th:text="${num}">1</a>
        </span>
    </div>
</body>
</html>

9. 项目结构及整合测试

9.1 项目结构

在这里插入图片描述

9.2 运行测试

访问localhost:8080/showUser,分页查询用户首页

在这里插入图片描述

点击页码跳转

在这里插入图片描述

测试删除:

在这里插入图片描述
删除后,还是在同页面

在这里插入图片描述

总结

mybatis-plus是mybatis功能的增强版,我们使用的话,也是引入对应的stater即可,相比mybatis更方便,无需指定配置mapper.xml(前提是mapper接口是使用继承baseMapper接口的方式),mybatis-plus提供了baseMapper接口类,我们可以使用自己的mapper接口去继承,可以快速的无需自己编写sql方法,baseMapper接口里面提供了丰富的方法。

mybatis-plus提供了很多插件,可以去其官网查看如何使用。

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

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

相关文章

【html】超链接样式

超链接样式超链接样式超链接样式 根据超链接的类型&#xff0c;显示不同图片的前缀 根据 <!doctype html> <html> <head> <meta charset"utf-8"> <title></title> <style type"text/css"> body {background: …

C# 托管堆遭破坏问题溯源分析

一&#xff1a;背景 1. 讲故事 年前遇到了好几例托管堆被损坏的案例&#xff0c;有些运气好一些&#xff0c;从被破坏的托管堆内存现场能观测出大概是什么问题&#xff0c;但更多的情况下是无法做出准确判断的,原因就在于生成的dump是第二现场&#xff0c;借用之前文章的一张…

Exynos4412 移植针对Samsung的Linux-6.1(四)NandFlash卡驱动

系列文章目录 Exynos4412 移植针对Samsung的Linux-6.1&#xff08;一&#xff09;下载、配置、编译Linux-6.1Exynos4412 移植针对Samsung的Linux-6.1&#xff08;二&#xff09;SD卡驱动——解决无法挂载SD卡的根文件系统Exynos4412 移植针对Samsung的Linux-6.1&#xff08;三…

C++基础——C++ 循环

C基础——C 循环C 循环循环类型循环控制语句无限循环C 循环 有的时候&#xff0c;可能需要多次执行同一块代码。一般情况下&#xff0c;语句是顺序执行的&#xff1a;函数中的第一个语句先执行&#xff0c;接着是第二个语句&#xff0c;依此类推。 编程语言提供了允许更为复杂…

计算机自动和声分析

思路&#xff1a;信号→和声 通过计算特征值&#xff08;特征向量&#xff09;区分音频的关键信息 Chroma特征向量 (32 条消息) 什么是 Chroma Features&#xff1f; - 知乎 (zhihu.com) 基本思想&#xff1a;音高听感的周期性 音高每高一个八度&#xff0c;就回到相似的听…

计算机相关专业提升学历的解决方案(博士研究生)

文章目录1、正规全日制博士1.1 申请 - 考核制1.2 硕博连读与直博2、继续教育&#xff08;非全日制&#xff09;2.1 在职博士2.2 同等学力申博3、海外博士3.1 海外博士3.2 中外合作博士博士录取政策 国内博士&#xff0c;没有具体的政策&#xff0c;招生权力下放到各个高校。 往…

Spark 行动算子

文章目录Spark 行动算子1、reduce2、collect3、count4、first5、take6、takeOrdered7、代码示例8、aggregate9、fold10、countByValue & countByKey (wordcount重点)Spark 行动算子 所谓的行动算子&#xff0c;其实就是触发作业执行的方法&#xff0c;之前的转换算子是不能…

Lua 模块与包

Lua 模块与包 参考至菜鸟教程。 模块类似于一个封装库&#xff0c;从 Lua 5.1 开始&#xff0c;Lua 加入了标准的模块管理机制&#xff0c;可以把一些公用的代码放在一个文件里&#xff0c;以 API 接口的形式在其他地方调用&#xff0c;有利于代码的重用和降低代码耦合度。 Lua…

一起自学SLAM算法:11.3 路径规划

连载文章&#xff0c;长期更新&#xff0c;欢迎关注&#xff1a; 路径规划其实就是在回答图11-1中机器人提出的第3个问题“我该如何去”&#xff0c;不管是在已知地图上导航或是在未知环境下通过一边探索地图一边导航&#xff0c;路径规划其实就是在地图上寻找到一条从起点到目…

CMMI3-5级如何高效落地?——CMMI落地4大工具

为了助力CMMI3-5级高效落地&#xff0c;近日CoCode旗下Co-ProjectV3.0智能项目管理平台全面升级&#xff0c;CMMI落地4大工具正式上线&#xff1a;CMMI成熟度自测工具、量化管理工具&#xff08;组织级过程改进工具和量化项目管理工具&#xff09;、组织级过程资产库。 01、CMM…

年后创业,该如何选择适合年轻人的小成本创业项目?

2023年创业大潮即将来袭&#xff0c;疫情政策的放开&#xff0c;会让越来越多的年轻人选择创业。单纯的工作已经不能满足年轻人的生活需求&#xff0c;那无经验、无人脉的年轻人该如何选择适合自己的创业项目&#xff1f;小编在这里总结了几点&#xff0c;适合年轻人的小成本项…

Android Kotlin 多线程编程 server

参考: 《第一行代码 第三版》 10.1 service 是什么 Service是实现程序后台运行的解决方案&#xff0c;适合执行非交互&#xff0c;后台预先的任务&#xff0c;即使用户打开其他应用&#xff0c;Service也能够正常运行 Service需要内部手动创建子线程 10.2 多线程编程 用法&a…

Makefile学习⑨:Makefile中的等号和shell命令的使用

Makefile学习⑨&#xff1a;Makefile中的等号和shell命令的使用 Makefile中的等号 “” 普通赋值符号&#xff0c;命令格式如下 变量值注意&#xff1a;变量的最终值为该文件中的最后进行赋值操作所赋的值。 &#xff08;不管在当前文件的何处进行赋值&#xff0c;在使用该…

【MySQL】MySQL经常使用时间日期相关函数

MySQL经常使用时间、日期相关函数 MySQL经常使用的时间、日期相关函数 1. 日期函数 显示当前日期函数&#xff1a;CURDATE(), CURRENT_DATE(), CURRENT_DATE SQL&#xff1a;select CURDATE(), CURRENT_DATE(), CURRENT_DATE from dual; 2. 时间函数 显示当前日期函数&…

Mysql专栏(五) Mysql高可用

Mysql专栏收尾之作&#xff0c;作为一名后端开发人员&#xff0c;对于Mysql的知识了解到这里已经足以应对99的场景了&#xff0c;毕竟没有必要非要跟DBA抢活儿干。 而且现在的趋势都是往云上走&#xff0c;云数据库已经帮我们处理了高可用和数据一致性的事情了&#xff0c;所以…

初阶指针的介绍

文章目录 指针是什么 指针和指针类型 野指针 指针运算 指针和数组 二级指针 指针数组 一、 指针是什么 指针理解的2个要点&#xff1a; 1. 指针是内存中一个最小单元的编号&#xff0c;也就是地址 2. 平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用…

达梦8数据库优化

1.什么是执行计划&#xff1f; 一条SQL语句在数据库中执行过程或访问路径的描述。 2.如何查看达梦数据库执行计划&#xff1f; 通过explain命令&#xff1a; EXPLAIN 执行的SQL语句&#xff0c;如 SQL> EXPLAIN SELECT * FROM TEST1; 1 #NSET2: [1, 1113, 602] 2 …

Vue笔记01 模板语法,数据代理,事件处理,计算监听属性,绑定样式,列表渲染,数据监测

基本使用 引入vue 创建vue实例并关联容器 一个Vue实例只应对应一个容器 一个Vue实例可以有多个组件 模板语法 使用Vue实例中数据 root容器中代码被称为vue模板 语法分为插值语法和指令(v-xxx) 插值语法 绑定标签体内容 {{}}中的可以是js表达式&#xff08;特殊的js代码&…

CF790 div4 F(双指针) H(逆序对)

乐&#xff0c;被div4薄纱了没想到把所有出现次数>k的数放一个数组里然后双指针还有H&#xff0c;连逆序对都没看出来&#xff0c;嘻感觉以后还是写写div4算了&#xff0c;写什么div2啊&#xff0c;caibiProblem - F - Codeforces题意&#xff1a;给定一个数列&#xff0c;长…

2023万象更新!smardaten企业级无代码新版本也来啦!

2022可以说是在反复的做核酸、查绿码中度过的&#xff0c;不曾想年终一个月还是躲不过“小阳人”的命运。而这一个月&#xff0c;研发部的“阳过”们依旧加班加点给我们带来了最新版本——V8R4C70。在2022-2023跨年之际&#xff0c;smardaten这次又有哪些新的变化呢&#xff0c…