【学习日记2023.6.3】之 工作台显示和报表导出

news2024/12/23 17:35:17

文章目录

  • 12. 工作台显示和报表导出
    • 12.1 工作台
      • 12.1.1 需求分析和设计
      • 12.1.2 代码开发
        • Controller层
        • Service层接口
        • Service层实现类
        • Mapper层
      • 12.1.3 功能测试
      • 12.1.4 提交代码
    • 12.2 Apache POI
      • 12.2.1 介绍
      • 12.2.2 入门案例
        • 12.2.2.1 将数据写入Excel文件
        • 12.2.2.2 读取Excel文件中的数据
    • 12.3 导出运营数据Excel报表
      • 12.3.1 需求分析和设计
      • 12.3.2 代码开发
        • Controller层
        • Service层接口
        • Service层实现类
        • Mapper层
      • 12.3.3 功能测试
      • 12.3.4 提交代码

12. 工作台显示和报表导出

  • 工作台
  • Apache POI
  • 导出运营数据Excel报表

12.1 工作台

12.1.1 需求分析和设计

产品原型

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

工作台展示的数据:

  • 今日数据
  • 订单管理
  • 菜品总览
  • 套餐总览
  • 订单信息

原型图:
请添加图片描述

名词解释:

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

接口设计:

  • 今日数据接口
  • 订单管理接口
  • 菜品总览接口
  • 套餐总览接口
  • 订单搜索(已完成)
  • 各个状态的订单数量统计(已完成)

1). 今日数据的接口设计
请添加图片描述

2). 订单管理的接口设计
请添加图片描述

3). 菜品总览的接口设计
请添加图片描述

4). 套餐总览的接口设计
请添加图片描述

12.1.2 代码开发

Controller层

WorkSpaceController.java

package com.sky.controller.admin;

import com.sky.result.Result;
import com.sky.service.WorkspaceService;
import com.sky.vo.BusinessDataVO;
import com.sky.vo.DishOverViewVO;
import com.sky.vo.OrderOverViewVO;
import com.sky.vo.SetmealOverViewVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.LocalTime;

/**
 * 工作台
 */
@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层接口

WorkspaceService.java

package com.sky.service;

import com.sky.vo.BusinessDataVO;
import com.sky.vo.DishOverViewVO;
import com.sky.vo.OrderOverViewVO;
import com.sky.vo.SetmealOverViewVO;
import java.time.LocalDateTime;

public interface WorkspaceService {

    /**
     * 根据时间段统计营业数据
     * @param begin
     * @param end
     * @return
     */
    BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end);

    /**
     * 查询订单管理数据
     * @return
     */
    OrderOverViewVO getOrderOverView();

    /**
     * 查询菜品总览
     * @return
     */
    DishOverViewVO getDishOverView();

    /**
     * 查询套餐总览
     * @return
     */
    SetmealOverViewVO getSetmealOverView();

}

Service层实现类

WorkspaceServiceImpl.java

package com.sky.service.impl;

import com.sky.constant.StatusConstant;
import com.sky.entity.Orders;
import com.sky.mapper.DishMapper;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.WorkspaceService;
import com.sky.vo.BusinessDataVO;
import com.sky.vo.DishOverViewVO;
import com.sky.vo.OrderOverViewVO;
import com.sky.vo.SetmealOverViewVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.Map;

@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 = processData(map);

        map.put("status", Orders.COMPLETED);
        //营业额
        Double turnover = 0.0;
        Optional<Double> optional = orderMapper.sumByMap(map).stream().map(TurnoverDTO::getTurnover).reduce(Double::sum);
        if (optional.isPresent()){//查询出来有值,给营业额重新置值
            turnover = optional.get();
        }

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

        //新增用户数
        Integer count = 0;
        List<UserCountDTO> userCountDTOList = userMapper.countNewUserByMap(map);
        if (!CollectionUtils.isEmpty(userCountDTOList)){
            //查询的userCountDTOList不为空,则optional有值可以直接调用get
            count = userCountDTOList.stream().map(UserCountDTO::getUserCount).reduce(Integer::sum).get();
        }
        Integer newUsers = count;

        return BusinessDataVO.builder()
                .turnover(turnover)
                .validOrderCount(validOrderCount)
                .orderCompletionRate(orderCompletionRate)
                .unitPrice(unitPrice)
                .newUsers(newUsers)
                .build();
    }
    
    /**
     * 查询日期范围内的订单数
     * @param map
     * @return
     */
    public Integer processData(Map map){
        Integer count = 0;
        List<OrderCountDTO> orderCountDTOList = orderMapper.countByMap(map);
        if (!CollectionUtils.isEmpty(orderCountDTOList)){
            //查询的有值optional可以直接调用get
            count = orderCountDTOList.stream().map(OrderCountDTO::getOrderCount).reduce(Integer::sum).get();
        }
        return count;
    }


    /**
     * 查询订单管理数据
     *
     * @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 = processData(map);

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

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

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

        //全部订单
        map.put("status", null);
        Integer allOrders = processData(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>

12.1.3 功能测试

可以通过如下方式进行测试:

  • 通过接口文档测试
  • 前后端联调测试

接下来我们使用上述两种方式分别测试。

接口文档测试

启动服务,访问http://localhost:8080/doc.html,进入工作台相关接口

**注意:**使用admin用户登录重新获取token,在全局参数设置中添加,防止token失效。

1). 今日数据查询
请添加图片描述

2). 菜品总览查询
请添加图片描述

3). 订单管理数据查询
请添加图片描述

4). 套餐总览查询
请添加图片描述

前后端联调测试

启动nginx,访问 http://localhost,进入工作台
请添加图片描述

12.1.4 提交代码

commit—>describe—>push

12.2 Apache POI

12.2.1 介绍

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

Apache POI 的应用场景:

  • 银行网银系统导出交易明细
    请添加图片描述

  • 各种业务系统导出Excel报表
    请添加图片描述

  • 批量导入业务数据
    请添加图片描述

12.2.2 入门案例

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>

12.2.2.1 将数据写入Excel文件

1). 代码开发

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 testWrite() throws Exception{
        //在内存中创建一个Excel文件对象
        XSSFWorkbook excel = new XSSFWorkbook();
        //创建Sheet页
        XSSFSheet sheet = excel.createSheet("yishooo");

        //在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("E:\yishooo.xlsx"));
        //通过输出流将内存中的Excel文件写入到磁盘上
        excel.write(out);

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

2). 实现效果

在E盘中生成yishooo.xlsx文件,创建名称为yishooo的Sheet页,同时将内容成功写入。
请添加图片描述

12.2.2.2 读取Excel文件中的数据

1). 代码开发

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
     */	
	@Test
    public void testRead() throws Exception{
        FileInputStream fis = new FileInputStream(new File("E:\\yishooo.xlsx"));
        //通过输入流读取指定的excel文件
        XSSFWorkbook excel = new XSSFWorkbook(fis);
        //获取excel文件的第1个Sheet页
        XSSFSheet sheet = excel.getSheetAt(0);
        //获取sheet页中的第一行的行号
        int firstRowNum = sheet.getFirstRowNum();
        //获取sheet页中的最后一行的行号
        int lastRowNum = sheet.getLastRowNum();
        for (int i = 0; i <= lastRowNum; i++) {
            //获取sheet页中的行
            XSSFRow row = sheet.getRow(i);
            //获取有数据的第一个单元格的索引
            short firstCellNum = row.getFirstCellNum();
            //获取有数据的最后一个单元格的索引
            short lastCellNum = row.getLastCellNum();
            for (int j = firstCellNum;j < lastCellNum;j++){
                XSSFCell cell = row.getCell(j);
                CellType cellType = cell.getCellTypeEnum();
                if (cellType == CellType.STRING){
                    String value = cell.getStringCellValue();
                    System.out.println(value);
                }
            }
            /*//获取行的第2个单元格
            XSSFCell cell1 = row.getCell(1);
            //获取单元格中的文本内容
            String cellValue1 = cell1.getStringCellValue();
            //获取行的第3个单元格和文本内容
            XSSFCell cell2 = row.getCell(2);
            String cellValue2 = cell2.getStringCellValue();
            System.out.println(cellValue1 + " " +cellValue2);*/
        }
        //关闭资源
        fis.close();
        excel.close();
    }
}

2). 实现效果

将yishooo.xlsx文件中的数据进行读取
请添加图片描述

12.3 导出运营数据Excel报表

12.3.1 需求分析和设计

产品原型

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

原型图:
请添加图片描述

导出的Excel报表格式:
请添加图片描述

业务规则:

  • 导出Excel形式的报表文件
  • 导出最近30天的运营数据

接口设计
请添加图片描述

注意:

  • 当前接口没有传递参数,因为导出的是最近30天的运营数据,后端计算即可,所以不需要任何参数
  • 当前接口没有返回数据,因为报表导出功能本质上是文件下载,服务端会通过输出流将Excel文件下载到客户端浏览器

12.3.2 代码开发

实现步骤

1). 设计Excel模板文件

2). 查询近30天的运营数据

3). 将查询到的运营数据写入模板文件

4). 通过输出流将Excel文件下载到客户端浏览器
请添加图片描述

在sky-pojo定义BusinessDataVO类

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BusinessDataVO implements Serializable {
    private LocalDate date; //日期

    private Double turnover;//营业额

    private Integer validOrderCount;//有效订单数

    private Double orderCompletionRate;//订单完成率

    private Double unitPrice;//平均客单价

    private Integer newUsers;//新增用户数

}

Controller层

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

	/**
     * 导出运营数据报表
     * @param response
     */
    @GetMapping("/export")
    @ApiOperation("导出运营数据报表")
    public void export(HttpServletResponse response){
        reportService.exportBusinessData(response);
    }

Service层接口

在ReportService接口中声明导出运营数据报表的方法:

	/**
     * 导出近30天的运营数据报表
     * @param response
     **/
    void exportBusinessData(HttpServletResponse response);

Service层实现类

在ReportServiceImpl实现类中实现导出运营数据报表的方法:

提前将运营数据报表模板.xlsx拷贝到项目的resources/template目录中

    /**导出近30天的运营数据报表
     * @param response
     **/
    public void exportBusinessData(HttpServletResponse response) {
               //准备开始时间和结束时间
        LocalDate begin = LocalDate.now().minusDays(30);
        LocalDate end = LocalDate.now().minusDays(1);
        //调用WorkSpaceService中的getBusinessData方法,得到过去30天运营数据汇总
        BusinessDataVO businessData = workspaceService.getBusinessData(LocalDateTime.of(begin, LocalTime.MIN), LocalDateTime.of(end, LocalTime.MAX));
        try {
            //读取template下的excel模板文件
            InputStream is = this.getClass().getClassLoader().getResourceAsStream("template/运营数据报表模板.xlsx");
            //基于提供好的模板文件创建一个新的Excel表格对象
            XSSFWorkbook excel = new XSSFWorkbook(is);
            //得到工作表
            XSSFSheet sheet = excel.getSheetAt(0);
            //设置第2行的起始截止日期
            sheet.getRow(1).getCell(1).setCellValue(begin + "至" + end);
            //获得第4行并设置单元格数据
            XSSFRow row = sheet.getRow(3);
            row.getCell(2).setCellValue(businessData.getTurnover());
            row.getCell(4).setCellValue(businessData.getOrderCompletionRate());
            row.getCell(6).setCellValue(businessData.getNewUsers());
            //获取第5行并设置单元格数据
            row = sheet.getRow(4);
            row.getCell(2).setCellValue(businessData.getValidOrderCount());
            row.getCell(4).setCellValue(businessData.getUnitPrice());

            //组装查询日期
            Map map = new HashMap();
            map.put("begin",LocalDateTime.of(begin,LocalTime.MIN));
            map.put("end",LocalDateTime.of(end,LocalTime.MAX));
            //按照日期范围统计每一天的营业数据
            List<BusinessDataVO> businessDataVOList = orderMapper.getBusinessDataVO(map);
            //按照日期范围统计每一天的订单总数量
            List<OrderCountDTO> orderCountDTOList = orderMapper.countByMap(map);
            //按照日期范围统计每一天的新增用户数量
            List<UserCountDTO> userCountDTOList = userMapper.countNewUserByMap(map);
            //循环写入近30日每一天的营业数据
            for (int i = 0; i < 30; i++) {
                LocalDate date = begin.plusDays(i);
                row = sheet.getRow(7 + i);
                row.getCell(1).setCellValue(date.toString());//设置日期列
                //判断businessDataVOList数据中是否有营业额
                Optional<BusinessDataVO> optional = businessDataVOList.stream().filter(businessDataVO -> {
                    return businessDataVO.getDate().isEqual(date);
                }).findFirst();
                if (optional.isPresent()){
                    //有营业额,取出来放到excel表格中
                    Double turnover = optional.get().getTurnover();
                    Integer validOrderCount = optional.get().getValidOrderCount();
                    Double unitPrice = optional.get().getUnitPrice();
                    row.getCell(2).setCellValue(turnover);//设置营业额
                    row.getCell(3).setCellValue(validOrderCount);//设置有效订单
                    Integer orderCount = orderCountDTOList.stream().filter(orderCountDTO -> {
                        return orderCountDTO.getOrderTime().isEqual(date);
                    }).findFirst().get().getOrderCount();
                    row.getCell(4).setCellValue(validOrderCount.doubleValue() / orderCount);//设置订单完成率
                    row.getCell(5).setCellValue(unitPrice);//设置平均客单价

                }else {
                    row.getCell(2).setCellValue(0.0);
                    row.getCell(3).setCellValue(0);
                    row.getCell(4).setCellValue(0.0);
                    row.getCell(5).setCellValue(0.0);
                }
                Optional<UserCountDTO> optional1 = userCountDTOList.stream().filter(userCountDTO -> {
                    return userCountDTO.getCreateTime().isEqual(date);
                }).findFirst();
                //设置新增用户数
                if (optional1.isPresent()){
                    row.getCell(6).setCellValue(optional1.get().getUserCount());
                }else {
                    row.getCell(6).setCellValue(0);
                }

            }
            //通过输出流将文件下载到客户端浏览器中
            excel.write(response.getOutputStream());//response调用的流由response自己关闭资源
            //关闭资源
            excel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Mapper层

OrderMapper.java

/**
 * 根据日期范围统计营业数据
 * @param map
 * @return
 */
List<BusinessDataVO> getBusinessDataVO(Map map);

OrderMapper.xml

<!--根据日期范围统计营业数据-->
<select id="getBusinessDataVO" resultType="com.sky.vo.BusinessDataVO">
   select date_format(order_time,'%Y-%m-%d') date,sum(amount) turnover, count(*) validOrderCount,
   sum(amount)/count(*) unitPrice from orders
   where status = 5
   <if test="beginTime != null">and order_time &gt;= #{beginTime}</if>
   <if test="endTime != null">and order_time &lt;= #{endTime}</if>
   group by date
</select>

12.3.3 功能测试

直接使用前后端联调测试。

进入数据统计
请添加图片描述

点击数据导出:Excel报表下载成功
请添加图片描述

12.3.4 提交代码

commit—>describe—>push

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

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

相关文章

Linux4.7Nginx优化与防盗链

文章目录 计算机系统5G云计算第六章 LINUX Nginx优化与防盗链一、Nginx服务优化和深入优化1.隐藏版本号2.修改用户与组3.缓存时间4.日志切割5.连接超时6.更改进程数7.配置网页压缩8.配置防盗链9.fpm参数优化 计算机系统 5G云计算 第六章 LINUX Nginx优化与防盗链 一、Nginx服…

操作系统复习4.1.0-文件管理结构

定义 一组有意义的信息的集合 属性 文件名、标识符、类型、位置、大小、创建时间、上次修改时间、文件所有者信息、保护信息 操作系统向上提供的功能 创建文件、删除文件、读文件、写文件、打开文件、关闭文件 这6个都是系统调用 创建文件 创建文件时调用Create系统调用…

django中使用celery

Celery介绍&#xff1a; 核心及优点&#xff1a;1.基于分布式系统架构&#xff08;负载均衡避免单点故障&#xff0c;高可用&#xff09; 2.实现了异步任务的调度&#xff08;快速&#xff09; 只需要通过配置文件的修改就可以实现架构的切换所以灵活 django-celery-beat 用…

Oracle中的循环

目录 一、简单循环 1.1LOOP 循环语法&#xff1a; 1.2LOOP 循环示例 二、for循环 2.1for循环语法&#xff1a; 2.2for循环示例 三、while循环 3.1while循环语法 3.2while循环示例 四、GOTO 循环 4.1GOTO 循环语法 4.2GOTO 循环示例 在 Oracle 数据库中&#xff0c;…

储能之动力电池与储能电池区别?

储能之动力电池与储能电池区别 1、概念1.1 动力电池1.2 储能电池 2、应用场景3、动力电池与储能电池的对比3.1 性能要求3.2 循环次数3.3 电池类型方面3.4 成本结构不同 1、概念 1.1 动力电池 动力电池即为工具提供动力来源的电源&#xff0c;多指为电动汽车、电动列车、电动自…

Oracle中ORA-12560:协议适配器错误

平时在长时间未登录Oracle数据库&#xff0c;再次登录时会出现如下错误&#xff1a; 当Oracle登录时出现12560协议适配器错误时&#xff0c;可以通过以下步骤尝试启动相应的服务&#xff1a; 第一步&#xff1a; 打开本地【服务】&#xff0c;点击最顶层的名称输入【O】&…

java-字符流和字节流(三)

java-字符流和字节流(三) 一、IO特殊操作流 1.1 标准流 1.1.1 标准输入流 System类中有两个静态的成员变量 public static final InputStream in&#xff1a;标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源public static final PrintStream out&am…

【StringBuilder类】添加和反转方法以及StringBuilder和String相互转换

StringBuilder类 如果对字符串进行拼接操作&#xff0c;每次拼接都会构建一个新的String对象&#xff0c;既耗时又浪费内存空间&#xff0c;而这种操作还不可避免。我们可以通过Java提供的StringBuilder类来解决这个问题。StringBuilder是一个可变的字符串类&#xff0c;我们可…

java-基础语法(一)

java-基础语法(一) 一、java变量 1.1、注释 单行注释 // // 这是单行注释文字多行注释 /* *//* 这是多行注释文字 这是多行注释文字 这是多行注释文字 */ 注意&#xff1a;多行注释不能嵌套使用。1.2 常量 常量&#xff1a;在程序运行过程中&#xff0c;其值不可以发生改变的…

Arthas-monitor/watch/trace 相关命令使用

tip&#xff1a;作为程序员一定学习编程之道&#xff0c;一定要对代码的编写有追求&#xff0c;不能实现就完事了。我们应该让自己写的代码更加优雅&#xff0c;即使这会费时费力。 开头&#xff1a; 本章所有的命令都非常重要&#xff0c;都是使用率相当高的。 文章目录 moni…

python---列表

列表 1. 列表的介绍1.1 访问列表元素1.2 索引从0而不是1开始1.3 使用列表中的各个值1.4 修改、添加和删除元素1.4.1 修改列表元素 1.5 在列表中添加元素1.5.1 在列表末尾添加元素1.5.2 在列表中插入元素 1.6 从列表中删除元素1.6.1 使用方法pop()删除元素1.6.2 弹出列表中任何位…

【TreeSet集合】自然排序Comparator的使用

自然排序Comparator的使用 存储学生对象并遍历&#xff0c;创建TreeSet集合使用无参构造方法 要求&#xff1a;按照年龄从小到大排序&#xff0c;年龄相同时&#xff0c;按照姓名的字母顺序排序 创建学生类&#xff1a; package com.gather.set.treeset; public class Student…

【利用AI让知识体系化】前端开发学习了解业务架构

文章目录 I. 前端技术入门1.1 HTML/CSS/Javascript 简介1.2 前端框架 React/Vue/Angular 了解1.3 前端工具 Git/Webpack/npm/yarn 的使用1.4 前端调试和性能优化技巧 II. 开发综合应用2.1 工程化开发的全流程2.2 单页面应用 (SPA)2.3 数据交互和批量操作2.4 模块化和组件化开发…

压缩感知重构之匹配追踪算法

算法的重构是压缩感知中重要的一步&#xff0c;是压缩感知的关键之处。因为重构算法关系着信号能否精确重建&#xff0c;国内外的研究学者致力于压缩感知的信号重建&#xff0c;并且取得了很大的进展&#xff0c;提出了很多的重构算法&#xff0c;每种算法都各有自己的优缺点&a…

[golang 微服务] 4. gRPC介绍,Protobuf结合gRPC 创建微服务

一.gRPC框架的介绍 简介 gRPC是一个 高性能、 开源和 通用的 RPC 框架&#xff0c; 面向移动端和 HTTP/2 设计,目前提供 C、Java 和 Go语言版本&#xff0c;分别是&#xff1a;grpc, grpc-java, grpc-go,其中 C 版本支持 C, C, Node.js, Python, Ruby, Objective-C, PHP 和 C# …

Windows Pyqt5配置环境过程(pycharm Anaconda)

必要安装 Anaconda下载地址 Pycharm下载地址 这两个推荐2019年左右的版本就行了&#xff0c;安装的时候选择“add path” Anaconda换源 换源之后叉掉终端之后再创建环境 Anaconda常用命令 Anaconda换源应该是只对conda install 有用&#xff0c;pip还要换源 使用清华源进行…

java-集合

java-集合 一、集合体系结构 集合类的特点 ​ 提供一种存储空间可变的存储模型&#xff0c;存储的数据容量可以随时发生改变 集合类的体系图 ​ 二、单列集合 2.1 Collection集合&#xff08;接口&#xff09; Collection集合概述 是单列集合的顶层接口&#xff0c;它表示一…

汇编栈寄存器SS与SP使用

入栈时,栈段地址与偏移地址计算 使用a命令输入下面汇编,然后使用u命令查看 写入汇编指令到内存 修改CS:IP指向当前代码段 使用t命令执行汇编指令,详细执行如下图标号 注意每行指令执行后寄存器变化. 取内存段单元数据 将内存段单元数据送入寄存器, 多次送入数据到同一寄存…

chatgpt赋能python:Python分词处理的重要性

Python分词处理的重要性 随着互联网的飞速发展&#xff0c;大数据的普及与应用越来越广泛。人们需要从海量的数据中找到自己需要的信息。因此&#xff0c;自然语言处理技术被广泛应用&#xff0c;其中分词技术是自然语言处理中最基础的一项技术。 在这个领域中&#xff0c;Py…

JS逆向——借助playwright实现逆向

原理&#xff1a; 1.修改js文件&#xff0c;将加密方法设定为全局变量并调用。 2.使用playwright替换浏览器加载的js文件 3.在python中通过playwright实现js注入获取加密结果 实现&#xff1a; 以下面链接为例&#xff1a; Scrape | Movie 1.首先&#xff0c;要知道页面…