导图社区 JAVA后端知识体系
这是一篇关于JAVA后端知识体系非常详细的思维导图,包括算法设计、SQL、Java、Easypoi、Maven、计算机网络体系结构、Spring Cloud、测试等内容。
编辑于2022-11-11 14:17:09 云南Huzz
算法设计
算法及其复杂度
起泡排序
从前向后逐对检查相邻元素,一旦发现逆序,就交换其位 置----扫描交换 
算法的定义
为了解决某一类问题而设计的一个指令 序列
输入
输出
确定性
任一算法都可以描述为由若干种基本操作组成的序列
可行性
有穷性
对于任何输入,按照算法,经过有穷次基本操作都可以得到正确的输出
时间复杂度
T(n). 对于规模为 n 的任意输 入,算法的运行时间都不会超过 O(f(n))
大Ω记号

Fibonacci 数
 使用迭代方式比较好, 不宜采用二分递归, 其二分递归会进行很多重复的操作
SQL
SQL 指结构化查询语言,全称是 Structured Query Language。 SQL 让您可以访问和处理数据库,包括数据插入、查询、更新和删除 SQL 面向数据库执行查询 SQL 可从数据库取回数据 SQL 可在数据库中插入新的记录 SQL 可更新数据库中的数据 SQL 可从数据库删除记录 SQL 可创建新数据库 SQL 可在数据库中创建新表 SQL 可在数据库中创建存储过程 SQL 可在数据库中创建视图 SQL 可以设置表、存储过程和视图的权限
使用
SELECT DISTINCT
DISTINCT 关键词用于返回唯一不同的值
ORDER BY
ORDER BY column_name,column_name ASC|DESC;
INSERT INTO
第一种形式无需指定要插入数据的列名,只需提供被插入的值即可: INSERT INTO table_name VALUES (value1,value2,value3,...); 第二种形式需要指定列名及被插入的值: INSERT INTO table_name (column1,column2,column3,...) VALUES (value1,value2,value3,...);
UPDATE
UPDATE table_name SET column1=value1,column2=value2,... WHERE some_column=some_value;
SELECT TOP
注意:并非所有的数据库系统都支持 SELECT TOP 语句。 MySQL 支持 LIMIT 语句来选取指定的条数数据, Oracle 可以使用 ROWNUM 来选取。 SQL Server / MS Access 语法 SELECT TOP number|percent column_name(s) FROM table_name; MySQL 语法 SELECT column_name(s) FROM table_name LIMIT number; Oracle 语法 SELECT column_name(s) FROM table_name WHERE ROWNUM <= number;
通配符
在 SQL 中,通配符与 SQL LIKE 操作符一起使用, MySQL 中使用 REGEXP 或 NOT REGEXP 运算符 (或 RLIKE 和 NOT RLIKE) 来操作正则表达式  下面的 SQL 语句选取 name 不以 A 到 H 字母开头的网站: 实例 SELECT * FROM Websites WHERE name REGEXP '^[^A-H]';
BETWEEN
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期
连接
INNER JOIN
SELECT column_name(s) FROM table1 INNER JOIN table2 ON table1.column_name=table2.column_name; 
LEFT JOIN
SELECT column_name(s) FROM table1 LEFT JOIN table2 ON table1.column_name=table2.column_name; 
FULL OUTER JOIN
并集 SELECT column_name(s) FROM table1 FULL OUTER JOIN table2 ON table1.column_name=table2.column_name; 
UNION
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。 请注意,UNION 内部的每个 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每个 SELECT 语句中的列的顺序必须相同。 SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2; 如果允许重复的值,请使用 UNION ALL: SELECT column_name(s) FROM table1 UNION ALL SELECT column_name(s) FROM table2;
SELECT INTO
从一个表复制信息到另一个表 注意: MySQL 数据库不支持 SELECT ... INTO 语句,但支持 INSERT INTO ... SELECT SELECT column_name(s) INTO newtable FROM table1;
CREATE DATABASE
CREATE DATABASE dbname
CREATE TABLE
CREATE TABLE table_name ( column_name1 data_type(size), column_name2 data_type(size), column_name3 data_type(size), .... );
数据类型
约束(Constraints)
SQL 约束用于规定表中的数据规则。 如果存在违反约束的数据行为,行为会被约束终止。 约束可以在创建表时规定(通过 CREATE TABLE 语句),或者在表创建之后规定(通过 ALTER TABLE 语句) CREATE TABLE table_name ( column_name1 data_type(size) constraint_name, column_name2 data_type(size) constraint_name, column_name3 data_type(size) constraint_name, .... );
NOT NULL
指示某列不能存储 NULL 值 CREATE TABLE Persons ( ID int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255) NOT NULL, Age int );
UNIQUE
保证某列的每行必须有唯一的值 MySQL: CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), UNIQUE (P_Id) ) SQL Server / Oracle / MS Access: CREATE TABLE Persons ( P_Id int NOT NULL UNIQUE, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) ) 如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName) ) ALTER TABLE 时的 SQL UNIQUE 约束 当表已被创建时,如需在 "P_Id" 列创建 UNIQUE 约束,请使用下面的 SQL: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Persons ADD UNIQUE (P_Id) 如需命名 UNIQUE 约束,并定义多个列的 UNIQUE 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Persons ADD CONSTRAINT uc_PersonID UNIQUE (P_Id,LastName) 撤销 UNIQUE 约束 如需撤销 UNIQUE 约束,请使用下面的 SQL: MySQL: ALTER TABLE Persons DROP INDEX uc_PersonID SQL Server / Oracle / MS Access: ALTER TABLE Persons DROP CONSTRAINT uc_PersonID
PRIMARY KEY
NOT NULL 和 UNIQUE 的结合。确保某列(或两个列多个列的结合)有唯一标识,有助于更容易更快速地找到表中的一个特定的记录 MySQL: CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), PRIMARY KEY (P_Id) ) SQL Server / Oracle / MS Access: CREATE TABLE Persons ( P_Id int NOT NULL PRIMARY KEY, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) ) 如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName) ) ALTER TABLE 时的 SQL PRIMARY KEY 约束 当表已被创建时,如需在 "P_Id" 列创建 PRIMARY KEY 约束,请使用下面的 SQL: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Persons ADD PRIMARY KEY (P_Id) 如需命名 PRIMARY KEY 约束,并定义多个列的 PRIMARY KEY 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Persons ADD CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName) 撤销 PRIMARY KEY 约束 如需撤销 PRIMARY KEY 约束,请使用下面的 SQL: MySQL: ALTER TABLE Persons DROP PRIMARY KEY SQL Server / Oracle / MS Access: ALTER TABLE Persons DROP CONSTRAINT pk_PersonID
FOREIGN KEY
保证一个表中的数据匹配另一个表中的值的参照完整性 CREATE TABLE 时的 SQL FOREIGN KEY 约束 下面的 SQL 在 "Orders" 表创建时在 "P_Id" 列上创建 FOREIGN KEY 约束: MySQL: CREATE TABLE Orders ( O_Id int NOT NULL, OrderNo int NOT NULL, P_Id int, PRIMARY KEY (O_Id), FOREIGN KEY (P_Id) REFERENCES Persons(P_Id) ) SQL Server / Oracle / MS Access: CREATE TABLE Orders ( O_Id int NOT NULL PRIMARY KEY, OrderNo int NOT NULL, P_Id int FOREIGN KEY REFERENCES Persons(P_Id) ) 如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: CREATE TABLE Orders ( O_Id int NOT NULL, OrderNo int NOT NULL, P_Id int, PRIMARY KEY (O_Id), CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id) REFERENCES Persons(P_Id) ) ALTER TABLE 时的 SQL FOREIGN KEY 约束 当 "Orders" 表已被创建时,如需在 "P_Id" 列创建 FOREIGN KEY 约束,请使用下面的 SQL: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Orders ADD FOREIGN KEY (P_Id) REFERENCES Persons(P_Id) 如需命名 FOREIGN KEY 约束,并定义多个列的 FOREIGN KEY 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Orders ADD CONSTRAINT fk_PerOrders FOREIGN KEY (P_Id) REFERENCES Persons(P_Id) 撤销 FOREIGN KEY 约束 如需撤销 FOREIGN KEY 约束,请使用下面的 SQL: MySQL: ALTER TABLE Orders DROP FOREIGN KEY fk_PerOrders SQL Server / Oracle / MS Access: ALTER TABLE Orders DROP CONSTRAINT fk_PerOrders
CHECK
保证列中的值符合指定的条件 CREATE TABLE 时的 SQL CHECK 约束 下面的 SQL 在 "Persons" 表创建时在 "P_Id" 列上创建 CHECK 约束。CHECK 约束规定 "P_Id" 列必须只包含大于 0 的整数。 MySQL: CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CHECK (P_Id>0) ) SQL Server / Oracle / MS Access: CREATE TABLE Persons ( P_Id int NOT NULL CHECK (P_Id>0), LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) ) 如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes') ) ALTER TABLE 时的 SQL CHECK 约束 当表已被创建时,如需在 "P_Id" 列创建 CHECK 约束,请使用下面的 SQL: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Persons ADD CHECK (P_Id>0) 如需命名 CHECK 约束,并定义多个列的 CHECK 约束,请使用下面的 SQL 语法: MySQL / SQL Server / Oracle / MS Access: ALTER TABLE Persons ADD CONSTRAINT chk_Person CHECK (P_Id>0 AND City='Sandnes') 撤销 CHECK 约束 如需撤销 CHECK 约束,请使用下面的 SQL: SQL Server / Oracle / MS Access: ALTER TABLE Persons DROP CONSTRAINT chk_Person MySQL: ALTER TABLE Persons DROP CHECK chk_Person
DEFAULT
规定没有给列赋值时的默认值 CREATE TABLE 时的 SQL DEFAULT 约束 下面的 SQL 在 "Persons" 表创建时在 "City" 列上创建 DEFAULT 约束: My SQL / SQL Server / Oracle / MS Access: CREATE TABLE Persons ( P_Id int NOT NULL, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) DEFAULT 'Sandnes' ) 通过使用类似 GETDATE() 这样的函数,DEFAULT 约束也可以用于插入系统值: CREATE TABLE Orders ( O_Id int NOT NULL, OrderNo int NOT NULL, P_Id int, OrderDate date DEFAULT GETDATE() ) ALTER TABLE 时的 SQL DEFAULT 约束 当表已被创建时,如需在 "City" 列创建 DEFAULT 约束,请使用下面的 SQL: MySQL: ALTER TABLE Persons ALTER City SET DEFAULT 'SANDNES' SQL Server / MS Access: ALTER TABLE Persons ADD CONSTRAINT ab_c DEFAULT 'SANDNES' for City Oracle: ALTER TABLE Persons MODIFY City DEFAULT 'SANDNES' 撤销 DEFAULT 约束 如需撤销 DEFAULT 约束,请使用下面的 SQL: MySQL: ALTER TABLE Persons ALTER City DROP DEFAULT SQL Server / Oracle / MS Access: ALTER TABLE Persons ALTER COLUMN City DROP DEFAULT
索引
更新一个包含索引的表需要比更新一个没有索引的表花费更多的时间,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引
CREATE INDEX
在表上创建一个简单的索引。允许使用重复的值: CREATE INDEX index_name ON table_name (column_name)
CREATE UNIQUE INDEX
在表上创建一个唯一的索引。不允许使用重复的值:唯一的索引意味着两个行不能拥有相同的索引值。Creates a unique index on a table. Duplicate values are not allowed: CREATE UNIQUE INDEX index_name ON table_name (column_name)
撤销
DROP INDEX
用于 MS Access 的 DROP INDEX 语法: DROP INDEX index_name ON table_name 用于 MS SQL Server 的 DROP INDEX 语法: DROP INDEX table_name.index_name 用于 DB2/Oracle 的 DROP INDEX 语法: DROP INDEX index_name 用于 MySQL 的 DROP INDEX 语法: ALTER TABLE table_name DROP INDEX index_name
DROP TABLE
DROP TABLE 语句用于删除表。 DROP TABLE table_name
DROP DATABASE
DROP DATABASE 语句用于删除数据库。 DROP DATABASE database_name
TRUNCATE TABLE
仅仅需要删除表内的数据,但并不删除表本身 TRUNCATE TABLE table_name
ALTER TABLE
ALTER TABLE 语句用于在已有的表中添加、删除或修改列。 SQL ALTER TABLE 语法 如需在表中添加列,请使用下面的语法: ALTER TABLE table_name ADD column_name datatype 如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式): ALTER TABLE table_name DROP COLUMN column_name 要改变表中列的数据类型,请使用下面的语法: SQL Server / MS Access: ALTER TABLE table_name ALTER COLUMN column_name datatype My SQL / Oracle: ALTER TABLE table_name MODIFY COLUMN column_name datatype Oracle 10G 之后版本: ALTER TABLE table_name MODIFY column_name datatype;
AUTO INCREMENT
用于 MySQL 的语法 下面的 SQL 语句把 "Persons" 表中的 "ID" 列定义为 auto-increment 主键字段: CREATE TABLE Persons ( ID int NOT NULL AUTO_INCREMENT, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255), PRIMARY KEY (ID) ) 用于 SQL Server 的语法 下面的 SQL 语句把 "Persons" 表中的 "ID" 列定义为 auto-increment 主键字段: CREATE TABLE Persons ( ID int IDENTITY(1,1) PRIMARY KEY, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) ) 用于 Access 的语法 下面的 SQL 语句把 "Persons" 表中的 "ID" 列定义为 auto-increment 主键字段: CREATE TABLE Persons ( ID Integer PRIMARY KEY AUTOINCREMENT, LastName varchar(255) NOT NULL, FirstName varchar(255), Address varchar(255), City varchar(255) ) 用于 Oracle 的语法 在 Oracle 中,代码稍微复杂一点。 您必须通过 sequence 对象(该对象生成数字序列)创建 auto-increment 字段。 请使用下面的 CREATE SEQUENCE 语法: CREATE SEQUENCE seq_person MINVALUE 1 START WITH 1 INCREMENT BY 1 CACHE 10
视图
视图总是显示最新的数据!每当用户查询视图时,数据库引擎通过使用视图的 SQL 语句重建数据
CREATE VIEW
CREATE VIEW [Current Product List] AS SELECT ProductID,ProductName FROM Products WHERE Discontinued=No
更新视图
CREATE OR REPLACE VIEW view_name AS SELECT column_name(s) FROM table_name WHERE condition
撤销
DROP VIEW view_name
SQL 日期
Date 函数
MySQL
返回当前的日期和时间
NOW()
返回当前的日期
CURDATE()
返回当前的时间
CURTIME()
提取日期或日期/时间表达式的日期部分
DATE()
返回日期/时间的单独部分
EXTRACT()
向日期添加指定的时间间隔
DATE_ADD()
从日期减去指定的时间间隔
DATE_SUB()
返回两个日期之间的天数
DATEDIFF()
用不同的格式显示日期/时间
DATE_FORMAT()
SQL Server
返回当前的日期和时间
GETDATE()
返回日期/时间的单独部分
DATEPART()
在日期中添加或减去指定的时间间隔
DATEADD()
返回两个日期之间的时间
DATEDIFF()
用不同的格式显示日期/时间
CONVERT()
SQL Date 数据类型
MySQL
DATE
YYYY-MM-DD
DATETIME
YYYY-MM-DD HH:MM:SS
TIMESTAMP
YYYY-MM-DD HH:MM:SS
YEAR
YYYY 或 YY
SQL Server
DATE
YYYY-MM-DD
DATETIME
YYYY-MM-DD HH:MM:SS
SMALLDATETIME
YYYY-MM-DD HH:MM:SS
TIMESTAMP
唯一的数字
函数
AVG()
AVG() 函数返回数值列的平均值。 SELECT AVG(column_name) FROM table_name
COUNT()
COUNT() 函数返回匹配指定条件的行数。 SQL COUNT(column_name) 语法 COUNT(column_name) 函数返回指定列的值的数目(NULL 不计入): SELECT COUNT(column_name) FROM table_name; SQL COUNT(*) 语法 COUNT(*) 函数返回表中的记录数: SELECT COUNT(*) FROM table_name; SQL COUNT(DISTINCT column_name) 语法 COUNT(DISTINCT column_name) 函数返回指定列的不同值的数目: SELECT COUNT(DISTINCT column_name) FROM table_name;
FIRST()
FIRST() 函数返回指定的列中第一个记录的值。 SQL FIRST() 语法 SELECT FIRST(column_name) FROM table_name;
LAST()
LAST() 函数返回指定的列中最后一个记录的值。 SQL LAST() 语法 SELECT LAST(column_name) FROM table_name; 注释:只有 MS Access 支持 LAST() 函数。
MAX()
MAX() 函数返回指定列的最大值。 SQL MAX() 语法 SELECT MAX(column_name) FROM table_name;
MIN()
SELECT MIN(column_name) FROM table_name;
GROUP BY
GROUP BY 语句用于结合聚合函数,根据一个或多个列对结果集进行分组。 SQL GROUP BY 语法 SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name;
HAVING
在 SQL 中增加 HAVING 子句原因是,WHERE 关键字无法与聚合函数一起使用。 HAVING 子句可以让我们筛选分组后的各组数据 SELECT column_name, aggregate_function(column_name) FROM table_name WHERE column_name operator value GROUP BY column_name HAVING aggregate_function(column_name) operator value;
EXISTS
EXISTS 运算符用于判断查询子句是否有记录,如果有一条或多条记录存在返回 True,否则返回 False。 SQL EXISTS 语法 SELECT column_name(s) FROM table_name WHERE EXISTS (SELECT column_name FROM table_name WHERE condition);
UCASE()
UCASE() 函数把字段的值转换为大写。 SELECT UCASE(column_name) FROM table_name;
LCASE()
LCASE() 函数把字段的值转换为小写。 SQL LCASE() 语法 SELECT LCASE(column_name) FROM table_name;
MID()
MID() 函数用于从文本字段中提取字符。 SQL MID() 语法 SELECT MID(column_name,start[,length]) FROM table_name; 参数 描述 column_name 必需。要提取字符的字段。 start 必需。规定开始位置(起始值是 1)。 length 可选。要返回的字符数。如果省略,则 MID() 函数返回剩余文本。
LEN()
LEN() 函数返回文本字段中值的长度。 SQL LEN() 语法 SELECT LEN(column_name) FROM table_name; MySQL 中函数为 LENGTH(): SELECT LENGTH(column_name) FROM table_name;
ROUND()
ROUND() 函数用于把数值字段舍入为指定的小数位数。 SQL ROUND() 语法 SELECT ROUND(column_name,decimals) FROM TABLE_NAME; 参数 描述 column_name 必需。要舍入的字段。 decimals 可选。规定要返回的小数位数。
NOW()
NOW() 函数返回当前系统的日期和时间。 SQL NOW() 语法 SELECT NOW() FROM table_name;
FORMAT()
FORMAT() 函数用于对字段的显示进行格式化 SELECT FORMAT(column_name,format) FROM table_name; 参数 描述 column_name 必需。要格式化的字段。 format 必需。规定格式。
Java
概述
编程
让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程
什么是Java
1. 面向对象编程; 2. 摒弃多继承、指针
三大版本
Java SE
标准版. 桌面、服务器、嵌入式环境和实时环境
Java EE
企业版. 可移植、健壮、可伸缩且安全的服务器端
Java ME
微型版. 移动设备和嵌入式设备
JVM、JRE、JDK
JVM
Java虚拟机. 实现跨平台
JDK
开发工具. 无需再单独安装JRE, 编译工具(javac.exe),打包工具(jar.exe)
JRE
Java虚拟机&核心类库(java.lang.*)
跨平台性
一次编译, 多处运行
java特点
简单
面向对象
封装
继承
多态
安全性
健壮性
强类型机制
异常处理
垃圾回收机制
多线程
网络编程
平台无关性
字节码
编译器编译后产生的文件(.class). 不面向任何特定的处理器,只面向虚拟机
编译器和解释器
编译器
面向虚拟机, 生成字节码
解释器
面向处理器, 生成机器码
java & C++比较
都支持封装、继承和多态
java不提供指针来直接访问内存,程序内存更加安全
Java的类是单继承的,C++支持多重继承
Java有自动内存管理机制
Oracle JDK & OpenJDK
Oracle JDK每三年发布一次,OpenJDK每三个月发布一次
Oracle JDK是OpenJDK的一个实现,并不是完全开源
Oracle JDK 比 OpenJDK 更稳定
基础语法
数据类型
基本数据类型
数值型
整型
byte (1)
字节型. 默认: 0 取值范围: -2^7 ~ 2^7-1
short (2)
短整型. 默认: 0 取值范围: -2^15 ~ 2^15-1
int (4)
long (8)
注意: 不能用作swith的参数
浮点型
float (4)
默认: 0.0F
double (8)
默认: 0.0D
字符型
char (2)
默认: '\u0000'
布尔型
boolean (1bit)
默认: false
引用数据类型
类
接口
数组
编码
Unicode编码 (标准码) 每个字符制订了一个唯一的数值
注释
编译的时候会被忽视,不会产生目标代码
单行注释 // xxxx
多行注释 /* xxxx */
文档注释 /** xxxx */
访问修饰符
保护对类、变量、方法和构造方法的访问
protected
同一包下可见 (子类可见)
public
到处可见 (子类可见)
不写(默认)
同一包下可见 (子类不可见)
private
同一个类下可见 (子类不可见)
运算符
& 按位与
&& 逻辑与
短路与运算
| 按位或
|| 逻辑或
关键字
final
被final修饰的类不能被继承
被final修饰的方法不能被重写
被final修饰的变量不能被改变
this
指向对象本身的一个指针
super
指向超类(父类)的一个指针
static
即使没有创建对象,也能使用属性和调用方法. 用来形成静态代码块以优化程序性能. 类初次被加载的时候,会按照static块的顺序来执行每个static块,并且只会执行一次. 注意: 1、静态只能访问静态 2、非静态既可以访问非静态的,也可以访问静态的
流程控制语句
break
要想跳出多重循环,可以在外面的循环语句前定义一个标号, 在里层循环体的代码中使用带有标号的break 语句,即可跳出外层循环. 例如: ok: for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { System.out.println("i=" + i + ",j=" + j); if (j == 5) { break ok; } } }
continue
return
面向对象
面向对象 & 面向过程
面向过程
性能好
不易复用, 不易扩展, 不易维护
面向对象
性能较低
低耦合
灵活 (易复用, 易扩展, 易维护)
三大特性
封装, 继承, 多态
抽象
共同特征抽取
封装
属性私有化. 提供一些可以被外界访问的属性的方法
继承
使用已存在的类作为基础, 建立新类
多态
一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定 实现多态有三个必要条件:继承、重写、向上转型
五大基本原则
单一职责原则
类功能要单一
开放封闭原则
模块 对扩张开发, 对修改封闭
里氏替换原则
子类代表父类出席
依赖倒置原则
高层次不依赖低层次, 抽象不依赖具体 低层次依赖于高层次, 具体依赖于抽象
接口分离原则
多个功能写成一个通用的接口, 不如一个功能就定义一个接口
抽象类与接口
抽象类
用来捕捉子类的通用特性
接口
抽象方法的集合. 行为的抽象,是一种行为的规范
相同点
不能实例化
位于继承的顶端
子类都必须覆写抽象方法
变量
成员变量
作用域: 类中有效 存储位置: 堆内存中 生命周期: 对象创建而创建, 对象销毁而释放
局部变量
作用域: 范围内有效 存储位置: 栈内存中 生命周期: 方法调用完,或语句结束后,自动释放
静态变量 & 实例变量
静态变量
内存中只会有一份. JVM只为静态变量分配一次内存空间
实例变量
创建实例时被创建, 创建了多少次实例, 就被迫创建多少次
内部类
内部类本身就是类的一个属性. 1. 方便的定义回调 2. 具有很好的封装性 3. 优化 java 单继承的缺陷 应用场景 1. 一些多算法场合 2. 解决一些非面向对象的语句块。 3. 适当使用内部类,使得代码更加灵活和富有扩展性。 4. 当某个类除了它的外部类,不再被其他的类使用时。 局部内部类和匿名内部类访问局部变量的时候,为什么变量必须要加上final 因为生命周期不一致, 局部变量直接存储在栈中,当方法执行结束后,非final的局部变量就被销毁。而局部内部类对局部变量的引用依然存在,如果局部内部类要调用局部变量时,就会出错
静态内部类
可以访问外部类所有的静态变量
成员内部类
可以访问外部类所有的变量和方法,包括静态和非静态,私有和公有 class Inner { public void visit() { System.out.println("visit outer static variable:" + radius); System.out.println("visit outer variable:" + count); } } // 创建 Inner inner = new HuzzTest().new Inner();
局部内部类
定义在方法中的内部类. 定义在实例方法中的局部类可以访问外部类的所有变量和方法,定义在静态方法中的局部类只能访问外部类的静态变量和方法。局部内部类的创建方式,在对应方法内,new 内部类(),如下: public static void testStaticFunctionClass(){ class Inner { } Inner inner = new Inner(); }
匿名内部类
匿名内部类必须继承一个抽象类或者实现一个接口; 匿名内部类不能定义任何静态成员和静态方法; 当所在的方法的形参需要被匿名内部类使用时,必须声明为 final; 匿名内部类不能是抽象的,它必须要实现继承的类或者实现的接口的所有抽象方法。
重写与重载
重写
方法名、参数列表相同 返回值小于等于父类 抛出异常小于等于父类 访问修饰符大于等于父类(里氏代换原则)
重载
相同参数列表不同(参数类型不同、个数不同、顺序不同) 重载的方法不能根据返回类型进行区分
对象相等判断
==
判断两个对象的地址是不是相等 判断两个对象是不是同一个对象。(基本数据类型 == 比较的是值,引用数据类型 == 比较的是内存地址)
equals()
判断两个对象是否相等
不覆盖 equals()
等价于通过“==”比较这两个对象
覆盖 equals()
若返回 true认为这两个对象相等
String的比较
String中的equals方法是被重写过的,因为object的equals方法是比较的对象的内存地址,而String的equals方法比较的是对象的值 当创建String类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个String对象
hashCode
散列码 返回一个int整数---------确定------->该对象在哈希表中的索引位置 例: HashSet 如何检查重复? 当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashcode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashcode 值作比较,如果没有相符的hashcode,HashSet会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调用 equals()方法来检查 hashcode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。 hashCode()与equals()的相关规定 如果两个对象相等,则hashcode一定也是相同的 两个对象相等,对两个对象分别调用equals方法都返回true 两个对象有相同的hashcode值,它们也不一定是相等的 因此,equals 方法被覆盖过,则 hashCode 方法也必须被覆盖
值传递
java只支持参数的值传递 方法得到的是所有参数值的一个拷贝 当一个对象实例作为一个参数被传递到方法中时,参数的值就是对该对象的引用的值拷贝
Java包
java.lang
基础类
java.io
所有输入输出
java.nio
完善 io 包中的功能,提高 io 包中性能
java.net
网络
java.util
系统辅助类,特别是集合类
java.sql
数据库操作
IO流
分类
流向
输入流
输出流
操作单元
字节流
字符流
流的角色
节点流
处理流
抽象类基类
输入流
InputStream
字节输入流
节点流
FileInputStream
PipedInputStream
ByteArrayInputStream
处理流
BufferedInputStream
DataInputStream
ObjectInputStream
SequenceInputStream
Reader
字符输入流
节点流
FileReader
PipedReader
CharArrayReader
处理流
BufferedReader
InputStreamReader
输出流
OutputStream
字节输出流
节点流
FileOutputStream
PipedOutputStream
ByteArrayOutputStream
处理流
BufferedOutputStream
DataOutputStream
ObjectOutputStream
PrintStream
Writer
字符输出流
节点流
FileWriter
PipedWriter
CharArrayWriter
处理流
BufferedWriter
OutputStreamWriter
PrintWriter
按操作划分
缓冲操作
BufferedInputStream
BufferedOutputStream
BufferedReader
BufferedWriter
基本数据类型操作
DataInputStream
DataOutputStream
对象序列化操作
ObjectInputStream
ObjectOutputStream
转化控制
InputStreamReader
OutputStreamWriter
打印控制
PrintStream
PrintWriter
文件操作
FileInputStream
FileOutputStream
FileReader
FileWriter
管道操作
PipedInputStream
PipedOutputStream
PipedReader
PipedWriter
数组操作
ByteArrayInputStream
ByteArrayOutputStream
CharArrayReader
CharArrayWriter
BIO,NIO,AIO
BIO (Blocking I/O)
同步阻塞I/O模式 读取写入必须阻塞在一个线程内等待其完成
NIO (New I/O)
同步非阻塞的I/O模型
AIO (Asynchronous I/O)
改进版 NIO 2 异步非阻塞的IO模型
Files的常用方法
Files. exists()
Files. createFile()
Files. createDirectory()
Files. delete()
Files. copy()
Files. move()
Files. size()
Files. read()
Files. write()
反射
动态获取的信息及动态调用对象的方法的功能称为java语言的反射机制
静态编译和动态编译
静态编译
在编译时确定类型,绑定对象
动态编译
运行时确定类型,绑定对象
反射机制优缺点
优点
动态加载类,提高代码灵活度
缺点
性能瓶颈:反射相当于一系列解释操作,通知 JVM 要做的事情,性能比直接的java代码要慢很多
应用场景
模块化的开发 动态代理 JDBC连接数据库时使用Class.forName()通过反射加载数据库的驱动程序
获取反射
通过new对象
Student stu = new Student(); Class classobj1 = stu.getClass();
通过路径
Class classobj2 = Class.forName("fanshe.Student");
通过类名
Class classobj3 = Student.class;
网络编程
常用API
String相关
字符型常量和字符串常量
字符常量
单引号引起的一个字符
相当于一个整形值(ASCII值),可以参加表达式运算
字符串常量
双引号引起的若干个字符
代表一个地址值(该字符串在内存中存放位置)
字符串常量池
String 底层就是一个 char 类型的数组
位于堆内存中,专门用来存储字符串常量
提高内存的使用率,避免开辟多块空间存储相同的字符串
创建字符串时 JVM 会首先检查字符串常量池,如果该字符串已经存在池中,则返回它的引用,如果不存在,则实例化一个字符串放到池中
String特性
不变性
String 是只读字符串,是一个典型的 immutable 对象,对它进行任何操作,其实都是创建一个新的对象,再把引用指向该对象
常量池优化
String 对象创建之后,会在字符串常量池中进行缓存,如果下次创建同样的对象时,会直接返回缓存的引用
final
使用 final 来定义 String 类,表示 String 类不能被继承,提高了系统的安全性
分配方式
String str="xyz"
分配到常量池中
String s = new String(“xyz”)
分到堆内存中
创建2个字符串对象
静态区的"xyz"
创建在堆上的对象
String 类的常用方法
indexOf()
返回指定字符的索引
charAt()
返回指定索引处的字符
replace()
字符串替换
trim()
去除字符串两端空白
split()
分割字符串,返回一个分割后的字符串数组
getBytes()
返回字符串的 byte 类型数组
length()
返回字符串长度
toLowerCase()
将字符串转成小写字母
toUpperCase()
将字符串转成大写字符
substring()
截取字符串
equals()
字符串比较
用 String 做HashMap的 key
因为字符串是不可变的,所以当创建字符串时,它的 hashcode 被缓存下来,不需要再次计算,所以相比于其他对象更快
String和StringBuffer、StringBuilder
可变性
string对象底层数组被final修饰导致不可变
线程安全性
String中的对象是不可变, 是常量,线程安全
StringBuffer对调用的方法加了同步锁,线程安全
StringBuilder并没有对方法进行加同步锁,非线程安全
性能
如果要操作少量的数据用 = String
单线程操作字符串缓冲区 下操作大量数据 = StringBuilder
多线程操作字符串缓冲区 下操作大量数据 = StringBuffer
Date相关
包装类相关
自动装箱与拆箱
装箱
将基本类型用它们对应的引用类型包装起来
拆箱
将包装类型转换为基本数据类型
Integer a= 127 与 Integer b = 127
对于对象引用类型:==比较的是对象的内存地址 对于基本数据类型:==比较的是值
如果整型字面量的值在-128到127之间,那么自动装箱时不会new新的Integer对象,而是直接引用常量池中的Integer对象,超过范围 a1==b1的结果是false
常用工具类库
单元测试
日志
Java8
Stream接口
每个Stream都有两种模式: 顺序执行(stream), 并行执行(parallelStream) # 当使用顺序方式去遍历时,每个item读完后再读下一个item; # 使用并行去遍历时,数组会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出
Stream<T> filter(Predicate<? super T> predicate)
返回由与给定谓词匹配的此流的元素组成的流 参数: predicate – 一个无干扰的、无状态的谓词,应用于每个元素以确定是否应该包含它
Stream<R> map(Function<? super T, ? extends R> mapper)
返回由将给定函数应用于此流的元素的结果组成的流 参数: mapper – 一个无干扰、无状态的函数,应用于每个元素
Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
多个Stream连接成一个Stream. List<Integer> result= Stream.of(Arrays.asList(1,3),Arrays.asList(5,6)).flatMap(a->a.stream()).collect(Collectors.toList());
Stream<T> distinct()
去重. 在并行管道中保持distinct()的稳定性相对昂贵
Stream<T> sorted()
排序. 对于有序流,排序是稳定的。 对于无序流,不保证稳定性
void forEach(Consumer<? super T> action)
遍历
函数式接口
[消费型函数式接口] 三种类型: 1. 唯一的抽象方法, 2. 使用default定义普通方法,3. 使用static定义静态方法. 一个新的注解: @FunctionInterface 某一个接口就是为了函数式接口而生
Function
接受一个输入参数T,返回一个结果R
R apply(T t)
接受输入参数,对输入执行所需操作后 返回一个结果
Function<V, R> compose(Function<? super V, ? extends T> before)
先执行before函数对象apply方法,再执行当前函数对象apply方法
Function<T, V> andThen(Function<? super R, ? extends V> after)
先执行当前函数对象apply方法, 再执行after函数对象apply方法
Function<T, T> identity()
返回一个执行了apply()方法之后只会返回输入参数的函数对象
Consumer
[消费型函数式接口] 接受一个输入参数并且无返回的操作
void accept(T t)
Consumer<T> andThen(Consumer<? super T> after)
Predicate
[断言型函数式接口] 返回一个布尔值结果.
boolean test(T t)
如果输入参数与谓词匹配,则为true ,否则为false
default Predicate<T> and(Predicate<? super T> other)
谓词连接 与
default Predicate<T> or(Predicate<? super T> other)
谓词连接 或
Predicate<T> negate()
表示此谓词的逻辑否定的谓词
Predicate<T> isEqual(Object targetRef)
测试两个参数是否相等
Supplier
供给型函数式接口
T get()
得到结果
集合
存储数据的容器
特点
用于存储对象
可变长度
集合和数组的区别
数组是固定长度的;集合可变长度的
数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型
数组存储的元素必须是同一个数据类型;集合存储的对象可以是不同数据类型
集合框架的好处
容量自增长
方便地扩展或改写集合,提高代码复用性和可操作性
提高了程序速度和质量
常用的集合类
Map接口和Collection接口是所有集合框架的父接口
Collection接口
Set接口
无序, 不可重复, 一个可null
HashSet
TreeSet
有序
LinkedHashSet
List接口
有序, 可重复, 多个可null
ArrayList
LinkedList
Stack
Vector
Queue
BlockingQueue
DeQue
Map接口
Key无序,唯一;value 不要求有序,允许重复
HashMap
TreeMap
Hashtable
ConcurrentHashMap
Properties
底层数据结构
List
Arraylist: Object数组
扩容每次增加 50%
Vector: Object数组
扩容每次会增加 1 倍
LinkedList: 双向循环链表
Set
1. set只能用迭代,因为他无序,无法用下标来取得想要的值; 2. 检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变
HashSet: 采用 HashMap 来保存元素
LinkedHashSet: LinkedHashSet 继承HashSet,通过 LinkedHashMap 实现
TreeSet
红黑树(自平衡的排序二叉树
Map
HashMap: 由数组+链表组成,当链表长度大于阈值,链表转化为红黑树
LinkedHashMap: 继承自 HashMap, 在HashMap的基础上增加了一条双向链表,使得保持键值对的插入顺序
线程安全
vector
比arraylist多了个同步化机制, 效率较低
statck
堆栈, 先进后出
HashTable
比HashMap多了个线程安全
enumeration
枚举,相当于迭代器
Collection接口
迭代器 Iterator: 提供遍历任何 Collection 的接口
List接口
Iterator
遍历 Set 和 List 集合
ListIterator
只能遍历 List, 可以双向遍历
遍历
for 循环遍历
迭代器遍历
foreach 循环遍历
采用了 Iterator 的方式实现
不能在遍历过程中操作数据集合
数组和 List 之间的转换
数组转 List
Arrays. asList(array)
List 转数组
toArray()
Set接口
基于 HashMap 实现
值存放于HashMap的key
检查重复
比较hash值
结合equles
HashSet与HashMap的区别

Queue
出队
poll()
返回第一个元素, 删除返回的对象. 如果没有元素返回 null
remove()
返回第一个元素, 删除返回的对象. 如果没有元素抛出 NoSuchElementException
Map接口
HashMap 的实现原理
1. 往HashMap中put元素时, 利用key的hashCode重新hash计算出当前对象的元素在数组中的下标
2. 若出现hash值相同的key. 如果key相同,则覆盖原始值;如果key不同(出现冲突),则将当前的key-value放入链表中
3. 获取时,直接找到hash值对应的下标,在进一步判断key是否相同,从而找到对应值
HashMap 与 HashTable
HashMap
非线程安全
如果需要多线程使用则用 ConcurrentHashMap 替代
效率高一点
null 可以作为1个键
HashTable
线程安全
基本被淘汰
null 不可以作为键
TreeMap
有序的key集合
ConcurrentHashMap
对整个桶数组进行了分割分段(Segment), 在每一个分段上都用lock锁进行保护
键值对不允许有null
Easypoi
1. 基于注解的导入导出,修改注解就可以修改Excel 2. 支持常用的样式自定义 3. 基于map可以灵活定义的表头字段 4. 支持一对多的导出,导入 5. 支持模板的导出,一些常见的标签,自定义标签 6. 支持HTML/Excel转换,如果模板还不能满足用户的变态需求,请用这个功能 7. 支持word的导出,支持图片,Excel
使用
1. easypoi 父包–作用大家都懂得 2. easypoi-annotation 基础注解包,作用与实体对象上,拆分后方便maven多工程的依赖管理 3. easypoi-base 导入导出的工具包,可以完成Excel导出,导入,Word的导出,Excel的导出功能 4. easypoi-web 耦合了spring-mvc 基于AbstractView,极大的简化spring-mvc下的导出功能 5. sax 导入使用xercesImpl这个包(这个包可能造成奇怪的问题哈),word导出使用poi-scratchpad,都作为可选包了
坐标
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>4.1.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>4.1.0</version> </dependency>
Spring Boot
<dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-spring-boot-starter</artifactId> <version>4.0.0</version> </dependency>
注解
@Excel 作用到filed上面,是对Excel一列的一个描述 @ExcelCollection 表示一个集合,主要针对一对多的导出,比如一个老师对应多个科目,科目就可以用集合表示 @ExcelEntity 表示一个继续深入导出的实体,但他没有太多的实际意义,只是告诉系统这个对象里面同样有导出的字段 @ExcelIgnore 和名字一样表示这个字段被忽略跳过这个导导出 @ExcelTarget 这个是作用于最外层的对象,描述这个对象的id,以便支持一个对象可以针对不同导出做出不同处理
@Excel
1. 基础 2. 图片处理 3. 时间处理 4. 合并处理
属性
name
类型
String
默认值
null
功能
列名,支持name_id
needMerge
类型
boolean
默认值
false
功能
纵向合并单元格 (用于含有list中,单个的单元格,合并list创建的多个row)
orderNum
类型
String
默认值
"0"
功能
列排序. 支持name_id
replace
类型
String[]
默认值
{}
功能
值替换 (导出是{a_id,b_id} 导入反过来)
savePath
类型
String
默认值
“upload”
功能
导入文件保存路径,如果是图片可以填写,默认是upload/className/ IconEntity这个类对应的就是upload/Icon/
type
类型
int
默认值
1
功能
导出类型 1 文本 2 图片 3 函数 10 数字 默认是文本
width
类型
double
默认值
10
功能
列宽
height
类型
double
默认值
10
功能
列高 (开发者计划废弃, 而统一使用ExcalTarget的height)
isStatistics
类型
boolean
默认值
false
功能
自动统计数据,在追加一行统计,把所有数据都和输出[这个处理会吞没异常,请注意这一点]
isHyperlink
类型
boolean
默认值
false
功能
超链接,如果是需要实现接口返回对象
ImportField
类型
boolean
默认值
true
功能
校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id
exportFormat
类型
String
默认值
""
功能
导出的时间格式,以这个是否为空来判断是否需要格式化日期
importFormat
类型
String
默认值
""
功能
导入的时间格式,以这个是否为空来判断是否需要格式化日期
format
类型
String
默认值
""
功能
时间格式,相当于同时设置了exportFormat 和 importFormat
databaseFormat
类型
String
默认值
"yyyyMMddHHmmss"
功能
导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出
numFormat
类型
String
默认值
""
功能
数字格式化,参数是Pattern,使用的对象是DecimalFormat
imageType
类型
int
默认值
1
功能
导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的
suffix
类型
String
默认值
""
功能
文字后缀,如% 90 变成90%
isWrap
类型
bollean
默认值
true
功能
换行
mergeRely
类型
int[]
默认值
{}
功能
合并单元格依赖关系,比如第二列合并是基于第一列 则{0}就可以了
mergeVertical
类型
boolean
默认值
false
功能
纵向合并内容相同的单元格
fixedIndex
类型
int
默认值
-1
功能
对应excel的列,忽略名字
isColumnHidden
类型
boolean
默认值
false
功能
导出隐藏列
@ExcelCollection
一对多的集合注解,用以标记集合是否被数据以及集合的整体排序
属性
id
类型
String
默认值
null
功能
定义ID
name
类型
String
默认值
null
功能
定义集合列名列名,支持name_id
orderNum
类型
int
默认值
0
功能
排序,支持name_id
type
类型
Class<?>
默认值
ArrayList.class
功能
导入时创建对象使用
@ExcelEntity
标记是不是导出excel 标记为实体类,一遍是一个内部属性类,标记是否继续穿透,可以自定义内部id
属性
id
类型
String
默认值
null
功能
定义ID
@ExcelIgnore
忽略这个属性
@ExcelTarget
限定一个到处实体的注解,以及一些通用设置,作用于最外面的实体
属性
value
类型
String
默认值
null
功能
定义ID
height
类型
double
默认值
10
功能
设置行高
fontSize
类型
short
默认值
11
功能
设置文字大小
样式 TODO
示例
导出
对象定义
public class StudentEntity implements Serializable { private String id; @Excel(name = "学生姓名", height = 20, width = 30, isImportField = "true_st") private String name; @Excel(name = "学生性别", replace = {"男_1", "女_2"}, suffix = "生", isImportField = "true_st") private int sex; @Excel(name = "出生日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd", isImportField = "true_st", width = 20) private Date birthday; @Excel(name = "进校日期", databaseFormat = "yyyyMMddHHmmss", format = "yyyy-MM-dd") private Date registrationDate; } // 导出 Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("计算机一班学生","学生"), StudentEntity .class, list); 效果: 
集合定义
@ExcelTarget("courseEntity") public class CourseEntity implements Serializable { private String id; @Excel(name = "课程名称", orderNum = "1", needMerge = true, width = 25) private String name; @ExcelEntity(id = "absent") private TeacherEntity mathTeacher; @ExcelCollection(name = "学生", orderNum = "4") private List<StudentEntity> students; } @ExcelTarget("teacherEntity") public class TeacherEntity implements Serializable { private String id; @Excel(name = "主讲老师_major,代课老师_absent", orderNum = "1", needMerge = true, isImportField = "true_major,true_absent") private String name; } 效果: 
图片的导出
从文件中导出
@Excel(name = "公司LOGO", type = 2, width = 40, height = 20, imageType = 1) private String companyLogo; imageType=1 (默认可以不填),表示从file读取,字段类型是个字符串类型 可以用相对路径也可以用绝对路径,绝对路径优先依次获取
从数据库中获取
@Excel(name = "公司LOGO", type = 2, width = 40, height = 20, imageType = 2) private byte[] companyLogo; 表示从数据库或者已经读取完毕,字段类型是个字节数组 直接使用
代码注解导出
基于List 的导出,ExcelExportEntity是注解经过处理翻译成的实体类,两者几乎是一对的,所以如果我们要动态自定义导出列,我们只要动态拼装ExcelExportEntity就可以了
ExcelExportEntity
private Object key; private double width = 10.0D; private double height = 10.0D; private int exportImageType = 0; private int orderNum = 0; private boolean isWrap; private boolean needMerge; private boolean mergeVertical; private int[] mergeRely; private String suffix; private boolean isStatistics; private String numFormat; private boolean isColumnHidden; private String enumExportField; private List<ExcelExportEntity> list;
demo
try { List<ExcelExportEntity> entity = new ArrayList<ExcelExportEntity>(); //构造对象等同于@Excel ExcelExportEntity excelentity = new ExcelExportEntity("姓名", "name"); excelentity.setNeedMerge(true); entity.add(excelentity); entity.add(new ExcelExportEntity("性别", "sex")); excelentity = new ExcelExportEntity(null, "students"); List<ExcelExportEntity> temp = new ArrayList<ExcelExportEntity>(); temp.add(new ExcelExportEntity("姓名", "name")); temp.add(new ExcelExportEntity("性别", "sex")); //构造List等同于@ExcelCollection excelentity.setList(temp); entity.add(excelentity); List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); //把我们构造好的bean对象放到params就可以了 Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("测试", "测试"), entity, list); FileOutputStream fos = new FileOutputStream("D:/excel/ExcelExportForMap.tt.xls"); workbook.write(fos); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
导入
ImportParams
属性
titleRows
类型
int
默认值
0
功能
表格标题行数
headRows
类型
int
默认值
1
功能
表头行数
startRows
类型
int
默认值
0
功能
字段真正值和列标题之间的距离 默认0
keyIndex
类型
int
默认值
0
功能
主键设置,如果这个cell没有值,就跳过 或者认为这个是list的下面的值,这一列必须有值,不然认为这列为无效数据
startSheetIndex
类型
int
默认值
0
功能
开始读取的sheet位置,默认为0
sheetNum
类型
int
默认值
1
功能
上传表格需要读取的sheet 数量,默认为1
needSave
类型
boolean
默认值
false
功能
是否需要保存上传的Excel
needVerfiy
类型
boolean
默认值
false
功能
是否需要校验上传的Excel
saveUrl
类型
String
默认值
“upload/excelUpload”
功能
保存上传的Excel目录,默认是 如 TestEntity这个类保存路径就是upload/excelUpload/Test/yyyyMMddHHmss_ 保存名称上传时间_五位随机数
verifyHanlder
类型
IExcelVerifyHandler
默认值
null
功能
校验处理接口,自定义校验
lastOfInvalidRow
类型
int
默认值
0
功能
最后的无效行数,不读的行数
readRows
类型
int
默认值
0
功能
手动控制读取的行数
importFields
类型
String[]
默认值
null
功能
导入时校验数据模板,是不是正确的Excel
keyMark
类型
String
默认值
“:”
功能
Key-Value 读取标记,以这个为Key,后面一个Cell 为Value,多个改为ArrayList
readSingleCell
类型
boolean
默认值
false
功能
按照Key-Value 规则读取全局扫描Excel,但是跳过List读取范围提升性能,仅仅支持titleRows + headRows + startRows 以及 lastOfInvalidRow
dataHanlder
类型
IExcelDataHandler
默认值
null
功能
数据处理接口,以此为主,replace,format都在这后面
使用示例
ImportParams params = new ImportParams(); params.setTitleRows(1); params.setHeadRows(1); List<MsgClient> list = ExcelImportUtil.importExcel( new File(PoiPublicUtil.getWebRootPath("import/ExcelExportMsgClient.xlsx")), MsgClient.class, params);
map导入
// 不创建实体, 使用Map导入 List<Map<String, Object>> list = ExcelImportUtil.importExcel( new File(PoiPublicUtil.getWebRootPath("import/check.xls")), Map.class, params);
更多
Maven
概述
Maven 是一个项目管理和整合工具 为开发者提供了一套完整的构建生命周期框架 目的是为开发者提供一个可复用、可维护、更易理解的工程综合模型 与这个模型交互的插件或者工具 构建 文档生成 报告 依赖 SCMs 发布 分发 邮件列表
POM
工程对象模型 包含了关于工程和各种配置细节的信息,Maven 使用这些信息构建工程 也包含了目标和插件
配置项
# project dependencies # plugins # goals # build profiles # project version # developers # mailing list
构成
所有的 POM 文件需要 project 元素和三个必须的字段:groupId, artifactId,version
project
根元素
groupId
这是工程组的标识。它在一个组织或者项目中通常是唯一的
artifactId
这是工程的标识。它通常是工程的名称 groupId 和 artifactId 一起定义了 artifact 在仓库中的位置
version
工程的版本号
Super POM
所有的 POM 都继承自一个父 POM 查看super POM默认配置: mvn help:effective-pom
构建生命周期
一组阶段的序列(sequence of phases) 每个阶段定义了目标被执行的顺序 一个典型的 Maven 构建生命周期是由以下几个阶段的序列组成: 
远程存储库
Maven的依赖库查询顺序: 1. 在 Maven 本地资源库中搜索,如果没有找到,进入第 2 步,否则退出。 2. 在 Maven 中央存储库搜索,如果没有找到,进入第 3 步,否则退出。 3. 在java.net Maven的远程存储库搜索,如果没有找到,提示错误信息,否则退出。 // 指明远程存储库 <repositories> <repository> <id>java.net</id> <url>https://maven.java.net/content/repositories/public/</url> </repository> </repositories>
计算机网络体系结构
网络协议
交换数据,就必须遵守一些事先约定好的规则,比如交换数据的格式、是否需要发送一个应答信息。这些规则被称为网络协议
TCP/IP 协议族
应用层
应用层( application-layer )的任务是通过应用进程间的交互来完成特定网络应用。应用层协议定义的是应用进程(进程:主机中正在运行的程序)间的通信和交互的规则。 对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如域名系统 DNS,支持万维网应用的 HTTP 协议,支持电子邮件的 SMTP 协议等等
运输层
运输层(transport layer)的主要任务就是负责向两台主机进程之间的通信提供通用的数据传输服务。应用进程利用该服务传送应用层报文。 运输层主要使用一下两种协议 传输控制协议-TCP:提供面向连接的,可靠的数据传输服务。 用户数据协议-UDP:提供无连接的,尽最大努力的数据传输服务(不保证数据传输的可靠性)。  运行在TCP协议上的协议: HTTP(Hypertext Transfer Protocol,超文本传输协议),主要用于普通浏览。 HTTPS(HTTP over SSL,安全超文本传输协议),HTTP协议的安全版本。 FTP(File Transfer Protocol,文件传输协议),用于文件传输。 POP3(Post Office Protocol, version 3,邮局协议),收邮件用。 SMTP(Simple Mail Transfer Protocol,简单邮件传输协议),用来发送电子邮件。 TELNET(Teletype over the Network,网络电传),通过一个终端(terminal)登陆到网络。 SSH(Secure Shell,用于替代安全性差的TELNET),用于加密安全登陆用。 运行在UDP协议上的协议: BOOTP(Boot Protocol,启动协议),应用于无盘设备。 NTP(Network Time Protocol,网络时间协议),用于网络同步。 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议),动态配置IP地址。 运行在TCP和UDP协议上: DNS(Domain Name Service,域名服务),用于完成地址查找,邮件转发等工作。
网络层
网络层的任务就是选择合适的网间路由和交换结点,确保计算机通信的数据及时传送。在发送数据时,网络层把运输层产生的报文段或用户数据报封装成分组和包进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报 ,简称数据报
Spring Cloud
服务注册
Zookeeper
特性
树状目录结构
每个子目录被称为znode 可以对每个znode进行增删改查
持久节点(Persistent)
客户端与zookeeper服务端断开连接后,该节点仍然存在
持久有序节点(Persistent_sequential)
在持久节点基础上,由zookeeper给该节点名称进行有序编号,如0000001,0000002
临时节点(Ephemeral)
客户端与zookeeper服务端断开连接后,该节点被删除。临时节点下,不存在子节点
临时有序节点(Ephemeral_sequential)
在临时节点基础上,由zookeeper给该节点名称进行有序编号,如0000001,0000002
节点监听(Wacher)
客户端A注册监听它关心的临时节点node的变化,当临时节点node发生变化时(如被删除的时候),zookeeper会通知客户端A
微服务中应用场景
分布式锁
服务注册与发现
服务注册原理
服务动态发现原理
测试
JUnit 5
常见用法
@DisplayName
用在类上和方法上,在类上使用它就表示该类为测试类,在方法上使用则表示该方法为测试方法 指定用例在测试报告中的展示名称
@BeforeAll / @AfterAll
整个测试类在开始前以及结束时的操作,只能修饰静态方法,主要用于在测试过程中所需要的全局数据和外部资源的初始化和清理
@BeforeEach / @AfterEach
所标注的方法会在每个测试用例方法开始前和结束时执行,主要是负责该测试用例所需要的运行环境的准备和销毁
@Disabled
禁用执行测试
@Nested
内嵌测试类
@RepeatedTest
当要运行一个测试方法 N次时,可以使用 @RepeatedTest 标记它
超时操作
assertTimeout
异常测试
assertThrows
参数化测试
junit-jupiter-engine.jar junit-jupiter-params.jar
基本数据源测试
@ValueSource
支持 Java 的八大基本类型和字符串,Class,使用时赋值给注解上对应类型属性,以数组方式传递 @ParameterizedTest // 必要注解,替代了 @Test 注解 @ValueSource(ints = {2, 4, 8}) void update() { System.out.println("测试用例方法update"); }
CSV 数据源测试
@CsvSource
可以注入指定 CSV 格式 (comma-separated-values) 的一组数据,用每个逗号分隔的值来匹配一个测试方法对应的参数 @ParameterizedTest @CsvSource({"1,One", "2,Two", "3,Three"}) @Test void remove() { System.out.println("测试用例方法remove"); }
主要特性
全新的断言和测试注解
更丰富的测试方式
动态测试,重复测试,参数化测试
模块化
Java 8 的支持
模块组成
JUnit Platform
用于JVM上启动测试框架的基础服务,提供命令行,IDE和构建工具等方式执行测试的支持
JUnit Jupiter
包含 JUnit 5 新的编程模型和扩展模型,主要就是用于编写测试代码和扩展代码
JUnit Vintage
用于在JUnit 5 中兼容运行 JUnit3.x 和 JUnit4.x 的测试用例
Spring Boot Test
单元测试
@RunWith
Junit4提供的注解,将Spring和Junit连接起来 假如使用Junit5,不再需要使用
@ExtendWith
@ExtendWith注解,@SpringBootTest和其它@*Test默认已经包含了该注解
@SpringBootTest
替代了spring-test中的@ContextConfiguration注解,目的是加载ApplicationContext,启动spring容器 @SpringBootTest注解会自动检索程序的配置文件,检索顺序是从当前包开始,逐级向上查找被@SpringBootApplication或@SpringBootConfiguration注解的类
功能测试
@SpringBootTest注解参数
webEnvironment
指定了web的environment
MOCK
此值为默认值,该类型提供一个mock环境,可以和@AutoConfigureMockMvc或@AutoConfigureWebTestClient搭配使用,开启Mock相关的功能。注意此时内嵌的服务(servlet容器)并没有真正启动,也不会监听web服务端口
RANDOM_PORT
启动一个真实的web服务,监听一个随机端口
DEFINED_PORT
启动一个真实的web服务,监听一个定义好的端口(从application.properties读取)
NONE
启动一个非web的ApplicationContext,既不提供mock环境,也不提供真实的web环境
切片测试
@*Test
开启后spring仅加载相关的bean,无关内容不会被加载
测试运行环境
mock能力
断言能力
Nginx
配置文件
# 配置文件详解: https://www.cnblogs.com/54chensongxia/p/12938929.html # 配置文件一共由三部分组成 # ==全局块== # 全局块是默认配置文件从开始到events块之间的一部分内容,主要设置一些影响Nginx服务器整体运行的配置指令,因此,这些指令的作用域是Nginx服务器全局 # 通常包括配置运行Nginx服务器的用户(组)、允许生成的worker process数、Nginx进程PID存放路径、日志的存放路径和类型以及配置文件引入等 # 指定可以运行nginx服务的用户和用户组,只能在全局块配置 # user [user] [group] # 将user指令注释掉,或者配置成nobody的话所有用户都可以运行 # user nobody nobody; # user指令在Windows上不生效,如果你制定具体用户和用户组会报小面警告 # nginx: [warn] "user" is not supported, ignored in D:\software\nginx-1.18.0/conf/nginx.conf:2 # 指定工作线程数,可以制定具体的进程数,也可使用自动模式,这个指令只能在全局块配置 # worker_processes number | auto; # 列子:指定4个工作线程,这种情况下会生成一个master进程和4个worker进程 # worker_processes 4; # 指定pid文件存放的路径,这个指令只能在全局块配置 # pid logs/nginx.pid; # 指定错误日志的路径和日志级别,此指令可以在全局块、http块、server块以及location块中配置。(在不同的块配置有啥区别??) # 其中debug级别的日志需要编译时使用--with-debug开启debug开关 # error_log [path] [debug | info | notice | warn | error | crit | alert | emerg] # error_log logs/error.log notice; # error_log logs/error.log info; #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; # ==events块== # events块涉及的指令主要影响Nginx服务器与用户的网络连接。常用到的设置包括是否开启对多worker process下的网络连接进行序列化,是否允许同时接收多个网络连接,选取哪种事件驱动模型处理连接请求,每个worker process可以同时支持的最大连接数等。 # 这一部分的指令对Nginx服务器的性能影响较大,在实际配置中应该根据实际情况灵活调整 # 当某一时刻只有一个网络连接到来时,多个睡眠进程会被同时叫醒,但只有一个进程可获得连接。如果每次唤醒的进程数目太多,会影响一部分系统性能。在Nginx服务器的多进程下,就有可能出现这样的问题。 # 开启的时候,将会对多个Nginx进程接收连接进行序列化,防止多个进程对连接的争抢 # 默认是开启状态,只能在events块中进行配置 # accept_mutex on | off; # 如果multi_accept被禁止了,nginx一个工作进程只能同时接受一个新的连接。否则,一个工作进程可以同时接受所有的新连接。 # 如果nginx使用kqueue连接方法,那么这条指令会被忽略,因为这个方法会报告在等待被接受的新连接的数量。 # 默认是off状态,只能在event块配置 # multi_accept on | off; # 指定使用哪种网络IO模型,method可选择的内容有:select、poll、kqueue、epoll、rtsig、/dev/poll以及eventport,一般操作系统不是支持上面所有模型的。 # 只能在events块中进行配置 # use method # use epoll # 设置允许每一个worker process同时开启的最大连接数,当每个工作进程接受的连接数超过这个值时将不再接收连接 # 当所有的工作进程都接收满时,连接进入logback,logback满后连接被拒绝 # 只能在events块中进行配置 # 注意:这个值不能超过超过系统支持打开的最大文件数,也不能超过单个进程支持打开的最大文件数,具体可以参考这篇文章:https://cloud.tencent.com/developer/article/1114773 # worker_connections 1024; events { worker_connections 1024; } # ==http块== # http块中,又包含http全局块、多个server块 # http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这个模块中。 # # 前面已经提到,http块中可以包含自己的全局块,也可以包含server块,server块中又可以进一步包含location块,在本书中我们使用“http全局块”来表示http中自己的全局块,即http块中不包含在server块中的部分。 # # 可以在http全局块中配置的指令包括文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。 # http块是Nginx服务器配置中的重要部分,代理、缓存和日志定义等绝大多数的功能和第三方模块的配置都可以放在这个模块中。 # # 前面已经提到,http块中可以包含自己的全局块,也可以包含server块,server块中又可以进一步包含location块,在本书中我们使用“http全局块”来表示http中自己的全局块,即http块中不包含在server块中的部分。 # # 可以在http全局块中配置的指令包括文件引入、MIME-Type定义、日志自定义、是否使用sendfile传输文件、连接超时时间、单连接请求数上限等。 http { include mime.types; default_type application/octet-stream; #log_format main '$remote_addr - $remote_user [$time_local] "$request" ' # '$status $body_bytes_sent "$http_referer" ' # '"$http_user_agent" "$http_x_forwarded_for"'; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; #gzip on; # 每个server块中,可以包含server全局块和多个location块 # server块和“虚拟主机”的概念有密切联系。 # 虚拟主机,又称虚拟服务器、主机空间或是网页空间,它是一种技术。该技术是为了节省互联网服务器硬件成本而出现的。这里的“主机”或“空间”是由实体的服务器延伸而来,硬件系统可以基于服务器群,或者单个服务器等。虚拟主机技术主要应用于HTTP、FTP及EMAIL等多项服务,将一台服务器的某项或者全部服务内容逻辑划分为多个服务单位,对外表现为多个服务器,从而充分利用服务器硬件资源。从用户角度来看,一台虚拟主机和一台独立的硬件主机是完全一样的。 # 在使用Nginx服务器提供Web服务时,利用虚拟主机的技术就可以避免为每一个要运行的网站提供单独的Nginx服务器,也无需为每个网站对应运行一组Nginx进程。虚拟主机技术使得Nginx服务器可以在同一台服务器上只运行一组Nginx进程,就可以运行多个网站。 # 在前面提到过,每一个http块都可以包含多个server块,而每个server块就相当于一台虚拟主机,它内部可有多台主机联合提供服务,一起对外提供在逻辑上关系密切的一组服务(或网站)。 # 和http块相同,server块也可以包含自己的全局块,同时可以包含多个location块。在server全局块中,最常见的两个配置项是本虚拟主机的监听配置和本虚拟主机的名称或IP配置。 server { # server块和“虚拟主机”的概念有密切联系。 # # 虚拟主机,又称虚拟服务器、主机空间或是网页空间,它是一种技术。该技术是为了节省互联网服务器硬件成本而出现的。这里的“主机”或“空间”是由实体的服务器延伸而来,硬件系统可以基于服务器群,或者单个服务器等。虚拟主机技术主要应用于HTTP、FTP及EMAIL等多项服务,将一台服务器的某项或者全部服务内容逻辑划分为多个服务单位,对外表现为多个服务器,从而充分利用服务器硬件资源。从用户角度来看,一台虚拟主机和一台独立的硬件主机是完全一样的。 # # 在使用Nginx服务器提供Web服务时,利用虚拟主机的技术就可以避免为每一个要运行的网站提供单独的Nginx服务器,也无需为每个网站对应运行一组Nginx进程。虚拟主机技术使得Nginx服务器可以在同一台服务器上只运行一组Nginx进程,就可以运行多个网站。 # # 在前面提到过,每一个http块都可以包含多个server块,而每个server块就相当于一台虚拟主机,它内部可有多台主机联合提供服务,一起对外提供在逻辑上关系密切的一组服务(或网站)。 # # 和http块相同,server块也可以包含自己的全局块,同时可以包含多个location块。在server全局块中,最常见的两个配置项是本虚拟主机的监听配置和本虚拟主机的名称或IP配置。 listen 80; server_name localhost; #charset koi8-r; #access_log logs/host.access.log main; location / { root html; index index.html index.htm; } #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apache's document root # concurs with nginx's one # #location ~ /\.ht { # deny all; #} } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} }
并发编程
进程
一个在内存中运行的应用程序, 每个进程有自己独立的内存空间, 可以包含多个线程
线程
进程中的一个执行任务, 多个线程共享进程的内存空间
进程与线程的区别
线程具有许多进程的特征, 称线程为轻型进程, 成进程为重型进程
进程是操作系统资源分配的基本单位, 线程是CPU调度和执行的基本单位
进程切换的资源开销大, 线程间的切换资源开销小
进程与进程之间的资源是独立的, 而同一个进程下的所有线程共享这个线程的资源
下文切换
一个CPU在任意时刻只能提供给一个线程使用, 为了提高CPU的利用率, 采取线程按时间片轮转的形式使用CPU. 当一个线程的时间片用完还没有完成任务, 就会重新进入就绪状态让给其他的线程使用. 任务从保存到再次加载的过程叫做一次上下文切换
用户线程
运行在前台, 执行具体的任务
守护线程
运行在后台, 为前台线程提供服务. 当用户线程结束时, 守护线程也会结束
死锁
两个或多个进程或线程在执行过程中, 竞争资源或彼此间的通信造成阻塞, 若无外力作用, 将永远无法推进.
死锁的四个必要条件
互斥条件
线程对所分配到的资源具有排它性, 一个资源只能被一个线程所占用, 直到该资源被线程释放
请求与保持条件
线程因请求 被占用资源 发生阻塞, 对以获得的资源保持不放
不剥夺条件
线程在资源使用完之前, 不能被其他线程剥夺
循环等待条件
发生死锁时, 所有线程必定形成一个环路, 永久死锁
创建线程的四种方式
继承Thread类
实现Runnable接口
使用Callable和Future
使用线程池. 如Executor框架
Runnable和Callable区别
Runnable接口的run方法无返回值, Callable接口的call方法有返回值
Runnable接口的run方法只能抛出异常, Callable接口的call方法可以处理异常(Callable用于产生结果,Future 用于获取结果)