Java工程基础_单元测试_配置文件_JavaBean
Java 工程基础:单元测试 + 配置文件 + JavaBean
本章位置:第二阶段 Java 核心框架
前置知识:JavaSE 基础、面向对象、异常、集合、IO、Maven
本章内容:JUnit 单元测试、配置文件、JavaBean
下一篇:单例、匿名内部类、枚举
学习目标:学会把 Java 代码从“能运行”逐步写成“方便测试、方便配置、方便维护”的工程代码。
一、为什么第二阶段先学这三个知识
第一阶段我们更多是在写:
public static void main(String[] args) {
}
然后通过:
运行 main 方法
测试代码。
进入第二阶段以后,项目会越来越大。
例如:
MyBatis
Servlet
SpringBoot
RBAC
业务项目
这时候会出现三个非常现实的问题:
1. 一个方法到底对不对,难道每次都运行整个项目?
2. 数据库地址、用户名、密码难道全部写死在 Java 代码里?
3. Java 对象怎样写才能让框架更容易创建、读取和修改?
对应解决方案就是:
单元测试
配置文件
JavaBean
第一部分:单元测试
二、什么是单元测试
单元测试:
Unit Test
可以理解为:
针对程序中某一个较小的功能单元进行自动测试。
这个“单元”通常可以是:
一个方法
一个类
一个业务功能
例如有:
public int add(
int a,
int b
) {
return a + b;
}
我们希望自动确认:
add(1, 2)
是不是等于 3
这就是一个很典型的单元测试。
三、为什么不能一直靠 main 方法测试
假设:
public static void main(
String[] args
) {
Calculator calculator =
new Calculator();
System.out.println(
calculator.add(
1,
2
)
);
}
然后自己看控制台:
3
这种方式的问题:
需要人工观察结果
测试代码和业务代码容易混在一起
测试数量多后非常混乱
很难一次执行全部测试
修改代码后不容易知道哪里被影响
所以项目开发会使用:
JUnit
四、JUnit 是什么
JUnit 是 Java 中非常经典的:
单元测试框架
当前 Java 项目中通常使用:
JUnit 5
JUnit 5 中最常见:
@Test
以及:
Assertions
五、Maven 项目引入 JUnit 5
在:
pom.xml
中加入:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
其中:
<scope>test</scope>
表示:
主要只在测试阶段使用
不会作为普通业务依赖使用。
六、标准 Maven 测试目录
正常 Maven 项目:
src
├─ main
│ ├─ java
│ └─ resources
│
└─ test
├─ java
└─ resources
业务代码:
src/main/java
测试代码:
src/test/java
七、为什么测试代码单独放
这样可以:
业务代码和测试代码分离
测试依赖只在测试阶段使用
Maven 可以自动识别测试目录
IDEA 可以直接运行测试
八、第一个被测试类
创建:
Calculator.java
package com.example;
public class Calculator {
public int add(
int a,
int b
) {
return a + b;
}
public int subtract(
int a,
int b
) {
return a - b;
}
}
九、第一个 JUnit 测试
在:
src/test/java
创建:
CalculatorTest.java
package com.example;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CalculatorTest {
@Test
void testAdd() {
Calculator calculator =
new Calculator();
int result =
calculator.add(
1,
2
);
assertEquals(
3,
result
);
}
}
十、@Test
@Test
表示:
这个方法是测试方法
JUnit 会识别它并执行。
十一、assertEquals()
assertEquals(
3,
result
);
意思:
我期望 result 等于 3
如果:
实际值 == 期望值
测试通过。
否则:
测试失败
十二、测试不是“打印结果”
错误思路:
System.out.println(
result
);
然后人工判断。
真正的自动测试应该使用:
断言
Assertion
让程序自己判断:
通过
失败
十三、常见断言
assertEquals
assertEquals(
expected,
actual
);
比较:
期望值和实际值
assertNotEquals
assertNotEquals(
10,
result
);
assertTrue
assertTrue(
age >= 18
);
assertFalse
assertFalse(
list.isEmpty()
);
assertNull
assertNull(
result
);
assertNotNull
assertNotNull(
user
);
assertSame
assertSame(
object1,
object2
);
判断:
两个引用是不是同一个对象
这和:
equals()
不是一回事。
十四、测试异常 assertThrows
假设:
public int divide(
int a,
int b
) {
if (b == 0) {
throw new IllegalArgumentException(
"除数不能为 0"
);
}
return a / b;
}
测试:
@Test
void testDivideByZero() {
Calculator calculator =
new Calculator();
assertThrows(
IllegalArgumentException.class,
() ->
calculator.divide(
10,
0
)
);
}
十五、测试方法命名
可以写:
testAdd()
也可以写得更清楚:
add_shouldReturn3_when1Plus2()
现代项目越来越推荐:
测试名称能表达场景和预期
例如:
given
when
then
思路。
十六、@BeforeEach
如果每个测试都要:
new Calculator()
可以:
@BeforeEach
void setUp() {
calculator =
new Calculator();
}
例如:
public class CalculatorTest {
private Calculator calculator;
@BeforeEach
void setUp() {
calculator =
new Calculator();
}
@Test
void testAdd() {
assertEquals(
3,
calculator.add(
1,
2
)
);
}
}
十七、@AfterEach
每个测试结束后执行:
@AfterEach
void tearDown() {
}
常用于:
清理测试数据
释放测试资源
十八、@BeforeAll
整个测试类开始前:
只执行一次
例如:
@BeforeAll
static void init() {
}
十九、@AfterAll
整个测试类结束后:
只执行一次
@AfterAll
static void destroy() {
}
二十、常用生命周期顺序
可以理解:
@BeforeAll
↓
@BeforeEach
↓
@Test
↓
@AfterEach
↓
@BeforeEach
↓
@Test
↓
@AfterEach
↓
@AfterAll
二十一、@DisplayName
可以给测试显示中文名称:
@Test
@DisplayName(
"1 + 2 应该等于 3"
)
void testAdd() {
}
二十二、@Disabled
暂时禁用测试:
@Disabled
@Test
void testSomething() {
}
一般用于:
暂时无法运行
尚未完成
环境暂时不满足
不要为了让项目“全绿”就随便禁用失败测试。
二十三、参数化测试简单了解
如果要测试:
1 + 2 = 3
2 + 3 = 5
5 + 5 = 10
不一定写三个方法。
JUnit 支持:
参数化测试
例如:
@ParameterizedTest
@CsvSource({
"1,2,3",
"2,3,5",
"5,5,10"
})
void testAdd(
int a,
int b,
int expected
) {
assertEquals(
expected,
calculator.add(
a,
b
)
);
}
二十四、什么样的方法值得测试
例如:
金额计算
积分计算
权限判断
订单状态转换
字符串解析
参数校验
工具类
都很适合单元测试。
二十五、什么不是优秀单元测试
如果一个测试:
必须连接真实线上数据库
必须访问真实第三方接口
必须依赖真实短信服务
那么它通常已经不再是:
纯粹的单元测试
而更接近:
集成测试
二十六、单元测试的重要特点
好的单元测试通常希望:
快
稳定
独立
可重复
结果明确
二十七、测试之间不要互相依赖
不要设计:
test1
必须先执行
然后 test2
才能成功
理想情况:
每一个测试都可以独立运行
二十八、IDEA 2024.3 快速创建测试
在业务类中:
Ctrl + Shift + T
可以打开:
Create New Test
选择:
JUnit5
然后选择要测试的方法。
二十九、IDEA 快速运行测试
可以点击测试方法左侧:
绿色三角
运行单个测试。
也可以运行整个:
测试类
三十、测试通过和失败
通常 IDEA 会显示:
绿色
测试通过
红色
测试失败
注意:
测试失败
不等于测试代码一定错
它可能意味着:
业务代码出现 bug
三十一、常见问题:org.junit.jupiter.api 不存在
如果出现:
程序包 org.junit.jupiter.api 不存在
检查:
pom.xml 是否有 junit-jupiter
Maven 是否重新加载
依赖是否成功下载
测试类是不是放在 src/test/java
IDEA 是否识别 Maven 项目
三十二、Maven 重新加载
修改 pom.xml 后:
Maven 工具窗口
→ Reload All Maven Projects
或者点击:
重新加载图标
三十三、测试源目录问题
标准目录:
src/test/java
通常 Maven 导入后 IDEA 会自动识别为:
Test Sources Root
如果没有识别:
先确认项目是不是标准 Maven 结构
不要一开始就到处手工修改目录类型。
三十四、测试代码不要放 main
不推荐:
src/main/java
CalculatorTest.java
应该:
src/test/java
CalculatorTest.java
三十五、单元测试阶段总结
必须掌握:
@Test
assertEquals
assertTrue
assertFalse
assertNull
assertNotNull
assertThrows
@BeforeEach
@AfterEach
并理解:
测试业务逻辑
不是只看控制台输出
第二部分:配置文件
三十六、为什么需要配置文件
假设数据库配置写在 Java:
String url =
"jdbc:mysql://localhost:3306/test";
String username =
"root";
String password =
"123456";
如果以后:
换数据库
换服务器
换端口
修改账号
就必须修改 Java 源码。
更合理:
把可变化的信息放在配置文件
三十七、什么信息适合配置
例如:
数据库地址
数据库账号
服务器端口
文件保存路径
第三方接口地址
功能开关
系统名称
超时时间
三十八、常见配置文件格式
Java 项目常见:
.properties
.xml
.yml
.yaml
.json
Java 基础阶段重点:
.properties
后面 SpringBoot 重点:
application.properties
application.yml
三十九、properties 基本格式
例如:
app.name=Java Blog
app.version=1.0
server.port=8080
结构:
key=value
四十、数据库配置例子
jdbc.url=jdbc:mysql://localhost:3306/student_db
jdbc.username=root
jdbc.password=123456
四十一、配置文件放在哪里
Maven 项目通常:
src/main/resources
例如:
src/main/resources
└─ app.properties
编译后会进入:
classpath
四十二、什么是 classpath
可以简单理解:
Java 程序运行时
用来查找类和资源的路径
Maven 中:
src/main/resources
的内容通常会复制到:
target/classes
四十三、读取 classpath 配置文件
推荐:
InputStream input =
ConfigDemo.class
.getClassLoader()
.getResourceAsStream(
"app.properties"
);
四十四、Properties 类
Java 提供:
java.util.Properties
专门处理:
key=value
类型配置。
四十五、读取 properties
Properties properties =
new Properties();
try (
InputStream input =
ConfigDemo.class
.getClassLoader()
.getResourceAsStream(
"app.properties"
)
) {
if (input == null) {
throw new IllegalStateException(
"配置文件不存在"
);
}
properties.load(input);
}
四十六、获取配置
String appName =
properties.getProperty(
"app.name"
);
例如:
String portText =
properties.getProperty(
"server.port"
);
四十七、配置值默认都是字符串
properties:
server.port=8080
读取:
String portText =
properties
.getProperty(
"server.port"
);
如果需要 int:
int port =
Integer.parseInt(
portText
);
四十八、getProperty 默认值
String value =
properties.getProperty(
"app.name",
"默认系统"
);
如果不存在:
app.name
返回:
默认系统
四十九、配置文件注释
# 系统名称
app.name=Java Blog
也可以:
! comment
五十、配置工具类
可以封装:
public final class ConfigUtil {
private static final Properties
PROPERTIES =
new Properties();
static {
try (
InputStream input =
ConfigUtil.class
.getClassLoader()
.getResourceAsStream(
"app.properties"
)
) {
if (input == null) {
throw new IllegalStateException(
"app.properties 不存在"
);
}
PROPERTIES.load(
input
);
} catch (
IOException e
) {
throw new ExceptionInInitializerError(
e
);
}
}
private ConfigUtil() {
}
public static String get(
String key
) {
return PROPERTIES
.getProperty(
key
);
}
}
使用:
String name =
ConfigUtil.get(
"app.name"
);
五十一、为什么配置类常用 static
因为配置通常:
整个应用共享
没有必要:
每次 new 一个配置对象
所以经常:
类加载时读取一次
五十二、配置文件不是数据库
配置文件适合:
少量配置
相对稳定的数据
不适合:
海量用户数据
订单数据
业务流水
这些应该:
数据库
五十三、不要把敏感配置提交公共仓库
例如:
db.password=真实生产密码
api.secret=真实密钥
不要直接提交到公开 Git 仓库。
真实项目常通过:
环境变量
独立私有配置
配置中心
Secret 管理
处理。
五十四、环境变量简单了解
Java 可以读取:
String password =
System.getenv(
"DB_PASSWORD"
);
这样:
密码不需要写在源码
五十五、系统属性
还可以:
System.getProperty(
"app.env"
);
启动 JVM 时传入:
-Dapp.env=dev
后面 SpringBoot 会有更完整的:
外部化配置
体系。
五十六、配置优先级思维
真实项目可能同时存在:
默认配置
配置文件
环境变量
启动参数
配置中心
最终:
不同来源有优先级
SpringBoot 后面会专门处理。
当前先建立:
配置不要全部写死
这个意识。
五十七、XML 配置简单了解
例如:
<config>
<database>
<url>
jdbc:mysql://localhost:3306/test
</url>
<username>
root
</username>
</database>
</config>
XML 特点:
结构清晰
层级丰富
内容较冗长
五十八、为什么 MyBatis 常看到 XML
后面 MyBatis 会使用:
mybatis-config.xml
Mapper.xml
原因是 XML 适合描述:
复杂层级配置
SQL 映射
五十九、YAML 简单了解
例如:
server:
port: 8080
spring:
application:
name: demo
后面 SpringBoot 常见:
application.yml
六十、配置文件常见错误
路径错误
例如:
Could not find resource
检查:
是否放在 src/main/resources
资源名称是否正确
是否写了多余路径
key 写错
配置:
server.port=8080
代码:
getProperty(
"server.prot"
);
得到:
null
编码问题
现代项目尽量统一:
UTF-8
尤其 IDEA:
Project Encoding
Properties Encoding
要注意一致性。
六十一、配置文件阶段总结
需要掌握:
为什么使用配置文件
.properties 格式
src/main/resources
classpath
Properties
getResourceAsStream
getProperty
配置工具类
第三部分:JavaBean
六十二、JavaBean 是什么
JavaBean 可以理解为:
按照一定规范编写的普通 Java 类。
很多框架都喜欢操作这种标准化对象。
例如:
MyBatis
Servlet
JSP
Spring
SpringBoot
都大量和 JavaBean 打交道。
六十三、一个标准 JavaBean 示例
public class Student {
private String name;
private Integer age;
public Student() {
}
public String getName() {
return name;
}
public void setName(
String name
) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(
Integer age
) {
this.age = age;
}
}
六十四、JavaBean 常见规范
通常包括:
1. 类是 public
2. 属性使用 private
3. 提供 public Getter / Setter
4. 提供无参构造
5. 根据需要实现 Serializable
六十五、为什么属性要 private
例如:
private String name;
这是:
封装
外部不直接修改:
字段
而通过:
getName()
setName()
访问。
六十六、Getter
public String getName() {
return name;
}
用于:
读取属性
六十七、Setter
public void setName(
String name
) {
this.name = name;
}
用于:
修改属性
六十八、布尔属性 Getter
例如:
private boolean enabled;
Getter 通常:
public boolean isEnabled() {
return enabled;
}
也可能看到:
getEnabled()
但传统 JavaBean 对 primitive boolean 常见:
isXxx
六十九、为什么需要无参构造
很多框架创建对象时会:
先调用无参构造
↓
再通过 Setter / 反射赋值
例如概念上:
Student student =
new Student();
student.setName(
"张三"
);
student.setAge(
20
);
七十、如果自己写了有参构造
例如:
public Student(
String name,
Integer age
) {
}
Java 不会再自动提供:
默认无参构造
如果框架需要:
new Student()
就可能失败。
所以经常同时提供:
public Student() {
}
七十一、JavaBean 和普通类有什么区别
普通 Java 类:
怎么设计都可以
JavaBean:
遵循一套通用约定
好处:
框架容易识别
工具容易操作
属性读取规则统一
七十二、JavaBean 属性不是简单等于字段
这是很重要的概念。
JavaBean 认为:
属性
主要通过:
Getter / Setter
识别。
例如:
public String getUsername()
可能形成 Bean 属性:
username
七十三、属性名如何推导
方法:
getName()
对应:
name
方法:
setAge(...)
对应:
age
方法:
isEnabled()
对应:
enabled
七十四、为什么框架喜欢 JavaBean
假设 JSON:
{
"name": "张三",
"age": 20
}
框架可能根据属性名:
name
age
找到:
setName()
setAge()
然后自动填充。
七十五、数据库结果映射也类似
数据库:
name
age
映射到:
Student
框架会利用:
属性名
Setter
反射
完成对象赋值。
这就是后面 MyBatis 的基础。
七十六、JavaBean 完整示例
import java.io.Serializable;
public class User
implements Serializable {
private static final long
serialVersionUID =
1L;
private Long id;
private String username;
private Integer age;
private boolean enabled;
public User() {
}
public User(
Long id,
String username,
Integer age,
boolean enabled
) {
this.id = id;
this.username =
username;
this.age = age;
this.enabled =
enabled;
}
public Long getId() {
return id;
}
public void setId(
Long id
) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(
String username
) {
this.username =
username;
}
public Integer getAge() {
return age;
}
public void setAge(
Integer age
) {
this.age = age;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(
boolean enabled
) {
this.enabled =
enabled;
}
@Override
public String toString() {
return "User{"
+ "id="
+ id
+ ", username='"
+ username
+ '\''
+ ", age="
+ age
+ ", enabled="
+ enabled
+ '}';
}
}
七十七、IDEA 快速生成 Getter / Setter
Windows 默认快捷键:
Alt + Insert
然后选择:
Getter and Setter
选择字段:
生成
七十八、快速生成构造方法
同样:
Alt + Insert
选择:
Constructor
可以生成:
无参构造
有参构造
七十九、快速生成 toString()
Alt + Insert
→ toString()
八十、为什么不要手写大量模板代码
学习阶段:
建议理解代码含义
但实际项目中:
Getter
Setter
Constructor
toString
可以使用 IDEA 自动生成,
减少:
拼写错误
重复劳动
八十一、JavaBean 参数校验放哪
简单对象可以在 Setter 中:
public void setAge(
Integer age
) {
if (
age != null
&& age < 0
) {
throw new IllegalArgumentException(
"年龄不能小于 0"
);
}
this.age = age;
}
但大型 Web 项目通常会使用:
Service 校验
Bean Validation
DTO 校验
不要把所有复杂业务逻辑塞进 Bean。
八十二、Entity、DTO、VO 和 JavaBean
后面会看到:
Entity
DTO
VO
POJO
它们很多本质上都可以:
遵循 JavaBean 风格
只是:
业务角色不同
八十三、POJO 是什么
POJO:
Plain Old Java Object
可以理解:
普通 Java 对象
通常:
不强制继承框架类
不依赖复杂框架接口
JavaBean 可以看作:
更加遵循特定规范的 POJO
八十四、JavaBean 和实体类
例如:
public class Student {
private Long id;
private String name;
}
这个对象既可能叫:
实体类
同时也可以符合:
JavaBean 规范
这两个词关注点不同。
八十五、综合案例:配置 + JavaBean
配置文件:
app.name=学生管理系统
app.version=1.0
app.maxUsers=100
Bean:
public class AppConfig {
private String name;
private String version;
private Integer maxUsers;
public AppConfig() {
}
// Getter / Setter
}
八十六、手动读取配置到 Bean
Properties properties =
new Properties();
try (
InputStream input =
Demo.class
.getClassLoader()
.getResourceAsStream(
"app.properties"
)
) {
properties.load(
input
);
}
AppConfig config =
new AppConfig();
config.setName(
properties
.getProperty(
"app.name"
)
);
config.setVersion(
properties
.getProperty(
"app.version"
)
);
config.setMaxUsers(
Integer.parseInt(
properties
.getProperty(
"app.maxUsers"
)
)
);
八十七、这就是框架自动配置的雏形
你现在是:
手动读取 properties
↓
手动 new Bean
↓
手动 set 属性
后面 SpringBoot 会变成:
自动读取配置
↓
自动创建 Bean
↓
自动绑定属性
所以现在这些基础非常重要。
八十八、综合案例:JavaBean + 单元测试
例如 User:
public class User {
private String username;
public String getUsername() {
return username;
}
public void setUsername(
String username
) {
this.username =
username;
}
}
测试:
@Test
void shouldSetUsername() {
User user =
new User();
user.setUsername(
"admin"
);
assertEquals(
"admin",
user.getUsername()
);
}
八十九、配置工具类测试
例如:
@Test
void shouldReadAppName() {
String appName =
ConfigUtil.get(
"app.name"
);
assertNotNull(
appName
);
}
这样:
配置是否正确
也可以自动检查。
九十、三个知识点的关系
可以用一张图理解:
配置文件
负责保存可变化的数据
│
▼
JavaBean
负责承载结构化数据
│
▼
业务代码
负责处理逻辑
│
▼
JUnit
负责验证逻辑是否正确
九十一、进入框架前必须建立的习惯
第一阶段经常写:
public static void main(...)
第二阶段开始应该逐渐建立:
业务类单独写
配置单独放
测试单独写
对象遵循规范
这就是:
工程化
的开始。
九十二、常见错误:业务配置写死
不推荐:
String uploadPath =
"D:\\project\\upload";
更好:
配置文件
九十三、常见错误:测试只打印
不推荐:
System.out.println(
result
);
推荐:
assertEquals(
expected,
actual
);
九十四、常见错误:测试依赖执行顺序
不推荐:
test1 创建数据
test2 必须使用 test1 数据
测试应该尽量:
彼此独立
九十五、常见错误:测试真实生产数据
单元测试不要直接:
删除生产数据库数据
调用真实支付接口
发送真实短信
测试环境必须:
和生产隔离
九十六、常见错误:配置文件放错位置
Maven 中:
src/main/resources
是非常重要的资源目录。
例如:
mybatis-config.xml
application.properties
jdbc.properties
以后都会放这里。
九十七、常见错误:new File(“src/main/resources/…”)
开发阶段可能能运行:
new File(
"src/main/resources/app.properties"
);
但打包成 jar 后:
src/main/resources
已经不存在。
classpath 资源应该优先通过:
ClassLoader
读取。
九十八、常见错误:JavaBean 没有无参构造
如果框架需要:
new User()
却只有:
public User(
String name
)
可能创建失败。
所以传统 JavaBean 通常提供:
无参构造
九十九、常见错误:字段全部 public
不推荐:
public String name;
推荐:
private String name;
再通过:
Getter / Setter
访问。
一百、常见错误:Getter 命名不规范
不推荐:
public String readName() {
}
如果你希望它被标准 JavaBean 工具识别为属性:
name
更标准:
getName()
一百零一、练习题 1:Calculator 单元测试
创建:
Calculator
包含:
add
subtract
multiply
divide
为每一个方法编写:
JUnit 测试
一百零二、练习题 2:异常测试
要求:
divide(10, 0)
抛出:
IllegalArgumentException
使用:
assertThrows()
测试。
一百零三、练习题 3:UserService 测试
创建:
boolean isAdult(
int age
)
测试:
18
17
20
0
一百零四、练习题 4:配置文件
创建:
system.properties
内容:
system.name
system.version
system.port
然后 Java 读取并输出。
一百零五、练习题 5:ConfigUtil
封装:
ConfigUtil.get(
String key
)
并为它写单元测试。
一百零六、练习题 6:Student JavaBean
字段:
id
studentNo
name
age
major
score
要求:
private 字段
无参构造
有参构造
Getter / Setter
toString
一百零七、练习题 7:配置绑定
配置:
student.defaultAge=18
student.defaultMajor=软件工程
读取后:
创建 Student 对象
一百零八、本章必须掌握
单元测试
JUnit 是什么
@Test
断言
@BeforeEach
assertThrows
测试目录
配置文件
为什么配置外置
properties
resources
classpath
Properties
getResourceAsStream
JavaBean
private 属性
Getter / Setter
无参构造
标准命名
框架为什么喜欢 Bean
一百零九、IDEA 快捷操作总结
创建测试
Ctrl + Shift + T
生成 Getter / Setter
Alt + Insert
然后:
Getter and Setter
生成构造方法
Alt + Insert
→ Constructor
生成 toString
Alt + Insert
→ toString()
一百一十、本章总结
这三个知识点表面上看并不完全一样,
但它们都在帮我们从:
“写几个 Java 方法”
进入:
“写一个更正规的 Java 项目”
具体来说:
JUnit
解决代码怎么自动验证
配置文件
解决变化的数据怎么从代码中分离
JavaBean
解决对象怎样标准化
它们会直接影响后面的:
MyBatis
Servlet
JSP
Spring
SpringBoot
尤其后面你会不断看到:
Bean
配置
测试
资源目录
属性绑定
所以这不是几个零散小知识,
而是正式进入 Java 框架开发前的基础准备。
下一篇继续整理:
单例模式
匿名内部类
枚举
把第一项课程中剩下的面向对象补充内容完整收尾。