【笔记/后端】谷粒商城基础篇
目录
- 一、环境配置
- 1 Docker
- 1.1 Docker是什么?
- 1.2 安装&启动
- 1.2.1 阿里云镜像加速
- 1.3 安装MySQL
- 1.4 安装Redis
- 2 开发环境
- 2.1 Maven
- 2.2 Git
- 2.3 Node
- 二、创建微服务项目
- 1 内容
- 2 问题记录
- 3 renren-generator
- 三、分布式组件
- 1 Nacos
- 1.1 注册中心
- 1.2 配置中心
- 1.2.1 如何使用Nacos作为配置中心统一管理配置?
- 1.2.2 细节
- 1.2.3 同时加载多个配置集
- 2 Feign
- 1.1 使用场景
- 1.2 调用其他服务的Application
- 3 Gateway
- 4 Aliyun OSS
- 四、前端开发基础
- 1 ES6
- 1.1 let和var
- 1.2 解构表达式
- 1.3 字符串扩展
- 1.4 函数优化
- 1.5 对象优化
- 1.6 对象扩展运算符
- 1.7 map和reduce
- 1.8 promise
- 1.9 模块化
- 1.9.1 导入导出
- 1.9.2 简化导出
- 1.9.3 不命名导出
- 2 Vue
- 2.1 基础属性
- 2.2 计算属性,监听器,过滤器
- 2.3 组件化
- 五、业务处理
- 1 逻辑删除
- 2 JSR303校验
- 2.1 开启校验
- 2.2 使用ControllerAdvice来集中处理异常
- 2.3 分组校验
- 2.4 自定义校验
- 3 POJO和SKU
- 3.1 电商领域名词
- 3.2 Object分类
- 4 其他
- 六、总结
- 1 分布式基础概念
- 2 基础开发
- 3 环境
- 4 开发规范
一、环境配置
1 Docker
1.1 Docker是什么?
基于镜像启动各种容器,每一种容器都是一个完整的运行环境,容器之间互相隔离。
1.2 安装&启动
docker官网:Developers -> Docs -> Get Docker -> Docker For Linux
systemctl start docker
docker images
查看安装的全部镜像
systemctl enable docker
开机自启
1.2.1 阿里云镜像加速
阿里云官网 -> 登录 -> 控制台 -> 容器镜像服务 -> 镜像工具 -> 镜像加速器 -> CentOS
1.3 安装MySQL
docker pull mysql:5.7
docker run -p 3306:3306 --name mysql \\ # 主机3306映射到容器3306 --name起名字
-v /mydata/mysql/log:/var/log/mysql \\ # 容器内文件挂载到虚拟机中
-v /mydata/mysql/data:/var/lib/mysql \\
-v /mydata/mysql/conf:/etc/mysql \\
-e MYSQL_ROOT_PASSWORD=root \\ # root用户密码
-d mysql:5.7 # 后台运行
下面供复制使用:
docker run -p 3306:3306 --name mysql -v /mydata/mysql/log:/var/log/mysql -v /mydata/mysql/data:/var/lib/mysql -v /mydata/mysql/conf:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
docker ps
查看现在运行的全部镜像
docker exec -it mysql /bin/bash
进入到容器内部
whereis mysql
在容器内部执行来查看mysql位置
修改/mydata/mysql/conf下mysql配置
[client]
default-character-set=utf8[mysql]
default-character-set=utf8[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
docker restart mysql
1.4 安装Redis
docker pull redis
不写版本下载最新版本
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
在/mydata/redis/conf/redis.conf中添加
appendonly yes
开启持久化
虚拟机重启后自动启动镜像
docker update redis --restart=always
2 开发环境
2.1 Maven
问题1 依赖子模块的模块打包失败
解决 给上层(父)模块install后成功
2.2 Git
配置git
# 配置用户名
git config --global user.name "username" # 名字
# 配置邮箱
git config --global user.email "username@email.com" # 注册账号时使用的邮箱
在码云中进入设置 -> SSH公钥 -> 将本机公钥粘贴进去
实现后续免密提交
2.3 Node
npm配置镜像仓库:
npm config set register <http://registry.npm.taobao.org/>
install后使用npm run dev
运行
问题: npm安装失败。
解决 1. node使用10.X版本,python版本改3.7(非必要) 2. 网络问题 3. npm install遇到循环c++提示等待即可
二、创建微服务项目
1 内容
商品服务、仓储服务、订单服务、优惠券服务、用户服务
共同:
- web openfeign
- 每一个服务,包名
com.atguigu.gulimall.xxx(product/order/ware/coupon/member)
- 模块名:
gulimall-coupon
2 问题记录
问题1 报错 POM文件爆红,以及
<repository>
中的网址禁止访问
解决 Maven版本问题,3.6.3解决
问题2 报错如下
'parent.relativePath' of POM io.renren:renren-fast:3.0.0 (/Users/dujianzhang/Documents/IdeaProjects/gulimall/renren-fast/pom.xml) points at pers.djz.gulimall:gulimall instead of org.springframework.boot:spring-boot-starter-parent, please verify your project structure```
解决 子模块没有指向上级目录父模块,在
<parent>
标签中添加<relativePath/>
使Maven打包时每次都直接从仓库获取
问题3 报错如下
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:423)at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61)
解决 尝试与MySQL建立SSL连接失败,在URL后面加上
?useSSL=false
3 renren-generator
使用方法
- 修改application.yml中的dataSource相关信息
- 修改generator.properties中生成项目目录结构信息
- 运行Application,在浏览器中前往生成器页面
- 勾选要进行逆向工程的数据库表,点击生成代码开始下载
问题1 idea不显示yaml小树叶
解决 备份编辑器设置,恢复编译器默认设置,重新导入备份设置不恢复file相关设置
问题2 Longblob无法解析
解决 替换成byte类型
问题3 renren generator实体类备注乱码
解决 使用navicat执行sql不要导入sql文件,复制sql文本执行查询
三、分布式组件
1 Nacos
1.1 注册中心
启动方式: ./startup.sh -m standalone
在application.yml中配置nacos注册中心的信息:
spring: cloud: nacos: discovery: server-addr: localhost:8848#一定要有应用名 application: name: gulimall-coupon
问题1 nacos在macOS上找不到
/Library/Internet
或Permission denied
解决 mac自带了一个jdk,在环境变量中声明自己安装的jdk的JAVA_HOME
export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home" export PATH="$PATH:$JAVA_HOME/bin" export CLASSPATH="$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:."
问题2 macOS上7000端口占用问题
解决 7000端口用于AirPlay,使用7001
1.2 配置中心
1.2.1 如何使用Nacos作为配置中心统一管理配置?
- 引入依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
- 创建一个bootstrap.properties
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=localhost:8848
- 在配置中心添加一个默认的数据集(Data Id) gulimall-coupon.properties,默认规则:
应用名.properties
- 给应用名.properties添加任何配置
- 动态获取配置
@RefreshScope
动态获取并刷新配置,注解在Application类上
@Value("${配置项的名}")
获取到配置
如果配置中心和当前应用的配置文件中都配置了相同的项,优先使用配置中心的配置
1.2.2 细节
- 命名空间:配置隔离
默认:public(保留空间),默认新增的所有配置都在public空间- 开发、测试、生产,利用命名空间来做环境隔离
注意:在bootstrap.properties配置上,需要使用哪个命名空间下的配置
spring.cloud.nacos.config.namespace=aa34a377-e984-4082-8959-e41e35dd9d51
- 每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置
- 开发、测试、生产,利用命名空间来做环境隔离
- 配置集:所有的配置的集合
- 配置集ID:类似文件名
Data ID:类似文件名 - 配置分组
默认所有的配置集都属于DEFAULT_GROUP
spring.cloud.nacos.config.group=1111
每个微服务创建自己的命名空间,使用配置分组区分环境,dev, test, prod
1.2.3 同时加载多个配置集
spring.cloud.nacos.config.ext-config[0].data-id=datasource.yml
spring.cloud.nacos.config.ext-config[0].group=dev
spring.cloud.nacos.config.ext-config[0].refresh=true
yaml写法
spring:cloud:nacos:ext-config:- data-id: oss.ymlgroup: DEFAULT_GROUPrefresh: true- data-id: ...group: ...refresh: ...
- 微服务任何配置信息,任何配置文件都可以放在配置中心中
- 只需要在bootstrap.properties中说明加载配置中心中哪些配置文件即可
@Value
@ConfigurationProperties
以前SpringBoot任何方法从配置文件中获取值都能使用,配置中心有的优先使用配置中心的
问题1 配置了bootstrap.properties中的nacos config服务器地址,依然报错endpoint is blank
解决 没有读取配置文件,springboot 2.4以上要在pom中添加依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> <version>3.1.0</version> </dependency>
或者是没有在resources下创建bootstrap配置文件指明配置中心地址
2 Feign
1.1 使用场景
- member想要调用coupon中的信息
- member向nacos注册中心查询目标服务地址
- 查询
1.2 调用其他服务的Application
/** 想要远程调用别的服务* 1 引入openfeign* 2 编写一个接口,告诉SpringCloud这个接口需要调用远程服务* 2.1 声明接口的每一个方法都是调用哪个远程服务的哪个请求* 3 开启远程调用功能* */
@EnableFeignClients(basePackages = "pers.djz.gulimall.member.feign")
@EnableDiscoveryClient
@SpringBootApplicationpublic
class GulimallMemberApplication { public static void main(String[] args) { SpringApplication.run(GulimallMemberApplication.class, args); }
}
feign包下的接口:
// name是nacos注册中心中要访问的微服务名称,url可不写
@FeignClient(name = "gulimall-coupon", url = "http://localhost:7001/")
public interface CouponFeignService { // 方法名不必相同,但访问url要对应上@PostMapping("/coupon/skufullreduction/saveInfo")R saveSkuReduction(@RequestBody SkuReductionTo skuReductionTo);
}
@RequestBody
将这个对象转为json- 找到gulimall-coupon服务,给
/coupon/spubounds/save
发送请求。将上一步转的json放在请求体位置,发送请求 - 对方服务收到请求。请求体里有JSON数据,
@RequestBody SpuBoundsEntity spuBounds
将请求体的JSON转为SpuBoundsEntity
只要JSON数据模型是兼容的,双方服务无需使用同一个VO
问题 运行后feign报错ribbon和loadbalance问题
解决 pom中如下引用<dependency><groupId>com.octopus.gulimall</groupId><artifactId>common</artifactId><version>0.0.1-SNAPSHOT</version><exclusions><exclusion><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId></exclusion></exclusions> </dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
3 Gateway
spring:cloud:gateway:routes:- id: qq_route# uri是符合断言的请求会跳转到的地址uri: https://www.qq.com/predicates:- Query=url, qq- id: baidu_routeuri: https://www.weibo.com/predicates:- Query=url, weibo
问题1 启动网关application报错:
Description:Parameter 0 of method loadBalancerWebClientBuilderBeanPostProcessor in org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration required a bean of type 'org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction' that could not be found.Action:Consider defining a bean of type 'org.springframework.cloud.client.loadbalancer.reactive.DeferringLoadBalancerExchangeFilterFunction' in your configuration.Process finished with exit code 1
解决 添加依赖:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> <version>3.1.1</version> </dependency>
问题2 通过
lb://renren-fast
进行网关控制报503错误,提示No servers available for service: renren-fast
解决 SpringCloud Alibaba和SpringBoot版本问题,改为2.1.8.RELEASE
和Greenwich.SR3
4 Aliyun OSS
- 在Aliyun官网使用对象存储服务,创建一个新的bucket存储文件
- 使用公共读
- 右上角AccessKey创建子账户供Open API调用
- Java导入starter后,自动注入OssClient类对象(新版本使用OSS类)
- starter导入后在application.yaml中配置endpoint、access-key和secret-key
- 实际开发中客户端向服务器请求签名后直接带着签名上传到OSS服务器(使用方法参考文档)
spring:cloud:alicloud:access-key: xxxsecret-key: xxxoss:endpoint: oss-cn-beijing.aliyuncs.combucket: xxx
@RestController
@RequestMapping("/oss")
public class OssController {@Autowiredprivate 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("/policy")public R policy() {// 填写Host地址,格式为https://bucketname.endpoint。String host = "https://" + bucket + "." + endpoint;// 设置上传回调URL,即回调服务器地址,用于处理应用服务器与OSS之间的通信。OSS会在文件上传完成后,把文件上传信息通过此回调URL发送给应用服务器。
// String callbackUrl = "https://192.168.0.0:8888";// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下。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);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());}return R.ok().put("data", respMap);}
}
四、前端开发基础
1 ES6
ECMAScript是浏览器脚本语言的规范
1.1 let和var
- let有严格的作用域,var会越域
- let不能重复声明同名变量,var可以
- let不存在变量提升,var会 变量提升:声明会提升到作用域顶端
function fun() {a = 1;var a;
}// 实际执行 var a; -> a = 1;
1.2 解构表达式
const [a, b, c] = [1, 2, 3];// a = 1, b = 2, c = 3
let person = {name: "jack", age: 18};
const {name, age} = person;// name = "jack", age = "age"
1.3 字符串扩展
let str = "hello.vue";
str.startsWith("hello");
// truestr.endsWith("vue");
// truestr.includes("e"); // true
// 字符串模版(多行字符串)
let ss = `<div> <span>hello</span></div>`
// 插入表达式(用``)
let info = `我是${abc}, 今年${age}了, 我想说: ${fun()}`;
1.4 函数优化
b = b || 1; // 判断b是否为空,如空给默认值1
function fun(a, b=1) { ...}
// 不定参数
function fun(...values) {console.log(values.length)
}
// 箭头函数
var print = obj => console.log(obj);
// print是一个函数
var sum = (a, b) => return a + b;
var sum2 = (a, b) => {let c = a + b; return a + c;
}
// 箭头函数+解构
var fun = ({name}) => console.log(name);
fun(person);
1.5 对象优化
const person = {name: "jack", age: 18};
Object.keys(person);
Object.values(person);
Object.entries(person);
// 合并
const target = {a: 1};
const source1 = {b: 2};
const source2 = {c: 3};
Object.assign(target, source1, source2);
// 声明对象简写
const age = 23;
const name = "张三";
const person = {age, name};
// 变量和属性同名可以简写
// 对象的函数属性简写
let person = {name: "jack",eat: function (food) {console.log(this.name + "在吃" + food);},// 箭头函数this不能使用,使用对象.属性来获取eat2: food => console.log(this.name + "在吃" + food);
}
person.eat("banana");
1.6 对象扩展运算符
// 拷贝对象
let p1 = {name: "jack", age: 18};
let someone = { ...p1 }
// 合并对象
let age1 = {age: 15};
let name1 = {name: "Amy"};
let p2 = {name: "zhangsan"};
p2 = {...age1, ...name1}; // p2.name = "Amy"
1.7 map和reduce
let arr = ['1', '20', '-5'];
arr = arr.map((item) => {return item * 2;
});
arr = arr.map(item => item * 2);
/**
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
1、previousValue(上一次调用回调返回的值,或者是提供的初始值(initialvalue))
2、currentvalue (数组中当前被处理的元素)
3、index(当前元素在数组中的索引)
4、array(调用 reduce 的数组)
*/
let result = arr.reduce((a, b) => {console.log(a, b);return a + b;
}, 100); // 100 1 ...
1.8 promise
Promise可以封装异步操作
function get(url, data) {return new Promise((resolve, reject) => {$.ajax({url: url,data: data,success: function (data) {resolve(data);},error: function (err) {reject(err);}});});
}
// 多级分类查询
get("mock/user.json").then((data) => {console.log("用户查询成功: ", data);return get(`mock/user_course_${data.id}.json`);
}).then((data) => {console.log("课程查询成功: ", data);return get(`mock/course_score_${data.id}.json`);
}).then((data) => {console.log("课程成绩查询成功", data);
}).catch((err) => {console.log("出现异常", err);
});
1.9 模块化
1.9.1 导入导出
util.js
var name = "jack";var age = 21;
function add(a, b) {return a + b;
}
export {name, age, add}
main.js
import {name, age, add} from "./util.js"
1.9.2 简化导出
export const util = ...
1.9.3 不命名导出
xx.js
export default {sum(a, b) {return a + b;}
}
// 随意命名
import abc from "./xx.js"
2 Vue
问题1 eslint语法检查过于严格
解决 在.eslintignore文件中添加要忽略的内容,如*.vue
<body><div id="app"><input type="text" v-model="num"/><button v-on:click="num++">
【笔记/后端】谷粒商城基础篇相关推荐
- 谷粒商城基础篇(保姆级总结)
谷粒商城基础篇 文章目录 谷粒商城基础篇 项目相关基础 知识介绍 微服务架构图和项目描述 **微服务划分图** Vrgrant systemctl命令 配置环境 Docker自启动命令 下载mysql ...
- 【谷粒商城基础篇】仓储服务:仓库维护
谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== 项目简介与分布式概念(第一.二章) 基础环境搭建(第三章) ===整合SpringCloud=== 整合 ...
- 【谷粒商城基础篇】基础环境搭建
谷粒商城笔记合集 分布式基础篇 分布式高级篇 高可用集群篇 ===简介&环境搭建=== 项目简介与分布式概念(第一.二章) 基础环境搭建(第三章) ===整合SpringCloud=== 整合 ...
- 谷粒商城-基础篇(详细流程梳理+代码)
文章目录 前言 一.项目环境搭建 1.1.安装virtualbox以及vagrant 1.2.Docker安装MySQL与Redis 1.3.前后端开发工具统一配置 1.4.Git工具安装与配置 1. ...
- 《谷粒商城基础篇》分布式基础环境搭建
前沿:思考一个问题,为啥要做笔记? 为了知识更有条理,为了自己学过之后下次遇到立刻可以想起来,即使想不起,也可以通过自己的笔记快速定位~ 毕竟互联网的知识迭代速度非常之快 笔记更是知识输入的一条路径, ...
- 谷粒商城基础篇——Day01
01.分布式基础&项目环境搭建 一.项目简介 1. 项目背景 1.1 电商模式 市面上有 5 种常见的电商模式 B2B.B2C.C2B.C2C.O2O 1) B2B 模式 B2B(Busine ...
- 谷粒商城基础篇爬坑笔记--No Feign Client for loadBalancing defined以及加载测试失败
在远程调用章节写完代码运行member模块开启失败,报错信息为: No Feign Client for loadBalancing defined. Did you forget to includ ...
- 谷粒商城基础篇爬坑笔记--项目导入intellij IDEA后pom.xml无法识别为maven文件和程序包import com.atguigu.common.XXX不存在两个问题解决方法
1项目导入intellij IDEA后pom.xml无法识别为maven文件. 情况如下图: intellij IDEA新手的常见问题(好吧我也是新手),解决方法: 完成后: 如果没有同步可以在控制台 ...
- 谷粒商城-基础篇-环境搭建(P1-P44)
文章目录 一.项目简介 二.分布式基础概念 1.微服务 2.集群&分布式&节点 3.远程调用 4.负载均衡 5.服务注册/发现&注册中心 6.配置中心 7.服务熔断&服 ...
最新文章
- mixamo网站FBX模型带骨骼绑定动作库
- ajax和map返回数据类型,ajax请求后台返回map类型并如何展示
- Spark机器学习(9):FPGrowth算法
- linux 自动化交互套件 expect 介绍 shell非交互
- Glusterfs入门
- shell远程执行命令
- 微课|《Python编程基础与案例集锦(中学版)》第3章(1)
- UVa 401 - Palindromes
- Ubunbu新建的用户使用SecureCrt无法Table补全、无法高亮
- 2020 数据中心机房建设方案
- 局域网组件拨号连接服务器上网,架设pppoe服务器拨号上网 防止ARP欺骗
- HTML5+CSS3练习小实例:发光果冻泡泡动画
- CDN概念和基本原理
- 男人买鞋有点难——中国十大皮鞋
- Android Studio如何建立VR视频
- OpenStack-Q版实战部署技术指导手册详情-让你轻松掌握-黑夜青儿
- 2021最新Navicat15下载安装包
- 牛客小白月赛6 I.公交线路
- 安装双系统后卸载统信
- Ubuntu_XMMS播放器使用
热门文章
- 一次弄懂Event Loop(彻底解决此类面试问题)
- VB.Net 解决winForm界面卡死
- acm-(好题、神题)2020-2021 Winter Petrozavodsk Camp, Day 5 B.Lockout vs tourist
- 一些关于dagger2的理解
- idea 启动报错: Failed to create JVM.JVM.Path XXXXXXX\jbr\ 我的解决办法
- VMware配置虚拟机网络
- 键盘事件是什么?键盘事件包括哪几种?
- 【数值计算】期末综合大作业
- 打击标题党,痛斥灌水文
- 从服装关键点、信息检索、个性化推荐到智能试衣,电商AI技术如何进化?