springboot + Vue前后端项目(第十九记)

news2024/11/21 0:13:52

项目实战第十九记

  • 写在前面
  • 1. redis安装(windows安装)
    • 1.1 获取软件链接地址:
    • 1.2 启动redis
    • 1.3 测试是否启动成功
    • 1.4 通过 Another Redis DeskTop软件可视化查看redis
  • 2. SpringBoot集成redis
    • 2.1 引入依赖
    • 2.2 注入RedisTemplate
    • 2.3 使用redis
    • 2.4 redis更新
    • 2.5 redis使用前后对比
  • 总结
  • 写在最后

写在前面

本篇主要讲解SpringBoot集成redis在系统中的简单应用

1. redis安装(windows安装)

1.1 获取软件链接地址:

链接:https://pan.baidu.com/s/1b-NFQzAcdujjy2WugWU6fQ 
提取码:6666

1.2 启动redis

在这里插入图片描述

1.3 测试是否启动成功

在这里插入图片描述

输入ping,显示pong;说明redis启动成功

在这里插入图片描述

1.4 通过 Another Redis DeskTop软件可视化查看redis

软件链接地址

链接:https://pan.baidu.com/s/1A_-8h-MHfcWKFh6UbWU8bw 
提取码:6666

如下图所示:

在这里插入图片描述

2. SpringBoot集成redis

2.1 引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

修改application.yml文件

  redis:
    port: 6379
    host: 127.0.0.1
#    password: XXX
#    mode: XXX
#    database: xxx

2.2 注入RedisTemplate

@Autowired
private RedisTemplate redisTemplate;

枚举类设置redis的键:

package com.ppj.constants;

public interface Constants {

    String CODE_200 = "200"; //成功
    String CODE_401 = "401";  // 权限不足
    String CODE_400 = "400";  // 参数错误
    String CODE_500 = "500"; // 系统错误
    String CODE_600 = "600"; // 其他业务异常

    String CODE_700 = "700";  //注册失败

    // redis
    String FILES_KEY = "FILES_FRONT_ALL";
}

2.3 使用redis

// JSONUtil是hutool工具包下面的
//1, 从redis中获取数据
        String jsonStr = JSONUtil.toJsonStr(redisTemplate.opsForValue().get(Constants.FILES_KEY));
        List<Files> filesList;
        //2, 判断取出的数据是否为空
        if(StrUtil.isBlank(jsonStr)){
            filesList = fileService.list();
            // 缓存到redis中
            redisTemplate.opsForValue().set(Constants.FILES_KEY,JSONUtil.toJsonStr(filesList));
        }else{
            // 从redis缓存中获取数据
           filesList = JSONUtil.toList(jsonStr, Files.class);
        }
        return Result.success(filesList);

2.4 redis更新

// 刷新缓存(遇到增删改,更新缓存)
public void flushRedis(String key){
   redisTemplate.delete(key);
}

完整的FileController代码:

package com.ppj.controller;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ppj.constants.Constants;
import com.ppj.entity.Files;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.List;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ppj.common.Result;

import com.ppj.service.IFileService;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author ppj
 * @since 2024-05-21
 */
@RestController
@RequestMapping("/file")
public class FileController {

    @Resource
    private IFileService fileService;

    @Value("${files.upload.path}")
    private String fileUploadPath;

    @Autowired
    private RedisTemplate redisTemplate;

    // 新增或者更新
    @PostMapping
    public Result save(@RequestBody Files file) {
        flushRedis(Constants.FILES_KEY);
        fileService.saveOrUpdate(file);
        return Result.success();
    }

    @DeleteMapping("/{fileIds}")
    public Result delete(@PathVariable Integer[] fileIds) {
        flushRedis(Constants.FILES_KEY);
        fileService.removeByIds(Arrays.asList(fileIds));
        return Result.success();
    }

    @GetMapping
    public Result findAll() {
        // 1, 从redis中获取数据
        String jsonStr = JSONUtil.toJsonStr(redisTemplate.opsForValue().get(Constants.FILES_KEY));
        List<Files> filesList;
        // 2,判断取出的数据是否为空
        if(StrUtil.isBlank(jsonStr)){
            filesList = fileService.list();
            // 缓存到redis中
            redisTemplate.opsForValue().set(Constants.FILES_KEY,JSONUtil.toJsonStr(filesList));
        }else {
            // 从redis缓存中获取数据
            filesList = JSONUtil.toList(jsonStr, Files.class);
        }
        return Result.success(filesList);
    }


    @GetMapping("/page")
    public Result findPage(@RequestParam Integer pageNum,
                                @RequestParam Integer pageSize,
                           @RequestParam String name) {
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name",name);
//        queryWrapper.orderByDesc("id");
        return Result.success(fileService.page(new Page<>(pageNum, pageSize), queryWrapper));
    }


    /**
     * 文件上传接口
     * @param file 前端传递过来的文件
     * @return
     * @throws IOException
     */
    @PostMapping("/upload")
    public String upload(@RequestParam MultipartFile file) throws IOException {
        String originalFilename = file.getOriginalFilename();
        String type = FileUtil.extName(originalFilename);
        long size = file.getSize();

        // 定义一个文件唯一的标识码
        String uuid = IdUtil.fastSimpleUUID();
        String fileUUID = uuid + StrUtil.DOT + type;

        File uploadFile = new File(fileUploadPath + fileUUID);
        // 判断配置的文件目录是否存在,若不存在则创建一个新的文件目录
        File parentFile = uploadFile.getParentFile();
        if(!parentFile.exists()) {
            parentFile.mkdirs();
        }

        String url;
        // 获取文件的md5
        String md5 = SecureUtil.md5(file.getInputStream());
        // 从数据库查询是否存在相同的记录
        Files dbFiles = getFileByMd5(md5);
        if (dbFiles != null) { // 文件已存在,直接返回数据库里的url
            url = dbFiles.getUrl();
        } else {  // 文件不存在才生成url,保存数据至数据库
            // 上传文件到磁盘
            file.transferTo(uploadFile);
            // 数据库若不存在重复文件,则不删除刚才上传的文件
            url = "http://localhost:9000/file/" + fileUUID;
            // 存储数据库
            Files saveFile = new Files();
            saveFile.setName(originalFilename);
            saveFile.setType(type);
            saveFile.setSize(size/1024);
            saveFile.setUrl(url);
            saveFile.setMd5(md5);
            fileService.saveOrUpdate(saveFile);
        }
        return url;
    }

    /**
     * 通过文件的md5查询文件
     * @param md5
     * @return
     */
    private Files getFileByMd5(String md5) {
        // 查询文件的md5是否存在
        QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("md5", md5);
        Files one = fileService.getOne(queryWrapper);
        return one != null ? one : null;
    }

    /**
     * 文件下载接口   http://localhost:9090/file/{fileUUID}
     * @param fileUUID
     * @param response
     * @throws IOException
     */
    @GetMapping("/{fileUUID}")
    public void download(@PathVariable String fileUUID, HttpServletResponse response) throws IOException {
        // 根据文件的唯一标识码获取文件
        File uploadFile = new File(fileUploadPath + fileUUID);
        // 设置输出流的格式
        ServletOutputStream os = response.getOutputStream();
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUUID, "UTF-8"));
        response.setContentType("application/octet-stream");

        // 读取文件的字节流
        os.write(FileUtil.readBytes(uploadFile));
        os.flush();
        os.close();
    }

    @PostMapping("/update")
    public Result changeEnable(@RequestBody Files files){
        flushRedis(Constants.FILES_KEY);
        return fileService.saveOrUpdate(files)?Result.success():Result.error();
    }

    // 刷新缓存(遇到增删改,更新缓存)
    public void flushRedis(String key){
        redisTemplate.delete(key);
    }

}

2.5 redis使用前后对比

redis未存储数据前,每刷新一次页面,就会重新去数据库请求一遍数据,后台会有日志打印信息,如下图所示:

在这里插入图片描述

当数据存储在redis后,刷新页面不再去请求数据库,而是直接从redis中取数据,从而减轻了数据库的访问压力。如下图所示,再次刷新,后台没有日志记录。
在这里插入图片描述

总结

  • 为什么使用redis,因为用它可以减轻数据库访问压力

写在最后

如果此文对您有所帮助,请帅戈靓女们务必不要吝啬你们的Zan,感谢!!不懂的可以在评论区评论,有空会及时回复。
文章会一直更新

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

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

相关文章

【经验分享】Claude3.5 Sonnet六大可扩展用途

Claude3.5 Sonnet六大可扩展用途 概述 Claude 3.5 Sonnet的性能比其他大模型都有好&#xff0c;本文基于Claude3.5 Sonnet的Artifact功能进行讨论和分析&#xff0c;提供了Claude3.5 Sonnet的六大可扩展用途。 用途 1.画SVG图像 2.设计网站 3.设计徽标 4.设计游戏 5.分…

JavaScript的学习之dom的查询(一)

一、获得元素 通过document对象调用&#xff1a; getElementById()&#xff1a;通过id属性获取一个元素节点对象getElementsByTagName()&#xff1a;通过标签名获取一组元素节点对象getElementsByName()&#xff1a;通过name属性来获取一组元素节点对象 核心学习代码 <scrip…

【语义分割】1-标注数据集-【单张图片】labelme标注json文件转mask

声明&#xff1a;我学习了b站&#xff1a;标注自己的语义分割数据集_哔哩哔哩_bilibili 并且复现了&#xff0c;记录了所思所得。 主要是说了&#xff1a; 做语义分割&#xff0c;数据集怎么用labelme标注成json文件&#xff0c;以及&#xff0c;json文件怎么转成mask 流程…

springcould-config git源情况下报错app仓库找不到

在使用spring config server服务的时候发现在启动之后的一段时间内控制台会抛出异常&#xff0c;spring admin监控爆红&#xff0c;控制台信息如下 --2024-06-26 20:38:59.615 - WARN 2944 --- [oundedElastic-7] o.s.c.c.s.e.JGitEnvironmentRepository : Error occured …

Linux - 记一次某Java程序启动报错(申请内存失败)

文章目录 问题可能原因分析可能原因分析尝试各种解决方案尝试解决过程 解决办法&#xff1a; 调整 overcommit_meory参数overcommit_memory详解什么是 overcommit_memory&#xff1f;overcommit_memory 的选项及其含义配置 overcommit_memory查看当前设置设置 overcommit_memor…

如何为您的企业实施营销翻译

要为您的业务实施营销翻译&#xff0c;您需要执行以下步骤&#xff1a; 评估市场需求 你首先需要做的事情之一是确定你的产品或服务可以销售的地区或国家。这可以通过 看看在这些地区已经取得成功的竞争对手阅读行业的市场调查和预测&#xff0c;了解市场趋势和潜在机会评估…

经销or直营,新老车企殊途终要同归

步入2024&#xff0c;汽车圈的新人、老人都逐渐活成了对方的样子。 2024年5月&#xff0c;先后有消息传来&#xff0c;阿维塔要从直营模式全部转向经销模式&#xff0c;蔚来新发布的子品牌“乐道”未来可能考虑合作或加盟&#xff0c;并单独建设门店。 而就在5月1日&#xff…

网工内推 | 国企信息工程师,信息系统项目管理师优先,最高14薪

01 上海浦东软件园股份有限公司 &#x1f537;招聘岗位&#xff1a;信息化管理工程师 &#x1f537;岗位职责&#xff1a; 1. 根据公司战略、数字化总体架构规划和IT 技术趋势&#xff0c;制定信息化系统的规划与设计&#xff0c;并制定实施计划。 2. 统筹公司信息化系统管理…

ONLYOFFICE 文档 8.1 发布:重塑文档处理

官网链接&#xff1a;ONLYOFFICE官网 一、PDF编辑器功能强大&#xff1a;创造跟随想象 在追求无界办公与高效创作的今天&#xff0c;ONLYOFFICE再次引领风潮&#xff0c;正式发布了其桌面编辑器的最新版本——ONLYOFFICE桌面编辑器8.1。这一版本不仅巩固了其作为顶级办公套件…

【分布式文件系统HDFS】文件操作基本命令的使用

目录 一、按照下述要求写出相应的文件操作命令&#xff0c;执行并观察结果 1. 新建目录 1.1 在本地文件系统按要求创建如下的文件夹 1.2 在HDFS文件系统按要求创建如下的文件夹 2. 编辑文件test1.txt&#xff0c;放入本地文件夹 /opt/user/myfile 3. 使用moveFromLocal命令…

计算机视觉:项目实战

目录 SSD1.安装ananconda2.安装cuda和cudnn3.配置Pytorch环境3.1 pytorch环境的配置与激活3.2 pytorch库的安装3.3 其它依赖库的安装 遇到的问题&#xff1a;1.EOFError: Ran out of input.2.No module named dlib. SSD 1.安装ananconda 见另一篇博文&#xff1a;https://blo…

随机步问题

随机步问题 1.题目简介2.题目分析3.创建变量4.主程序5.程序效果6.程序可以改进的点 1.题目简介 2.题目分析 数组初始化 生成随机方向 判断程序结束的标志 当前元素为Z&#xff0c;或者四个方向都堵住了 3.创建变量 arry[ROW][COL]创建二维数组 _Bool a,b,c,d判断是否会出现四…

搜索引擎的妙用:掌握这些技巧,让你的搜索更高效!

搜索引擎是我们日常生活中不可或缺的工具&#xff0c;它帮助我们快速找到所需的信息。但是&#xff0c;你真的知道如何高效地使用搜索引擎吗&#xff1f;下面&#xff0c;我将分享一些高级搜索技巧&#xff0c;让你的搜索更加精准和高效。 1. 完全匹配搜索 当你想要搜索一个特…

Python数据可视化-地图可视化

1.首先绘制实现数据可视化的思维导图 具体要实现什么功能-怎么处理&#xff0c;先把思路写好 数据来源&#xff1a; 爬取的数据 运行结果&#xff1a; 部分代码&#xff1a; 完整代码请在下方↓↓↓&#x1f447;获取 转载请注明出处&#xff01;

调频信号FM的原理与matlab与FPGA实现

平台&#xff1a;matlab r2021b&#xff0c;vivado2023.1 本文知识内容摘自《软件无线电原理和应用》 调频(FM)是载波的瞬时频率随调制信号成线性变化的一种调制方式&#xff0c;音频调频信号的数学表达式可以写为&#xff1a; Fm频率调制&#xff0c;载波的幅度随着调制波形…

不同材质的不锈钢氮气柜优缺点和使用场景分析

不锈钢氮气柜是一种用于存储对湿度敏感的物品的专用储藏设备&#xff0c;通过充入干燥的氮气来降低柜内湿度&#xff0c;保护存储物免受氧化或腐蚀。 根据不同的材质&#xff0c;不锈钢氮气柜可分为&#xff1a; 一、201不锈钢氮气柜&#xff1a; 201不锈钢因其较低的镍含量而成…

【揭秘新潮流】实践教学新宠SmartEDA,让电子设计课“潮“起来!

在信息时代的浪潮下&#xff0c;电子设计课程早已不再是枯燥乏味的代名词。随着技术的飞速发展&#xff0c;一种名为SmartEDA的实践教学新选择正逐渐崭露头角&#xff0c;为电子设计课程注入了前所未有的活力与趣味性。今天&#xff0c;就让我们一起走进SmartEDA的世界&#xf…

25届最近4年中国科学技术大学自动化考研院校分析

中国科学技术大学 目录 一、学校学院专业简介 二、考试科目指定教材 三、近4年考研分数情况 四、近4年招生录取情况 五、最新一年分数段图表 六、历年真题PDF 七、初试大纲复试大纲 八、学费&奖学金&就业方向 一、学校学院专业简介 二、考试科目指定教材 1、…

Maven列出所有的依赖树

在 IntelliJ IDEA 中&#xff0c;你可以使用 Maven 插件来列出项目的依赖树。Maven 插件提供了一个名为dependency:tree的目标&#xff0c;可以帮助你获取项目的依赖树详细信息。 要列出项目的依赖树&#xff0c;可以执行以下步骤&#xff1a; 打开 IntelliJ IDEA&#xff0c;…

Kubernetes之Controller详解

本文尝试从Kubernetes Controller的种类、交互逻辑、最佳实践、伪代码示例及历史演进5个方面对其进行详细阐述&#xff0c;希望对您有所帮助&#xff01; 一、Kubernetes Controller种类 Kubernetes Controller Manager 是 Kubernetes 集群的核心组件之一&#xff0c;负责管理…