Mall谷粒商城(基础篇的开发)

项目简介

Mall商城项目致力于打造一个完整的大型分布式架构的电商平台,采用先阶段流行的前后端分离模式编写。

Mall商城是一套电商项目,包括前台的商城系统以及后台管理系统,基于SpringCloud、SpringCloud Alibaba、Mybatis-plus实现。

前台商城系统包括:用户登陆、注册、商品搜索、商品详情、购物车、订单、秒杀活动等模块。

后台管理系统包括:系统管理、商品系统、优惠营销、库存系统、订单系统、用户系统、内容管理等七大模块。

项目架构

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

接口文档

https://easydoc.net/s/78237135/ZUqEdvA4/d3EezLdO

项目演示

前台商城系统项目演示

后台管理系统项目演示

电商项目的基础

SPU和SKU

SPUStanderd Product Unit(标准化产品单元)是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。

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

例如:iPhone XS MAX是SPU,IPhone XS MAX 128G 黑色是SKU.

Mall谷粒商城(基础篇的开发)

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

每个分类下的商品共享规格参数,与销售属性。

只是有些商品不一定要用这个分类下全部的属性。

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

SPU来决定规格参数的值,SKU来决定销售属性的值。

环境搭建

本地环境:

root@uin-virtual-machine:/# uname -a
Linux uin-virtual-machine 5.11.0-38-generic #42~20.04.1-Ubuntu SMP Tue Sep 28 16:01:15 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux
root@uin-virtual-machine:/#

增加一个小tip:配置静态IP,配了都说好。

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

Gateway 网关地址 10.211.55.1、Iface网卡 eth0、netmask子网掩码 255.255.255.0、当前IP 10.211.55.15

为Ubuntu 20.04 设置静态IP简明教程(和把大象装冰箱一样简单) – 云+社区 – 腾讯云 (tencent.com)

docker

dokcer在mac本地安装是很简单的事情,比如用homebrew。

ubuntu安装docker。

Mall谷粒商城(基础篇的开发)

ubuntu 18.04 arm64版 安装docker 踩坑_踩坑的小方的博客-CSDN博客_arm ubuntu安装docker

在此感谢博主!!。

Mall谷粒商城(基础篇的开发)

ubuntu中设置docker以及容器开机自启 – 代码先锋网 (codeleading.com)

这一步很重,可以省去很多不必要的麻烦。

docker安装Redis(并开启持久化)

docker pull redis
mkdir -p /mydata/redis/conf
touch /mydata/redis/conf/redis.conf
docker run -p 6379:6379 --name redis -v /mydata/redis/data:/data -v /mydata/redis/conf/redis.conf:/etc/redis/redis.conf -d redis redis-server /etc/redis/redis.conf

使用docker安装redis并持久化_马克图布No1的博客-CSDN博客_docker redis 持久化

Mall谷粒商城(基础篇的开发)

docker安装Mysql

由于我是Arm的系统架构,Docker Hub上没有适用于arm64架构的mysql镜像。

docker pull mysql/mysql-server:latest

Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)

创建并启动MySQL服务容器

docker run --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql/mysql-server

这时使用宿主机连接没有授权访问,需要进入mysql修改mysql访问权限。

docker exec -it mysql bash
mysql -u root -p 123456
#授权
CREATE USER 'root'@'%' IDENTIFIED BY 'root';
GRANT ALL ON *.* TO 'root'@'%';
#刷新权限

mysql> flush privileges;
修改root用户密码

mysql> ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
#刷新权限

mysql> flush privileges;

Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)

Ubuntu docker安装Mysql

Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)

项目搭建

版本说明

版本说明 · alibaba/spring-cloud-alibaba Wiki (github.com)

SpringClound Alibaba 组件的版本。

Mall谷粒商城(基础篇的开发)

SpringCloud的版本。

Mall谷粒商城(基础篇的开发)

使用快速开发平台renren-fast

搭建后台系统

git clone https://gitee.com/renrenio/renren-fast.git

搭建后台的前端页面

git clone https://gitee.com/renrenio/renren-fast-vue.git

各模块的端口规定

商品服务 product 8081

仓储服务 ware 8082

订单服务 order 8083

优惠券服务 coupon 8084

会员服务 member 8085

搭建分布式的基本环境

架构图

Mall谷粒商城(基础篇的开发)

技术选型

Mall谷粒商城(基础篇的开发)

其他的组件详情:微服务相关组件 – BeaBrick0 – 博客园 (cnblogs.com)

版本选择

https://github.com/alibaba/spring-cloud-alibaba

https://github.com/alibaba/spring-cloud-alibaba/blob/2021.x/README-zh.md

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

使用Spring cloud Alibaba Nacos做配置中心和注册中心

Mall谷粒商城(基础篇的开发)

Nacos 注册中心(服务发现/注册)

Nacos 配置中心(动态配置管理)

https://github.com/alibaba/Nacos

Mall谷粒商城(基础篇的开发)

之前我们使用Spring Cloud Eurek 来做,但是后来停止维护了。

Mall谷粒商城(基础篇的开发)

使用Nacos来做服务的注册中心

demo链接:https://github.com/alibaba/spring-cloud-alibaba/blob/2021.x/spring-cloud-alibaba-examples/nacos-example/nacos-discovery-example/readme-zh.md

Mall谷粒商城(基础篇的开发)
  1. 首先,修改 pom.xml 文件,引入 Nacos Discovery Starter。

     com.alibaba.cloud
     spring-cloud-starter-alibaba-nacos-discovery

Mall谷粒商城(基础篇的开发)
  1. 在应用的 /src/main/resources/application.properties 配置文件中配置 Nacos Server 地址

由于我们还没有Nacos服务,所以我们要去下载。

  1. 首先需要获取 Nacos Server,支持直接下载和源码构建两种方式。
  2. 直接下载:Nacos Server 下载页
  3. 源码构建:进入 Nacos Github 项目页面,将代码 git clone 到本地自行编译打包,参考此文档推荐使用源码构建方式以获取最新版本
  4. 启动 Server,进入解压后文件夹或编译打包好的文件夹,找到如下相对文件夹 nacos/bin,并对照操作系统实际情况之下如下命令。
  5. Linux/Unix/Mac 操作系统,执行命令 sh startup.sh -m standalone
  6. Windows 操作系统,执行命令 cmd startup.cmd

Mall谷粒商城(基础篇的开发)

找到这个版本。

Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)

跳转链接:localhost:8848/nacos

登陆账户和密码:nacos nacos

Mall谷粒商城(基础篇的开发)
 spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

Mall谷粒商城(基础篇的开发)
  1. 使用 @EnableDiscoveryClient 注解开启服务注册与发现功能
 @SpringBootApplication
 @EnableDiscoveryClient
 public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }

    @RestController
    class EchoController {
        @GetMapping(value = "/echo/{string}")
        public String echo(@PathVariable String string) {
                return string;
        }
    }
 }

Mall谷粒商城(基础篇的开发)

应用启动

  1. 增加配置,在 nacos-discovery-provider-example 项目的 /src/main/resources/application.properties 中添加基本配置信息
 spring.application.name=service-provider
 server.port=18082
  1. 启动应用,支持 IDE 直接启动和编译打包后启动。
  2. IDE直接启动:找到 nacos-discovery-provider-example 项目的主类 ProviderApplication,执行 main 方法启动应用。
  3. 打包编译后启动:在 nacos-discovery-provider-example 项目中执行 mvn clean package 将工程编译打包,然后执行 java -jar nacos-discovery-provider-example.jar启动应用。

Mall谷粒商城(基础篇的开发)
Mall谷粒商城(基础篇的开发)

使用Nacos做配置中心

https://github.com/alibaba/spring-cloud-alibaba/blob/2021.x/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md

Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)

操作流程

  1. 首先,修改 pom.xml 文件,引入 Nacos Config Starter。

     com.alibaba.cloud
     spring-cloud-starter-alibaba-nacos-config

  1. 在应用的 /src/main/resources/bootstrap.properties 配置文件中配置 Nacos Config 元数据
 spring.application.name=nacos-config-example
 spring.cloud.nacos.config.server-addr=127.0.0.1:8848
  1. 测试

Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

假设现在有这样一个需求:我们需要修改 name ,现在项目已经上线了,怎么做

显然改项目中的配置,是不理智的。我们只需要将我们的配置交给配置中心,我们直接在配置中心改配置文件

Mall谷粒商城(基础篇的开发)

我们可以在Nacos的配置中心进行配置。

Mall谷粒商城(基础篇的开发)

如果配置中心和当前项的配置文件都配置了相同的项,优先使用配置中心的配置。

如果配置不成功,可以加一下识别bootStrap.properties的依赖。


     org.springframework.cloud
     spring-cloud-starter-bootstrap

Mall谷粒商城(基础篇的开发)

测试成功。

更多的细节

命名空间

Mall谷粒商城(基础篇的开发)

用于进行租户粒度的 配置隔离。不同的命名空间下,可以存相同的 Group 或 Data ID的配置。Namespace 的常用场景之一是不同的环境的配置的区分隔离,例如开发测试环境和生产环境(如配置、服务)隔离等。

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

利用命名空间做环境隔离。

基于微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己的命名空间。

Mall谷粒商城(基础篇的开发)
配置集

一组相关或者不想关的配置项的集合称为配置集。本系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别的配置项。

配置集ID

类似于文件名。

Mall谷粒商城(基础篇的开发)
配置分组

默认所有的配置集都属于:DEFAULT_GROUP

比如叫双11、618、双12.

#更改默认组
spring.cloud.nacos.config.group=1111

在本项目中采用每个微服务创建自己的命名空间,使用配置分组区分环境,比如dev、test、prod环境

怎么去同时加载多个配置文件?

Mall谷粒商城(基础篇的开发)
spring.application.name=coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=f00c6f6d-ccad-4762-8599-f09604d2915f
spring.cloud.nacos.config.group=prod

#---------------相当于加载了一个datasource.yml配置文件----tart-----
spring.cloud.nacos.config.extension-configs[0].data-id=datasource.yml
#那个组 dev
spring.cloud.nacos.config.extension-configs[0].group=dev
#动态刷新
spring.cloud.nacos.config.extension-configs[0].refresh=true
#---------------相当于加载了一个配置文件----end-----

#---------------相当于加载了一个mybatis.yml配置文件----tart-----
spring.cloud.nacos.config.extension-configs[1].data-id=mybatis.yml
#那个组 dev
spring.cloud.nacos.config.extension-configs[1].group=dev
#动态刷新
spring.cloud.nacos.config.extension-configs[1].refresh=true
#---------------相当于加载了一个配置文件----end-----

#---------------相当于加载了一个other.yml配置文件----tart-----
spring.cloud.nacos.config.extension-configs[2].data-id=other.yml
#那个组 dev
spring.cloud.nacos.config.extension-configs[2].group=dev
#动态刷新
spring.cloud.nacos.config.extension-configs[2].refresh=true
#---------------相当于加载了一个配置文件----end-----

当然是注释掉了,application.yml 中的配置文件。

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)
总结

我们以后给微服务配置任何信息,都可以在配置中心去配置,只需要在 bootstrap.properties 中声明加载那些配置文件。

配置中心有的优先使用配置中心的。

关于nacos的更多的信息

Mall谷粒商城(基础篇的开发)

https://nacos.io/zh-cn/docs/what-is-nacos.html

使用Spring Cloud OpenFeign 作远程调用(声明式的HTTP客户端)

https://spring.io/projects/spring-cloud-openfeign

Mall谷粒商城(基础篇的开发)

简介

也叫粪坑。

Feign 是一个声明式的 HTTP 客户端,它的目的就是让远程调用更加简单。Feign 提供了 HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好 HTTP 请求的参数、格式、地址等信息。

Feign 整合了 Rilbbon(负载均衡)和Hystrix(服务烯断),可以让我们不再需要显式地使用这两个组件。

SpringCloudFeign 在 Nettix Feign 的基础上扩展了对 SpringMVC 注解的支持,在其实现下,我们只需创建一个接口并用注解的方式来配置它,即可完成对服务提供方的接口綁定。简化了SpringCloudRibbon 自行封装服务调用客户端的开发量。

demo

@SpringBootApplication
@EnableFeignClients
public class WebApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebApplication.class, args);
    }

    @FeignClient("name")
    static interface NameService {
        @RequestMapping("/")
        public String getName();
    }
}

案例

需求:member(会员)服务先要远程调用coupon(优惠卷)服务。

流程分析

  1. 想要远程调用其他的服务
  2. 引入openfeign的依赖,让他拥有远程调用的能力
  3. 编写一个接口,告诉SpringCloud这个接口需要远程调用远程服务
    1. 声明的接口的每一个方法都是调用那个远程服务的那一个请求Mall谷粒商城(基础篇的开发)
  4. 开启远程调用服务的功能 @EnableFeignClients(basePackages = "com.uin.member.feign")

Mall谷粒商城(基础篇的开发)

启动测试

会有报错,通过看控制台:No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?

Mall谷粒商城(基础篇的开发)

导入这个负载均衡的依赖。重新测试。

Mall谷粒商城(基础篇的开发)

使用Spring Cloud Alibaba Sentinel 服务容错(限流、熔断、降级)

之前使用的Spring Cloud Netflix Hystrix来做服务降级、服务熔断

https://github.com/alibaba/Sentinel

Mall谷粒商城(基础篇的开发)

使用Spring Cloud Gateway 做ApI网关(webFlux编程)

详细配置介绍:https://spring.io/projects/spring-cloud-gateway

Mall谷粒商城(基础篇的开发)

操作流程

  1. 完善对应的版本信息
  2. 要使用网关,需要开起API网关的服务与发现,这样请求可以通过我们的网关,网关可以发现其他的服务,并将请求转发到其他的服务。

https://spring.io/guides/gs/gateway/

https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

使用Spring Cloud Sleuth 来做调用链的监控

https://spring.io/projects/spring-cloud-sleuth

Mall谷粒商城(基础篇的开发)

使用Spring Cloud Alibaba Seata来做分布式事务的解决方案

https://github.com/seata/seata

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

使用Spring Cloud Alibaba-OSS来做文件上传

上传方案选择:服务端签名后直传

Mall谷粒商城(基础篇的开发)

上传之前先找我们的服务器,要一个防伪签名,拿着防伪签名,去访问oss。

Java (aliyun.com)

服务端签名后直传 (aliyun.com)

本文主要介绍如何基于Post Policy的使用规则在服务端通过各种语言代码完成签名,然后通过表单直传数据到OSS。由于服务端签名直传无需将AccessKey暴露在前端页面,相比JavaScript客户端签名直传具有更高的安全性。

Mall谷粒商城(基础篇的开发)

Java (aliyun.com)

应用服务器核心代码解析

应用服务器源码包含了签名直传服务以及上传回调服务的完整示例代码。

注意 以下仅提供核心代码片段,如需了解这两个功能的完整实现,请参见应用服务器源码(Java版本)

  • 签名直传服务 签名直传服务响应客户端发送给应用服务器的GET消息,代码片段如下:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
       String accessId = "yourAccessKeyId";
       String accessKey = "yourAccessKeySecret";
       // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
       String endpoint = "oss-cn-hangzhou.aliyuncs.com";
       // 填写Bucket名称,例如examplebucket。
       String bucket = "examplebucket";
       // 填写Host名称,格式为https://bucketname.endpoint。
       String host = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com";
       // 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
       String callbackUrl = "https://192.168.0.0:8888";
       // 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。
       String dir = "exampledir/";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessId, accessKey);
        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);

            Map respMap = new LinkedHashMap();
            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));

            JSONObject jasonCallback = new JSONObject();
            jasonCallback.put("callbackUrl", callbackUrl);
            jasonCallback.put("callbackBody",
                    "filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}");
            jasonCallback.put("callbackBodyType", "application/x-www-form-urlencoded");
            String base64CallbackBody = BinaryUtil.toBase64String(jasonCallback.toString().getBytes());
            respMap.put("callback", base64CallbackBody);

            JSONObject ja1 = JSONObject.fromObject(respMap);
            // System.out.println(ja1.toString());
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "GET, POST");
            response(request, response, ja1.toString());

        } catch (Exception e) {
            // Assert.fail(e.getMessage());
            System.out.println(e.getMessage());
        } finally {
            ossClient.shutdown();
        }
    }
  • 上传回调服务 上传回调服务响应OSS发送给应用服务器的POST消息,代码片段如下:
protected boolean VerifyOSSCallbackRequest(HttpServletRequest request, String ossCallbackBody)
            throws NumberFormatException, IOException {
        boolean ret = false;
        String autorizationInput = new String(request.getHeader("Authorization"));
        String pubKeyInput = request.getHeader("x-oss-pub-key-url");
        byte[] authorization = BinaryUtil.fromBase64String(autorizationInput);
        byte[] pubKey = BinaryUtil.fromBase64String(pubKeyInput);
        String pubKeyAddr = new String(pubKey);
        if (!pubKeyAddr.startsWith("https://gosspublic.alicdn.com/")
                && !pubKeyAddr.startsWith("https://gosspublic.alicdn.com/")) {
            System.out.println("pub key addr must be oss addrss");
            return false;
        }
        String retString = executeGet(pubKeyAddr);
        retString = retString.replace("-----BEGIN PUBLIC KEY-----", "");
        retString = retString.replace("-----END PUBLIC KEY-----", "");
        String queryString = request.getQueryString();
        String uri = request.getRequestURI();
        String decodeUri = java.net.URLDecoder.decode(uri, "UTF-8");
        String authStr = decodeUri;
        if (queryString != null && !queryString.equals("")) {
            authStr += "?" + queryString;
        }
        authStr += "\n" + ossCallbackBody;
        ret = doCheck(authStr, authorization, retString);
        return ret;
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String ossCallbackBody = GetPostBody(request.getInputStream(),
                Integer.parseInt(request.getHeader("content-length")));
        boolean ret = VerifyOSSCallbackRequest(request, ossCallbackBody);
        System.out.println("verify result : " + ret);
        // System.out.println("OSS Callback Body:" + ossCallbackBody);
        if (ret) {
            response(request, response, "{\"Status\":\"OK\"}", HttpServletResponse.SC_OK);
        } else {
            response(request, response, "{\"Status\":\"verify not ok\"}", HttpServletResponse.SC_BAD_REQUEST);
        }
    }

关于上传回调的API接口说明,请参见Callback

Mall谷粒商城(基础篇的开发)

使用前端自定义校验和后端JSR303做双重校验

前端自定义校验实现可参考前端代码,这里只介绍后端的校验的实现。

后端校验只需要在需要校验的字段加上相关的校验规则,并告诉SpringMVC需要校验的参数。

Mall谷粒商城(基础篇的开发)

同时可以自定义错误提示。

Mall谷粒商城(基础篇的开发)Mall谷粒商城(基础篇的开发)

使用SpringMVC的@ControllerAdvice实现统一异常的处理

package com.uin.product.exception;

import com.uin.utils.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.HashMap;
import java.util.Map;

/**
 * @author wanglufei
 * @description: 集中处理(感知)错误
 * @date 2022/4/22/2:43 PM
 */
@Slf4j
//@ControllerAdvice(basePackages = "com.uin.product.controller")
//@ResponseBody
//效果一样
@RestControllerAdvice(basePackages = "com.uin.product.controller")
public class UinControllerAdvice {
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public R handlerFormNumException(MethodArgumentNotValidException e) {
        log.error("数据校验出现问题:{},异常类型:{}", e.getMessage(), e.getClass());
        BindingResult result = e.getBindingResult();
        Map map = new HashMap<>();
        result.getFieldErrors().forEach((item) -> {
            //错误消息提示
            String message = item.getDefaultMessage();
            //那个字段出现了问题
            String field = item.getField();
            //将这些错误的信息用map装起来
            map.put(field, message);
        });
        return R.error().put("data", map);
    }

}

搭建服务过程中遇到的问题

此处之描述大问题,小问题一百度就出来了。

当使用gateway网关将后端的请求路由到后端的renren-fast服务是出现图片不显示,服务出现503或者404

同时高版本的还需要添加:


     org.springframework.cloud
     spring-cloud-loadbalancer

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

总结

历经11天,终于写完了商场的基础分布式项目的搭建和维护。中途也奔溃过、难受过、放弃过。每次特别难受的时候,跑到厕所偷偷的哭会儿。每天早8晚9,待在实验室硬肝这个项目,逃过很多课,所以还在肝的兄弟们,别放弃!相信自己!好吧?

中间还要出去找暑假实习,去面试。终于在4.27号,找到了一个自己还算是满意的公司,给的薪资也可以。先将就干着吧,毕竟也是第一次实习。

Mall谷粒商城(基础篇的开发)

还记得在4.26的面试,面试官还问到我,服务之间的远程调用。我吊打面试官!!!面完就给offer,不过实习给的工资有点低,公司还可以,做银行的业务。

沿途拍到的。

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

Mall谷粒商城(基础篇的开发)

收获很多,特别感谢雷丰阳老师。收获很多。不行了,眼泪快掉下来了。😭

在此总结分布式基础篇做了哪些内容。

  • 分布式的基础篇概念

微服务、注册中心、配置中心、远程调用、Feign、网关

  • 基础开发

SpringBoot 2.6.3、SpringCloud、Mybatis-Plus、Vue组件化、阿里云对象存储

  • 环境

Ubuntu 20.0.4、Docker、Mysql、Redis、逆向工程&人人开源

  • 开发规范

  • 数据校验JSR303、全局异常处理、全局统一返回、全局跨域处理

  • 枚举状态、业务状态码、VO与TO、PO的划分、逻辑删除
  • Lombok:@Data、@Slf4j

Original: https://www.cnblogs.com/bearbrick0/p/16191978.html
Author: BearBrick0
Title: Mall谷粒商城(基础篇的开发)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/572456/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • <1>Linux简介及基本操作

    一、什么是Unix/linux 下C 开发(uc 开发)和前边学的C 编程有什么区别 ? C 语言学的是 1 )C 的语法 2 )标准C 的库函数: printf malloc f…

    Java 2023年6月15日
    079
  • Spring-cloud-alibaba-nacos(注册中心)快速入门

    1、引入依赖 com.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery 2.1.0.RELEASE 2、配置文件…

    Java 2023年6月5日
    073
  • 史上最简单的 SpringCloud 教程 | 终章

    https://blog.csdn.net/forezp/article/details/70148833转载请标明出处:http://blog.csdn.net/forezp/a…

    Java 2023年5月30日
    057
  • Maven(一)——下载与安装

    Maven(一)——下载与安装 下载 安装 解压即安装 配置 依赖Java,需要配置JAVA_HOME 设置MAVEN自身运行环境,配置MAVEN_HOME 新建系统变量MAVEN…

    Java 2023年6月16日
    063
  • 解决:public abstract java.lang.Class org.mybatis.spring.annotation.MapperScan.factoryBean()

    https://blog.csdn.net/weixin_50060275/article/details/115690015 Original: https://www.cnbl…

    Java 2023年5月29日
    079
  • 微信登录

    微信配置文件 微信开放平台 appid wx.open.app-id=你的appid 微信开放平台 appsecret wx.open.app-secret=你的secret 微信…

    Java 2023年6月15日
    086
  • 句子

    脑中的空白为谁而留 持续了太久今天依旧为何始终绕不过时间轴 凋零的勇气散落在哪里 生涯一半的荒芜难道还不够 已经没有力气再驱动一丝的笑意 熟悉的对白无言的结局 重启 更多原创技术内…

    Java 2023年6月5日
    071
  • 浅析js前端如何将word文档转为html:docx是怎样存储图片的、Java使用POI如何实现、前端使用Mammoth.js如何实现

    先聊聊需求背景:公司运营需求,说在富文本编辑器中发布包含图片的 Word 文档时,图片和文本内容不能一起复制,每次她们都得分开处理,对于包含较多图片的 Word 时,她们处理起来很…

    Java 2023年5月29日
    075
  • Spring(十六):声明式事务管理

    一、什么是事务 事务就是一系列的业务逻辑的操作,必须要全部执行成功,否则每个操作所执行的内容都要撤销。 二、事务的四大特性 1.原子性(atomicity):事务虽然有一系列的操作…

    Java 2023年6月15日
    085
  • String类为什么被设计成不可变类

    1.享元模式: 1.共享元素模式,也就是说:一个系统中如果有多处用到了相同的一个元素,那么我们应该只存储一份此元素,而让所有地方都引用这一个元素。 2.Java中String就是根…

    Java 2023年6月5日
    097
  • Linux 定时任务调度

    定时任务调度 任务调度:是指系统在某个时间执行的特定的命令或程序 任务调度分类 系统工作:有些重要的工作必须周而复始的执行 个别用户工作:个别用户可能希望执行某些程序 cronta…

    Java 2023年6月5日
    078
  • BeanFactory与FactoryBean有什么区别?

    相同点:都是用来创建bean对象的 不同点:使用beanFactory创建对象的时候,必须要遵循严格的生命周期流程,太复杂了,如果想要简单的自定义某个对象的创建,同时创建好的对象想…

    Java 2023年6月8日
    049
  • 大刘终于当上架构师了

    今天这篇文章是架构师大刘的故事,架构师大刘——3 个 180 的男人(身高、体重、房子…………的贷款) 如果你想将来成为一名架构师,…

    Java 2023年6月7日
    073
  • Spring自动装配

    前提 1、byName 2、byType 3、使用注解进行自动装配 (1)spring配置文件设置约束 (2)开启属性注解支持 (3)@Autowired (4)@Qualifie…

    Java 2023年6月5日
    074
  • 设计模式 《head first 设计模式》

    策略设计模式:strategy pattern 定义了算法族,分别封装起来,让他们之间可以互相替换。 此模式让算法的变化独立于算法的客户类 客户类,以 接口定义的 实例变量作其域,…

    Java 2023年6月9日
    0180
  • spring IOC的理解,原理与底层实现?

    从总体到局部 控制反转:理论思想,原来的对象是由使用者来进行控制,有了spring之后,可以把整个对象交给spring来帮我们进行管理DI(依赖注入):把对应的属性的值注入到具体的…

    Java 2023年6月8日
    071
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球