项目6:实现数据字典的展示与缓存

news2025/6/17 7:24:39

项目6:实现数据字典的展示与缓存

1.数据字典如何展示?

2.前后端如何设计?

3.前端设计代码?

4.后端设计代码?

5.实现数据字典缓存到redis

项目6:实现数据字典的展示与缓存

1.数据字典如何展示?

①数据字典展示

  • 树形结构

②树形结构数据展示的方式

  • 非延迟加载
    后台返回的数据中有嵌套数据,嵌套的数据放在Children属性中
  • 延迟加载
    不需要包含嵌套属性,要定义Boolean属性的hasChildren,表示当前节点是否包好子数据,true为包含,false为不包含。点击当前节点时,通过load方法加载子数据

2.前后端如何设计?

①前端设计

  • 通过利用延迟加载

②后端设计

  • 利用Dict的entity类设计一个逻辑字段hasChildren,数据表中并没该字段,而是方便前端展示
  • 如何为hasChildren赋值?
    可以利用该表的id查询是否有parent_id=该id的数据,有则为true,没有则为false

3.前端设计代码?

①设计 请求api

srb-admin\src\api\core\dict.js

import request from '@/utils/request'
export default {
  listByParentId(parentId) {
    return request({
      url: `/admin/core/dict/listByParentId/${parentId}`,
      method: 'get',
    })
  },
}

②涉及具体组件中的表格(参考element-ui)

srb-admin\src\views\core\dict\list.vue

<template>
  <div class="app-container">
    <!--Excel导入按钮-->
    <div style="margin-bottom: 10px">
      <el-button
        @click="dialogVisible = true"
        type="primary"
        size="mini"
        icon="el-icon-download"
      >
        导入Excel
      </el-button>
      <el-button
        @click="exportData"
        type="primary"
        size="mini"
        icon="el-icon-upload2"
      >
        导出Excel
      </el-button>
    </div>

    <!--显示一个dialog对话框-->
    <el-dialog title="数据字典导入" :visible.sync="dialogVisible" width="30%">
      <el-form>
        <el-form-item label="请选择Excel文件">
          <!--accept为只接受xls,xlsx的文件后缀,
          name名字必须要和后端的名字保持一致,
          avtion为提交地址发起ajax远程调用(和自己写的request请求无关),自己处理成功失败-->
          <el-upload
            :auto-upload="true"
            :multiple="false"
            :limit="1"
            :on-exceed="fileUploadExceed"
            :on-success="fileUploadSuccess"
            :on-error="fileUploadError"
            :action="BASE_API + '/admin/core/dict/import'"
            name="file"
            accept="application/vnd.ms-excel,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
          >
            <el-button size="small" type="primary">点击上传</el-button>
          </el-upload>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取消</el-button>
      </div>
    </el-dialog>

    <!--数据字典
    渲染树形数据必须指定row-key为id
    懒加载设置lazy(有了展开按钮)
    load为延迟加载函数
    -->
    <el-table :data="list" border row-key="id" lazy :load="load">
      <el-table-column label="名称" align="left" prop="name" />
      <el-table-column label="编码" prop="dictCode" />
      <el-table-column label="值" align="left" prop="value" />
    </el-table>
  </div>
</template>

<script>
import dictApi from '@/api/core/dict'
export default {
  data() {
    return {
      dialogVisible: false, //对话框是否显式
      BASE_API: process.env.VUE_APP_BASE_API, //获取后端接口地址
      list: [], //数据字典列表
    }
  },

  created() {
    this.fetchData()
  },
  methods: {
    //获取数据字典
    fetchData() {
      //获取顶层类别
      dictApi.listByParentId(1).then((response) => {
        this.list = response.data.list
      })
    },

    // 上传多于一个文件时
    fileUploadExceed() {
      this.$message.warning('只能选取一个文件')
    },

    //上传成功回调(http通信成功,有可能业务失败或业务失败)
    fileUploadSuccess(response) {
      if (response.code === 0) {
        //业务成功
        this.$message.success('数据导入成功')
        this.dialogVisible = false
      } else {
        //业务事变
        this.$message.error(response.message)
      }
    },

    //上传失败回调(http通信不成功)
    fileUploadError(error) {
      this.$message.error('数据导入失败')
    },

    //Excel数据导出
    exportData() {
      //导出excel,
      window.location.href = this.BASE_API + '/admin/core/dict/export'
    },
    //加载二级节点
    load(tree, treeNode, resolve) {
      //获取parent_id为点击id的数据
      dictApi.listByParentId(tree.id).then((response) => {
        resolve(response.data.list)
      })
    },
  },
}
</script>

4.后端设计代码?

①更新entity类

package com.atguigu.srb.core.pojo.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * <p>
 * 数据字典
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
@Data
@EqualsAndHashCode(callSuper = false)
@ApiModel(value="Dict对象", description="数据字典")
public class Dict implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "id")
      @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    @ApiModelProperty(value = "上级id")
    private Long parentId;

    @ApiModelProperty(value = "名称")
    private String name;

    @ApiModelProperty(value = "值")
    private Integer value;

    @ApiModelProperty(value = "编码")
    private String dictCode;

    @ApiModelProperty(value = "创建时间")
    private LocalDateTime createTime;

    @ApiModelProperty(value = "更新时间")
    private LocalDateTime updateTime;

    @ApiModelProperty(value = "删除标记(0:不可用 1:可用)")
    @TableField("is_deleted")
    @TableLogic
    private Boolean deleted;


    //数据库表没要有此字段, 表达逻辑概念的属性
    @TableField(exist = false)
    private Boolean hasChildren;


}

②编写controller接口

package com.atguigu.srb.core.controller.admin;


import com.alibaba.excel.EasyExcel;
import com.atguigu.common.exception.BusinessException;
import com.atguigu.common.result.R;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.atguigu.srb.core.service.DictService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.List;

/**
 * <p>
 * 数据字典 前端控制器
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
@Api(tags = "数据字典管理")
@RestController
@RequestMapping("/admin/core/dict")
@Slf4j
@CrossOrigin
public class AdminDictController {

    @Resource
    DictService dictService;


    @ApiOperation("Excel数据的批量导入(导入到数据库)")
    @PostMapping("/import")
    public R batchImport(
            @ApiParam(value="Excel数据字典文件")
            @RequestParam("file") MultipartFile file){

        try {
            InputStream inputStream = file.getInputStream();
            dictService.importData(inputStream);
            return R.ok().message("数据字典批量导入成功");
        } catch (Exception e) {
            //返回R对象,并且打印异常跟踪栈
            throw new BusinessException(ResponseEnum.UPLOAD_ERROR,e);
        }

    }

    @ApiOperation("Excel数据的导出")
    //访问页面
    @GetMapping("/export")
    public void export(HttpServletResponse response){
        try {
            // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
            //设置类型为excel
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("mydict", "UTF-8").replaceAll("\\+", "%20");
            //设置附件的形式下载到浏览器端
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), ExcelDictDTO.class).sheet("数据字典").doWrite(dictService.listDictData());

        } catch (IOException e) {
            //EXPORT_DATA_ERROR(104, "数据导出失败"),
            throw  new BusinessException(ResponseEnum.EXPORT_DATA_ERROR, e);
        }
    }


    @ApiOperation("根据上级id获取子节点数据列表")
    @GetMapping("/listByParentId/{parentId}")
    public R listByParentId(
            @ApiParam(value = "上级节点id", required = true)
            @PathVariable Long parentId) {
        List<Dict> dictList = dictService.listByParentId(parentId);
        return R.ok().data("list", dictList);
    }

}


③编写service

package com.atguigu.srb.core.service;

import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.baomidou.mybatisplus.extension.service.IService;

import java.io.InputStream;
import java.util.List;

/**
 * <p>
 * 数据字典 服务类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
public interface DictService extends IService<Dict> {


    void importData(InputStream inputStream);

    List<ExcelDictDTO> listDictData();

    List<Dict> listByParentId(Long parentId);
}

package com.atguigu.srb.core.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.srb.core.listener.ExcelDictDTOListener;
import com.atguigu.srb.core.mapper.DictMapper;
import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.atguigu.srb.core.service.DictService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 数据字典 服务实现类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
@Slf4j
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Resource
    private  DictMapper dictMapper;

    //读取数据
    //写入数据库,利用事务的操作成功全成功,失败全失败(只要异常出现则回滚)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importData(InputStream inputStream) {
        //传入输入流,
        EasyExcel.read(inputStream, ExcelDictDTO.class, new ExcelDictDTOListener(dictMapper)).sheet().doRead();
        log.info("Excel导入成功");
    }

    @Override
    public List<ExcelDictDTO> listDictData() {
        List<Dict> dictList = dictMapper.selectList(null);
        //创建ExcelDictDTO列表,将Dict列表转化为ExcelDictDTO列表
        ArrayList<ExcelDictDTO> excelDictDTOList = new ArrayList<>(dictList.size());
        dictList.forEach(dict -> {

            ExcelDictDTO excelDictDTO = new ExcelDictDTO();
            //对象拷贝,dict拷贝到excelDictDTO(相同列拷贝)
            BeanUtils.copyProperties(dict, excelDictDTO);
            excelDictDTOList.add(excelDictDTO);
        });
        return excelDictDTOList;
    }

    /**
     * @param parentId: 
     * @return List<Dict>
     * @author Likejin
     * @description 根据parentId查询列表
     * @date 2023/4/12 15:42
     */

    @Override
    public List<Dict> listByParentId(Long parentId) {

        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("parent_id",parentId);
        List<Dict> dictList = dictMapper.selectList(dictQueryWrapper);
        //填充hasChildren字段
        dictList.forEach(dict -> {
            //判断当前节点是否有子节点,找到当前的dict的下级有没有子节点
            //即用当前dic的id当做parent_id去查,如果有数据则有子节点,如果没有数据则有子节点
            Boolean hasChildren = this.hasChildren(dict.getId());
            dict.setHasChildren(hasChildren);
        });
        return dictList;
    }
    /**
     * @param id:
     * @return Boolean
     * @author Likejin
     * @description 判断当前id的节点是否有子节点
     * @date 2023/4/12 15:03
     */

    private Boolean hasChildren(Long id){
        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("parent_id",id);
        Integer count = dictMapper.selectCount(dictQueryWrapper);
        if(count.intValue()>0){
            return true;
        }
        return false;
    }
}

5.实现数据字典缓存到redis

①为什么要用缓存技术?

  • 数据字典的数据一段时间不会变,redis内存存储,查询速度快

②引入流程

  • 引入redis依赖
    redis连接池管理
    redis存储json序列化
  • 为什么序列化
    如果不序列化,默认使用jdk序列化存储可读性太差
    序列化后可以直接存储json数据
  • 实现逻辑
    即前端先查redis,redis有则取出数据。
    redis没有则查询数据库,将数据库的数据存入redis,返回数据
    注意:redis出错但是不能影响数据库取数据后返回,故需要在查redis数据和存redis数据都try-catch

③引入redis依赖

   <!-- spring boot redis缓存引入 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- 缓存连接池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <!-- redis 存储 json序列化 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
        </dependency>

④配置redis的application.yml以及简单测试

server:
  port: 8110 # 服务端口
spring:
  #redis的配置
  redis:
    host: localhost
    port: 6379
    database: 0
    timeout: 3000ms #最大等待时间,超时则抛出异常,否则请求一直等待
    #连接池的连接
    lettuce:
      pool:
        max-active: 20  #最大连接数,负值表示没有限制,默认8
        max-wait: -1    #最大阻塞等待时间,负值表示没限制,默认-1
        max-idle: 8     #最大空闲连接,默认8
        min-idle: 0     #最小空闲连接,默认0
  profiles:
    active: dev # 环境设置
  application:
    name: service-core # 服务名
  datasource: # mysql数据库连接
    type: com.zaxxer.hikari.HikariDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db200921_srb_core?serverTimezone=GMT%2B8&characterEncoding=utf-8
    username: root
    password: abc123

mybatis-plus: #mybatis
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:com/atguigu/srb/core/mapper/xml/*.xml

# 设置日志级别
#logging:
#  level:
#    root: ERROR
package com.atguigu.srb.core;

import com.atguigu.srb.core.mapper.DictMapper;
import com.atguigu.srb.core.pojo.entity.Dict;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@SpringBootTest
@RunWith(SpringRunner.class)
public class RedisTemplateTests {
    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private DictMapper dictMapper;

    @Test
    public void saveDict(){
        Dict dict = dictMapper.selectById(1);
        //向数据库中存储string类型的键值对, 过期时间5分钟,序列化方案,序列化为jdk字符串
        redisTemplate.opsForValue().set("dict", dict, 5, TimeUnit.MINUTES);
    }

    @Test
    public void getDict(){
        Dict dict = (Dict)redisTemplate.opsForValue().get("dict");
        System.out.println(dict);
    }
}

⑤配置redis

  • 通用配置写在service-base包下
package com.atguigu.srb.base.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {


    @Bean
    public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {

        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        //设置连接池工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        //首先解决key的序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        redisTemplate.setKeySerializer(stringRedisSerializer);

        //解决value的序列化方式
        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);

        //序列化时将类的数据类型存入json,以便反序列化的时候转换成正确的类型
        ObjectMapper objectMapper = new ObjectMapper();
        //objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);

        // 解决jackson2无法反序列化LocalDateTime的问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());

        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);

        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        return redisTemplate;
    }
}


⑥redis实现逻辑

  • 即实现逻辑实际在controller调用的service层实现(前端根据parent_id查询列表)
package com.atguigu.srb.core.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.srb.core.listener.ExcelDictDTOListener;
import com.atguigu.srb.core.mapper.DictMapper;
import com.atguigu.srb.core.pojo.dto.ExcelDictDTO;
import com.atguigu.srb.core.pojo.entity.Dict;
import com.atguigu.srb.core.service.DictService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 数据字典 服务实现类
 * </p>
 *
 * @author Likejin
 * @since 2023-04-09
 */
@Slf4j
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Resource
    private  DictMapper dictMapper;

    @Resource
    private RedisTemplate redisTemplate;

    //读取数据
    //写入数据库,利用事务的操作成功全成功,失败全失败(只要异常出现则回滚)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importData(InputStream inputStream) {
        //传入输入流,
        EasyExcel.read(inputStream, ExcelDictDTO.class, new ExcelDictDTOListener(dictMapper)).sheet().doRead();
        log.info("Excel导入成功");
    }

    @Override
    public List<ExcelDictDTO> listDictData() {
        List<Dict> dictList = dictMapper.selectList(null);
        //创建ExcelDictDTO列表,将Dict列表转化为ExcelDictDTO列表
        ArrayList<ExcelDictDTO> excelDictDTOList = new ArrayList<>(dictList.size());
        dictList.forEach(dict -> {

            ExcelDictDTO excelDictDTO = new ExcelDictDTO();
            //对象拷贝,dict拷贝到excelDictDTO(相同列拷贝)
            BeanUtils.copyProperties(dict, excelDictDTO);
            excelDictDTOList.add(excelDictDTO);
        });
        return excelDictDTOList;
    }

    /**
     * @param parentId:
     * @return List<Dict>
     * @author Likejin
     * @description 根据parentId查询列表
     * @date 2023/4/12 15:42
     */

    @Override
    public List<Dict> listByParentId(Long parentId) {


        //首先查询redis中是否存在数据
        //一级分类放到一个键中
        //一级分类的各个二级分类再存储
        try {
            List<Dict> dictList =(List<Dict>) redisTemplate.opsForValue().get("srb:core:dictList:" + parentId);
            if(dictList !=null){
                log.info("从redis获取数据列表");
                //如果redis取值出错,数据还可以从数据库中查
                return dictList;
            }
        } catch (Exception e) {
            log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));
        }
        //如果存在则从redis直接返回数据列表
        //前面已经返回

        //如果不存在则查询数据库,同时将数据库中的数据放入缓存redis中
        log.info("从数据库中获取数据列表");
        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("parent_id",parentId);
        List<Dict> dictList = dictMapper.selectList(dictQueryWrapper);
        //填充hasChildren字段
        dictList.forEach(dict -> {
            //判断当前节点是否有子节点,找到当前的dict的下级有没有子节点
            //即用当前dic的id当做parent_id去查,如果有数据则有子节点,如果没有数据则有子节点
            Boolean hasChildren = this.hasChildren(dict.getId());
            dict.setHasChildren(hasChildren);
        });
        try {
            log.info("将数据存入redis");
            redisTemplate.opsForValue().set("srb:core:dictList:" + parentId,dictList,5, TimeUnit.MINUTES);
            //返回数据
        } catch (Exception e) {
            log.error("redis服务器异常:" + ExceptionUtils.getStackTrace(e));
        }
        return dictList;
    }
    /**
     * @param id:
     * @return Boolean
     * @author Likejin
     * @description 判断当前id的节点是否有子节点
     * @date 2023/4/12 15:03
     */

    private Boolean hasChildren(Long id){
        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        dictQueryWrapper.eq("parent_id",id);
        Integer count = dictMapper.selectCount(dictQueryWrapper);
        if(count.intValue()>0){
            return true;
        }
        return false;
    }
}

⑦存储redis结果

在这里插入图片描述
在这里插入图片描述

未更新

未更新

未更新

未更新

未更新

未更新

未更新

未更新

未更新

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

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

相关文章

WEB攻防-通用漏洞PHP反序列化POP链构造魔术方法原生类

目录 一、序列化和反序列化 二、为什么会出现反序列化漏洞 三、序列化和反序列化演示 <演示一> <演示二> <演示二> 四、漏洞出现演示 <演示一> <演示二> 四、ctfshow靶场真题实操 <真题一> <真题二> <真题三> &l…

C++入门到入土(一)

C语言中&#xff0c;我们这样定义&#xff0c;输出100。 因为局部作用域的访问权限大于全局作用域的。 当我们加入头文件#include <time.h>的时候&#xff0c;就会报错 看报错&#xff0c;我们也知道&#xff0c;time重定义&#xff0c;因为我们头文件time.h里面有time函…

验证码识别过程中切割图片的几种方案

目录 方案一&#xff1a;图片均分 方案二&#xff1a;寻找轮廓并截取 方案三&#xff1a;聚类算法 方案四&#xff1a;垂直投影法 源码下载 在用机器学习识别验证码的过程中&#xff0c;我们通常会选择把验证码中的各个字符切割出来然后单独识别&#xff0c;切割质量会直接…

JS Hook 基本使用

前言 Hook技术也叫钩子函数&#xff0c;功能是把网站的代码拉出来&#xff0c;改成我们自己想执行的代码片段&#xff0c;简单来说就是可以控制执行函数的入参和出参&#xff1b; 一、资源下载 编程猫插件&#xff1a;https://pan.baidu.com/s/1SP8xHoDpugssFRpu-nLxPw?pwdz…

ARM 编译器 Arm Compiler for Embedded 6 相关工具链简介

目录 1, Introduction to Arm Compiler 6 1.1 armclang 1.2 armasm 1.3 armlink 1.4 armar 1.5 fromelf 1.6 Arm C libraries 1.7 Arm C libraries 1,8 Application development &#xff0c;ARM程序开发流程 2&#xff0c;ARM 编译器 5和ARM 编译器 6的兼容性 3&…

Opencv项目实战:22 物体颜色识别并框选

目录 0、项目介绍 1、效果展示 2、项目搭建 3、项目代码展示与部分讲解 Color_trackbar.py bgr_detector.py test.py 4、项目资源 5、项目总结 0、项目介绍 本次项目要完成的是对物体颜色的识别并框选&#xff0c;有如下功能&#xff1a; &#xff08;1&#xff09;…

【权限提升】Linux Sudo权限提升漏洞(CVE-2023-22809)

文章目录前言一、Sudo介绍二、漏洞概述三、漏洞成因四、漏洞分析五、影响版本六、本地复现七、修复建议前言 Sudo存在权限提升漏洞,攻击者可过特定的payload获取服务器ROOT权限 一、Sudo介绍 sudo (su " do")允许系统管理员将权限委托给某些用户(或用户组),能够以…

网络安全与防御

1. 什么是IDS&#xff1f; IDS(入侵检测系统)&#xff1a;入侵检测是防火墙的合理补充&#xff0c;帮助系统对付网络攻击&#xff0c;扩展了系统管理员的安全管理能力&#xff0c;提高了信息安全基础结构的完整性。主要针对防火墙涉及不到的部分进行检测。 入侵检测主要面对的…

ChatGPT技术原理、研究框架,应用实践及发展趋势(附166份报告)

​ 一、AI框架重要性日益突显&#xff0c;框架技术发展进入繁荣期&#xff0c;国内AI框架技术加速发展&#xff1a; 1、AI框架作为衔接数据和模型的重要桥梁&#xff0c;发展进入繁荣期&#xff0c;国内外框架功能及性能加速迭代&#xff1b; 2、Pytorch、Tensorflow占据AI框…

5.2 中心极限定理

学习目标&#xff1a; 要学习中心极限定理&#xff0c;我会采取以下几个步骤&#xff1a; 学习基本概念&#xff1a;了解什么是随机变量、样本、总体、概率密度函数等基本概念&#xff0c;为学习中心极限定理打下基础&#xff1b;学习正态分布&#xff1a;中心极限定理的核心…

【JavaEE】计算机组成以及操作系统(进程)的基本知识

目录 前言 1、计算机基本组成 1.1、存储器 2、操作系统 2.1、 进程&#xff08;任务&#xff09;的概念 2.2、进程的管理 2.2.1、进程控制块PCB&#xff08;process control block&#xff09; 2.3、CPU分配&#xff08;进程调度&#xff09; 2.3.1、并发 2.3.2、并…

string容器

1、string的构造和赋值 #include #include using namespace std; void test01() { string str1(“hello world”); //使用字符串初始化 cout<<str1<<endl; string str2(5,‘A’); //使用 n 个字符串是初始化 cout<<str2<<endl; string str3 str2; …

深度学习数据集—水果数据集大合集

近期整理的各类水果&#xff08;包括干果&#xff09;数据集&#xff0c;分享给大家。 1、8类水果图片数据集&#xff08;每类100张图片左右&#xff09;[橘子&#xff0c;菠萝&#xff0c;苹果&#xff0c;木瓜&#xff0c;火龙果&#xff0c;香蕉&#xff0c;樱桃&#xff0…

系统升级 | RK3568开发平台成功搭载SylixOS国产实时操作系统

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

【GPT4】微软 GPT-4 测试报告(5)与外界环境的交互能力

欢迎关注【youcans的AGI学习笔记】原创作品 微软 GPT-4 测试报告&#xff08;1&#xff09;总体介绍 微软 GPT-4 测试报告&#xff08;2&#xff09;多模态与跨学科能力 微软 GPT-4 测试报告&#xff08;3&#xff09;编程能力 微软 GPT-4 测试报告&#xff08;4&#xff09;数…

被裁了,39 岁阿里 P9,攒下 1.5 亿....

今天刷知乎&#xff0c;在问题 “40 岁因为财务自由决定不上班的人&#xff0c;个人资产总和到底有多少” 下看到一位阿里 P9 的匿名回答让我狠狠的酸了一把~ 这刚刚失业的四十岁高级码农自曝了自己的人生经历&#xff0c;作为一名“阿里 P9”的程序员&#xff0c;他讲述了自己…

重庆理工大学教授程平:智能会计时代,应充分发挥数据资产的价值

近日&#xff0c;由用友主办的「智能会计 价值财务」2023企业数智化财务创新峰会北京站在北京国家会计学院圆满举办&#xff01;来自知名院校的专家学者、央国企等大型企业财务领路人、以及权威财经媒体相约北京国家会计学院&#xff0c;一同见证“智能会计”新时代的到来&…

centos 搭建 wiki

需要安装软件 mysqlmm-wikinginx&#xff08;非必须&#xff09; mysql 1.查询本机是否安装mysql rpm -qa | grep mysql 如安装&#xff0c;知道mysql账号密码&#xff0c;可以直接使用&#xff0c;跳过此步骤 如已安装&#xff08;centos可能默认已安装mysql或者之前有人…

day13_oop

今日内容 零、 复习昨日 一、final 二、static 三、多态 四、向上转型&向下转型 五、多态应用 零、 复习昨日 封装 类的封装: 1 属性私有 2提供setget 继承 A extends B子类可以使用父类非私有属性和方法好处: 复用,多态准备 重写/覆写/覆盖/Override 子类重写父类的方法,以…

什么是雪花算法?啥原理?

1、SnowFlake核心思想 SnowFlake 算法&#xff0c;是 Twitter 开源的分布式 ID 生成算法。 其核心思想就是&#xff1a;使用一个 64 bit 的 long 型的数字作为全局唯一 ID。在分布式系统中的应用十分广泛&#xff0c;且 ID 引入了时间戳&#xff0c;基本上保持自增的&#xf…