Spring 技术栈学习文档(面向前端开发者)
本文档以前端开发者熟悉的概念作为类比,帮助你快速理解 Spring 后端技术栈。建议按章节顺序阅读,每一章都会用前端的视角解释新概念。
目录
- 前置知识:从前端视角理解后端
- [Java 基础速览](#Java 基础速览 "#2-java-%E5%9F%BA%E7%A1%80%E9%80%9F%E8%A7%88")
- [Spring 是什么?为什么要用它?](#Spring 是什么?为什么要用它? "#3-spring-%E6%98%AF%E4%BB%80%E4%B9%88%E4%B8%BA%E4%BB%80%E4%B9%88%E8%A6%81%E7%94%A8%E5%AE%83")
- [核心概念一:IoC 与依赖注入(DI)](#核心概念一:IoC 与依赖注入(DI) "#4-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%E4%B8%80ioc-%E4%B8%8E%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85%A5di")
- [核心概念二:AOP 面向切面编程](#核心概念二:AOP 面向切面编程 "#5-%E6%A0%B8%E5%BF%83%E6%A6%82%E5%BF%B5%E4%BA%8Caop-%E9%9D%A2%E5%90%91%E5%88%87%E9%9D%A2%E7%BC%96%E7%A8%8B")
- [Spring Boot:开箱即用的脚手架](#Spring Boot:开箱即用的脚手架 "#6-spring-boot%E5%BC%80%E7%AE%B1%E5%8D%B3%E7%94%A8%E7%9A%84%E8%84%9A%E6%89%8B%E6%9E%B6")
- [Spring MVC:构建 REST API](#Spring MVC:构建 REST API "#7-spring-mvc%E6%9E%84%E5%BB%BA-rest-api")
- [数据访问:Spring Data JPA 与 MyBatis](#数据访问:Spring Data JPA 与 MyBatis "#8-%E6%95%B0%E6%8D%AE%E8%AE%BF%E9%97%AEspring-data-jpa-%E4%B8%8E-mybatis")
- [Spring Security:认证与授权](#Spring Security:认证与授权 "#9-spring-security%E8%AE%A4%E8%AF%81%E4%B8%8E%E6%8E%88%E6%9D%83")
- [Spring Cloud:微服务全家桶](#Spring Cloud:微服务全家桶 "#10-spring-cloud%E5%BE%AE%E6%9C%8D%E5%8A%A1%E5%85%A8%E5%AE%B6%E6%A1%B6")
- 实战项目结构示例
- 学习路径建议
1. 前置知识:从前端视角理解后端
1.1 前后端的角色对比
| 维度 | 前端 | 后端(Spring) |
|---|---|---|
| 运行环境 | 浏览器 / Node.js | JVM(Java 虚拟机) |
| 主要语言 | JavaScript / TypeScript | Java / Kotlin |
| 包管理器 | npm / yarn / pnpm | Maven / Gradle |
| 构建工具 | Webpack / Vite | Maven / Gradle |
| 主流框架 | React / Vue | Spring / Spring Boot |
| 启动入口 | index.html / main.ts |
Application.java 的 main 方法 |
| 部署产物 | 静态文件 / Node 服务 | JAR / WAR 包 |
1.2 后端在做什么?
如果说前端是"店铺的门面"(展示商品、接待顾客),那么后端就是"店铺的后厨和仓库":
- 接收前端的请求(HTTP API)------ 类似服务员接单
- 处理业务逻辑 ------ 类似厨师做菜
- 读写数据库 ------ 类似仓库管理员取放食材
- 返回结果给前端 ------ 类似上菜
Spring 就是帮你高效组织"后厨和仓库"的一套工具。
2. Java 基础速览
学 Spring 之前,需要对 Java 有基本认识。这里只讲必要部分,重点用 JS/TS 来对比。
2.1 类与对象
JavaScript(ES6):
javascript
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
return `Hello, ${this.name}`;
}
}
const u = new User("Alice", 25);
Java:
java
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String sayHello() {
return "Hello, " + this.name;
}
// getter / setter(Java 习惯)
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}
User u = new User("Alice", 25);
关键差异:
- Java 的变量必须声明类型(
String name、int age),这就是"强类型"。TypeScript 也类似。 private/public是访问修饰符。private表示只能在类内部访问,外部通过getName()这种 getter 方法读写。- Java 没有
var/let(其实有var,是局部变量类型推断,但用得少)。
2.2 接口(Interface)
接口就像"契约",TypeScript 开发者会非常熟悉:
typescript
// TypeScript
interface UserService {
findById(id: number): User;
save(user: User): void;
}
java
// Java
public interface UserService {
User findById(Long id);
void save(User user);
}
// 实现接口
public class UserServiceImpl implements UserService {
@Override
public User findById(Long id) { /* ... */ }
@Override
public void save(User user) { /* ... */ }
}
Spring 中"面向接口编程"是非常重要的思想,后面会反复见到。
2.3 注解(Annotation)
注解是 Java 的"装饰器",类似于 TypeScript 的 @Decorator:
java
@Component // 告诉 Spring:这个类要交给我管
@Deprecated // 标记为过时
@Override // 标记为重写父类方法
public class MyService { }
Spring 的精髓很大程度上就在于"用注解描述意图" ,例如 @RestController、@Autowired、@Transactional 等等。
2.4 Maven 与 Gradle
类似于前端的 package.json,Java 项目用 pom.xml(Maven)或 build.gradle(Gradle)来管理依赖。
pom.xml 示例(Maven):
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.2.0</version>
</dependency>
</dependencies>
对应前端的:
json
{
"dependencies": {
"express": "^4.18.0"
}
}
3. Spring 是什么?为什么要用它?
3.1 Spring 的定位
Spring 是一个 Java 应用框架,最早诞生于 2003 年,目的是简化企业级 Java 应用的开发。
可以这样类比:
- 没有 Spring 的 Java 后端开发 ≈ 用原生 JS 写复杂前端应用(什么都要自己造)
- 用了 Spring ≈ 用 React/Vue 写前端(有完善的生态、工具链、最佳实践)
3.2 Spring 全家桶
"Spring" 已经不再指单一框架,而是一整套生态:
| 模块 | 作用 | 前端类比 |
|---|---|---|
| Spring Framework | 核心框架,提供 IoC/AOP | React 核心库 |
| Spring Boot | 开箱即用的脚手架 | Create React App / Vite |
| Spring MVC | 构建 Web/REST API | Express / Koa |
| Spring Data | 简化数据库访问 | Prisma / TypeORM |
| Spring Security | 安全(认证、授权) | Passport.js |
| Spring Cloud | 微服务全家桶 | (前端没有完全对应的) |
学习顺序建议:先掌握 Spring Boot + Spring MVC + Spring Data,足以应对 80% 的工作场景,再按需深入 Spring Security 和 Spring Cloud。
4. 核心概念一:IoC 与依赖注入(DI)
这是 Spring 最核心的思想,理解了它,Spring 就懂了一半。
4.1 问题场景
假设你写了一个 UserController,它依赖 UserService 来处理业务逻辑:
java
// 传统写法
public class UserController {
private UserService userService = new UserServiceImpl();
public User getUser(Long id) {
return userService.findById(id);
}
}
问题:
UserController自己new出来UserService,两者耦合死了。- 想换个实现(比如测试时用 Mock)?必须改代码。
- 系统庞大时,依赖关系会变成一团乱麻。
4.2 IoC:控制反转
控制反转(Inversion of Control) 的核心思想是:
我不自己创建依赖对象,而是让一个"容器"帮我创建好,再"注入"给我。
类比前端:你不会自己手动管理 React 组件的状态依赖,而是通过 props / context 接收,由父组件或 Provider 注入。Spring 的容器就相当于一个全局的 Provider。
4.3 依赖注入(DI)的写法
Spring 通过注解实现依赖注入:
java
@RestController // 标记为 Controller,Spring 会管理它
public class UserController {
private final UserService userService;
// 构造器注入(推荐方式)
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
}
@Service // 标记为 Service,Spring 会创建实例
public class UserServiceImpl implements UserService {
@Override
public User findById(Long id) { /* ... */ }
}
发生了什么?
- 启动时,Spring 扫描所有带
@Service、@Component、@RestController等注解的类,创建实例并放入"容器"。 - Spring 看到
UserController的构造器需要一个UserService,就从容器里找一个匹配的实例(这里是UserServiceImpl),自动传进去。 - 你不需要
new任何东西,Spring 全帮你做好了。
4.4 常见的 IoC 注解
| 注解 | 用途 |
|---|---|
@Component |
通用组件标记 |
@Service |
业务逻辑层 |
@Repository |
数据访问层 |
@Controller / @RestController |
Web 层 |
@Autowired |
自动注入依赖(构造器注入时可省略) |
@Configuration |
标记配置类 |
@Bean |
在配置类中手动注册一个对象 |
4.5 三种注入方式
java
public class MyController {
// 1. 构造器注入(推荐 ✅)
private final UserService userService;
public MyController(UserService userService) {
this.userService = userService;
}
// 2. 字段注入(不推荐,但常见)
@Autowired
private UserService userService;
// 3. Setter 注入
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
推荐构造器注入 的原因:依赖明确、容易测试、字段可以 final。
5. 核心概念二:AOP 面向切面编程
5.1 问题场景
很多功能是"横切"在多个业务方法里的,比如:
- 记录日志
- 性能监控
- 事务管理
- 权限校验
如果在每个方法里都手写这些代码,会非常冗余:
java
public User getUser(Long id) {
log.info("开始查询用户: " + id);
long start = System.currentTimeMillis();
try {
User user = userRepository.findById(id);
log.info("查询成功,耗时: " + (System.currentTimeMillis() - start) + "ms");
return user;
} catch (Exception e) {
log.error("查询失败", e);
throw e;
}
}
5.2 AOP 的思路
AOP(Aspect-Oriented Programming) 把这些横切逻辑抽取出来,让你像"贴膏药"一样把它"切入"到业务方法上,业务代码保持干净。
类比前端:类似 React 的高阶组件(HOC)或中间件模式(Redux middleware、Express middleware),将通用逻辑包裹在主流程外。
5.3 简单示例
java
@Aspect
@Component
public class LoggingAspect {
// 切入点:所有 service 包下的方法
@Around("execution(* com.example.service.*.*(..))")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed(); // 执行原方法
long elapsed = System.currentTimeMillis() - start;
System.out.println(joinPoint.getSignature() + " 耗时: " + elapsed + "ms");
return result;
}
}
写完这个,所有 service 包下的方法都会自动打印耗时,业务代码无需改动。
5.4 常见的 AOP 应用
@Transactional:自动开启/提交/回滚数据库事务@Cacheable:自动缓存方法返回值@PreAuthorize:在方法执行前校验权限
初学者不一定要自己写 AOP,但要理解:你看到的很多注解背后都是 AOP 在工作。
6. Spring Boot:开箱即用的脚手架
6.1 为什么需要 Spring Boot?
早期 Spring 配置非常繁琐:要写大量 XML,配置 Tomcat,配置数据源......
Spring Boot 把这些配置都默认好了,体验类似从"手写 webpack 配置"到"用 Vite 一键启动"。
6.2 创建一个 Spring Boot 项目
最简单的方式 :访问 start.spring.io,勾选依赖,下载即可。常用依赖:
Spring Web:构建 REST APISpring Data JPA:数据库访问MySQL Driver:MySQL 驱动Lombok:减少样板代码(自动生成 getter/setter)
6.3 最小可运行的应用
java
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootApplication 等价于三个注解的组合:
@SpringBootConfiguration:标记为配置类@EnableAutoConfiguration:开启自动配置(核心魔法)@ComponentScan:扫描当前包及子包下的组件
运行 main 方法,一个内嵌 Tomcat 的 Web 服务就启动了,默认监听 8080 端口。
6.4 配置文件
Spring Boot 使用 application.yml 或 application.properties 配置:
yaml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/mydb
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update
show-sql: true
类似前端项目里的 .env 文件或 Vite 配置。
6.5 项目结构
bash
src/
├── main/
│ ├── java/
│ │ └── com/example/demo/
│ │ ├── DemoApplication.java # 启动类
│ │ ├── controller/ # 控制器(接收 HTTP 请求)
│ │ ├── service/ # 业务逻辑
│ │ ├── repository/ # 数据访问
│ │ ├── entity/ # 数据库实体
│ │ └── dto/ # 数据传输对象
│ └── resources/
│ ├── application.yml # 配置文件
│ └── static/ # 静态资源
└── test/ # 测试代码
7. Spring MVC:构建 REST API
7.1 MVC 模式
- M(Model):数据模型
- V(View):视图(前后端分离时一般不用,前端来负责)
- C(Controller):控制器,处理请求
7.2 一个完整的 REST API 示例
java
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// GET /api/users
@GetMapping
public List<User> listUsers() {
return userService.findAll();
}
// GET /api/users/123
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
// POST /api/users
@PostMapping
public User createUser(@RequestBody UserDto dto) {
return userService.create(dto);
}
// PUT /api/users/123
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody UserDto dto) {
return userService.update(id, dto);
}
// DELETE /api/users/123
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
}
7.3 常用注解对照表
| 注解 | 用途 | 前端类比(Express) |
|---|---|---|
@RestController |
标记为 REST 控制器 | app.use(router) |
@RequestMapping("/api") |
类级别路径前缀 | router.use('/api', ...) |
@GetMapping("/x") |
GET 请求 | router.get('/x', ...) |
@PostMapping |
POST | router.post(...) |
@PathVariable |
URL 路径参数 | req.params.id |
@RequestParam |
URL 查询参数 | req.query.name |
@RequestBody |
请求体(JSON) | req.body |
@RequestHeader |
请求头 | req.headers |
7.4 请求与响应数据
Spring Boot 默认用 Jackson 处理 JSON。前端发送:
json
POST /api/users
{
"name": "Alice",
"email": "alice@example.com"
}
后端自动反序列化成对象:
java
@PostMapping
public User createUser(@RequestBody UserDto dto) {
// dto.getName() = "Alice"
// dto.getEmail() = "alice@example.com"
return userService.create(dto);
}
返回对象时也会自动序列化为 JSON。
7.5 参数校验
java
public class UserDto {
@NotBlank(message = "用户名不能为空")
private String name;
@Email(message = "邮箱格式不正确")
private String email;
@Min(value = 0, message = "年龄不能为负")
private Integer age;
}
@PostMapping
public User createUser(@Valid @RequestBody UserDto dto) {
// 如果校验失败,会抛出异常,可以统一处理
return userService.create(dto);
}
7.6 统一异常处理
java
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, String>> handleValidation(MethodArgumentNotValidException e) {
Map<String, String> errors = new HashMap<>();
e.getBindingResult().getFieldErrors().forEach(err ->
errors.put(err.getField(), err.getDefaultMessage())
);
return ResponseEntity.badRequest().body(errors);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleAll(Exception e) {
return ResponseEntity.status(500).body("服务器错误: " + e.getMessage());
}
}
8. 数据访问:Spring Data JPA 与 MyBatis
后端不可避免要操作数据库。Spring 提供了两套主流方案。
8.1 Spring Data JPA(推荐入门)
JPA 是 Java 的 ORM 规范,类似于前端的 Prisma、TypeORM。
定义实体(对应数据库表):
java
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 50)
private String name;
@Column(unique = true)
private String email;
private Integer age;
// getter / setter ...
}
定义 Repository(数据访问层):
java
public interface UserRepository extends JpaRepository<User, Long> {
// 这就够了!Spring 自动实现增删改查
// 按方法名自动生成查询
List<User> findByNameContaining(String keyword);
Optional<User> findByEmail(String email);
// 自定义 SQL
@Query("SELECT u FROM User u WHERE u.age > :age")
List<User> findByAgeGreaterThan(@Param("age") int age);
}
在 Service 中使用:
java
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User findById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("用户不存在"));
}
public User create(UserDto dto) {
User user = new User();
user.setName(dto.getName());
user.setEmail(dto.getEmail());
return userRepository.save(user);
}
}
自动生成的方法:
| 方法名 | 作用 |
|---|---|
findAll() |
查所有 |
findById(id) |
按主键查 |
save(entity) |
新增或更新 |
deleteById(id) |
删除 |
count() |
计数 |
8.2 MyBatis(国内更流行)
MyBatis 是"半自动 ORM",需要自己写 SQL,但更灵活,适合复杂查询场景。
java
// Mapper 接口
@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User findById(Long id);
@Insert("INSERT INTO users(name, email) VALUES(#{name}, #{email})")
@Options(useGeneratedKeys = true, keyProperty = "id")
int insert(User user);
}
JPA vs MyBatis 怎么选?
- 简单 CRUD 多 → JPA 更快
- 复杂报表、性能调优需求多 → MyBatis 更可控
- 国内互联网公司主流 → MyBatis(尤其是 MyBatis-Plus)
8.3 事务管理
java
@Service
public class OrderService {
@Transactional // 这个方法里的所有数据库操作要么全部成功,要么全部回滚
public void createOrder(OrderDto dto) {
orderRepository.save(...);
inventoryRepository.decrease(...);
paymentService.charge(...);
// 任何一步抛异常,前面的操作都会回滚
}
}
9. Spring Security:认证与授权
Web 应用绕不开"登录"和"权限"。Spring Security 是事实标准。
9.1 基本概念
- 认证(Authentication):你是谁?(登录、Token 校验)
- 授权(Authorization):你能干什么?(角色、权限)
9.2 JWT 认证流程(最常见的方案)
bash
前端 后端
│ │
│ POST /login │
│ (username, pwd) │
├──────────────────>│
│ │ 校验用户名密码
│ │ 生成 JWT Token
│ JWT Token │
│<──────────────────┤
│ │
│ GET /api/users │
│ Header: Bearer xx │
├──────────────────>│
│ │ 校验 Token
│ │ 提取用户信息
│ 返回数据 │
│<──────────────────┤
9.3 简化配置示例
java
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(auth -> auth
.requestMatchers("/api/auth/**").permitAll() // 登录接口放行
.requestMatchers("/api/admin/**").hasRole("ADMIN") // 管理员接口
.anyRequest().authenticated() // 其他都需要登录
)
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
9.4 方法级别的权限控制
java
@PreAuthorize("hasRole('ADMIN')")
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.delete(id);
}
注意:Spring Security 学习曲线较陡,建议入门阶段先用一个能跑的模板,等业务复杂了再深入。
10. Spring Cloud:微服务全家桶
当系统变大,单体应用难以维护时,就需要拆分成多个独立服务,这就是"微服务"。
10.1 微服务架构示意
scss
┌─────────────┐
│ 网关 │
│ (Gateway) │
└──────┬──────┘
│
┌──────────────────┼──────────────────┐
│ │ │
┌────▼─────┐ ┌────▼─────┐ ┌────▼─────┐
│ 用户服务 │ │ 订单服务 │ │ 商品服务 │
└────┬─────┘ └────┬─────┘ └────┬─────┘
│ │ │
└──────────────────┼──────────────────┘
│
┌──────▼──────┐
│ 注册中心 │
│ (Nacos/Eureka)│
└─────────────┘
10.2 Spring Cloud 主要组件
| 组件 | 作用 |
|---|---|
| Spring Cloud Gateway | API 网关,统一入口 |
| Nacos / Eureka | 服务注册与发现 |
| OpenFeign | 服务间调用(声明式 HTTP 客户端) |
| Sentinel / Hystrix | 限流、熔断 |
| Spring Cloud Config | 配置中心 |
| Sleuth + Zipkin | 链路追踪 |
10.3 服务调用示例
用 OpenFeign 调用其他服务,就像调用本地方法:
java
@FeignClient(name = "order-service")
public interface OrderClient {
@GetMapping("/orders/user/{userId}")
List<Order> getOrdersByUser(@PathVariable Long userId);
}
@Service
public class UserService {
private final OrderClient orderClient;
public UserDetail getUserDetail(Long userId) {
User user = userRepository.findById(userId).orElseThrow();
List<Order> orders = orderClient.getOrdersByUser(userId); // 自动 HTTP 调用
return new UserDetail(user, orders);
}
}
10.4 学习建议
微服务不是入门必修。建议你先把单体应用做熟,再来学微服务,否则容易抓不住重点。
11. 实战项目结构示例
一个典型的 Spring Boot 项目长这样:
bash
src/main/java/com/example/blog/
├── BlogApplication.java # 启动类
│
├── config/ # 配置类
│ ├── SecurityConfig.java
│ └── SwaggerConfig.java
│
├── controller/ # 控制器层
│ ├── UserController.java
│ └── ArticleController.java
│
├── service/ # 业务逻辑层
│ ├── UserService.java
│ └── impl/
│ └── UserServiceImpl.java
│
├── repository/ # 数据访问层
│ ├── UserRepository.java
│ └── ArticleRepository.java
│
├── entity/ # 数据库实体
│ ├── User.java
│ └── Article.java
│
├── dto/ # 数据传输对象
│ ├── request/
│ │ ├── LoginRequest.java
│ │ └── ArticleCreateRequest.java
│ └── response/
│ ├── UserResponse.java
│ └── ArticleResponse.java
│
├── exception/ # 异常处理
│ ├── BusinessException.java
│ └── GlobalExceptionHandler.java
│
└── util/ # 工具类
└── JwtUtil.java
分层调用关系
markdown
HTTP 请求
│
▼
Controller(接收请求、参数校验、调用 Service)
│
▼
Service(业务逻辑、事务管理、调用 Repository)
│
▼
Repository(数据库操作)
│
▼
数据库
这种分层结构非常稳定,几乎所有 Spring Boot 项目都遵循它。
12. 学习路径建议
阶段一:Java + Spring Boot 基础(2-3 周)
- Java 语法(类、接口、注解、泛型、Lambda)
- Maven 基础
- Spring Boot 入门:搭建项目、写第一个 REST API
- Spring MVC:增删改查全流程
- Spring Data JPA:连接数据库、CRUD
实战目标:做一个 ToDo 应用的后端 API。
阶段二:进阶能力(2-4 周)
- 参数校验、全局异常处理
- 日志(Logback / SLF4J)
- Lombok(简化代码)
- Swagger / SpringDoc(自动生成 API 文档)
- 单元测试(JUnit + Mockito)
- Spring Security + JWT 登录鉴权
实战目标:做一个博客系统(含用户登录、文章发布、评论)。
阶段三:生态拓展(按需)
- Redis 缓存(Spring Data Redis)
- 消息队列(RabbitMQ / Kafka)
- MyBatis-Plus
- 定时任务(@Scheduled / Quartz)
- 微服务(Spring Cloud)
- 容器化部署(Docker + Spring Boot)
推荐资源
- 官方文档 :spring.io,最权威
- 示例库 :start.spring.io 生成项目模板
- 中文教程:廖雪峰的 Java 教程、《Spring Boot 实战》
- 视频:B 站搜"Spring Boot 教程",找近期更新且评论好的
给前端同学的特别建议
- 不要被 Java 的"啰嗦"吓到:Java 写起来确实比 JS 啰嗦,但配合 IDE(IntelliJ IDEA)和 Lombok 后会舒服很多。
- 重点理解 IoC 和注解:这是 Spring 的灵魂,前端没有完全对应的概念。
- 多动手少看视频 :直接跟着官方 Guides(spring.io/guides)写代码。
- 善用 Postman / Apifox 调接口:在没有前端的情况下用它验证后端逻辑。
- 理解 HTTP 协议:状态码、Header、Body、Cookie、Session、Token,这些前后端都用得到,掌握后能少踩很多坑。
附录:常见面试与实践问题
Q1:@Autowired 和构造器注入有什么区别? 构造器注入是推荐做法,因为依赖关系明确、字段可以为 final、便于单元测试。@Autowired 字段注入虽然简洁但隐藏了依赖。
Q2:@Service 和 @Component 有区别吗? 功能上一样,都是把类注册到 Spring 容器。语义上 @Service 表示业务层、@Repository 表示数据层,便于阅读和未来增强(比如 @Repository 会自动转换数据库异常)。
Q3:Spring Boot 怎么知道要扫描哪些类? @SpringBootApplication 包含 @ComponentScan,默认扫描启动类所在包及其子包。所以启动类最好放在最外层包。
Q4:事务为什么有时候不生效? 常见原因:
- 同一个类内方法互相调用(绕过了 Spring 代理)
- 异常被
try-catch吞掉了 - 方法不是
public - 抛出了 Checked Exception(默认只回滚 RuntimeException)
Q5:JPA 的"懒加载"是什么? 默认情况下,关联对象(如 User.orders)不会立即从数据库查出,而是用到时再查。如果在事务外访问,会抛 LazyInitializationException,需要在 service 层内访问,或显式使用 @EntityGraph。
祝你学习顺利!记住:后端学习的关键不是记住所有注解,而是理解"分层"和"解耦"的思想。 🚀