课程项目的大致发展是:单体架构 -> 高可用集群 -> 分布式架构 -> 微服务。
其中就需要理解,单体架构、集群、分布式和微服务之间的区别了。
借用 知乎的热门回答,简单来讲就是 单体架构 可以看做一名厨师,当门店生意很好的时候,此时雇请多第二名厨师,而这位厨师和之前的厨师能做出一模一样的饭菜,此时就可以看做为一个 集群;而再后来生意更加好的时候,雇请了一些配菜员,他能干洗菜、切菜之类的工作,用来分担厨师的负担,此时厨师和配菜员的关系就是 分布式;如果工作再细分下去,比如这个配菜员只能洗菜,那个配菜员只能切菜,那么这就是 微服务 的概念了。
项目的开端同时这里也区别一下 高并发 和 高吞吐 之间的概念区别。可以拿CPU举例,高吞吐 可以看做单核的处理能力,即一个请求发送到后端,此时系统数据量很大时,后端处理结果返回的响应速度。而 高并发 就像是多核的处理分配问题,一个网站积累的用户越多,对后端的请求量就会越来越大,此时后端应对这种情况下的响应速度。
项目的开始就是技术的选型,区分了 SpringBoot 和 SpringMVC 的区别,其实主要理解 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-logging 给 Exclude 剔除出去,并添加 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 语法(根据商品主键获取评论数接口);@RequestParam 的 required 属性为 false 时,前端的传值方式(根据关键词获取商品列表接口);使用 PageHelper 分页插件(根据关键词获取商品列表接口);MyBatis 的 购物车的存储信息方式:
cookie:
优点:性能好、访问快,没有与数据库交互缺点1:更换电脑购物车数据会丢失缺点2:电脑被其他人登录,隐私安全问题 Session
优点:初期性能好。访问快缺点1:Session 基于内存,用户量庞大影响服务器性能缺点2:只能存在与当前会话,不适用集群与分布式系统 数据库
优点:数据持久化,可在任何地方任何时间访问缺点:频繁读写数据库,造成数据库压力 Redis 缓存
优点:数据持久化,可在任何地方任何时间访问优点2:频繁读写只基于缓存,不会造成数据库压力优点3:适用于集群与分布式,可扩展性强 高并发导致扣库存问题,解决方式:
synchronized 修饰词:不推荐使用,集群下无用,性能低下锁数据库:不推荐,导致数据库性能低下分布式锁:zookeepper,reids适用乐观锁,什么是乐观锁,什么是悲观锁,什么是减少乐观锁的粒度,提高并发能力(创建订单接口) Service层抛出异常 RuntimeException 触发事务回滚(创建订单接口);Mapper封装了常用的方法中使用 pojo 实例查询(根据用户id获取用户地址);使用语法糖 BeanUtils.copyProperties(Object source, Object target); 实现不同类的对象之间相同属性的赋值(用户修改地址);付款超时时,要设置订单的交易状态为关闭,定时任务的创建:
使用 @schedule 注释开启定时任务,缺点:
1、有时间差,即每条订单不一定会刚刚达到一天的时长后就马上关闭,程序不严谨2、假如数据量大,全表查找全部未支付的订单对数据库造成性能负担3、不支持集群,假设部署了多台服务器,定时任务就会多台执行,导致浪费,解决方案只使用一台服务器单独使用定时任务所以 @schedule 只适用一些小型轻量级项目,传统项目 最好使用消息队列:MQ -> RabbitMQ,Kafka 等的延时任务 使用 RestTemplate 向支付中心发起请求
5 用户中心模块
使用 hibernate 检查传入参数是否符合规格(更新用户消息接口);添加静态资源服务(获取头像图片);将 properties 文件映射为 Bean 实例使用(上传用户头像接口);限制上传文件的大小,并且全局捕获异常(上传用户头像接口);注意存放文件时,Window系统和Linux系统的路径区别(上传用户头像接口);更新头像 url 到数据库,需要添加时间戳,以防浏览器缓存;MyBatis 插入一个列表的数据(用户评价商品接口);MyBatis 嵌套查询,避免 PageHelper 插件出错(获取用户的所有订单接口);Mapper封装了常用的方法中使用 updateByExampleSelective,使 exemple 和 pojo 联合更新操作(根据用户id获取用户地址);
6 项目发布
linux 虚拟机如何联网,修改 /etc/sysconfig/network-scripts/ifcfg-ens33 文件的 ONBOOT 为 yes;使用 ifconfig 获取 IP 地址,端口为 22,连接 SecureCRT,FileZilla;设置防火墙,《Centos7 防火墙配置》;打包 war 包:
1、设置 controller 层的 pom.xml 的打包类型为 war2、设置剔除 SpringBoot 内置 tomcat3、设置 war 包启动类



