谷粒商城--品牌管理(OSS、JSR303数据校验)-2

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 谷粒商城--品牌管理(OSS、JSR303数据校验)

multiUpload.vue

多文件上传组件


<template>
  <div>
    <el-upload
      action="http://gulimall-hello.oss-cn-beijing.aliyuncs.com"
      :data="dataObj"
      :list-type="listType"
      :file-list="fileList"
      :before-upload="beforeUpload"
      :on-remove="handleRemove"
      :on-success="handleUploadSuccess"
      :on-preview="handlePreview"
      :limit="maxCount"
      :on-exceed="handleExceed"
      :show-file-list="showFile"
    >
      <i class="el-icon-plus"></i>
    </el-upload>
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt />
    </el-dialog>
  </div>
</template>
<script>
import { policy } from "./policy";
import { getUUID } from '@/utils'
export default {
  name: "multiUpload",
  props: {
    //图片属性数组
    value: Array,
    //最大上传图片数量
    maxCount: {
      type: Number,
      default: 30
    },
    listType:{
      type: String,
      default: "picture-card"
    },
    showFile:{
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      dataObj: {
        policy: "",
        signature: "",
        key: "",
        ossaccessKeyId: "",
        dir: "",
        host: "",
        uuid: ""
      },
      dialogVisible: false,
      dialogImageUrl: null
    };
  },
  computed: {
    fileList() {
      let fileList = [];
      for (let i = 0; i < this.value.length; i++) {
        fileList.push({ url: this.value[i] });
      }
      return fileList;
    }
  },
  mounted() {},
  methods: {
    emitInput(fileList) {
      let value = [];
      for (let i = 0; i < fileList.length; i++) {
        value.push(fileList[i].url);
      }
      this.$emit("input", value);
    },
    handleRemove(file, fileList) {
      this.emitInput(fileList);
    },
    handlePreview(file) {
      this.dialogVisible = true;
      this.dialogImageUrl = file.url;
    },
    beforeUpload(file) {
      let _self = this;
      return new Promise((resolve, reject) => {
        policy()
          .then(response => {
            console.log("这是什么${filename}");
            _self.dataObj.policy = response.data.policy;
            _self.dataObj.signature = response.data.signature;
            _self.dataObj.ossaccessKeyId = response.data.accessid;
            _self.dataObj.key = response.data.dir +getUUID()+"_${filename}";
            _self.dataObj.dir = response.data.dir;
            _self.dataObj.host = response.data.host;
            resolve(true);
          })
          .catch(err => {
            console.log("出错了...",err)
            reject(false);
          });
      });
    },
    handleUploadSuccess(res, file) {
      this.fileList.push({
        name: file.name,
        // url: this.dataObj.host + "/" + this.dataObj.dir + "/" + file.name; 替换${filename}为真正的文件名
        url: this.dataObj.host + "/" + this.dataObj.key.replace("${filename}",file.name)
      });
      this.emitInput(this.fileList);
    },
    handleExceed(files, fileList) {
      this.$message({
        message: "最多只能上传" + this.maxCount + "张图片",
        type: "warning",
        duration: 1000
      });
    }
  }
};
</script>
<style>
</style>

policy.js

服务端签名


import http from '@/utils/httpRequest.js'
export function policy() {
   return  new Promise((resolve,reject)=>{
        http({
            url: http.adornUrl("/third-party/oss/policy"),
            method: "get",
            params: http.adornParams({})
        }).then(({ data }) => {
            resolve(data);
        })
    });
}

阿里云开启跨域

8c9b02c285cf764508b58244af6a5251_51d7fdfe5235c60b689aaafc0ee736ab.png


测试

图片可以正常上传和显示


bb4af34f47bc501ee1f92c474abc9bba_9e91bd511ec03082ded1d37c93117747.png


8d09e34292e8a778744112fbdcb9885a_ea762bc31dd6a88245cae77139d4d629.png


数据校验


前端数据校验

就是规定添加的属性要符合规定,不然会出现想不到的异常!


例如:添加品牌选项框中,设置检索首字母那么我们就要规定首字母不能是多个字母只能是a-z或A-Z之间的一个


那么我们就可以对这个输入框进行绑定,如下


6e285799ad315feac9aec108917c4535_8b353cdfe806f99bdf09834462a20d38.png


实现效果如下:


40f60084788811232ca5934f179bce67_44e51e943b4660672c24981115f89548.png


JSR303数据校验

后端的处理前端传来的数据时,虽然前端已做限制但是还不够严谨,例如我们可以跳过页面通过一些工具直接发送请求也可以完成添加等操作,所以后端也需要做数据校验!


java中也提供了一系列的校验方式,它这些校验方式在“javax.validation.constraints”包中,@Email,@NotNull等注解。


一、添加依赖


后面可能其他模块也能用到,所以这里把依赖添加到common模块


<!--jsr3参数校验器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
    <version>2.3.2.RELEASE</version>
</dependency>

这个依赖提供了NotNull,@NotBlank和@NotEmpty这些判断


二、给需要校验的bean添加注解


/**
 * 品牌
 * 
 * @author xiaocai
 * @email mildcaq@gmail.com
 * @date 2022-07-27 21:05:30
 */
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
   private static final long serialVersionUID = 1L;
   /**
    * 品牌id
    */
   @TableId
   private Long brandId;
   /**
    * 品牌名
    */
   @NotBlank
   private String name;
   /**
    * 品牌logo地址
    */
   private String logo;
   /**
    * 介绍
    */
   private String descript;
   /**
    * 显示状态[0-不显示;1-显示]
    */
   @NotNull
   private Integer showStatus;
   /**
    * 检索首字母
    */
   @NotEmpty
   private String firstLetter;
   /**
    * 排序
    */
   @NotNull
   @Min(0)
   private Integer sort;
}

未在控制类中指定方法开启校验时如下:


ccbf74750b20e6e3afa74ff9ead6b9a8_d62b0645e4b23b841db850cd81aed44b.png


controller中给请求方法加校验注解@Valid,开启校验,

/**
 * 保存
 */
@RequestMapping("/save")
public R save(@RequestBody @Valid BrandEntity brand){
    brandService.save(brand);
    return R.ok();
}

这里我错误信息只返回是Bad Request


视频中老师所讲的是有详细信息的,这个差异应该是版本原因不影响!


fedb447034cbd53c7811f1ba84e2d914_15009a5cca7378e1f1add7a2ba1f4a35.png


这种返回的错误结果并不符合我们的业务需要。我们想让捕捉这个错误的详细信息,并且能够统一返回我们自定义的信息!


三、通过BindResult捕获校验结果


修改内容如下:


@RequestMapping("/save")
public R save(@Valid @RequestBody BrandEntity brand,BindingResult result){
    if( result.hasErrors()){
        Map<String,String> map=new HashMap<>();
        //1.获取错误的校验结果
        result.getFieldErrors().forEach((item)->{
            //获取发生错误时的message
            String message = item.getDefaultMessage();
            //获取发生错误的字段
            String field = item.getField();
            map.put(field,message);
        });
        return R.error(400,"提交的数据不合法").put("data",map);
    }else {
    }
    brandService.save(brand);
    return R.ok();
}

再次测试


好啦,这下把错误信息都捕获到喽!


ba698ad63a9b72ba4cf94f81beb808c0_f8926a20659e84ac59542fb84fe02bcf.png


但是,这种是针对于该请求设置了一个内容校验,如果针对于每个请求都单独进行配置,显然不是太合适,实际上可以统一的对于异常进行处理。


四、统一异常处理


可以使用SpringMvc所提供的@ControllerAdvice,通过“basePackages”能够说明处理哪些路径下的异常。


(1)抽取一个异常处理类


详细信息都写在了注释里,可以作为参考!!!


@Slf4j
@RestControllerAdvice(basePackages = "com.caq.mall.product.controller")
public class MallExceptionAdvice {
    //指定的包下所有的校验异常都会被这个方法捕捉
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleValidException(MethodArgumentNotValidException exception) {
        //定义map,存放所有错误信息
        Map<String, String> map = new HashMap<>();
        //通过BindResult捕获校验结果
        BindingResult bindingResult = exception.getBindingResult();
        //遍历校验结果中所有字段的错误,字段为key,错误信息为value存放到map中
        bindingResult.getFieldErrors().forEach(fieldError -> {
            String message = fieldError.getDefaultMessage();
            String field = fieldError.getField();
            map.put(field, message);
        });
//        控制台打印错误信息
        log.error("数据校验出现问题{},异常类型{}", exception.getMessage(), exception.getClass());
//        返回错误结果,并显示所有错误的数据
        return R.error(400, "数据校验出现问题").put("data", map);
    }
}

(2)测试: http://localhost:88/api/product/brand/save


接下来我们去掉我们控制类中save方法的校验,看看统一异常处理能否生效


还是可以哦!


4f18dea1317ec1660ee53a6278a64096_f8b997232d8a85940f19a69ac2befcad.png


(3)错误状态码


正规开发过程中,错误状态码有着严格的定义规则


/***
 * 错误码和错误信息定义类
 * 1. 错误码定义规则为5为数字
 * 2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常
 * 3. 维护错误码后需要维护错误描述,将他们定义为枚举形式
 * 错误码列表:
 *  10: 通用
 *      001:参数格式校验
 *  11: 商品
 *  12: 订单
 *  13: 购物车
 *  14: 物流
 */
public enum BizCodeEnum {
    UNKNOW_EXEPTION(10000,"系统未知异常"),
    VALID_EXCEPTION( 10001,"参数格式校验失败");
    private int code;
    private String msg;
    BizCodeEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
}

(4)默认异常处理


上面的统一异常处理只是针对了校验相关的错误,那么如果是其他异常呢?


那就再来个默认的异常处理呗


   @ExceptionHandler(value = Throwable.class)
    public R handleException(Throwable throwable){
        log.error("未知异常{},异常类型{}",throwable.getMessage(),throwable.getClass());
        return R.error(BizCodeEnum.UNKNOW_EXEPTION.getCode(),BizCodeEnum.UNKNOW_EXEPTION.getMsg());
    }
相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
相关文章
|
存储 弹性计算 安全
对象存储OSS快速上手——ossutil工具管理OSS
本实验是对象存储OSS进阶实验。通过本实验,用户可学会如何使用ossutil工具在Linux环境下用命令管理oss,完成文件上传下载等操作。
|
5月前
|
存储 安全 前端开发
APP管理后台OSS技术改造
旨在记录之前使用的上传文件是放在服务器的现在改成了oss更加高效管理
|
6月前
|
存储 编解码 监控
使用oss服务管理对象
使用oss服务管理对象
69 1
|
对象存储
谷粒商城--品牌管理(OSS、JSR303数据校验)-3
谷粒商城--品牌管理(OSS、JSR303数据校验)
63 0
|
存储 前端开发 JavaScript
谷粒商城--品牌管理(OSS、JSR303数据校验)-1
谷粒商城--品牌管理(OSS、JSR303数据校验)
108 0
|
数据可视化 数据挖掘 数据库
TDengine OSS 与 qStudio 实现无缝协同,革新数据分析和管理方式
为了帮助社区用户更好地进行数据分析和管理,丰富可视化解决方案的多样性,我们将开源的时序数据库 TDengine OSS 与开源的数据库分析工具进行了集成,相信这对终极开源工具一定能帮助你释放数据潜力。
126 0
java202304java学习笔记第五十二天员工管理-阿里云oss-集成服务2
java202304java学习笔记第五十二天员工管理-阿里云oss-集成服务2
88 0
|
4月前
|
机器学习/深度学习 人工智能 专有云
人工智能平台PAI使用问题之怎么将DLC的数据写入到另一个阿里云主账号的OSS中
阿里云人工智能平台PAI是一个功能强大、易于使用的AI开发平台,旨在降低AI开发门槛,加速创新,助力企业和开发者高效构建、部署和管理人工智能应用。其中包含了一系列相互协同的产品与服务,共同构成一个完整的人工智能开发与应用生态系统。以下是对PAI产品使用合集的概述,涵盖数据处理、模型开发、训练加速、模型部署及管理等多个环节。
|
22天前
|
分布式计算 Java 开发工具
阿里云MaxCompute-XGBoost on Spark 极限梯度提升算法的分布式训练与模型持久化oss的实现与代码浅析
本文介绍了XGBoost在MaxCompute+OSS架构下模型持久化遇到的问题及其解决方案。首先简要介绍了XGBoost的特点和应用场景,随后详细描述了客户在将XGBoost on Spark任务从HDFS迁移到OSS时遇到的异常情况。通过分析异常堆栈和源代码,发现使用的`nativeBooster.saveModel`方法不支持OSS路径,而使用`write.overwrite().save`方法则能成功保存模型。最后提供了完整的Scala代码示例、Maven配置和提交命令,帮助用户顺利迁移模型存储路径。
|
3月前
|
存储 机器学习/深度学习 弹性计算
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
阿里云EMR数据湖文件系统问题之OSS-HDFS全托管服务的问题如何解决
下一篇
无影云桌面