SpringBoot+SSM项目实战 苍穹外卖(12) Apache POI

news2024/11/17 9:28:45

继续上一节的内容,本节是苍穹外卖后端开发的最后一节,本节学习Apache POI,完成工作台、数据导出功能。

目录

  • 工作台
  • Apache POI
    • 入门案例
  • 导出运营数据Excel报表

工作台

工作台是系统运营的数据看板,并提供快捷操作入口,可以有效提高商家的工作效率。

工作台展示的数据:今日数据、订单管理、菜品总览、套餐总览、订单信息

营业额:已完成订单的总金额
有效订单:已完成订单的数量
订单完成率:有效订单数 / 总订单数 * 100%
平均客单价:营业额 / 有效订单数
新增用户:新增用户的数量

在这里插入图片描述

通过上述原型图分析,共包含6个接口。今日数据接口、订单管理接口、菜品总览接口、套餐总览接口、订单搜索(已完成)、各个状态的订单数量统计(已完成)

1). 今日数据的接口设计

请添加图片描述

2). 订单管理的接口设计

请添加图片描述

3). 菜品总览的接口设计

请添加图片描述

4). 套餐总览的接口设计

请添加图片描述

Controller层

添加controller.admin.WorkSpaceController.java

/**
 * 工作台
 */
@RestController
@RequestMapping("/admin/workspace")
@Slf4j
@Api(tags = "工作台相关接口")
public class WorkSpaceController {

    @Autowired
    private WorkspaceService workspaceService;

    /**
     * 工作台今日数据查询
     * @return
     */
    @GetMapping("/businessData")
    @ApiOperation("工作台今日数据查询")
    public Result<BusinessDataVO> businessData(){
        //获得当天的开始时间
        LocalDateTime begin = LocalDateTime.now().with(LocalTime.MIN);
        //获得当天的结束时间
        LocalDateTime end = LocalDateTime.now().with(LocalTime.MAX);

        BusinessDataVO businessDataVO = workspaceService.getBusinessData(begin, end);
        return Result.success(businessDataVO);
    }

    /**
     * 查询订单管理数据
     * @return
     */
    @GetMapping("/overviewOrders")
    @ApiOperation("查询订单管理数据")
    public Result<OrderOverViewVO> orderOverView(){
        return Result.success(workspaceService.getOrderOverView());
    }

    /**
     * 查询菜品总览
     * @return
     */
    @GetMapping("/overviewDishes")
    @ApiOperation("查询菜品总览")
    public Result<DishOverViewVO> dishOverView(){
        return Result.success(workspaceService.getDishOverView());
    }

    /**
     * 查询套餐总览
     * @return
     */
    @GetMapping("/overviewSetmeals")
    @ApiOperation("查询套餐总览")
    public Result<SetmealOverViewVO> setmealOverView(){
        return Result.success(workspaceService.getSetmealOverView());
    }
}

Service层实现类

WorkspaceServiceImpl.java

@Service
@Slf4j
public class WorkspaceServiceImpl implements WorkspaceService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private SetmealMapper setmealMapper;

    /**
     * 根据时间段统计营业数据
     * @param begin
     * @param end
     * @return
     */
    public BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end) {
        /**
         * 营业额:当日已完成订单的总金额
         * 有效订单:当日已完成订单的数量
         * 订单完成率:有效订单数 / 总订单数
         * 平均客单价:营业额 / 有效订单数
         * 新增用户:当日新增用户的数量
         */

        Map map = new HashMap();
        map.put("begin",begin);
        map.put("end",end);

        //查询总订单数
        Integer totalOrderCount = orderMapper.countByMap(map);

        map.put("status", Orders.COMPLETED);
        //营业额
        Double turnover = orderMapper.sumByMap(map);
        turnover = turnover == null? 0.0 : turnover;

        //有效订单数
        Integer validOrderCount = orderMapper.countByMap(map);

        Double unitPrice = 0.0;

        Double orderCompletionRate = 0.0;
        if(totalOrderCount != 0 && validOrderCount != 0){
            //订单完成率
            orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount;
            //平均客单价
            unitPrice = turnover / validOrderCount;
        }

        //新增用户数
        Integer newUsers = userMapper.countByMap(map);

        return BusinessDataVO.builder()
                .turnover(turnover)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate)
                .unitPrice(unitPrice)
                .newUsers(newUsers)
                .build();
    }


    /**
     * 查询订单管理数据
     *
     * @return
     */
    public OrderOverViewVO getOrderOverView() {
        Map map = new HashMap();
        map.put("begin", LocalDateTime.now().with(LocalTime.MIN));//获得当天的开始时间
        map.put("status", Orders.TO_BE_CONFIRMED);

        //待接单
        Integer waitingOrders = orderMapper.countByMap(map);

        //待派送
        map.put("status", Orders.CONFIRMED);
        Integer deliveredOrders = orderMapper.countByMap(map);

        //已完成
        map.put("status", Orders.COMPLETED);
        Integer completedOrders = orderMapper.countByMap(map);

        //已取消
        map.put("status", Orders.CANCELLED);
        Integer cancelledOrders = orderMapper.countByMap(map);

        //全部订单
        map.put("status", null);
        Integer allOrders = orderMapper.countByMap(map);

        return OrderOverViewVO.builder()
                .waitingOrders(waitingOrders)
                .deliveredOrders(deliveredOrders)
                .completedOrders(completedOrders)
                .cancelledOrders(cancelledOrders)
                .allOrders(allOrders)
                .build();
    }

    /**
     * 查询菜品总览
     *
     * @return
     */
    public DishOverViewVO getDishOverView() {
        Map map = new HashMap();
        map.put("status", StatusConstant.ENABLE);
        Integer sold = dishMapper.countByMap(map);

        map.put("status", StatusConstant.DISABLE);
        Integer discontinued = dishMapper.countByMap(map);

        return DishOverViewVO.builder()
                .sold(sold)
                .discontinued(discontinued)
                .build();
    }

    /**
     * 查询套餐总览
     *
     * @return
     */
    public SetmealOverViewVO getSetmealOverView() {
        Map map = new HashMap();
        map.put("status", StatusConstant.ENABLE);
        Integer sold = setmealMapper.countByMap(map);

        map.put("status", StatusConstant.DISABLE);
        Integer discontinued = setmealMapper.countByMap(map);

        return SetmealOverViewVO.builder()
                .sold(sold)
                .discontinued(discontinued)
                .build();
    }
}

Mapper层

在SetmealMapper中添加countByMap方法定义

/**
 * 根据条件统计套餐数量
 * @param map
 * @return
 */
Integer countByMap(Map map);

在SetmealMapper.xml中添加对应SQL实现

<select id="countByMap" resultType="java.lang.Integer">
    select count(id) from setmeal
    <where>
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="categoryId != null">
            and category_id = #{categoryId}
        </if>
    </where>
</select>

在DishMapper中添加countByMap方法定义

/**
 * 根据条件统计菜品数量
 * @param map
 * @return
 */
Integer countByMap(Map map);

在DishMapper.xml中添加对应SQL实现

<select id="countByMap" resultType="java.lang.Integer">
    select count(id) from dish
    <where>
        <if test="status != null">
            and status = #{status}
        </if>
        <if test="categoryId != null">
            and category_id = #{categoryId}
        </if>
    </where>
</select>

测试

请添加图片描述





Apache POI

Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是,我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。
一般情况下,POI 都是用于操作 Excel 文件。

在这里插入图片描述

Apache POI 的应用场景:银行网银系统导出交易明细、各种业务系统导出Excel报表、批量导入业务数据。

入门案例

Apache POI既可以将数据写入Excel文件,也可以读取Excel文件中的数据,接下来分别进行实现。

Apache POI的maven坐标:(项目中已导入)

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>3.16</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.16</version>
</dependency>

将数据写入Excel文件

package com.sky.test;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class POITest {

    /**
     * 基于POI向Excel文件写入数据
     * @throws Exception
     */
    public static void write() throws Exception{
        //在内存中创建一个Excel文件对象
        XSSFWorkbook excel = new XSSFWorkbook();
        //创建Sheet页
        XSSFSheet sheet = excel.createSheet("itcast");

        //在Sheet页中创建行,0表示第1行
        XSSFRow row1 = sheet.createRow(0);
        //创建单元格并在单元格中设置值,单元格编号也是从0开始,1表示第2个单元格
        row1.createCell(1).setCellValue("姓名");
        row1.createCell(2).setCellValue("城市");

        XSSFRow row2 = sheet.createRow(1);
        row2.createCell(1).setCellValue("张三");
        row2.createCell(2).setCellValue("北京");

        XSSFRow row3 = sheet.createRow(2);
        row3.createCell(1).setCellValue("李四");
        row3.createCell(2).setCellValue("上海");

        FileOutputStream out = new FileOutputStream(new File("D:\\itcast.xlsx"));
        //通过输出流将内存中的Excel文件写入到磁盘上
        excel.write(out);

        //关闭资源
        out.flush();
        out.close();
        excel.close();
    }
    public static void main(String[] args) throws Exception {
        write();
    }
}

在D盘中生成itcast.xlsx文件,创建名称为itcast的Sheet页,同时将内容成功写入。

在这里插入图片描述

读取Excel文件中的数据

package com.sky.test;

import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

public class POITest {
    /**
     * 基于POI读取Excel文件
     * @throws Exception
     */
    public static void read() throws Exception{
        FileInputStream in = new FileInputStream(new File("D:\\itcast.xlsx"));
        //通过输入流读取指定的Excel文件
        XSSFWorkbook excel = new XSSFWorkbook(in);
        //获取Excel文件的第1个Sheet页
        XSSFSheet sheet = excel.getSheetAt(0);

        //获取Sheet页中的最后一行的行号
        int lastRowNum = sheet.getLastRowNum();

        for (int i = 0; i <= lastRowNum; i++) {
            //获取Sheet页中的行
            XSSFRow titleRow = sheet.getRow(i);
            //获取行的第2个单元格
            XSSFCell cell1 = titleRow.getCell(1);
            //获取单元格中的文本内容
            String cellValue1 = cell1.getStringCellValue();
            //获取行的第3个单元格
            XSSFCell cell2 = titleRow.getCell(2);
            //获取单元格中的文本内容
            String cellValue2 = cell2.getStringCellValue();

            System.out.println(cellValue1 + " " +cellValue2);
        }

        //关闭资源
        in.close();
        excel.close();
    }

    public static void main(String[] args) throws Exception {
        read();
    }
}

将itcast.xlsx文件中的数据进行读取

在这里插入图片描述





导出运营数据Excel报表

在数据统计页面,有一个数据导出的按钮,点击该按钮时就会下载一个文件。这是一个Excel形式的文件,主要包含最近30日运营相关的数据。表格的形式已经固定,主要由概览数据和明细数据两部分组成。导出这个报表之后,相对应的数字就会填充在表格中。

在这里插入图片描述

导出的Excel报表格式:

在这里插入图片描述

在这里插入图片描述

当前接口没有传递参数,因为导出的是最近30天的运营数据,后端计算即可,所以不需要任何参数

当前接口没有返回数据,因为报表导出功能本质上是文件下载,服务端会通过输出流将Excel文件下载到客户端浏览器

实现步骤:1). 设计Excel模板文件 2). 查询近30天的运营数据 3). 将查询到的运营数据写入模板文件 4). 通过输出流将Excel文件下载到客户端浏览器

Controller层

根据接口定义,在ReportController中创建export方法:

/**
 * 导出运营数据报表
 * @param response
 */
@GetMapping("/export")
@ApiOperation("导出运营数据报表")
public void export(HttpServletResponse response){ //直接在形参里获取到响应对象response
    reportService.exportBusinessData(response);
}

Service层实现类

按照excel模版编写代码填充数据

请添加图片描述

在ReportServiceImpl实现类中实现导出运营数据报表的方法。注意要提前将资料中的运营数据报表模板.xlsx拷贝到项目的resources/template目录中

/**导出近30天的运营数据报表
 * @param response
 **/
public void exportBusinessData(HttpServletResponse response) { //直接在形参里获取到响应对象response
    LocalDate begin = LocalDate.now().minusDays(30);
    LocalDate end = LocalDate.now().minusDays(1); //查到截止昨天 不查今天 因为今天的数据可能还在变
    //查询概览运营数据,提供给Excel模板文件
    BusinessDataVO businessData = workspaceService.getBusinessData(LocalDateTime.of(begin,LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));
    InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
    try {
        //基于提供好的模板文件创建一个新的Excel表格对象
        XSSFWorkbook excel = new XSSFWorkbook(inputStream);
        //获得Excel文件中的一个Sheet页
        XSSFSheet sheet = excel.getSheet("Sheet1");

        //填充数据-时间
        sheet.getRow(1).getCell(1).setCellValue(begin + "至" + end);//填充数据至第2行第2个单元格

        XSSFRow row = sheet.getRow(3);//获得第4行
        //获取单元格
        row.getCell(2).setCellValue(businessData.getTurnover());//第4行第3格填充营业额
        row.getCell(4).setCellValue(businessData.getOrderCompletionRate());//第4行第5格填充订单完成率
        row.getCell(6).setCellValue(businessData.getNewUsers());//第4行第7格填充新增用户数
        row = sheet.getRow(4);//获得第5行
        row.getCell(2).setCellValue(businessData.getValidOrderCount());//第5行第3格填充有效订单数
        row.getCell(4).setCellValue(businessData.getUnitPrice());//第5行第5格填充平均客单价
        //到此概览数据填充完毕 还剩明细数据没有填
        //明细数据每行分别是日期、营业额、有效订单、订单完成率、平均客单价和新增用户数 跟上面的概览数据是一样的
        //区别是概览数据是最近三十天的 明细数据是具体到每一天的
        for (int i = 0; i < 30; i++) {
            LocalDate date = begin.plusDays(i);//要获取每一天的数据
            //准备明细数据
            businessData = workspaceService.getBusinessData(LocalDateTime.of(date,LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));
            row = sheet.getRow(7 + i);
            row.getCell(1).setCellValue(date.toString());
            row.getCell(2).setCellValue(businessData.getTurnover());
            row.getCell(3).setCellValue(businessData.getValidOrderCount());
            row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row.getCell(5).setCellValue(businessData.getUnitPrice());
            row.getCell(6).setCellValue(businessData.getNewUsers());
        }
        //通过输出流将文件下载到客户端浏览器中
        ServletOutputStream out = response.getOutputStream();
        excel.write(out);
        //关闭资源
        out.flush();
        out.close();
        excel.close();

    }catch (IOException e){
        e.printStackTrace();
    }
}

InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(“template/运营数据报表模板.xlsx”);
这个语句用到了类加载器(getClassLoader())来获取运营数据报表模板.xlsx的输入流,什么原理呢?
在Java的resources文件夹src/main/resources文件夹下的内容会被打包到生成的JAR(或者WAR)文件中,因此这些资源文件会被ClassLoader加载。
在我们的代码中,this.getClass().getClassLoader().getResourceAsStream(“template/运营数据报表模板.xlsx”)这句代码的作用是通过类加载器获取运营数据报表模板.xlsx文件的输入流。
这里的getClassLoader()方法是java.lang.Class类的一个方法,用于获取类的ClassLoader。
getResourceAsStream(“template/运营数据报表模板.xlsx”)方法会在类路径下的template文件夹中查找名为运营数据报表模板.xlsx的文件,并返回该文件的输入流对象。
最后,getFile()方法获取该URL的文件表示形式,即文件的路径。
由于运营数据报表模板.xlsx位于resources文件夹的template文件夹下,它会被编译到类路径中。因此,通过类加载器就可以获取到这个文件的输入流。
这种方式通常用于获取类路径下的配置文件、模板文件等资源。
当应用程序打包成可执行的JAR文件时,这种方式仍然适用,因为resources文件夹中的内容会被包含在JAR文件中,ClassLoader可以正确地加载这些资源。更多的参考这篇博客 Java高级: 反射

进入数据统计,点击数据导出,Excel报表下载成功:

请添加图片描述

完结撒花。

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

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

相关文章

SQLServer 为角色开视图SELECT权限,报错提示需要开基础表权限

问题&#xff1a; 创建了个视图V&#xff0c;里面包含V库的a表&#xff0c;和T库的b表 为角色开启视图V的SELECT权限&#xff0c;提示T库的b表无SELECT权限&#xff0c;报错如下 解决方案&#xff1a; ①在T库建个视图TV&#xff0c;里面包含b表&#xff08;注意是在b表的对…

《2023年度程序员收入报告》 :旧金山位居第一,北京程序员中位数超60万元

2024年刚刚拉开序幕&#xff0c;备受瞩目的程序员薪资调研报告再度登场。由知名数据采集平台levels.fyi 搜集并整理了《2023年全球程序员收入报告》&#xff0c;为我们揭示了程序员最新的收入情况&#xff0c;其中有哪些值得关注的亮点呢&#xff1f; 行情向好&#xff0c;大多…

MS8257N超低噪声、宽带、可选反馈电阻跨阻放大器

产品简述 MS8257N 是一颗宽带、快速过载恢复时间、快速建立时 间、跨阻增益可调、超低噪声的跨阻放大器&#xff0c;主要用于光电 监测和各种高性能的光电系统。快速过载恢复特性和内部输 入保护电路可以让信号从过载传输中快速恢复正常。两档可 选跨阻增益保证了极高的动…

Matlab深度学习进行波形分割(二)

&#x1f517; 运行环境&#xff1a;Matlab &#x1f6a9; 撰写作者&#xff1a;左手の明天 &#x1f947; 精选专栏&#xff1a;《python》 &#x1f525; 推荐专栏&#xff1a;《算法研究》 &#x1f510;#### 防伪水印——左手の明天 ####&#x1f510; &#x1f497; 大家…

Ubuntu 22.04 安装prometheus

服务器监控和报警软件有很多&#xff0c;为什么我们会选择Prometheus而不是其他软件呢&#xff1f; 因为它有以下优点&#xff1a; 自带简易web监控页面&#xff0c;用户可以很方便地查看监控数据和使用仪表盘。能实时收集数据并根据自定义警报规则推送告警&#xff1b;具有丰…

企业如何找到合适的内容策略?媒介盒子分享

企业如果想要抢先占领用户心智的话&#xff0c;媒介盒子认为首先需要找到合适的内容策略&#xff0c;好的内容能够与消费者建立双向信任的关系&#xff0c;一种让消费者对品牌的好感度提升&#xff0c;进而成为品牌的忠实用户&#xff0c;接下来媒介盒子就来和大家聊聊&#xf…

Selenium Grid - 多台计算机上并行运行

当你希望在多台计算机上并行运行测试&#xff1f;Selenium Grid可以帮你实现。 官方文档原文&#xff1a; https://www.selenium.dev/documentation/grid/getting_started/ Selenium Grid允许通过将客户端发送的命令路由到远程浏览器实例&#xff0c;在远程机器上执行WebDriv…

mac上搭建 hadoop 伪集群

1. hadoop介绍 Hadoop是Apache基金会开发的一个开源的分布式计算平台&#xff0c;主要用于处理和分析大数据。Hadoop的核心设计理念是将计算任务分布到多个节点上&#xff0c;以实现高度可扩展性和容错性。它主要由以下几个部分组成&#xff1a; HDFS (Hadoop Distributed Fi…

Kafka生产消费流程

Kafka生产消费流程 1.Kafka一条消息发送和消费的流程图(非集群) 2.三种发送方式 准备工作 创建maven工程&#xff0c;引入依赖 <dependency><groupId>org.apache.kafka</groupId><artifactId>kafka-clients</artifactId><version>3.3.1…

【MATLAB】 HANTS滤波算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 HANTS滤波算法是一种时间序列谐波分析方法&#xff0c;它综合了平滑和滤波两种方法&#xff0c;能够充分利用遥感图像存在时间性和空间性的特点&#xff0c;将其空间上的分布规律和时间上的变化规律联系起来…

【MySQL性能优化】- MySQL结构与SQL执行过程

MySQL结构与SQL执行过程 &#x1f604;生命不息&#xff0c;写作不止 &#x1f525; 继续踏上学习之路&#xff0c;学之分享笔记 &#x1f44a; 总有一天我也能像各位大佬一样 &#x1f3c6; 博客首页 怒放吧德德 To记录领地 &#x1f31d;分享学习心得&#xff0c;欢迎指正…

BPMN 2.0 相关定义概要描述

官方文档&#xff1a;https://www.omg.org/spec/BPMN/2.0/ BPMN 2.0 &#xff08;BPMN&#xff0c;业务流程模型和标记&#xff0c;Business Process Model And Notation&#xff09; 是一种业务流程建模和执行的标准&#xff0c;它使用 XML 格式来描述业务流程。 以下是 BPM…

Eureka 本机集群实现

距离上次发布博客已经一年多了&#xff0c;主要就是因为考研&#xff0c;没时间学习技术的内容&#xff0c;现在有时间继续完成关于代码方面的心得&#xff0c;希望跟大家分享。 今天在做一个 Eureka 的集群实现&#xff0c;我是在本电脑上跑的&#xff0c;感觉这个挺有意思&a…

alibaba.item_get API:电商行业中的数据驱动决策支持

alibaba.item_get API 是阿里巴巴提供的一个用于获取商品详情的接口。在电商行业中&#xff0c;数据驱动的决策支持是非常重要的&#xff0c;而这个 API 可以帮助你获取到商品的各种详细信息&#xff0c;从而为你的决策提供支持。 具体来说&#xff0c;通过使用 alibaba.item_…

可以部署到Vercel的一些有趣项目

博客地址 可以部署到Vercel的一些有趣项目-雪饼分享几款可以部署在Vercel上的项目&#xff0c;更新中~ 免费的域名要不要&#xff1f; 如果你还不会将项目部署到Vercel&#xff0c;或是绑定域名建议阅读 将项目部署到Vercel&#xff0c;并绑定域名 Excalidraw 白板 一个开源的…

Netty通信中的粘包半包问题(二)

在前面我们已经分析过Netty会出现的粘包半包问题&#xff0c;还没看过前面的博客的&#xff0c;可以先去看下之前写的博客 Netty通信中的粘包半包问题(一) 解放方式:特殊分隔符解决,在每个报文后面加上一个特殊分隔符&#xff0c;以此来告诉服务端每个报文的数据结界是什么 1.…

RIP【新华三与华为区别】

【介绍】 rip分为rip 1 与 rip 2 &#xff0c;rip 2 是对 rip 1 的一种升级&#xff0c;rip 2 可以进行认证等功能 【命令】 新华三&#xff1a; [HC3-R1] rip #启用rip [HC3-R1-rip] version 2 #告知rip 版本号 [HC3-R1-rip] network 192.168.1.0 #宣告其网段 [HC3-R1-rip] …

13、Redis高频面试题

1、项目中为什么用Redis 我们项目中之所以选择Redis&#xff0c;主要是因为Redis有下面这些优点&#xff1a; 操作速度快&#xff1a;Redis的数据都保存在内存中&#xff0c;相比于其它硬盘类的存储&#xff0c;速度要快很多数据类型丰富&#xff1a;Redis支持 string&#x…

STM32蓝牙小车、红外循迹小车、超声波避障小车项目设计

一、前言 本文旨在分享我学习STM32的过程中&#xff0c;为了强化学习成果&#xff0c;试着制作一些实训项目。最开始做的就是STM32蓝牙小车、STM32红外循迹小车、STM32超声波避障小车。 相信看完本文的你&#xff0c;一定可以亲手制作一辆属于自己的智能小车&#xff01; 注&am…

HTML--表单

睡不着就看书之------------------------ 表单 作用&#xff1a;嗯~~动态页面需要借助表单实现 表单标签&#xff1a; 主要分五种&#xff1a; form&#xff0c;input&#xff0c;textarea&#xff0c;select&#xff0c;option 从外观来看&#xff0c;表单就包含以下几种&…