# 谷粒商城
**Repository Path**: ElzatAlim/gulimall
## Basic Information
- **Project Name**: 谷粒商城
- **Description**: 谷粒商城
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2021-10-06
- **Last Updated**: 2024-06-13
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
**docker启动**
systemctl start docker
service docker start
**重启docker服务**
systemctl restart docker
sudo service docker restart
**关闭docke**r
systemctl stop docker
service docker stop
**查看是否启动成功**
docker ps -a
Docker MYSQL 启动命令(-v是挂在 前面的真是目录 后者是镜像目录)
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
-e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
**查看Docker正在运行中的镜像**
docker ps
**进入Docker镜像交互**
docker exec -it mysql(镜像名称或者是ID) /bin/bash
**配置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
**重启Dockers镜像**
docker restart mysql
**下载Redis镜像**
docker pull redis
**创建文件**
touch redis.conf
**启动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
**进入dockers中的redis-cli**
docker exec -it redis redis-cli
**重启redis**
docker restrat redis
**redis持久配置**
配置文件中添加一行 appendonly yes 再重启 (应该是开启AOF持久)
**docker镜像自动启动**
sudo docker update mysql --restart=always
**npm安装依赖提示Error: Can't find Python executable "python", you can set the PYTHON env variable**
**参考**
https://www.cnblogs.com/fxwoniu/p/13846586.html
https://blog.csdn.net/m0_49230198/article/details/117863312
其他错误可以先不管 试着npm run dev
sass安装失败的问题
切换成淘宝镜像 再下载
npm install node-sass@4.13.1 版本从package.jason中查看
**Vue生命周期**
**GateWay统一配置跨域配置**
```java
@Configuration
public class CorsConfig {
@Bean
public CorsWebFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
// 请求方法 *支持所有方法
config.addAllowedMethod("*");
//跨域处理 *允许所有的域
// config.addAllowedOrigin("http://127.0.0.1:3625");
config.addAllowedOrigin("*");
// 请求头 *支持所有
config.addAllowedHeader("*");
// 是否允许携带Cookie进行跨域
config.setAllowCredentials(true);
//匹配所有请求
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
```
**MybatisPlus逻辑删除配置**
1.配置(高版本可以省略)
```yml
mybatis-plus:
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
```
2.在字段上面加上TableLogic
**JSR303后端校验技术**
1.给校验Bean添加校验数据
javax.validation.constraints 包下的注解
2.在控制层添加@Valid注解 开启校验
3.配置返回校验后的错误信息
**统一处理异常(JSR303)**
1.控制层只保留@Valid注解
2.新建一个枚举类 用于错误信息
```java
public enum BizCodeEnume {
UNKNOW_EXCEPTION(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;
}
}
```
3.编写错误捕获类
```java
@Slf4j
//@ResponseBody
//@ControllerAdvice(basePackages = "com.aili.gulimall.product.controller")
@RestControllerAdvice(basePackages = "com.aili.gulimall.product.controller")
public class GuliMallExceptionControllerAdvice {
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public R handleVaildException(MethodArgumentNotValidException exception) {
BindingResult bindingResult = exception.getBindingResult();
if (bindingResult.hasErrors()) {
Map map = new HashMap<>();
bindingResult.getFieldErrors().forEach((item) -> {
map.put(item.getField(), item.getDefaultMessage());
});
log.error("数据校验出现问题", map);
return R.error(BizCodeEnume.VALID_EXCEPTION.getCode(), BizCodeEnume.VALID_EXCEPTION.getMsg()).put("data", map);
}
log.error("数据校验出现问题");
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(), BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
@ExceptionHandler(value = Throwable.class)
public R handleException(Throwable throwable) {
return R.error(BizCodeEnume.UNKNOW_EXCEPTION.getCode(), BizCodeEnume.UNKNOW_EXCEPTION.getMsg());
}
}
```
**JSR303 分组校验功能**
1.创建两个接口 做为分组

2.实体类校验注解中添加groups属性
```java
...........
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 = {UpdateGroup.class,AddGroup.class})
private String name;
.........
}
```
3.控制层@Valid注解替换成@Validated,并且参数指定分组接口
```
/**
* 保存
*/
@RequestMapping("/save")
public R save(@Validated({AddGroup.class}) @RequestBody BrandEntity brand ){
brandService.save(brand);
return R.ok();
}
```
注意:没有指定分组的校验规则只在没有指定分组的@Valid注解才会生效
**JSR303自定义检验**
1.编写一个自定义的校验注解(参考其他校验注解)
```java
package com.aili.common.valid;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* @author 艾力
* @date 2021/11/4 14:01
**/
@Documented
@Constraint(validatedBy = {ListValueConstraintValidator.class})
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {
String message() default "{com.aili.common.valid.ListValue.message}";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
int[] vals() default {};
}
```
提示配置文件 ValidationMessages.properties
```properties
com.aili.common.valid.ListValue.message = 必须提交指定的值
```
2.编写一个自定义的检验器
```java
package com.aili.common.valid;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;
/**
* @author 艾力
* @date 2021/11/4 14:15
**/
public class ListValueConstraintValidator implements ConstraintValidator {
private Set set = new HashSet<>();
//初始化
@Override
public void initialize(ListValue constraintAnnotation) {
int[] vals = constraintAnnotation.vals();
for (int val : vals) {
set.add(val);
}
ConstraintValidator.super.initialize(constraintAnnotation);
}
//校验
@Override
public boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {
return set.contains(integer);
}
}
```
3.关联自定义的校验器校验带自定义的检验注解的参数
自定义注解里面配置
```java
@Constraint(validatedBy = {ListValueConstraintValidator.class})
```
注:配置文件乱码可以将转换成Unicode再配置 在线转换网站:http://tool.chinaz.com/tools/unicode.aspx
**Vue父子组件**
被导入的组件给父组件发送事件
```javascript
methods: {
//每次点击的时候
handleNodeClick(data,node,component) {
console.log(data,node,component);
//向父组件发送事件
this.$emit('tree-node-click', data,node,component);
},
.........
}
```
再父组件绑定事件
```html
.....
```
**Vue组件之间发布和订阅事件(另一种)**
使用pubsub-js来实现
1.安装PubSub
首先在终端使用一下指令安装PubSub
```
npm install --save pubsub-js
```
安装成功就能在这里看到pubsub-js
2.引入组件
在要使用的组件中引入pubsub-js,这个不能全局引入只能哪个组件中使用就在哪个组件中引入
3.消息订阅
在被调用的组件中使用 PubSub.subscribe(name,function)订阅消息
被调用组件
4.发布
在调用组件使用 PubSub.publish(name,data);发布消息
**Json返回过滤**
实体类字段上添加注解JsonInclude 如果这个集合空的话就不会返回空集合
**MybatisPlus分页插件配置**
编写Config类
```java
@Configuration
@EnableTransactionManagement //开启事务
@MapperScan("com.aili.gulimall.product.dao")
public class MybatisConfig {
//引入分页插件
// 旧版
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
paginationInterceptor.setOverflow(true);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
paginationInterceptor.setLimit(-1);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
return paginationInterceptor;
}
}
```
**远程调用微服务接口**
1.被调用的微服务启动类添加@EnableDiscoveryClient服务注册与发现注解
2.调用的微服务启动类添加@EnableFeignClients 注解开启远程调用
3.编写接口
**统一配置时间返回格式**
**MybatisPlus queryWrapper大于等于**
原符号 < <= > >= <>
对应函数 lt() le() gt() ge() ne()
Mybatis-plus写法: queryWrapper.ge("create_time", localDateTime);
Mybatis写法: where create_time >= #{localDateTime}
**MybatisPlus 自动补充修改时间和创建时间**
编写类
```java
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
/**
* @author 艾力
* @date 2021/1/12 19:25
**/
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
//类中的属性名称
this.setFieldValByName("createTime", new Date(), metaObject);
this.setFieldValByName("updateTime", new Date(), metaObject);
}
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime", new Date(), metaObject);
}
}
```
实体类中添加注解:
**库存服务 API详解**
领取采购单 http://127.0.0.1:88/api/ware/purchase/received
body(采购单ID):
```json
[13]
```
完成采购 http://127.0.0.1:88/api/ware/purchase/done
body:
```json
{"id":12,"items":[
{"itemId":11,"status":3,"reason":""},
{"itemId":12,"status":3,"reason":""},
{"itemId":13,"status":3,"reason":""},
{"itemId":14,"status":3,"reason":""},
{"itemId":15,"status":3,"reason":""},
{"itemId":16,"status":3,"reason":""},
{"itemId":17,"status":3,"reason":""},
{"itemId":18,"status":3,"reason":""},
{"itemId":19,"status":3,"reason":""},
{"itemId":20,"status":3,"reason":""},
{"itemId":21,"status":3,"reason":""}
]}
```