Kevin's blog Kevin's blog
首页
  • Java基础
  • Java高级
  • MySQL
  • JDBC
  • Java 8新特性
  • 原生Servlet
  • 延迟队列
  • 分布式事务
  • ActiveMQ
  • Elasticsearch
  • Stream API
  • Redis 实战(黑马程序员)
  • Redis 课程(尚硅谷)
  • Redis数据类型和常用命令
  • 版本控制
  • Spring Framework
  • Spring MVC Framework
  • MyBatis Framework
  • MyBatis Plus Framework
  • Spring Boot Framework
  • 韩顺平 Spring Boot Framework
  • 在线教育
  • 谷粒商城 - 分布式基础 高级 集群
  • 谷粒商城 - 详细开发文档
  • docker基础
  • docker-compose容器编排
  • docker swarm集群管理
  • Vue2基础
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Kevin

Java系统笔记
首页
  • Java基础
  • Java高级
  • MySQL
  • JDBC
  • Java 8新特性
  • 原生Servlet
  • 延迟队列
  • 分布式事务
  • ActiveMQ
  • Elasticsearch
  • Stream API
  • Redis 实战(黑马程序员)
  • Redis 课程(尚硅谷)
  • Redis数据类型和常用命令
  • 版本控制
  • Spring Framework
  • Spring MVC Framework
  • MyBatis Framework
  • MyBatis Plus Framework
  • Spring Boot Framework
  • 韩顺平 Spring Boot Framework
  • 在线教育
  • 谷粒商城 - 分布式基础 高级 集群
  • 谷粒商城 - 详细开发文档
  • docker基础
  • docker-compose容器编排
  • docker swarm集群管理
  • Vue2基础
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《JavaScript高级程序设计》
    • 《ES6 教程》
    • 《Vue》
    • 《React》
    • 《TypeScript 从零实现 axios》
    • 《Git》
    • TypeScript
    • JS设计模式总结
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 项目 在线教育

  • 项目 谷粒商城

    • 谷粒商城—分布式基础第一部分
    • 谷粒商城—分布式基础第二部分
    • 谷粒商城—分布式基础第三部分
    • 谷粒商城—分布式基础第四部分
    • 谷粒商城—分布式基础第五部分
      • 19. 分组校验功能(完成多场景的复杂校验)
        • 1、给校验注解,标注上groups,指定什么情况下才需要进行校验
        • 2、业务方法参数上使用@Validated注解
        • 3、默认情况下,在分组校验情况下,没有指定指定分组的校验注解,将不会生效,它只会在不分组的情况下生效。
      • 20. 自定义校验功能
        • 1、编写一个自定义的校验注解
        • 2、编写一个自定义的校验器
        • 3、关联自定义的校验器和自定义的校验注解
        • 4、使用实例
      • 21. 商品SPU和SKU管理
      • 22. 点击子组件,父组件触发事件
      • 23. 规格参数新增与VO
      • 24. 查询分组关联属性和删除关联
      • 25. 查询分组未关联的属性
      • 26. 添加属性和分组的关联关系
      • 27. 发布商品
      • 28. 商品管理
      • 29. 仓库管理
      • 30. 获取spu规格
      • 31. 修改商品规格
      • 小结:
        • 1. 在open fen中会将调用的数据转换为JSON,接收方接收后,将JSON转换为对象,此时调用方和被调用方的处理JSON的对象不一定都是同一个类,只要它们的字段类型吻合即可。
        • 2. 事务究竟要如何加上?
      • 其他
        • 1. 文档参考地址
        • 2. 开机启动docker
        • 3. 查看命令的安装位置
        • 4. vscode中生成代码片段
        • 5. vscode快捷键
        • 6. 关闭eslint的语法检查
        • 7. 安装mybatisx插件
        • 8. mysql的批量删除
        • 9. String.join
        • 10. 在Service中微服务比较多的时候,可以配置将一些微服务放置到compound中,组成一个小组
        • 11. mysql的dateTime和timestamp的区别?
        • 12. SpringBoot中的事务
        • 13. IDEA RESTFUll clinet
      • FAQ
        • 1. TypeError: _vm.previewHandle is not a function
    • 谷粒商城—分布式高级
    • 谷粒商城—高可用集群
  • 项目 谷粒商城详细开发文档

  • Project
  • 项目 谷粒商城
zhihuanwang
2024-04-08
目录

谷粒商城—分布式基础第五部分

# 19. 分组校验功能(完成多场景的复杂校验)

# 1、给校验注解,标注上groups,指定什么情况下才需要进行校验

如:指定在更新和添加的时候,都需要进行校验

	@NotEmpty
	@NotBlank(message = "品牌名必须非空",groups = {UpdateGroup.class,AddGroup.class})
	private String name;
1
2
3

在这种情况下,没有指定分组的校验注解,默认是不起作用的。想要起作用就必须要加groups。

# 2、业务方法参数上使用@Validated注解

@Validated的value方法:

Specify one or more validation groups to apply to the validation step kicked off by this annotation. 指定一个或多个验证组以应用于此注释启动的验证步骤。

JSR-303 defines validation groups as custom annotations which an application declares for the sole purpose of using them as type-safe group arguments, as implemented in SpringValidatorAdapter.

JSR-303 将验证组定义为自定义注释,应用程序声明的唯一目的是将它们用作类型安全组参数,如 SpringValidatorAdapter 中实现的那样。

Other SmartValidator implementations may support class arguments in other ways as well.

其他SmartValidator 实现也可以以其他方式支持类参数。

# 3、默认情况下,在分组校验情况下,没有指定指定分组的校验注解,将不会生效,它只会在不分组的情况下生效。

# 20. 自定义校验功能

# 1、编写一个自定义的校验注解


@Documented
@Constraint(validatedBy = { ListValueConstraintValidator.class})
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
public @interface ListValue {
    String message() default "{com.bigdata.common.valid.ListValue.message}";

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

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

    int[] value() default {};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 2、编写一个自定义的校验器


public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {
    private Set<Integer> set=new HashSet<>();
    @Override
    public void initialize(ListValue constraintAnnotation) {
        int[] value = constraintAnnotation.value();
        for (int i : value) {
            set.add(i);
        }

    }

    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {


        return  set.contains(value);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# 3、关联自定义的校验器和自定义的校验注解

@Constraint(validatedBy = { ListValueConstraintValidator.class})
1

# 4、使用实例

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

# 21. 商品SPU和SKU管理

重新执行“sys_menus.sql”

# 22. 点击子组件,父组件触发事件

现在想要实现点击菜单的左边,能够实现在右边展示数据

image-20200430215649355

父子组件传递数据:

1)子组件给父组件传递数据,事件机制;

在category中绑定node-click事件,

  <el-tree :data="menus" :props="defaultProps" node-key="catId" ref="menuTree" @node-click="nodeClick"	></el-tree>
1

2)子组件给父组件发送一个事件,携带上数据;

    nodeClick(data,Node,component){
       console.log("子组件",data,Node,component);
       this.$emit("tree-node-click",data,Node,component);
    }, 
1
2
3
4

this.$emit(事件名,"携带的数据");

3)父组件中的获取发送的事件

<category @tree-node-click="treeNodeClick"></category>
1
    //获取发送的事件数据
    treeNodeClick(data,Node,component){
     console.log("attgroup感知到的category的节点被点击",data,Node,component);
     console.log("刚才被点击的菜单ID",data.catId);
    },
1
2
3
4
5

# 23. 规格参数新增与VO

规格参数新增时,请求的URL:Request URL:

http://localhost:88/api/product/attr/base/list/0?t=1588731762158&page=1&limit=10&key=

当有新增字段时,我们往往会在entity实体类中新建一个字段,并标注数据库中不存在该字段,然而这种方式并不规范

1588732021702

比较规范的做法是,新建一个vo文件夹,将每种不同的对象,按照它的功能进行了划分。在java中,涉及到了这几种类型

1588732152646

Request URL: http://localhost:88/api/product/attr/save,现在的情况是,它在保存的时候,只是保存了attr,并没有保存attrgroup,为了解决这个问题,我们新建了一个vo/AttrVo,在原AttrEntity基础上增加了attrGroupId字段,使得保存新增数据的时候,也保存了它们之间的关系。

通过" BeanUtils.copyProperties(attr,attrEntity);"能够实现在两个Bean之间拷贝数据,但是两个Bean的字段要相同

   @Override
    public void saveAttr(AttrVo attr) {
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attr,attrEntity);
        this.save(attrEntity);
    }
1
2
3
4
5
6

问题:现在有两个查询,一个是查询部分,另外一个是查询全部,但是又必须这样来做吗?还是有必要的,但是可以在后台进行设计,两种查询是根据catId是否为零进行区分的。

# 24. 查询分组关联属性和删除关联

获取属性分组的关联的所有属性

API:https://easydoc.xyz/doc/75716633/ZUqEdvA4/LnjzZHPj (opens new window)

发送请求:/product/attrgroup/{attrgroupId}/attr/relation

获取当前属性分组所关联的属性

1588766303205

如何查找:既然给出了attr_group_id,那么到中间表中查询出来所关联的attr_id,然后得到最终的所有属性即可。

可能出现null值的问题

# 25. 查询分组未关联的属性

/product/attrgroup/{attrgroupId}/noattr/relation

API:https://easydoc.xyz/doc/75716633/ZUqEdvA4/d3EezLdO (opens new window)

获取属性分组里面还没有关联的本分类里面的其他基本属性,方便添加新的关联

Request URL: http://localhost:88/api/product/attrgroup/1/noattr/relation?t=1588780783441&page=1&limit=10&key=

1588780868214

属性分组,对应于“pms_attr_group”表,每个分组下,需要查看到关联了哪些属性信息,销售属性不需要和分组进行关联,但是规格参数要和属性分组进行关联。

规格参数:对应于pms_attr表,attr_type=1,需要显示分组信息

销售属性:对应于pms_attr`表,attr_type=0,不需要显示分组信息

分组ID为9的分组:Request URL: http://localhost:88/api/product/attrgroup/9/noattr/relation?t=1588822258669&page=1&limit=10&key=

对应的数据库字段

attr_group_id attr_group_name sort descript icon catelog_id


        9  主体                    1  型号 平台                   wu               454
       10  显卡                    1  显存容量                    wu               454
       11  输入设备                  1  鼠标 键盘                   wu               454
       12  主板                    1  显卡类型 芯片组                wu               454
       13  规格                    1  尺寸                      wu               454

查询attrgroupId=9的属性分组:

AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(attrgroupId);
1

获取到分类信息:

 Long catelogId = attrGroupEntity.getCatelogId();
1

目标:获取属性分组没有关联的其他属性

也就是获取attrgroupId=9的属性分组中,关联的分类catelog_id =454 (台式机),其他基本属性

在该属性分组中,现在已经关联的属性:

1588822997675

本分类下,存在哪些基本属性?

没有关联的其他属性

已经关联的属性,这些属性是如何关联上的?

答:在创建规格参数的时候,已经设置了需要关联哪些属性分组。

想要知道还没有关联哪些,先查看关联了哪些,如何排除掉这些就是未关联的

在中间表中显示了属性和属性分组之间的关联关系,在属性表中显示了所有的属性,

先查询中间表,得到所有已经关联的属性的id,然后再次查询属性表,排除掉已经建立关联的属性ID,将剩下的属性ID和属性建立起关联关系

# 26. 添加属性和分组的关联关系

请求类型:Request URL: http://localhost:88/api/product/attrgroup/attr/relation

请求方式:POST

请求数据:[{"attrId":10,"attrGroupId":9}]

API:https://easydoc.xyz/doc/75716633/ZUqEdvA4/VhgnaedC (opens new window)

响应数据:

{
	"msg": "success",
	"code": 0
}
1
2
3
4

本质就是在中间表pms_attr_attrgroup_relation中,添加一条记录的过程

# 27. 发布商品

获取所有会员等级:/member/memberlevel/list

API:https://easydoc.xyz/doc/75716633/ZUqEdvA4/jCFganpf (opens new window)

在“gulimall-gateway”中修改“”文件,添加对于member的路由

        - id: gulimall-member
          uri: lb://gulimall-member
          predicates:
            - Path=/api/member/**
          filters:
            - RewritePath=/api/(?<segment>/?.*),/$\{segment}
1
2
3
4
5
6

在“gulimall-member”中,创建“bootstrap.properties”文件,内容如下:

spring.cloud.nacos.config.name=gulimall-member
spring.cloud.nacos.config.server-addr=192.168.137.14:8848
spring.cloud.nacos.config.namespace=795521fa-77ef-411e-a8d8-0889fdfe6964
spring.cloud.nacos.config.extension-configs[0].data-id=gulimall-member.yml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
1
2
3
4
5
6

获取分类关联的品牌:/product/categorybrandrelation/brands/list

API:https://easydoc.xyz/doc/75716633/ZUqEdvA4/HgVjlzWV (opens new window)

遇到PubSub问题

  1. 首先安装pubsub-js
`npm install --save pubsub-js`
1
  1. 订阅方组件
`import PubSub from 'pubsub-js'`
1

该this.PubSub为PubSub。

获取分类下所有分组&关联属性

请求类型:/product/attrgroup/{catelogId}/withattr

请求方式:GET

请求URL:http://localhost:88/api/product/attrgroup/225/withattr?t=1588864569478

mysql默认的隔离级别为读已提交,为了能够在调试过程中,获取到数据库中的数据信息,可以调整隔离级别为读未提交:

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
1

但是它对于当前的事务窗口生效,如果想要设置全局的,需要加上global字段。

# 28. 商品管理

当新建时:

t: 1588983621569
status: 0
key: 
brandId: 0
catelogId: 0
page: 1
limit: 10
1
2
3
4
5
6
7

当上架时:

t: 1588983754030
status: 1
key: 
brandId: 0
catelogId: 0
page: 1
limit: 10
1
2
3
4
5
6
7

当下架时:

t: 1588983789089
status: 2
key: 
brandId: 0
catelogId: 0
page: 1
limit: 10
1
2
3
4
5
6
7

在SPU中,写出的日期数据都不符合规则: image-20200509083248660

想要符合规则,可以设置写出数据的规则:

spring.jackson

  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
1
2

SKU检索:

Request URL: http://localhost:88/api/product/skuinfo/list?t=1588989437944&page=1&limit=10&key=&catelogId=0&brandId=0&min=0&max=0

请求体:

t: 1588989437944
page: 1
limit: 10
key: 
catelogId: 0
brandId: 0
min: 0
max: 0
1
2
3
4
5
6
7
8

API: https://easydoc.xyz/doc/75716633/ZUqEdvA4/ucirLq1D

# 29. 仓库管理

库存信息表:wms_ware_info

【1】仓库列表功能:

【2】查询商品库存:

【3】查询采购需求:

【4】 合并采购需求:

合并整单选中parcharseID:Request URL: http://localhost:88/api/ware/purchase/merge

请求数据:

{purchaseId: 1, items: [1, 2]}
items: [1, 2]
1
2

合并整单未选择parcharseID :Request URL: http://localhost:88/api/ware/purchase/merge

image-20200509170916557

items: [1, 2]
1

涉及到两张表:wms_purchase_detail,wms_purchase

现在采购单中填写数据,然后关联用户,关联用户后,

总的含义,就是根据采购单中的信息,更新采购需求,在采购单中填写采购人员,采购单号,采购的时候,更新采购细节表中的采购人员ID和采购状态。

image-20200509191108806

领取采购单

http://localhost:88/api/ware/purchase/received

(1)某个人领取了采购单后,先看采购单是否处于未分配状态,只有采购单是新建或以领取状态时,才更新采购单的状态

(2)

【1】仓库列表功能: https://easydoc.xyz/doc/75716633/ZUqEdvA4/mZgdqOWe

【2】查询商品库存: https://easydoc.xyz/doc/75716633/ZUqEdvA4/hwXrEXBZ

【3】查询采购需求: https://easydoc.xyz/doc/75716633/ZUqEdvA4/Ss4zsV7R

【4】 合并采购需求:https://easydoc.xyz/doc/75716633/ZUqEdvA4/cUlv9QvK

【5】查询未领取的采购单: https://easydoc.xyz/doc/75716633/ZUqEdvA4/hI12DNrH

【6】领取采购单: https://easydoc.xyz/doc/75716633/ZUqEdvA4/vXMBBgw1

完成采购,在完成采购过程中,需要涉及到设置SKU的name信息到仓库中,这是通过远程调用“gulimall-product”来实现根据sku_id查询得到sku_name的,如果这个过程发生了异常,事务不想要回滚,目前采用的方式是通过捕获异常的方式,防止事务回滚,是否还有其他的方式呢?这个问题留待以后解决。

 @Override
    public void addStock(Long skuId, Long wareId, Integer skuNum) {

        List<WareSkuEntity> wareSkuEntities = wareSkuDao.selectList(new QueryWrapper<WareSkuEntity>().eq("sku_id", skuId).eq("ware_id", wareId));

        if(wareSkuEntities == null || wareSkuEntities.size() ==0 ){
             //新增
            WareSkuEntity wareSkuEntity = new WareSkuEntity();
            wareSkuEntity.setSkuId(skuId);
            wareSkuEntity.setWareId(wareId);
            wareSkuEntity.setStock(skuNum);
            wareSkuEntity.setStockLocked(0);

            //远程查询SKU的name,若失败无需回滚
            try {
                R info = productFeignService.info(skuId);
                if(info.getCode() == 0){
                    Map<String,Object> data=(Map<String,Object>)info.get("skuInfo");
                    wareSkuEntity.setSkuName((String) data.get("skuName"));
                }
            } catch (Exception e) {

            }

            wareSkuDao.insert(wareSkuEntity);
        }else{
            //插入
            wareSkuDao.addStock(skuId,wareId,skuNum);
        }

    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

# 30. 获取spu规格

在SPU管理页面,获取商品规格的时候,出现400异常,浏览器显示跳转不了

问题现象:

image-20200510182051355

出现问题的代码:

    attrUpdateShow(row) {
      console.log(row);
      this.$router.push({
        path: "/product-attrupdate",
        query: { spuId: row.id, catalogId: row.catalogId }
      });
    },
1
2
3
4
5
6
7

暂时不知道如何解决问题。只能留待以后解决。

经过测试发现,问题和上面的代码没有关系,问题出现在“attrupdate.vue”上,该vue页面无法通过浏览器访问,当输入访问URL( http://localhost:8001/#/product-attrupdate )的时候,就会出现404,而其他的请求则不会出现这种情况,不知为何。

通过POSTMAN进行请求的时候,能够请求到数据。

经过分析发现,是因为在数据库中没有该页面的导航所导致的,为了修正这个问题,可以在“sys-menu”表中添加一行,内容位:

image-20200510231012714

这样当再次访问的时候,在“平台属性”下,会出现“规格维护”菜单,

image-20200510231041708

当再次点击“规格”的时候,显示出菜单

image-20200510231200130

不过这种菜单并不符合我们的需要,我们需要让它以弹出框的形式出现。

# 31. 修改商品规格

API: https://easydoc.xyz/doc/75716633/ZUqEdvA4/GhnJ0L85

URL:/product/attr/update/{spuId}

# 小结:

# 1. 在open fen中会将调用的数据转换为JSON,接收方接收后,将JSON转换为对象,此时调用方和被调用方的处理JSON的对象不一定都是同一个类,只要它们的字段类型吻合即可。

调用方:

@FeignClient(value = "gulimall-coupon")
public interface CouponFenService {

    @PostMapping("/coupon/spubounds/save")
    R saveSpuBounds(@RequestBody SpuBoundTo spuBoundTo);

    @PostMapping("/coupon/skufullreduction/saveInfo")
    R saveSkuReduction(@RequestBody SkuReductionTo skuReductionTo);
}
1
2
3
4
5
6
7
8
9

被调用方:

    @PostMapping("/save")
    public R save(@RequestBody SpuBoundsEntity spuBounds){
		spuBoundsService.save(spuBounds);

        return R.ok();
    }

    @PostMapping("/saveInfo")
    public R saveInfo(@RequestBody SkuReductionTo skuReductionTo){
        skuFullReductionService.saveSkuReduction(skuReductionTo);
        return R.ok();
    }
1
2
3
4
5
6
7
8
9
10
11
12

调用方JSON化时的对象SpuBoundTo:

@Data
public class SpuBoundTo {
    private Long spuId;
    private BigDecimal buyBounds;
    private BigDecimal growBounds;
}
1
2
3
4
5
6

被调用方JSON数据对象化时的对象SpuBoundsEntity:

/**
 * 商品spu积分设置
 * 
 * @author cosmoswong
 * @email [email protected]
 * @date 2020-04-23 23:38:48
 */
@Data
@TableName("sms_spu_bounds")
public class SpuBoundsEntity implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * id
	 */
	@TableId
	private Long id;
	/**
	 * 
	 */
	private Long spuId;
	/**
	 * 成长积分
	 */
	private BigDecimal growBounds;
	/**
	 * 购物积分
	 */
	private BigDecimal buyBounds;
	/**
	 * 优惠生效情况[1111(四个状态位,从右到左);0 - 无优惠,成长积分是否赠送;1 - 无优惠,购物积分是否赠送;2 - 有优惠,成长积分是否赠送;3 - 有优惠,购物积分是否赠送【状态位0:不赠送,1:赠送】]
	 */
	private Integer work;

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# 2. 事务究竟要如何加上?

存在Batch操作的时候,才需要加上事务,单个操作无需添加事务控制。

SpringBoot中的是事务

批量操作的时候,才需要事务

一个事务标注的方法上,方法内存在这些操作:

(1)批量更新一个表中字段

(2)更新多张表中的操作

实际上不论是哪种类型,方法中所有对于数据库的写操作,都会被整体当做一个事务,在这个事务过程中,如果某个操作出现了异常,则整体都不会被提交。这就是对于SpringBoot中的@Transactional的理解。

@EnableTransactionManagement和@Transactional的区别?

https://blog.csdn.net/abysscarry/article/details/80189232 https://blog.csdn.net/Driver_tu/article/details/99679145

https://www.cnblogs.com/leaveast/p/11765503.html

# 其他

# 1. 文档参考地址

http://www.jayh.club/#/02.PassJava%E6%9E%B6%E6%9E%84%E7%AF%87/01.%E5%88%9B%E5%BB%BA%E9%A1%B9%E7%9B%AE%E5%92%8C%E6%B7%BB%E5%8A%A0%E6%A8%A1%E5%9D%97 (opens new window)

https://blog.csdn.net/ok_wolf/article/details/105400748

https://www.cnblogs.com/javalbb/p/12690862.html (opens new window)

https://blog.csdn.net/ok_wolf/article/details/105456170

https://easydoc.xyz/doc/75716633/ZUqEdvA4/jCFganpf

# 2. 开机启动docker

image-20200422221237751

在Docker中设置开机启动容器

image-20200423005200485

#查看防火墙状态
[root@hadoop-104 module]# systemctl status firewalld
  firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2020-04-22 21:26:23 EDT; 10min ago
     Docs: man:firewalld(1)
 Main PID: 5947 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─5947 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

Apr 22 21:26:20 hadoop-104 systemd[1]: Starting firewalld - dynamic firewall daemon...
Apr 22 21:26:23 hadoop-104 systemd[1]: Started firewalld - dynamic firewall daemon.
#查看防火墙是否是开机启动
[root@hadoop-104 module]# systemctl list-unit-files|grep firewalld
firewalld.service                             enabled 
#关闭开机启动防火墙
[root@hadoop-104 module]# systemctl disable firewalld             
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
#停止防火墙
[root@hadoop-104 module]# systemctl stop firewalld         
#再次查看防火墙
[root@hadoop-104 module]# systemctl list-unit-files|grep firewalld
firewalld.service                             disabled
[root@hadoop-104 module]# 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 3. 查看命令的安装位置

whereis mysql:查看mysql的安装位置

# 4. vscode中生成代码片段

image-20200425165814903

新建一个全局的代码片段,名字为vue,然后回车:

image-20200425165929332

将下面的代码片段粘贴到“vue.code-snippets”

{
    // Place your 全局 snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and 
    // description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope 
    // is left empty or omitted, the snippet gets applied to all languages. The prefix is what is 
    // used to trigger the snippet and the body will be expanded and inserted. Possible variables are: 
    // $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. 
    // Placeholders with the same ids are connected.
    // Example:
    // "Print to console": {
    // 	"scope": "javascript,typescript",
    // 	"prefix": "log",
    // 	"body": [
    // 		"console.log('$1');",
    // 		"$2"
    // 	],
    // 	"description": "Log output to console"
    // }
    "生成vue模板": {
        "prefix": "vue",
        "body": [
            "<!-- $1 -->",
            "<template>",
            "<div class='$2'>$5</div>",
            "</template>",
            "",
            "<script>",
            "//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)",
            "//例如:import 《组件名称》 from '《组件路径》';",
            "",
            "export default {",
            "//import引入的组件需要注入到对象中才能使用",
            "components: {},",
            "data() {",
            "//这里存放数据",
            "return {",
            "",
            "};",
            "},",
            "//监听属性 类似于data概念",
            "computed: {},",
            "//监控data中的数据变化",
            "watch: {},",
            "//方法集合",
            "methods: {",
            "",
            "},",
            "//生命周期 - 创建完成(可以访问当前this实例)",
            "created() {",
            "",
            "},",
            "//生命周期 - 挂载完成(可以访问DOM元素)",
            "mounted() {",
            "",
            "},",
            "beforeCreate() {}, //生命周期 - 创建之前",
            "beforeMount() {}, //生命周期 - 挂载之前",
            "beforeUpdate() {}, //生命周期 - 更新之前",
            "updated() {}, //生命周期 - 更新之后",
            "beforeDestroy() {}, //生命周期 - 销毁之前",
            "destroyed() {}, //生命周期 - 销毁完成",
            "activated() {}, //如果页面有keep-alive缓存功能,这个函数会触发",
            "}",
            "</script>",
            "<style lang='scss' scoped>",
            "//@import url($3); 引入公共css类",
            "$4",
            "</style>"
        ],
        "description": "生成VUE模板"
    },
    "http-get请求": {
        "prefix": "httpget",
        "body": [
            "this.\\$http({",
            "url: this.\\$http.adornUrl(''),",
            "method: 'get',",
            "params: this.\\$http.adornParams({})",
            "}).then(({ data }) => {",
            "})"
        ],
        "description": "httpGET请求"
    },
    "http-post请求": {
        "prefix": "httppost",
        "body": [
            "this.\\$http({",
            "url: this.\\$http.adornUrl(''),",
            "method: 'post',",
            "data: this.\\$http.adornData(data, false)",
            "}).then(({ data }) => { });"
        ],
        "description": "httpPOST请求"
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

更多详细说明见: https://blog.csdn.net/z772330927/article/details/105730430/

# 5. vscode快捷键

ctrl+shift+f 全局搜索

alt+shift+f 格式化代码

# 6. 关闭eslint的语法检查

image-20200428171043110


1

# 7. 安装mybatisx插件

在Marketplace中搜索“mybatisx”,安装后重启IDEA,使用时会自动在@Mapper标注的接口上,产生小图标,然后alt+enter,generate statement,就会自动的在xml文件中生成SQL。

1588730028929

# 8. mysql的批量删除

DELETE FROM  `pms_attr_attrgroup_relation` WHERE (attr_id= ? AND attr_group_id ) OR (attr_id= ? AND attr_group_id )
1

# 9. String.join

java.lang.String @NotNull 
public static String join(@NotNull CharSequence delimiter,
                          @NotNull Iterable<? extends CharSequence> elements)
1
2
3

Returns a new String composed of copies of the CharSequence elements joined together with a copy of the specified delimiter.

返回一个由CharSequence元素的副本和指定分隔符的副本组成的新字符串。

For example,

 List<String> strings = new LinkedList<>();
 strings.add("Java");strings.add("is");
 strings.add("cool");
 String message = String.join(" ", strings);
 //message returned is: "Java is cool"

 Set<String> strings = new LinkedHashSet<>();
 strings.add("Java"); strings.add("is");
 strings.add("very"); strings.add("cool");
 String message = String.join("-", strings);
 //message returned is: "Java-is-very-cool"

Note that if an individual element is null, then "null" is added.

注意,如果单个元素为null,则添加“null”。

Params: delimiter – a sequence of characters that is used to separate each of the elements in the resulting String 用于分隔结果字符串中的每个元素的字符序列

elements – an Iterable that will have its elements joined together. 将其元素连接在一起的可迭代的。

Returns: a new String that is composed from the elements argument 由elements参数组成的新字符串

Throws: NullPointerException – If delimiter or elements is null

    public static String join(CharSequence delimiter,
            Iterable<? extends CharSequence> elements) {
        Objects.requireNonNull(delimiter);
        Objects.requireNonNull(elements);
        StringJoiner joiner = new StringJoiner(delimiter);
        for (CharSequence cs: elements) {
            joiner.add(cs);
        }
        return joiner.toString();
    }
1
2
3
4
5
6
7
8
9
10

能够看到实际上它就是通过创建StringJoiner,然后遍历elements,加入每个元素来完成的。

StringJoiner

java.util public final class StringJoiner
extends Object
1
2

StringJoiner is used to construct a sequence of characters separated by a delimiter and optionally starting with a supplied prefix and ending with a supplied suffix. tringJoiner用于构造由分隔符分隔的字符序列,可以选择以提供的前缀开始,以提供的后缀结束。

Prior to adding something to the StringJoiner, its sj.toString() method will, by default, return prefix + suffix. However, if the setEmptyValue method is called, the emptyValue supplied will be returned instead. This can be used, for example, when creating a string using set notation to indicate an empty set, i.e. "{}", where the prefix is "{", the suffix is "}" and nothing has been added to the StringJoiner. 在向StringJoiner添加内容之前,它的sj.toString()方法在默认情况下会返回前缀+后缀。但是,如果调用setEmptyValue方法,则返回所提供的emptyValue。例如,当使用set符号创建一个字符串来表示一个空集时,可以使用这种方法。“{}”,其中前缀是“{”,后缀是“}”,没有向StringJoiner添加任何内容。

apiNote: The String "[George:Sally:Fred]" may be constructed as follows:

 StringJoiner sj = new StringJoiner(":", "[", "]");
 sj.add("George").add("Sally").add("Fred");
 String desiredString = sj.toString();
1
2
3

A StringJoiner may be employed to create formatted output from a java.util.stream.Stream using java.util.stream.Collectors.joining(CharSequence). For example: 使用StringJoiner从java.util.stream创建格式化输出流,使用java.util.stream.Collectors.joining (CharSequence进行)。例如:

 List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
 String commaSeparatedNumbers = numbers.stream()
     .map(i -> i.toString())
     .collect(Collectors.joining(", "));
1
2
3
4

通过分析源码发现,在“”内部维护了一个StringBuilder,所有加入到它内部的元素都会先拼接上分割符,然后再拼接上加入的元素

 public StringJoiner add(CharSequence newElement) {
        prepareBuilder().append(newElement);
        return this;
 }
1
2
3
4
   private StringBuilder prepareBuilder() {
        if (value != null) {
            value.append(delimiter);
        } else {
            value = new StringBuilder().append(prefix);
        }
        return value;
    }
1
2
3
4
5
6
7
8

# 10. 在Service中微服务比较多的时候,可以配置将一些微服务放置到compound中,组成一个小组

image-20200508222508833

以后再运行时,直接选择这个compound即可很方便的运行或停止一组微服务:

image-20200508223524543

另外可以单独为每个微服务,设置需要的运行时最大堆内存大小:

image-20200508222812353

# 11. mysql的dateTime和timestamp的区别?

MySQL中datetime和timestamp的区别及使用 (opens new window)

TIMESTAMP和DATETIME的相同点:

1> 两者都可用来表示YYYY-MM-DD HH:MM:SS[.fraction]类型的日期。

TIMESTAMP和DATETIME的不同点:

1> 两者的存储方式不一样

对于TIMESTAMP,它把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储。查询时,将其又转化为客户端当前时区进行返回。

而对于DATETIME,不做任何改变,基本上是原样输入和输出。

2> 两者所能存储的时间范围不一样

timestamp所能存储的时间范围为:'1970-01-01 00:00:01.000000' 到 '2038-01-19 03:14:07.999999'。

datetime所能存储的时间范围为:'1000-01-01 00:00:00.000000' 到 '9999-12-31 23:59:59.999999'。

总结:TIMESTAMP和DATETIME除了存储范围和存储方式不一样,没有太大区别。当然,对于跨时区的业务,TIMESTAMP更为合适。

https://www.cnblogs.com/Jashinck/p/10472398.html

# 12. SpringBoot中的事务

https://blog.csdn.net/Z__Sheng/article/details/89489053

# 13. IDEA RESTFUll clinet

IntelliJ IDEA 使用 rest client (opens new window)

#

# FAQ

# 1. TypeError: _vm.previewHandle is not a function

编辑 (opens new window)
上次更新: 2024/06/15, 15:12:25
谷粒商城—分布式基础第四部分
谷粒商城—分布式高级

← 谷粒商城—分布式基础第四部分 谷粒商城—分布式高级→

最近更新
01
04.Spring Boot 韩顺平
10-12
02
day14
08-29
03
day09
08-29
更多文章>
Theme by Vdoing | Copyright © 2019-2025 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式