IT - 知识体系
2023-06-27 16:35:10 0 举报
AI智能生成
IT知识导图
作者其他创作
大纲/内容
Java
Java 基础
基本概念
类和对象
类
设计
找实体
找属性
找关系
ER图
成员
属性
包括静态的类变量和非静态的实例变量
代码块
包括静态代码块和非静态代码块
非静态代码块又称为构造块
构造方法
包括无参构造和有参构造
方法
包括静态方法和非静态方法
内部类
变量
关键字
权限控制
public
protected
private
本类或父类实例引用
this
super
继承类或实现接口
extends
implements
导入包或类
import
声明类所在包
package
声明类或接口
class
interface
声明基本数据类型变量
byte
int
short
long
double
float
char
boolean
修饰抽象类或抽象方法
abstract
声明静态成员变量或方法
static
流程控制
switch
if
else
循环
for
do
while
break
continue
异常处理
throw
throws
try
catch
finally
同步控制
synchronized
方法返回
return
新建实例
new
判断实例类型
instanceof
最终类、方法、变量
final
被final修饰的类不能被继承
被final修饰的方法不能被重写
被final修饰的变量不能被修改
成员变量不缓存
volatile
本地方法
native
方法无返回值
void
数据类型
基本类型
数字型
整型
byte
short
int
long
非整型
float
double
非数字型
布尔型
字符型
引用类型
类类型
接口
枚举
运算符
一元运算符
二元运算符
三元运算符
布尔表达式 ? 为真时的值 : 为假时的值
流程控制
条件分支
switch
if
else
条件表达式
循环
for
do
while
break
continue
异常处理
throw
throws
try
catch
finally
枚举、反射、泛型
String常用 API
注释
单行注释
多行注释
javadoc标签
html标签
集合框架
并发框架
IO框架
多线程
创建线程的几种方式
线程的生命周期
如何保证线程安全
transient
Java进阶 JVM相关
类加载机制
类加载过程
流程
加载
验证
准备
解析
初始化
类加载器
双亲委派
JVM 内存结构
线程独享
说明
组成
虚拟机栈
说明
为虚拟机执行JAVA方法服务
由栈帧组成
栈帧(stack frame)
说明
每个方法在执行的同时都会创建一个栈帧
每个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程
方法中创建的对象还是保存在堆中,但是对象的引用保存在局部变量表中,对象引用还是线程独享的,
方法中的对象是放在heap上的这个是可以共享的,但是对这个对象来讲method每次被调用都会生成一个新的对象,
因此对象引用所引用的对象实际上只有一个线程可以访问。
每个线程在调用相同方法时,都会重新创建方法中的变量,所以即使方法中的对象保存在堆中,
但是这些对象是只有创建它的线程可以访问,但是对于同一个线程的不同方法,可以操作同一个对象变量
方法中的对象是放在heap上的这个是可以共享的,但是对这个对象来讲method每次被调用都会生成一个新的对象,
因此对象引用所引用的对象实际上只有一个线程可以访问。
每个线程在调用相同方法时,都会重新创建方法中的变量,所以即使方法中的对象保存在堆中,
但是这些对象是只有创建它的线程可以访问,但是对于同一个线程的不同方法,可以操作同一个对象变量
组成
局部变量表
基本数据类型
对象引用
returnAddress类型
操作数栈
动态链接
方法出口(方法返回地址)
程序计数器
当前线程所执行的字节码的行号指示器
本地方法栈
说明
为虚拟机执行本地方法服务
共享内存
堆(heap)(垃圾回收堆:GC堆)
说明
被所有线程共享的内存区域
用于存放所有对象实例以及数组
在虚拟机启动时创建
方法区
说明
用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器编译后的代码等数据
组成
已被虚拟机加载的类信息
常量
说明
存放在常量池
常量池用于存放编译期生成的各种字面量和符号引用(比如类的符号引用),这部分内容将在类加载后进入
方法区的运行时常量池中存放。
方法区的运行时常量池中存放。
组成
字面量
符号引用
静态变量
即时编译器编译后的代码
JVM 垃圾回收机制
Java 调试排错相关
JavaEE
Servlet
Listener
Filter
web.xml
计算机基础
操作系统
Linux
Linux历史和版本
Unix发展史
Linux内核
进程
ps
lsof
程序
发行版(Debian, Ubuntu, Fedora, CentOS, Arch Linux等)
总览
登录
命令
命令选项
终端
exit
帮助
Shell
Linux shell是用户与Linux系统交互的主要方式,它提供了命令行界面和脚本语言。常用的Linux shell包括Bash、Zsh等。
变量
标准输入/输入
管道
流程控制
条件语句
if
循环语句
while
for
条件表达式
运算符
各种符号
$
$()
""
''
``
|
||
&
&&
函数
Linux用户和权限管理
用户管理(useradd, usermod, userdel等)
passwd
群组管理(groupadd, groupmod, groupdel等)
权限管理(chmod, chown, chgrp等)
文件系统
inode
硬链接/软连接
文件类型
普通文件(-):用于存储信息和数据, Linux 用户可以根据访问权限对普通文件进行查看、更改和删除。比如:图片、声音、PDF、text、视频、源代码等等。
目录文件(d,directory file):目录也是文件的一种,用于表示和管理系统中的文件,目录文件中包含一些文件名和子目录名。打开目录事实上就是打开目录文件。
符号链接文件(l,symbolic link):保留了指向文件的地址而不是文件本身。
字符设备(c,char):用来访问字符设备比如键盘。
设备文件(b,block):用来访问块设备比如硬盘、软盘。
管道文件(p,pipe) : 一种特殊类型的文件,用于进程之间的通信。
套接字文件(s,socket):用于进程间的网络通信,也可以用于本机之间的非网络通信。
目录树
目录结构
/bin, /sbin
/etc
/home
/lib, /lib64
/media, /mnt
/opt
/root
/usr, /usr/local
/var
命令
ls
rm
mv
cp
cd
pwd
scp
绝对路径/相对路径
网络
ifconfig
ping
telnet
curl
wget
磁盘
mount
unmount
df
du
工具
字符处理
grep
awk
sed
cat
tail
less
more
vi
vim
压缩
gzip
zip
unzip
tar
日期
date
其他
who
which
history
echo
网络
数据结构
概念
数据结构是一种存储和组织数据的方式,旨在便于访问和修改。没有一种单一的数据结构对所有用途均有效,所以重要的是知道几种数据结构的优势和局限。
分类
按照存储结构角度分类
线性存储结构
是什么
将具有“一对一”关系的数据“线性”地存储到物理空间中,这种存储结构就称为线性存储结构(简称线性表)。
使用线性表存储的数据,如同向数组中存储数据那样,要求数据类型必须一致,也就是说,线性表存储的数据,要么全部都是整形,要么全部都是字符串。一半是整形,另一半是字符串的一组数据无法使用线性表存储。
分类
顺序表(数组)
物理存储地址连续
数据元素连续存储,并通过连续的物理存储地址维系数据之间逻辑关系的存储结构
链表
物理存储地址随机
数据元素随机存储,并通过指针表示数据之间逻辑关系的存储结构
链表中每个数据的存储都由以下两部分组成:
数据元素本身,其所在的区域称为数据域;
指向直接后继元素的指针,所在的区域称为指针域;
数据元素本身,其所在的区域称为数据域;
指向直接后继元素的指针,所在的区域称为指针域;
栈
队列
按照数据存储在物理空间的连续性分类
顺序存储结构(顺序表)
链式存储结构(链表)
树存储结构
二叉树
多路查找树
堆
其他
红黑树
图存储结构
图
种类
散列表
堆
跳表
trie树
算法
概念
操作数据的方法
数据结构是为算法服务的,算法要作用在特定的数据结构之上。
复杂度分析
种类
时间复杂度
最好
最坏
平均
均摊
空间复杂度
基本算法思想
贪心算法
分治算法
动态规划
回溯算法
枚举算法
二分法
排序算法
搜索算法
查找算法
字符串匹配
其他
算法设计与分析的基本方法
递归
二分查找
哈希算法
字符串匹配算法
子主题
数据库
关系型数据库设计三大范式
什么是范式?
简言之就是,数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。
数据表结构所符合的某种设计标准的级别
哪三种
列不可再分(列的原子性)
当关系模式R的所有属性都不能在分解为更基本的数据单位时,称R是满足第一范式的,简记为1NF。满足第一范式是关系模式规范化的最低要求,否则,将有很多基本操作在这样的关系模式中实现不了。
确保每列完全依赖于主键(要求每个表只描述一
件事情)
件事情)
如果关系模式R满足第一范式,并且R得所有非主属性都完全依赖于R的每一个候选关键属性,称R满足第二范式,简记为2NF。
确保每列直接依赖于主键,不依赖于其它非主属性(非主键外的所有列必须互不依赖)
设R是一个满足第一范式条件的关系模式,X是R的任意属性集,如果X非传递依赖于R的任意一个候选关键字,称R满足第三范式,简记为3NF.
说明
三大范式只是一般设计数据库的基本理念,可以建立冗余较小、结构合理的数据库。如果有特殊情况,当然要特殊对待,数据库设计最重要的是看需求跟性能,需求>性能>表结构。所以不能一味的去追求范式建立数据库。
https://www.zhihu.com/question/24696366
分类
关系型数据库
非关系型数据库
MySQL
语句
DDL:数据库定义语言(对结构进行操作)
DML:数据库操作语言(数据操作)
DQL(数据库查询语言)
事务
概念
把一个或多个DML操作当作一个不可分割的最小工作单元;要么全部成功,要么全部失败。
事务只和DML语句有关,或者说DML语句才有事务。
四大特性(AICD)
原子性
概念
把一个事务视为数据库中一个不可分割的最小工作单位,事务的各步操作是不可分的(原子的);要么都执行,要么都不执行
化学角度类比:原子(atom)指化学反应不可再分的基本微粒,是一般物质的最小单位。数据库角度:是数据库中不可分割的最小工作单位。
隔离性
概念
一个事务所做的修改在最终提交之前,对其他事务是不可见的。 -> 每一个事务在最终提交之前能够看到的数据总是一致的
隔离性保证别的事务不会影响当前事务
隔离级别
概念
用来规定一个事务从开始直到提交之前,所做的任何修改对其他事务是否可见。
种类
未提交读
一个事务能读取到其他事务未提交的数据
导致脏读,不可重复读,幻读
提交读
一个事务只能读取到其他事务已经提交的数据
导致不可重复读,幻读
可重复读(mysql默认事务隔离级别)
一个事务只能读取到其他事务已经提交的数据
同一个事务中多次读取同样记录的结果是一致的。
导致幻读
msyql通过多版本并发控制(MVCC)解决了幻读问题
使用了以乐观锁为理论基础的MVCC(多版本并发控制)来避免这两种问题
可串行化
并行事务的四大问题:
1.更新丢失:和别的事务读到相同的东西,各自写,自己的写被覆盖了。(谁写的快谁的更新就丢失了)
2.脏读:读到别的事务未提交的数据。(万一回滚,数据就是脏的无效的了)
3.不可重复读:一个事务读取到了另外一个事务中已提交的update的数据。
4.幻读:一个事务读取到了另外一个事务中已提交的insert或delete的数据。
1.更新丢失:和别的事务读到相同的东西,各自写,自己的写被覆盖了。(谁写的快谁的更新就丢失了)
2.脏读:读到别的事务未提交的数据。(万一回滚,数据就是脏的无效的了)
3.不可重复读:一个事务读取到了另外一个事务中已提交的update的数据。
4.幻读:一个事务读取到了另外一个事务中已提交的insert或delete的数据。
持久性
概念
一旦事务提交,则其所做的修改就会永久保存到数据库中。
一致性
概念
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。比如转账,转账前两个账户余额之和为2k,转账之后也应该是2K。
一致性是基础,也是最终目的,其他三个特性(原子性、隔离性和持久性)都是为了保证一致性的。
原子性:比如有的操作成功,有的操作不成功,就不能保持一致性。
持久性:比如数据库崩溃或者断电等情况,这个时候,依赖于对日志的 REDO/UNDO 操作就可以保证一致性
持久性:原子性在并发情况下不能保证一致性。比如会存在脏读、幻读和不可重复读等问题,为了保证并发情况下的一致性,又引入了隔离性的概念。
原子性:比如有的操作成功,有的操作不成功,就不能保持一致性。
持久性:比如数据库崩溃或者断电等情况,这个时候,依赖于对日志的 REDO/UNDO 操作就可以保证一致性
持久性:原子性在并发情况下不能保证一致性。比如会存在脏读、幻读和不可重复读等问题,为了保证并发情况下的一致性,又引入了隔离性的概念。
事务锁
种类
读锁
写锁
粒度
表
行
mvcc实现原理
其他
一致性是事务的最终目的,原子性、隔离性、持久性都是为了实现一致性。
存储引擎
种类
innodb
MyISAM
MEMORY/HEAP
各自特点?
为什么默认的是innodb?
索引
是什么
存储引擎用于快速查找记录的一种数据结构
按照不同的角度分类
数据结构角度
b-tree
说明
B树是为了磁盘或其它存储设备⽽设计的⼀种多叉(下⾯你会看到,相对于⼆叉,B树每个内结点有多个
分⽀,即多叉)平衡查找树。 多叉平衡
分⽀,即多叉)平衡查找树。 多叉平衡
B树的⾼度⼀般都是在2-4这个⾼度,树的⾼度直接影响IO读写的次数。
如果是三层树结构---⽀撑的数据可以达到20G,如果是四层树结构---⽀撑的数据可以达到⼏⼗T
r-tree
hash索引
全文索引
物理存储的角度
聚簇索引
以主键创建的索引
叶子节点存储的是主键和对应的数据行
是通往真实数据行的唯一途径
非聚簇索引
索引字段特性角度
主键索引
唯一索引
普通索引
前缀索引
组成索引的字段个数角度
单列索引
联合索引(复合索引)
说明
二叉树
二叉查找树是基于二分查找法来提高数据查找速度的二叉树的数据结构;
二叉查找树是采用二分查找法把数据按规则组装成一个树形结构的数据,减少无关数据的检索,提升了数据检索的速度;
规则
顶端的节点称为根节点
不在顶端并且拥有子节点的节点称为非叶子节点,非叶子节点只能允许最多两个子节点
没有子节点的节点我们称之为叶子节点
若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值
若任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值
平衡二叉树(红黑树)
子主题
B树(B-Tree)
概念
B树和平衡二叉树不同,B树属于多叉树又名平衡多路查找树(查找路径不只两个),数据库索引里大量使用者B-Tree和B+Tree的数据结构。
规则
顶端的节点称为根节点
不在顶端并且拥有子节点的节点称为非叶子节点,非叶子节点允许多个子节点
没有子节点的节点我们称之为叶子节点
每一个非叶子节点数据分布规则为左边的子节点小当前节点的值,右边的子节点大于当前节点的值
所有叶子节点均在同一层、叶子节点除了包含了关键字还包含了数据;
b+树
B树和B+树的最⼤区别在于⾮叶⼦节点是否存储数据的问题
B树是⾮叶⼦节点和叶⼦节点都会存储数据。
B+树只有叶⼦节点才会存储数据,⽽且存储的数据都是在⼀⾏上,⽽且这些数据都是有指针指向的,也
就是有顺序的。 索引列 order by
就是有顺序的。 索引列 order by
哪些情况需要创建索引
1. 主键⾃动建⽴唯⼀索引
2. 频繁作为查询条件的字段应该创建索引
3. 多表关联查询中,关联字段应该创建索引 on 两边都要创建索引
4. 查询中排序的字段,应该创建索引
5. 频繁查找字段 覆盖索引
6. 查询中统计或者分组字段,应该创建索引 group by
2. 频繁作为查询条件的字段应该创建索引
3. 多表关联查询中,关联字段应该创建索引 on 两边都要创建索引
4. 查询中排序的字段,应该创建索引
5. 频繁查找字段 覆盖索引
6. 查询中统计或者分组字段,应该创建索引 group by
哪些情况不需要创建索引
1. 表记录太少
2. 经常进⾏增删改操作的表
3. 频繁更新的字段
4. where条件⾥使⽤频率不⾼的字段
优点
第一、通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
第二、可以大大加快数据的检索速度,这也是创建索引的最主要的原因。
第三、可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
第四、在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的 时间。
第五、通过使用索引,可以在查询的过程中,使用查询优化器,提高系统的性能。
缺点
第一、创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
第二、索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物 理空间。如果要建立聚簇索引,那么需要的空间就会更大。
第三、当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降 低了数据的维护速度。
回表查询
主要涉及聚簇索引、非聚簇索引两个概念,非聚簇索引的叶子节点因为不包含整行的所有数据,索引会通过非聚簇索引找到数据行的主键,再通过聚簇索引查找整行数据的过程
索引覆盖
通过二级索引查询时,回表不是必须的过程,当 Query 的所有字段在二级索引中就能找到时,就不需要回表
执行计划
执行流程
建表规范
在数据库设计过程中,在满足业务需求的要求下,要考虑性能,其次才是三大范式。需求>性能>表结构
选用合适的数据类型
关联字段类型长度要一致
关联字段建立索引
NoSQL数据库
Redis
MongoDB
ElasticSearch
开发工具
Maven
Gradle
Git
Docker
K8S
软件
运维工具:ansible
Idea
DBeaver
Xshell
Beyond Compare
Typora
Lens
He3
APIFox
Another Redis
Pycharm
框架
Spring
SpringMVC
SpringBoot
Mybatis
Shiro
Spring Security
Jooq
Druid
HikariCP
中间件
Nginx
MQ
Kafka
RabbitMQ
Redis
系统设计
分布式
分布式id
分布式锁
分布式会话
分布式存储
分布式任务
分布式事务
分布式日志
配置中心
注册中心
Zookeeper
Nacos
服务远程调用
RPC
Dubbo
算法
cap/base
paxos
raft
gossip
高性能
读写分离
分库分表
负载均衡
消息队列
高可用
冗余设计
服务限流
熔断、降级
超时、重试
性能测试
编程
RESP API
API规范
URI
格式: https://{host}:{port}/{application}/api/{version}/{resources}
字母一律小写,使用横线 '-' 作为连字符,不允许使用下划线
正确示例: /api/v1.0/automation/sap-jobs
正确示例: /api/v1.0/automation/sap-jobs
使用/来表示资源的层级关系
资源统一使用复数形式
只有 POST 时, URI 才能使用动词, 且只应放在最后
清晰易懂,没有歧义,并避免过多的路径嵌套
不应以 "/" 结尾
使用-来分隔一些单词
, 或 ; 可以用来表示同级资源的关系
有时候我们需要表示同级资源的关系时,可以使用,或;来进行分割。例如哪天github可以比较某个文件在随意两次提交记录之间的差异,或许可以使用/git/git /block-sha1/sha1.h/compare/e3af72cdafab5993d18fae056f87e1d675913d08;bd63e61bdf38e872d5215c07b264dcc16e4febca作为URI。 不过,现在github是使用…来做这个事情的,例如/git/git/compare/master…next。
长度应控制在 2083 个字符以内
必须加入 API 版本:
格式为 v<大版本号>.<小版本号>, 如: v1.2
大版本号从 1 开始, 小版本号从 0 开始, 即最小版本号为 v1.0
协议变化时, 当且仅当新协议向后兼容时, 增加小版本号, 否则, 应增加大版本号, 并重置小版本为 0
只是 API 内部实现的增强,而不影响 API 交互结构时,不需要改变版本号。
API 升级时, 新旧版本必须存在适当的共存期, 不得使用覆盖的方式开发和升级
格式为 v<大版本号>.<小版本号>, 如: v1.2
大版本号从 1 开始, 小版本号从 0 开始, 即最小版本号为 v1.0
协议变化时, 当且仅当新协议向后兼容时, 增加小版本号, 否则, 应增加大版本号, 并重置小版本为 0
只是 API 内部实现的增强,而不影响 API 交互结构时,不需要改变版本号。
API 升级时, 新旧版本必须存在适当的共存期, 不得使用覆盖的方式开发和升级
不应包含资源的扩展名(以 Content-Type 协商的数据格式为准)
错误示例: GET /automation/api/v1.0/servers.json
错误示例: GET /automation/api/v1.0/servers.json
当是参数是对资源的限定时, 应使用路径变量, 如资源的 ID
正确示例: PUT /automation/api/v1.0/servers/{serverId}
正确示例: PUT /automation/api/v1.0/servers/{serverId}
URI 可以使用查询字段作为过滤条件,并在 API 文档中明确说明每个字段的含义、格式、使用场景等。
正确示例:GET /automation/api/v1.0/servers?page=1&size=20
正确示例:GET /automation/api/v1.0/servers?page=1&size=20
总结
全小写,使用横线'-'作为连字符
只有post 请求中,uri 才可以使用
不以"/" 结尾
资源统一使用复数形式
method
只允许使用的动词
GET
不可用 GET 来创建、删除、修改资源等对持久化资源/服务器状态有副作用的场景
通常使用 GET 来查询资源; 仅当一些请求体较大较复杂的情况需使用 POST
POST
既然PUT和POST操作都是向服务器端发送数据的,那么两者有什么区别呢。POST主要作用在一个集合资源之上的(url),而PUT主要作用在一个具体资源之上的(url/xxx),通俗一下讲就是,如URL可以在客户端确定,那么可使用PUT,否则用POST。
PATCH
PUT
DELETE
OPTIONS
HEAD
请求头
content-type
Accept
Authorization
请求体
数据交换有哪些要求
请求/响应报文使用 JSON 报文(RFC7159), 编码为 UTF-8
服务端返回数据应使用统一的外层结构
应使用 小驼峰式命名法, 参考: 命名的礼仪
不可强制要求客户端传送空字段
避免冗余数据的来回传递
服务端/客户端不可对端传来的数据都应有一定的容错和忽略机制, 且不应依赖字段的顺序
数据格式遵从 2.12 Data Formats, 日期时间统一采用:
ISO 标准时间格式,时区为 UTC (GMT +0 ) 时区,如:2020-01-02T19:55:46.123Z
时间戳格式, 单位为毫秒, 类型为长整型 (long/bigint/int64),由对端自行格式化
ISO 标准时间格式,时区为 UTC (GMT +0 ) 时区,如:2020-01-02T19:55:46.123Z
时间戳格式, 单位为毫秒, 类型为长整型 (long/bigint/int64),由对端自行格式化
引申
时间戳是否存在时区的问题:
时间戳的定义:从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。
从定义中发现,时间戳规定了地点(相当于时区)和起始时间,所以不存在时区问题。
时间戳的定义:从格林威治时间1970年01月01日00时00分00秒起至现在的总秒数。
从定义中发现,时间戳规定了地点(相当于时区)和起始时间,所以不存在时区问题。
API 提供方可选择性支持其他数据格式 , 并通过 Content-Type 来协商。
分页及带排序查询api如何写
示例
/api/v1/servers?page=1&size=20&sort=ip,asc&sort=name,desc
page
从 1 开始, 代表第一页, 默认值为 1
size
每页大小
size 无效时可使用默认值
须视情况, 限制最大返回数量
sort
值格式为: "字段名,方向", 以逗号分割, 如按照 name 升序则是 "name,asc", 降序是 "name,desc"
支持多个排序字段是, 以第一个 sort 为主排序规则, 其次是第二个, 依次类推
响应头
响应体
结构
success
Boolean
是
标识是否调用成功。如果正确使用HTTP返回码,该字段其实不需要。但为了前端调用的便利性,目前该字段依然强制要求。
是
标识是否调用成功。如果正确使用HTTP返回码,该字段其实不需要。但为了前端调用的便利性,目前该字段依然强制要求。
code
String
是 (失败时)
成功时,补充性信息
出错时,服务端返回的错误编码(不同于 HTTP 状态码)。
是 (失败时)
成功时,补充性信息
出错时,服务端返回的错误编码(不同于 HTTP 状态码)。
message
String
是 (失败时)
成功时,补充性的信息
出错时,服务端给出的错误信息及排错建议
应尽可能根据 Accept-Language 进行国际化, 否则使用缺省语言
是 (失败时)
成功时,补充性的信息
出错时,服务端给出的错误信息及排错建议
应尽可能根据 Accept-Language 进行国际化, 否则使用缺省语言
data
Object / Array
是 (成功时)
服务端成功响应请求后,返回给客户端的数据。以 JSON 对象或对象列表方式返回。针对每一个API,需要具体定义。定义规范同请求体数据结构。
是 (成功时)
服务端成功响应请求后,返回给客户端的数据。以 JSON 对象或对象列表方式返回。针对每一个API,需要具体定义。定义规范同请求体数据结构。
timestamp
long
是
时间戳(UTC), 精确到毫秒
是
时间戳(UTC), 精确到毫秒
messageCode
String 否 (兼容字段) 同 code
requestId
String
否
服务端返回的客户端请求唯一编号,用于服务端排错,由服务端决定是否启用。
否
服务端返回的客户端请求唯一编号,用于服务端排错,由服务端决定是否启用。
说明
sucess, timestamp 始终必填,code, message 失败时必填,data 成功时必填
[遵守] API 不应直接返回 PO, 应定义对应的 VO, 避免返回敏感字段, 可使用 setter 和 getter 处理兼容问题
[遵守] API 返回类型的范型应明确且完整, 如: ResultBody<List<UserVO>>
状态码
编码规范
作用
编程规范主要解决的是代码的可读性问题
编码规范相对于设计原则、设计模式,更加具体、更加偏重代码细节、更加能落地
持续的小重构依赖的理论基础主要就是编程规范。
规范
命名(类,方法,变量,表名,字段名)
系统
业务分层
模块拆解
代码
命名
类名
方法名
变量名
数据库
表,数据库命名
编码,字符集,排序规则
通用字段
索引
关联字段需要长度类型一致,并且在注释中写明是哪个表的哪个字段
经验
代码重构
持续重构是保持代码质量不下降的有效手段,能有效避免代码腐化到无可救药的地步。
设计思想、设计原则、设计模式一个最重要的应用场景就是在重构的时候。
单元测试
面向对象
概念
面向对象是一种编程范式;在进行程序设计的过程中,将现实世界中的事物或活动设计为类,然后协调类创建的对象完成系统功能
面向对象编程因为其具有丰富的特性(封装、抽象、继承、多态),可以实现很多复杂的设计思路,是很多设计原则、设计模式等编码实现的基础。
面向对象围绕着对象或类来做需求分析和设计的。分析和设计两个阶段最终的产出是类的设计,包括程序被拆解为哪些类,每个类有哪些属性方法,类与类之间如何交互等等。它们比其他的分析和设计更加具体、更加落地、更加贴近编码,更能够顺利地过渡到面向对象编程环节。这也是面向对象分析和设计,与其他分析和设计最大的不同点。
四大特性
封装
抽象
继承
多态
面向对象分析
面向对象分析就是要搞清楚做什么
面向对象设计
面向对象设计就是要搞清楚怎么做。两个阶段最终的产出是类的设计,包括程序被拆解为哪些类,每个类有哪些属性方法、类与类之间如何交互等等。
面向对象编程
概念
面向对象编程是一种编程范式或编程风格。它以类或对象作为组织代码的基本单元,并将封装、抽象、继承、多态四个特性,作为代码设计和实现的基石 。
面向对象编程语言是支持类或对象的语法机制,并有现成的语法机制,能方便地实现面向对象编程四大特性(封装、抽象、继承、多态)的编程语言。
参考资料
https://my.oschina.net/u/4294107/blog/3743332
设计原则
概念
设计原则是指导我们代码设计的一些经验总结,对于某些场景下,是否应该应用某种设计模式,具有指导意义。比如,“开闭原则”是很多设计模式(策略、模板等)的指导原则。
原则
(SOLID)
单一职责原则(SRP:Single Responsibility Principle)
一个类只能承担一个事情
其实就是开发人员经常说的”高内聚,低耦合”
也就是说,每个类应该只有一个职责,对外只能提供一种功能,而引起类变化的原因应该只有一个。在设计模式中,所有的设计模式都遵循这一原则。
开闭原则(OCP: Open Closed Principle)
一个对象对扩展开放,对修改关闭。
对类的改动是通过增加代码进行的,而不是修改现有代码。
也就是说软件开发人员一旦写出了可以运行的代码,就不应该去改动它,而是要保证它能一直运行下去,如何能够做到这一点呢?这就需要借助于抽象和多态,即把可能变化的内容抽象出来,从而使抽象的部分是相对稳定的,而具体的实现则是可以改变和扩展的。
里式替换原则(LSP: Liskov Substitution Principle)
子类型能够替换它们的基类型
在任何父类出现的地方都可以用它的子类来替代。
其实就是说:同一个继承体系中的对象应该有共同的行为特征。
接口隔离原则(ISP: Interface Segregation Principle)
抽象不持有特定逻辑,应持有实现的公有逻辑
一个接口不需要提供太多的行为,一个接口应该只提供一种对外的功能,不应该把所有的操作都封装到一个接口中。
依赖倒置原则(DIP: Dependency Inversion Principle)
要依赖于抽象,不要依赖于具体实现。
在应用程序中,所有的类如果使用或依赖于其他的类,则应该依赖这些其他类的抽象类,而不是这些其他类的具体类。为了实现这一原则,就要求我们在编程的时候针对抽象类或者接口编程,而不是针对具体实现编程。
DRY
不做重复的事,不写重复类似的代码
KISS
keep it simple,尽量简单的代码,让代码更容易被别人理解
YANGNI
you ain't gonna need it,只着眼必需的功能,不添加认为可能需要的功能
LOD 迪米特原则
一个对象应当对其他对象尽可能少的了解
降低各个对象之间的耦合,提高系统的可维护性。在模块之间应该只通过接口编程,而不理会模块的内部工作原理,它可以使各个模块耦合度降到最低,促进软件的复用
其他
降低系统耦合度,复杂度
相关的“在一起”,叫内聚,不相关的“在一起”,叫耦合。
维护性,复用性,灵活性,扩展性
设计模式
是什么
设计模式是针对软件开发中经常遇到的一些设计问题,总结出来的一套解决方案或者设计思路。
大部分设计模式要解决的都是代码的可扩展性问题。
从抽象程度上来讲,设计原则比设计模式更抽象。设计模式更加具体、更加可执行。
24种设计模式
创建型(6种)
概念
主要解决对象的创建问题,封装复杂的创建过程,解耦对象的创建代码和使用代码。
种类
单例模式
概念
一个类只允许创建一个对象(或者叫实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式。
场景
一个类只能有一个实例
一个类多个实例会存在问题的时候
资源抢占
种类
饿汉式
使用static关键字,类加载的时候实例化
不支持延迟加载
线程安全
懒汉式
支持延迟加载
性能不如饿汉式
双重校验锁
支持延迟加载
线程安全,性能好
类似懒汉式,基于懒汉式改造
静态内部类
支持延迟加载
类似饿汉式,基于饿汉式改造
原理:类加载机制,内部静态类在使用时才会被加载
枚举
支持延迟加载
线程安全
需要考虑的问题点
创建对象的线程安全问题
是否支持延迟加载
在真正用到对象的时候才创建
构造函数需要private访问权限
考虑getInstance()性能是否高(是否加锁)
工厂模式
定义了一个创建对象的接口, 但由子类决定要实例化的类是哪一个. 工厂方法让类把实例化推迟到子类
场景
不同条件创建不同实例
组成
精彩评价
跟整理衣服差不多。衣服少的时候,都放一起,多的时候,按照一定规则分一下,整理一下子
简单工厂模式
定义一个创建产品对象的工厂接口,将产品对象的实际创建工作推迟到具体子工厂类当中。这满足创建型模式中所要求的“创建与使用相分离”的特点。
场景
对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。
特点
优点:
工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
客户端无需知道所创建具体产品的类名,只需知道参数即可。
也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。
缺点:
简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
工厂类包含必要的逻辑判断,可以决定在什么时候创建哪一个产品的实例。客户端可以免除直接创建产品对象的职责,很方便的创建出相应的产品。工厂和产品的职责区分明确。
客户端无需知道所创建具体产品的类名,只需知道参数即可。
也可以引入配置文件,在不修改客户端代码的情况下更换和添加新的具体产品类。
缺点:
简单工厂模式的工厂类单一,负责所有产品的创建,职责过重,一旦异常,整个系统将受影响。且工厂类代码会非常臃肿,违背高聚合原则。
使用简单工厂模式会增加系统中类的个数(引入新的工厂类),增加系统的复杂度和理解难度
系统扩展困难,一旦增加新产品不得不修改工厂逻辑,在产品类型较多时,可能造成逻辑过于复杂
简单工厂模式使用了 static 工厂方法,造成工厂角色无法形成基于继承的等级结构。
对于产品种类相对较少的情况,考虑使用简单工厂模式。使用简单工厂模式的客户端只需要传入工厂类的参数,不需要关心如何创建对象的逻辑,可以很方便地创建所需产品。
组成
简单工厂(SimpleFactory):是简单工厂模式的核心,负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
抽象产品(Product):是简单工厂创建的所有对象的父类,负责描述所有实例共有的公共接口。
具体产品(ConcreteProduct):是简单工厂模式的创建目标。
建造者模式
使用生成器模式封装一个产品的构造过程, 并允许按步骤构造. 将一个复杂对象的构建与它的表示分离, 使得同样的构建过程可以创建不同的表示。。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。
组成
产品
抽象建造者
具体建造者
指挥者
产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个零部件。
抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。
场景
相同的方法,不同的执行顺序,产生不同的结果。
多个部件或零件,都可以装配到一个对象中,但是产生的结果又不相同。
产品类非常复杂,或者产品类中不同的调用顺序产生不同的作用。
初始化一个对象特别复杂,参数多,而且很多参数都具有默认值。
特点
该模式的主要优点如下:
封装性好,构建和表示分离。
扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
其缺点如下:
产品的组成部分必须相同,这限制了其使用范围。
如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
封装性好,构建和表示分离。
扩展性好,各个具体的建造者相互独立,有利于系统的解耦。
客户端不必知道产品内部组成的细节,建造者可以对创建过程逐步细化,而不对其它模块产生任何影响,便于控制细节风险。
其缺点如下:
产品的组成部分必须相同,这限制了其使用范围。
如果产品的内部变化复杂,如果产品内部发生变化,则建造者也要同步修改,后期维护成本较大。
资料
多例模式
在一个解决方案中结合两个或多个模式, 以解决一般或重复发生的问题
原型模式
当创建给定类的实例过程很昂贵或很复杂时, 就使用原型模式.
场景
创建一个对象成本高(比如需要io获取到,网络获取到,或者计算很多逻辑获取到),但是拥有另外一个大部分数据一直的对象,则可以从已有的对象种直接拷贝。
结构型
主要解决“类或对象的组合”问题
种类
代理模式
适配器模式
将一个类的接口, 转换成客户期望的另一个接口. 适配器让原本接口不兼容的类可以合作无间. 对象适配器使用组合, 类适配器使用多重继承.
桥接模式
使用桥接模式通过将实现和抽象放在两个不同的类层次中而使它们可以独立改变.
“将抽象和实现解耦,让它们可以独立变化。”
装饰者模式
动态地将责任附加到对象上, 若要扩展功能, 装饰者提供了比继承更有弹性的替代方案.
组合模式
允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合.
行为型
主要解决的就是“类或对象之间的交互”问题
种类
观察者模式
模板模式
策略模式
职责链模式
迭代器模式
状态模式
访问者模式
备忘录模式
命令模式
解释器模式
中介模式
类的关系
依赖
类A当中使用了类B,其中类B是作为类A的方法参数、方法中的局部变量、或者静态方法调用。
关联
类A当中使用了类B作为成员变量;同时类B中也使用了类A作为成员变量。
聚合
组合
继承
实现
0 条评论
下一页