[Java]RuoYi帝可得-2文件储存

文件存储

本地存储

在若依框架目前的实现中,是把图片存储到了服务器本地的目录

  1. 本地存储存在的问题
  • 性能瓶颈
  • 磁盘满了
  • 单点故障
  1. 自定义存储服务
  • FastDFS
  • Minlo
  1. 第三方储存服务
  • 我们要使用云服务方案替代本地储存方案
阿里云OSS

阿里云对象存储OSS (Object Storage Service),是一款海量、安全、低成本、高可靠的云存储服务。使用OSS,您可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。

阿里云使用步骤

  1. SDK: Software Development Kit的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK.
  2. BuCket: 存储空间是用户用于存储对象(Object,就是文件)的容器,所有的对象都必须隶属于某个存储空间。
  3. 创建Bucket
x-file-storage

文件存储

XFile Storage官网: https://x-file-storage.xuyanwu.cn/

  1. 一行代码将文件存储到本地、阿里云OSS、华为云OBS、七牛云Kodo、腾讯云COS....其它兼容S3协议的存储平台
  1. 优势
  • 简化配置
  • 易于集成
  • 功能丰富
  • 开箱即用

集成到项目中,官网写的很详细,这里只做关键记录

  1. 引入依赖

    复制代码
         <!-- 文件上传  -->
         <dependency>
             <groupId>org.dromara.x-file-storage</groupId>
             <artifactId>x-file-storage-spring</artifactId>
             <version>2.3.0</version>
         </dependency>
    
         <!-- 阿里云OSS -->
         <dependency>
             <groupId>com.aliyun.oss</groupId>
             <artifactId>aliyun-sdk-oss</artifactId>
             <version>3.16.1</version>
         </dependency>
  1. 配置参数

    文件存储配置

    dromara:
    x-file-storage: #文件存储配置
    default-platform: aliyun-oss-1 #默认使用的存储平台
    thumbnail-suffix: ".min.jpg" #缩略图后缀,例如【.min.jpg】【.png】
    #对应平台的配置写在这里,注意缩进要对齐
    aliyun-oss:
    - platform: aliyun-oss-1 # 存储平台标识,default-platform要和该配置保持一致
    enable-storage: true # 启用存储
    access-key:
    secret-key:
    end-point: oss-cn-qingdao.aliyuncs.com # 从阿里云控制台获取 【对象存储/Bucket列表/dkd-project-app/概览/访问端口/外网访问】
    bucket-name: dkd-project-app
    domain: https://dkd-project-app.oss-cn-qingdao.aliyuncs.com/ # 访问域名,注意"/"结尾,例如:https://abc.oss-cn-shanghai.aliyuncs.com/ 【自己拼就行】
    base-path: dkd-images/ # 基础路径

  1. 添加注解
  1. 后端代码改造

    package com.dkd.web.controller.common;

    /**

    • 通用请求处理

    • @author ruoyi
      */
      @RestController
      @RequestMapping("/common")
      public class CommonController
      {
      private static final Logger log = LoggerFactory.getLogger(CommonController.class);

      @Autowired
      private ServerConfig serverConfig;

      @Autowired
      private FileStorageService fileStorageService;

      private static final String FILE_DELIMETER = ",";

      /**

      • 通用上传请求(单个)
        */
        @PostMapping("/upload")
        public AjaxResult uploadFile(MultipartFile file) throws Exception
        {
        try
        {
        // 原始代码
        // // 上传文件路径
        // String filePath = RuoYiConfig.getUploadPath();
        // // 上传并返回新文件名称
        // String fileName = FileUploadUtils.upload(filePath, file);
        // String url = serverConfig.getUrl() + fileName;
        // AjaxResult ajax = AjaxResult.success();
        // ajax.put("url", url);
        // ajax.put("fileName", fileName);
        // ajax.put("newFileName", FileUtils.getName(fileName));
        // ajax.put("originalFilename", file.getOriginalFilename());
        // return ajax;

        复制代码
         // 指定oss保存的文件路径 (例 dkd-images/2020/12/09/文件名)
         String objectName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) +  "/";
         FileInfo fileInfo = fileStorageService.of(file)
                 .setPath(objectName) //保存到相对路径下,为了方便管理,不需要可以不写
                 .upload();
         AjaxResult ajax = AjaxResult.success();
         ajax.put("url", fileInfo.getUrl());
         ajax.put("fileName", fileInfo.getUrl());
         // 注意:这里的值需要改成URL, 因为前端的访问地址已经做了判断,是http开头就直接显示图片
         ajax.put("newFileName", fileInfo.getUrl());
         ajax.put("originalFilename", file.getOriginalFilename());
         return ajax;

        }
        catch (Exception e)
        {
        return AjaxResult.error(e.getMessage());
        }
        }

    }

  2. 前端代码改造

  1. 重启服务,测试一下

设备管理

前置工作

需求说明

  1. 业务场景: 管理员在系统录入设备信息后,员工将负责设备(智能售货机)的投放和商品补货工作
  1. 设备管理主要涉及到三个功能模块,业务流程如下:
  • 新增设备类型: 允许管理员定义新的售货机型号,包括其规格和容量。
  • 新增设备: 在新的设备类型定义后,系统应允许添加新的售货机实例,并将它们分配到特定的点位。
  • 新增货道: 对于每个新添加的设备,系统应支持定义新的货道,后期用于关联相应的商品SKU。

库表设计: 对于设备管理数据模型,下面是示意图:

  • 关系字段:vm_type_id、node_id、vm_id
  • 数据字典:vm_status(0未投放、1运营、3撤机)
  • 冗余字段:addr、business_type、region_id、partner_id(简化查询接口、提高查询效率)
代码生成

使用若依代码生成器,生成设备类型、设备、货道前后端基础代码,并导入到项目中:

  1. 创建目录菜单
  1. 添加数据字典
  1. 配置代码生成信息
  1. 下载代码并导入项目
设备类型改造

参考页面原型,完成基础布局展示改造

  1. 在vmType/index.vue视图组件中修改

    复制代码
     <el-form-item>
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
    
         <el-button icon="Refresh" @click="resetQuery">重置</el-button>
    
     </el-form-item>

    <el-table v-loading="loading" :data="vmTypeList" @selection-change="handleSelectionChange">




    <template #default="scope">


    复制代码
     <el-table-column label="货道行" align="center" prop="vmRow" />
     <el-table-column label="货道列" align="center" prop="vmCol" />
     <el-table-column label="设备容量" align="center" prop="channelMaxCapacity" />
     <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
         <template #default="scope">
         <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['manage:vmType:edit']">修改</el-button>
    
         <el-button link type="primary" @click="handleDelete(scope.row)" v-hasPermi="['manage:vmType:remove']">删除</el-button>
    
         </template>
    
     </el-table-column>
    复制代码
         <el-form-item label="型号编码" prop="model">
             <el-input v-model="form.model" placeholder="请输入型号编码" />
         </el-form-item>
    
         <el-form-item label="货道数" prop="vmRow">
             <el-input-number v-model="form.vmRow" placeholder="请输入"  :min="1" :max="10"/>行&nbsp;&nbsp;
             <el-input-number v-model="form.vmCol" placeholder="请输入"  :min="1" :max="10"/>列
         </el-form-item>
    
         <el-form-item label="货道容量" prop="channelMaxCapacity">
             <el-input-number v-model="form.channelMaxCapacity" placeholder="请输入"  :min="1" :max="10"/>个
         </el-form-item>
    
         <el-form-item label="设备图片" prop="image">
             <image-upload v-model="form.image"/>
         </el-form-item>
    
     </el-form>
    
     <template #footer>
         <div class="dialog-footer">
             <el-button type="primary" @click="submitForm">确 定</el-button>
             <el-button @click="cancel">取 消</el-button>
         </div>
    
     </template>
设备管理改造

参考页面原型,完成基础布局展示改造

  1. 刷新设备表数据

    update tb_vending_machine set partner_id=2 where id=80;
    update tb_vending_machine set addr=(select address from tb_node where id = 1) where node_id=1;
    update tb_vending_machine set addr=(select address from tb_node where id = 2) where node_id=2;

  1. 在vm/index.vue视图组件中修改

    复制代码
     <el-form-item>
         <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
         <el-button icon="Refresh" @click="resetQuery">重置</el-button>
     </el-form-item>

    <el-table v-loading="loading" :data="vmList" @selection-change="handleSelectionChange">



    <template #default="scope">


    {{ item.name }}

    复制代码
       </div>
    
     </template>
  2. 在VendingMachineServiceImpl中修改

    /**

    • 修改设备管理
    • @param vendingMachine 设备管理
    • @return 结果
      */
      @Override
      public int updateVendingMachine(VendingMachine vendingMachine)
      {
      if (vendingMachine.getNodeId()!=null) {
      // 查询点位表,补充:区域、点位、合作商等信息
      Node node = nodeService.selectNodeById(vendingMachine.getNodeId());
      BeanUtil.copyProperties(node,vendingMachine,"id");// 商圈类型、区域、合作商
      vendingMachine.setAddr(node.getAddress());// 设备地址
      }
      vendingMachine.setUpdateTime(DateUtils.getNowDate());// 更新时间
      return vendingMachineMapper.updateVendingMachine(vendingMachine);
      }

商品管理

前置工作

业务场景: 智能售货机的货道管理、商品类型以及具体商品信息的管理

  1. 商品管理主要涉及到三个功能模块,业务流程如下:
  1. 对于商品管理数据模型,下面是示意图:

关系字段: class_id、sku_id、vm_id

生成代码

使用若依代码生成器,生成商品管理前后端基础代码,并导入到项目中:

  1. 创建目录菜单
  1. 配置代码生成信息
  1. 下载代码并导入项目
商品类型改造

参考页面原型,完成基础布局展示改造

  1. 在skuClass/index.vue视图组件中修改

    <el-table v-loading="loading" :data="skuClassList" @selection-change="handleSelectionChange">




    <template #default="scope">
    <el-button link type="primary" @click="handleUpdate(scope.row)" v-hasPermi="['manage:skuClass:edit']">修改

    复制代码
       <el-button link type="primary"  @click="handleDelete(scope.row)" v-hasPermi="['manage:skuClass:remove']">删除</el-button>
    
     </template>
  2. 修改全局异常处理器,添加以下内容

表中对class_name字段进行了唯一性约束,保证该值得唯一性

但这个提示不精确,要进行修改

修改全局异常处理器

复制代码
/**
 * 数据完整性异常
 */
@ExceptionHandler(DataIntegrityViolationException.class)
public AjaxResult handelDataIntegrityViolationException(DataIntegrityViolationException e) {

    if (e.getMessage().contains("foreign")) {

        return AjaxResult.error("无法删除,有其他数据引用");
    }
    if(e.getMessage().contains("Duplicate")){
        return AjaxResult.error("无法保存,名称已存在");
    }
    return AjaxResult.error("数据完整性异常,请联系管理员");
}
商品管理改造

参考页面原型,完成基础布局展示改造

  1. 在sku/index.vue视图组件中修改

    搜索
    复制代码
     <el-button icon="Refresh" @click="resetQuery">重置</el-button>

    <el-table v-loading="loading" :data="skuList" @selection-change="handleSelectionChange">




    <template #default="scope">