《java架构师成长直通车》课程阶段一学习笔记

单体架构、高可用集群、分布式架构、微服务

课程项目的大致发展是:单体架构 -> 高可用集群 -> 分布式架构 -> 微服务
其中就需要理解,单体架构、集群、分布式和微服务之间的区别了。
借用 知乎的热门回答,简单来讲就是 单体架构 可以看做一名厨师,当门店生意很好的时候,此时雇请多第二名厨师,而这位厨师和之前的厨师能做出一模一样的饭菜,此时就可以看做为一个 集群;而再后来生意更加好的时候,雇请了一些配菜员,他能干洗菜、切菜之类的工作,用来分担厨师的负担,此时厨师和配菜员的关系就是 分布式;如果工作再细分下去,比如这个配菜员只能洗菜,那个配菜员只能切菜,那么这就是 微服务 的概念了。

同时这里也区别一下 高并发高吞吐 之间的概念区别。可以拿CPU举例,高吞吐 可以看做单核的处理能力,即一个请求发送到后端,此时系统数据量很大时,后端处理结果返回的响应速度。而 高并发 就像是多核的处理分配问题,一个网站积累的用户越多,对后端的请求量就会越来越大,此时后端应对这种情况下的响应速度。

项目的开端

项目的开始就是技术的选型,区分了 SpringBootSpringMVC 的区别,其实主要理解 SpringBoot 的核心设计思想就能明白二者的区别,它的核心设计思想就是:约定优于配置,它默认配置了很多框架的使用方式,就像 Maven 整合了所有的 jar 包,SpringBoot 整合了所有的框架,本质上开发人员只需规定应用中不符合约定的部分就可以了,而不是得像 SpringMVC 那样配置所有信息。例如 SpringBoot 约定 Controller 层就是 Web 请求层,这就可以省略了 MVC 的配置,约定了 以 Service 结尾 的类自动注入事务,这就可以省略 Spring 的切面事务配置等等。

在确认使用 SpringBoot 后就可以正式地学习教程了。

  • 项目的开启初期就应该理顺数据表、创建好数据表,这里使用了 PDman 数据建模工具,详情可看 《PDMan笔记》,同时初始化项目的聚合工程,详情可看《SpringBoot 笔记(项目初始化)》
  • 使用了自定义的 MyBatis 逆向生成工具,他可以帮助生成 Pojo、Dao、Mapper,并且生成的 Mapper 接口封装了常用的方法。
  • 整合 Swagger2,Swagger 2是一个接口文档生成工具,使用它可以与前端对接时省事很多,同时它也能提供很好的测试接口功能;
  • 整合日志,由于SpringBoot包含的日志包比较臃肿,这里在 pom 文件中使用右键选择 Diagrams -> show dependencies i显示依赖汇总图,并把内置的 spring-boot-starter-loggingExclude 剔除出去,并添加 slf4j 日志依赖,同时编写 log4j.properties 依赖配置文件,此时要注意的是日志的输出路径,如果是window系统时,不写具体的硬盘名称,会以项目所在的硬盘添加该设置的路径作为最终日志文件的存放路径;
  • 设置 Service 层切面,日志输出记录每个 Service 的耗时时间
  • 单元测试,直接配置在api层即可;
  • 开发环境和生产环境时,Application.yml 文件的配置;
  • 设置跨域
  • 设置 spring-boot-devtools 热部署,《IntelliJ IDEA Spring boot devtools 实现热部署》,要注意

至此,项目的初始化就基本完成了。

完成单体项目下来需要记下来的点

1 用户模块

  • 统一规范,VO,BO,pojo;
  • 前后端的 cookies 交互;
  • @RequestBody@RequestParam@PathVariable(首页根据分类Id 获取六个商品推荐的接口) 的区别;

2 首页模块

  • Mapper封装了常用的方法中使用 example 实例的升降序查询(首页获取轮播图列表接口);
  • 自定义Mapper接口,返回的pojo类中还有数组属性的字段,该如何编写 XML 文件映射到自定义 VO 对象(根据父级Id 获取其下一级的所有子分类信息接口);
  • sql 语句中的反单引号 ` 的作用;

3 商品模块

  • sql语句根据表中某个字段的取值不同,从而查询该表对应条件时的汇总数量,使用 case 语法(根据商品主键获取评论数接口);
  • @RequestParamrequired 属性为 false 时,前端的传值方式(根据关键词获取商品列表接口);
  • 使用 PageHelper 分页插件(根据关键词获取商品列表接口);
  • MyBatis 的 <if> 标签;<choose> 标签;test 属性判断单个字符串时,如何告诉 Mybatis 该比较类型是 String,而不要和 char 类型混淆;${}#{} 的区别(根据关键词获取商品列表接口);
  • 数组转化到集合的语法糖:Collections.addAll(集合, 数组);(根据规格id集合字符串获取最新商品信息接口);
  • MyBatis 的 <foreach> 标签(根据规格id集合字符串获取最新商品信息接口);

4 订单模块

  • 购物车的存储信息方式:
    • Cookie:
      • 优点:性能好、访问快,没有与数据库交互
      • 缺点1:更换电脑购物车数据会丢失
      • 缺点2:电脑被其他人登录,隐私安全问题
    • Session
      • 优点:初期性能好。访问快
      • 缺点1:Session 基于内存,用户量庞大影响服务器性能
      • 缺点2:只能存在与当前会话,不适用集群与分布式系统
    • 数据库
      • 优点:数据持久化,可在任何地方任何时间访问
      • 缺点:频繁读写数据库,造成数据库压力
    • Redis 缓存
      • 优点:数据持久化,可在任何地方任何时间访问
      • 优点2:频繁读写只基于缓存,不会造成数据库压力
      • 优点3:适用于集群与分布式,可扩展性强
  • 高并发导致扣库存问题,解决方式:
  • Service层抛出异常 RuntimeException 触发事务回滚(创建订单接口);
  • Mapper封装了常用的方法中使用 pojo 实例查询(根据用户id获取用户地址);
  • 使用语法糖 BeanUtils.copyProperties(Object source, Object target); 实现不同类的对象之间相同属性的赋值(用户修改地址);
  • 付款超时时,要设置订单的交易状态为关闭,定时任务的创建:
    • 使用 @schedule 注释开启定时任务,缺点:
      • 1、有时间差,即每条订单不一定会刚刚达到一天的时长后就马上关闭,程序不严谨
      • 2、假如数据量大,全表查找全部未支付的订单对数据库造成性能负担
      • 3、不支持集群,假设部署了多台服务器,定时任务就会多台执行,导致浪费,解决方案只使用一台服务器单独使用定时任务
      • 所以 @schedule 只适用一些小型轻量级项目,传统项目
    • 最好使用消息队列:MQ -> RabbitMQKafka 等的延时任务
  • 使用 RestTemplate 向支付中心发起请求

5 用户中心模块

  • 使用 hibernate 检查传入参数是否符合规格(更新用户消息接口);
  • 添加静态资源服务(获取头像图片);
  • properties 文件映射为 Bean 实例使用(上传用户头像接口);
  • 限制上传文件的大小,并且全局捕获异常(上传用户头像接口);
  • 注意存放文件时,Window系统和Linux系统的路径区别(上传用户头像接口);
  • 更新头像 url 到数据库,需要添加时间戳,以防浏览器缓存;
  • MyBatis 插入一个列表的数据(用户评价商品接口);
  • MyBatis 嵌套查询,避免 PageHelper 插件出错(获取用户的所有订单接口);
  • Mapper封装了常用的方法中使用 updateByExampleSelective,使 exemple 和 pojo 联合更新操作(根据用户id获取用户地址);

6 项目发布

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值