java学习连续打卡30天(1)
背景:
Spring Boot 的学习过程可以类比为搭建一个高效运转的“数字厨房”。它提供了一套“约定大于配置”的自动化装备(自动配置),内嵌了“厨灶”(Tomcat等服务器),并通过“标准菜谱”(Starter依赖)快速备齐所需“食材”和“工具”,让你能专注于烹饪“菜品”(业务逻辑),而非繁琐的准备工作。为了让你在30天内系统掌握这项技能,我为你制定了以下学习路线。
一、Spring Boot基础
1、访问官网初始化工具
# 方式1:网页版访问
https://start.spring.io/# 方式2:使用IDEA内置的Spring Initializr
File → New → Project → Spring Initializr我这里使用方法2进行初始化

2、项目结构解析
创建后的标准项目结构:
my-springboot-app/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/example/demo/
│ │ │ ├── DemoApplication.java # 启动类
│ │ │ ├── controller/ # 控制器层
│ │ │ ├── service/ # 业务逻辑层
│ │ │ └── repository/ # 数据访问层
│ │ └── resources/
│ │ ├── static/ # 静态资源(css,js,图片)
│ │ ├── templates/ # 模板文件
│ │ └── application.properties # 配置文件
│ └── test/ # 测试代码
└── pom.xml # Maven配置3、核心注解深度解析
@SpringBootApplication - 启动类的灵魂
package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication // ← 核心注解,组合了三个重要功能
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}@SpringBootApplication 实际上是三个注解的组合:
// @SpringBootApplication 等价于:
@SpringBootConfiguration // 标识这是Spring Boot配置类
@EnableAutoConfiguration // 启用自动配置
@ComponentScan // 组件扫描,自动发现Bean
public class DemoApplication {// ...
}各注解作用详解:
@SpringBootConfiguration:标记该类为配置类,可以替代传统的XML配置
@EnableAutoConfiguration:启用自动配置机制,根据依赖自动配置Spring应用
@ComponentScan:自动扫描当前包及其子包下的组件(@Component, @Service, @Controller等)
4、编写第一个REST控制器
创建第一个Hello World接口:
package com.example.demo.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController // 组合了@Controller和@ResponseBody
public class HelloController {@GetMapping("/hello") // 处理GET请求,路径为/hellopublic String sayHello() {return "Hello, Spring Boot! 🚀";}@GetMapping("/hello/{name}")public String sayHelloToUser(@PathVariable String name) {return "Hello, " + name + "! Welcome to Spring Boot!";}
}5、运行和测试应用
方式一:IDE中直接运行
在启动类
DemoApplication.java中右键点击Run DemoApplication
方式二:命令行运行
# 进入项目根目录
mvn spring-boot:run# 或者先打包再运行
mvn clean package
java -jar target/demo-1.0.0.jar6、基础配置详解
application.properties 基础配置
# 应用配置
spring.application.name=my-first-springboot# 服务器配置
server.port=8080
server.servlet.context-path=/api# 日志配置
logging.level.com.example=DEBUG
logging.level.org.springframework.web=INFO7、开发工具和技巧
Spring Boot DevTools - 开发神器
在pom.xml中添加:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional>
</dependency>功能特性:
🔥 热部署:代码修改后自动重启应用
🎯 LiveReload:静态资源修改自动刷新浏览器
⚡ 快速启动:开发时使用更快的重启机制
扩展练习:返回JSON数据
@GetMapping("/user")
public Map<String, Object> getUser() {Map<String, Object> user = new HashMap<>();user.put("id", 1);user.put("name", "Spring Boot Learner");user.put("email", "learner@example.com");user.put("timestamp", new Date());return user;
}常见问题排查:
Q: 访问404错误?
检查控制器是否在启动类的子包中
确认请求路径是否正确
检查是否有context-path配置
Q: 热部署不工作?
确认已添加devtools依赖
IDE需要开启自动编译
检查是否在开发环境
二、日常小技巧;
1. 使用 StringBuilder 进行字符串拼接
在循环或频繁拼接字符串时,不要直接使用 +,因为它会创建大量临时 String 对象。
// 反例 (低效)
String result = "";
for (String str : stringList) {result += str; // 每次循环都会 new 一个 StringBuilder 和 String 对象
}// 正例 (高效)
StringBuilder sb = new StringBuilder();
for (String str : stringList) {sb.append(str);
}
String result = sb.toString();2. 使用 Arrays.asList() 和 List.of() 快速初始化列表
// 老方法
List<String> list1 = new ArrayList<>();
list1.add("A");
list1.add("B");
list1.add("C");// 简洁方法 (返回的列表大小不可变)
List<String> list2 = Arrays.asList("A", "B", "C");
// Java 9+ 的不可变列表
List<String> list3 = List.of("A", "B", "C");3. 使用 isEmpty() 判断字符串或集合是否为空
这比检查长度或大小更直观,且避免了 NullPointerException 的风险(如果事先判空)。
String str = "...";
List<String> list = ...;// 好
if (str != null && !str.isEmpty()) { ... }
if (list != null && !list.isEmpty()) { ... }// 更好:使用 Apache Commons Lang 或 Spring 的 StringUtils
if (StringUtils.isNotEmpty(str)) { ... }4、 返回空集合而非 null
这可以让调用者免于不必要的 null 检查。
// 反例
public List<String> getData() {if (/* 没有数据 */) {return null; // 调用者必须判空}// ...
}// 正例
public List<String> getData() {if (/* 没有数据 */) {return Collections.emptyList(); // 或者 new ArrayList<>()}// ...
}逻辑与判空技巧
5. 使用 Objects.equals() 安全地进行对象判等
它可以避免空指针异常。
String a = null;
String b = "hello";// 反例 (会抛出 NPE)
if (a.equals(b)) { ... }// 正例 (安全)
if (Objects.equals(a, b)) { ... }6、充分利用 Stream API
用于处理集合,使代码更声明式、更易读。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");// 过滤、转换、收集
List<String> result = names.stream().filter(name -> name.startsWith("A") || name.startsWith("C")) // 过滤.map(String::toUpperCase) // 映射.sorted() // 排序.collect(Collectors.toList()); // 收集为 ListSystem.out.println(result); // [ALICE, CHARLIE]7、使用 Lambda 表达式和方法引用
简化匿名内部类的编写。
// 匿名内部类
button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {doSomething();}
});// Lambda 表达式
button.addActionListener(e -> doSomething());// 方法引用
names.forEach(System.out::println);