阿里云OSS、数据校验和表的分析

品牌表
阿里云OSS、数据校验和表的分析_第1张图片
新增菜单
阿里云OSS、数据校验和表的分析_第2张图片

使用逆向生成的 vue 页面
阿里云OSS、数据校验和表的分析_第3张图片

复制到 product 文件夹下,重启 renren-fast-vue 项目,但是这里只有查询,没有新增和删除,是因为权限的问题
阿里云OSS、数据校验和表的分析_第4张图片

Ctrl + Shift + F 全局搜索 isAuth
阿里云OSS、数据校验和表的分析_第5张图片
是在 index.js 中定义是否有权限的,注释掉直接返回 true,一直都有权限

/**
 * 是否有权限
 * @param {*} key
 */
/**
 * 是否有权限
 * @param {*} key
 */
export function isAuth (key) {
  // return JSON.parse(sessionStorage.getItem('permissions') || '[]').indexOf(key) !== -1 || false
  return true;
}

在测试就都好使了,但是细节需要完善
在这里插入图片描述
关闭 Eslint 语法检查
阿里云OSS、数据校验和表的分析_第6张图片

文件上传功能

阿里云OSS、数据校验和表的分析_第7张图片
参考文档:https://help.aliyun.com/document_detail/31947.html?spm=5176.8465980.0.dexternal.4e701450OZd0NW

创建 bucket,阿里云对象存储-服务端签名后直传
阿里云OSS、数据校验和表的分析_第8张图片

创建 gulimall-third-party 模块,引入第三方服务


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.1.8.RELEASEversion>
        <relativePath/> 
    parent>
    <groupId>com.atguigu.gulimallgroupId>
    <artifactId>gulimall-third-partyartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>gulimall-third-partyname>
    <description>第三方服务description>
    <properties>
        <java.version>1.8java.version>
        <spring-cloud.version>Greenwich.SR3spring-cloud.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>com.atguigu.gulimallgroupId>
            <artifactId>gulimall-commonartifactId>
            <version>0.0.1-SNAPSHOTversion>
            <exclusions>
                <exclusion>
                    <groupId>com.baomidougroupId>
                    <artifactId>mybatis-plus-boot-starterartifactId>
                exclusion>
            exclusions>
        dependency>

        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alicloud-ossartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-openfeignartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>2.1.0.RELEASEversion>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

project>

注册中心 和 服务中心 的地址都要写上,一个不写注册中心都注册不上,端口号改为 3000
阿里云OSS、数据校验和表的分析_第9张图片
bootstrap.properties

spring.application.name=gulimall-third-party
spring.cloud.nacos.config.namespace=2c95d4e7-2400-49ae-ba0a-a3bd9e470c11
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

spring.cloud.nacos.config.ext-config[0].data-id=oss.yml
spring.cloud.nacos.config.ext-config[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.ext-config[0].refresh=true

application.yml

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    alicloud:
      access-key: 填写自己的阿里云
      secret-key: 填写自己的阿里云
      oss:
        endpoint: oss-cn-beijing.aliyuncs.com
        bucket: gulishangcheng24
#    alicloud:
#    access-key: LTAI5tNhkwhLZWnEK5m2eukX
#    acce
#    oss:
#      endpoint: oss-cn-beijing.aliyuncs.com
  application:
    name: gulimall-third-party

server:
  port: 30000

配置中心新建 third-party 命名空间,填写阿里云 RAM 的配置(之后在配置也可以)
阿里云OSS、数据校验和表的分析_第10张图片

OssController

@RestController
public class OssController {

    @Resource
    OSS ossClient;

    @Value("${spring.cloud.alicloud.oss.endpoint}")
    private String endpoint;

    @Value("${spring.cloud.alicloud.oss.bucket}")
    private String bucket;

    @Value("${spring.cloud.alicloud.access-key}")
    private String accessId;

    @RequestMapping("/oss/policy")
    public Map<String, String> policy() {

        String host = "https://" + bucket + "." + endpoint; // host的格式为 bucketname.endpoint
        // callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实信息。
        // String callbackUrl = "http://88.88.88.88:8888";
        String format = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        String dir = format + "/"; // 用户上传文件时指定的前缀。

        Map<String, String> respMap = null;

        try {
            long expireTime = 30;
            long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
            Date expiration = new Date(expireEndTime);
            // PostObject请求最大可支持的文件大小为5 GB,即CONTENT_LENGTH_RANGE为5*1024*1024*1024。
            PolicyConditions policyConds = new PolicyConditions();
            policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000);
            policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, dir);

            String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
            byte[] binaryData = postPolicy.getBytes("utf-8");
            String encodedPolicy = BinaryUtil.toBase64String(binaryData);
            String postSignature = ossClient.calculatePostSignature(postPolicy);

            respMap = new LinkedHashMap<String, String>();
            respMap.put("accessid", accessId);
            respMap.put("policy", encodedPolicy);
            respMap.put("signature", postSignature);
            respMap.put("dir", dir);
            respMap.put("host", host);
            respMap.put("expire", String.valueOf(expireEndTime / 1000));
            // respMap.put("expire", formatISO8601Date(expiration));



        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        } finally {
            ossClient.shutdown();
        }
        return respMap;

    }

}

启动服务浏览器输入 http://localhost:30000/oss/policy/ 测试返回数据
阿里云OSS、数据校验和表的分析_第11张图片
浏览器就可以请求这个接口,然后服务器给浏览器返回这串信息,浏览器带着它以及要上传的文件提交到阿里云服务器,阿里云进行校验并存储上传的内容

接下来配置一下网关,localhost:88/api/thirdparty/oss/policy
阿里云OSS、数据校验和表的分析_第12张图片
测试成功
阿里云OSS、数据校验和表的分析_第13张图片

复制 upload 文件夹到 components
阿里云OSS、数据校验和表的分析_第14张图片
改成自己的阿里云地址
阿里云OSS、数据校验和表的分析_第15张图片

brand-add-or-update.vue 引入并声明组件
阿里云OSS、数据校验和表的分析_第16张图片
这个名字根据 components 定义来的
阿里云OSS、数据校验和表的分析_第17张图片
更改一下后端 policy 方法返回值,从返回 map 改为返回 R 对象,前端要从 data 里面拿数据
阿里云OSS、数据校验和表的分析_第18张图片
在这里插入图片描述
在这里插入图片描述
阿里云仓库配置一下跨域,要不上传文件 403
在这里插入图片描述
阿里云OSS、数据校验和表的分析_第19张图片

这个图片回显真搞我心态啊,弄了好久就是不回显,后端前端查,弄了半天把前端 upload 文件夹删了从弄一遍就回显了,应该是我前端哪块不小心弄错了

阿里云OSS、数据校验和表的分析_第20张图片
细节:显示状态按钮在数据库里面存放的是 0 和 1,激活是 1,不激活是 0
阿里云OSS、数据校验和表的分析_第21张图片
添加商品成功之后这显示的是文本信息,应该显示的是图片,我们要自定义显示,去 elementui 上面找
阿里云OSS、数据校验和表的分析_第22张图片
这引入 elementui 图片组件的时候报错,应该是 renren-fast-vue 的工程里没有引入这个组件,我们自己手动引入,到 elementui 官网快速上手里面有
在这里插入图片描述
改过之后还是不回显图片,干脆使用原生的 image 组件

基于表单的数据校验

前端表单校验

        firstLetter: [
          {
            validator: (rule, value, callback) => {
              if (value == "") {
                callback(new Error("首字母必须填写"));
              } else if (!/^[a-zA-Z]$/.test(value)) {
                callback(new Error("首字母必须a-z或者A-Z之间"));
              } else {
                callback();
              }
            },
            trigger: "blur",
          },
        ],
        sort: [
          {
            validator: (rule, value, callback) => {
              if (value == "") {
                callback(new Error("排序字段必须填写"));
              } else if (!Number.isInteger(value) || value < 0) {
                callback(new Error("排序必须是一个大于等于 0 的整数"));
              } else {
                callback();
              }
            },
            trigger: "blur",
          },
        ],

统一异常处理

返回状态码放到 common 模块中

package com.atguigu.common.exception;

public enum BizCodeEnume {

    UNKNOW_EXEPTION(10000,"系统未知异常"),

    VALID_EXCEPTION( 10001,"参数格式校验失败");

    private int code;
    private String msg;

    BizCodeEnume(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public int getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }
}

异常处理类 Product 模块中

@Slf4j
@RestControllerAdvice(basePackages = "com.atguigu.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {

    // 处理特定异常
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handleVaildException(MethodArgumentNotValidException e) {
        log.error("数据校验出错{}, 异常类型:{}", e.getMessage(), e.getClass());
        BindingResult bindingResult = e.getBindingResult();
        Map<String, String> errorMap = new HashMap<>();
        bindingResult.getFieldErrors().forEach((fieldError) -> {
            errorMap.put(fieldError.getField(), fieldError.getDefaultMessage());
        });
        return R.error(BizCodeEnume.VALID_EXCEPTION.getCode(), BizCodeEnume.VALID_EXCEPTION.getMsg()).put("data", errorMap);
    }

    // 大的异常
    @ExceptionHandler(value = Throwable.class)
    public R handleException(Throwable throwable) {
        return R.error(BizCodeEnume.UNKNOW_EXEPTION.getCode(), BizCodeEnume.UNKNOW_EXEPTION.getMsg());
    }
}

新增情况下的校验和修改情况下的校验可能不一样 —— 分组校验

/**
 * 品牌
 * 
 * @author renjianbang
 * @email [email protected]
 * @date 2021-04-20 09:51:57
 */
@Data
@TableName("pms_brand")
public class BrandEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * 品牌id
	 */
	@NotNull(message = "修改必须指定品牌id", groups = {UpdateGroup.class})
	@Null(message = "新增不能指定id", groups = {AddGroup.class})
	@TableId
	private Long brandId;
	/**
	 * 品牌名
	 */
	@NotBlank(message = "品牌名必须提交", groups = {AddGroup.class, UpdateGroup.class})
	private String name;
	/**
	 * 品牌logo地址
	 */
	@NotBlank(groups = {AddGroup.class})
	@URL(message = "logo必须是一个合法的url地址", groups = {AddGroup.class, UpdateGroup.class})
	private String logo;
	/**
	 * 介绍
	 */
	private String descript;
	/**
	 * 显示状态[0-不显示;1-显示]
	 */
	private Integer showStatus;
	/**
	 * 检索首字母
	 */
	@NotEmpty(groups = {AddGroup.class})
	@Pattern(regexp = "/^[a-zA-Z]$/", message = "检索首字母必须是一个字母", groups = {AddGroup.class, UpdateGroup.class})
	private String firstLetter;
	/**
	 * 排序
	 */
	@NotNull(groups = {AddGroup.class})
	@Min(value = 0, message = "排序必须大于等于0", groups = {AddGroup.class, UpdateGroup.class})
	private Integer sort;

}

controller 不同的方法选择不同的分组,根据 spring 提供的注解 @Validated

    /**
     * 保存
     */
    @RequestMapping("/save")
    //@RequiresPermissions("product:brand:save")
    public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand){
		brandService.save(brand);
        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    //@RequiresPermissions("product:brand:update")
    public R update(@Validated(UpdateGroup.class) @RequestBody BrandEntity brand){
		brandService.updateById(brand);

        return R.ok();
    }

groups 参数需要传递接口,接口规定了在什么时候触发规则

public interface AddGroup {
}
public interface UpdateGroup {
}

自定义校验

common 模块引入

        <dependency>
            <groupId>javax.validationgroupId>
            <artifactId>validation-apiartifactId>
            <version>2.0.1.Finalversion>
        dependency>
  • 编写自定义的校验注解
@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class}) // 校验器
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE }) // 哪都可以标注
@Retention(RUNTIME)
public @interface ListValue {
    // 使用该属性去Validation.properties中取
    String message() default "{com.atguigu.common.valid.ListValue.message}";

    Class<?>[] groups() default { };

    Class<? extends Payload>[] payload() default { };

    // 数组,需要用户自己指定
    int[] vals() default {};
}
  • 编写自定义校验器
public class ListValueConstraintValidator
        implements ConstraintValidator<ListValue,Integer> { //<注解,校验值类型>

    // 存储所有可能的值
    private Set<Integer> set = new HashSet<>();

    @Override // 初始化,你可以获取注解上的内容并进行处理
    public void initialize(ListValue constraintAnnotation) {
        // 获取后端写好的限制 // 这个value就是ListValue里的value,我们写的注解是@ListValue(value={0,1})
        int[] value = constraintAnnotation.vals();
        for (int i : value) {
            set.add(i);
        }
    }

    @Override // 覆写验证逻辑
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        // 看是否在限制的值里
        return  set.contains(value);
    }
}

实体类添加自定义注解

	/**
	 * 显示状态[0-不显示;1-显示]
	 */
	@ListValue(vals = {0, 1}, groups = {AddGroup.class})
	private Integer showStatus;

SPU 和 SKU

基础概念

三级分类
阿里云OSS、数据校验和表的分析_第23张图片
SPU 和 SKU

SPU:Standard Product Unit(标准化产品单元)是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
iphoneX 是 SPU、MI 8 是 SPU
iphoneX 64G 黑曜石 是 SKU
MI8 8+64G+黑色 是 SKU

SKU:Stock Keeping Unit(库存量单位)即库存进出计量的基本单元,可以是以件,盒,托盘等为单位。SKU 这是对于大型连锁超市DC(配送中心)物流管理的一个必要的方法。现在已经被引申为产品统一编号的简称,每种产品均对应有唯一的 SKU 号

SKU 是 SPU 更具体的信息

基本属性【规格参数】与销售属性

 属性是以三级分类组织起来的
 规格参数中有些是可以提供检索的
 规格参数也是基本属性,他们具有自己的分组
 属性的分组也是以三级分类组织起来的
 属性名确定的,但是值是每一个商品不同来决定的

每个分类下的商品共享规格参数,与销售属性。只是有些商品不一定要用这个分类下全部的
属性;

属性表: pms_attr

阿里云OSS、数据校验和表的分析_第24张图片

属性分组表: pms_attr_group

阿里云OSS、数据校验和表的分析_第25张图片

属性表和属性分组表关联起来的表: pms_attr_attrgroup_relation

阿里云OSS、数据校验和表的分析_第26张图片

商品属性值表: pms_product_attr_value,,保存了各个属性所对应的属性值和各种 id 什么的

阿里云OSS、数据校验和表的分析_第27张图片

spu 描述信息表: pms_spu_info,概括商品信息,具体指在上面的那张表,这张表比较笼统

阿里云OSS、数据校验和表的分析_第28张图片

sku 信息表: pms_sku_info,spu 包含 sku,一个商品到底有多少个 sku 存放在这里面

阿里云OSS、数据校验和表的分析_第29张图片

sku 销售属性值表:pms_sku_sale_attr_value

阿里云OSS、数据校验和表的分析_第30张图片

结合数据库的表好好理解下面这两张图,就能清晰很多

【属性分组-规格参数-销售属性-三级分类】关联关系

阿里云OSS、数据校验和表的分析_第31张图片

SPU-SKU-属性表

阿里云OSS、数据校验和表的分析_第32张图片

你可能感兴趣的:(谷粒商城,java,分布式)