Spring 技术栈学习文档(面向前端开发者)

Spring 技术栈学习文档(面向前端开发者)

本文档以前端开发者熟悉的概念作为类比,帮助你快速理解 Spring 后端技术栈。建议按章节顺序阅读,每一章都会用前端的视角解释新概念。


目录

  1. 前置知识:从前端视角理解后端
  2. [Java 基础速览](#Java 基础速览 "#2-java-%E5%9F%BA%E7%A1%80%E9%80%9F%E8%A7%88")
  3. [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")
  4. [核心概念一: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")
  5. [核心概念二: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")
  6. [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")
  7. [Spring MVC:构建 REST API](#Spring MVC:构建 REST API "#7-spring-mvc%E6%9E%84%E5%BB%BA-rest-api")
  8. [数据访问: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")
  9. [Spring Security:认证与授权](#Spring Security:认证与授权 "#9-spring-security%E8%AE%A4%E8%AF%81%E4%B8%8E%E6%8E%88%E6%9D%83")
  10. [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")
  11. 实战项目结构示例
  12. 学习路径建议

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.javamain 方法
部署产物 静态文件 / 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 nameint 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) { /* ... */ }
}

发生了什么?

  1. 启动时,Spring 扫描所有带 @Service@Component@RestController 等注解的类,创建实例并放入"容器"。
  2. Spring 看到 UserController 的构造器需要一个 UserService,就从容器里找一个匹配的实例(这里是 UserServiceImpl),自动传进去。
  3. 你不需要 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 API
  • Spring 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.ymlapplication.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 周)

  1. Java 语法(类、接口、注解、泛型、Lambda)
  2. Maven 基础
  3. Spring Boot 入门:搭建项目、写第一个 REST API
  4. Spring MVC:增删改查全流程
  5. Spring Data JPA:连接数据库、CRUD

实战目标:做一个 ToDo 应用的后端 API。

阶段二:进阶能力(2-4 周)

  1. 参数校验、全局异常处理
  2. 日志(Logback / SLF4J)
  3. Lombok(简化代码)
  4. Swagger / SpringDoc(自动生成 API 文档)
  5. 单元测试(JUnit + Mockito)
  6. Spring Security + JWT 登录鉴权

实战目标:做一个博客系统(含用户登录、文章发布、评论)。

阶段三:生态拓展(按需)

  1. Redis 缓存(Spring Data Redis)
  2. 消息队列(RabbitMQ / Kafka)
  3. MyBatis-Plus
  4. 定时任务(@Scheduled / Quartz)
  5. 微服务(Spring Cloud)
  6. 容器化部署(Docker + Spring Boot)

推荐资源

  • 官方文档spring.io,最权威
  • 示例库start.spring.io 生成项目模板
  • 中文教程:廖雪峰的 Java 教程、《Spring Boot 实战》
  • 视频:B 站搜"Spring Boot 教程",找近期更新且评论好的

给前端同学的特别建议

  1. 不要被 Java 的"啰嗦"吓到:Java 写起来确实比 JS 啰嗦,但配合 IDE(IntelliJ IDEA)和 Lombok 后会舒服很多。
  2. 重点理解 IoC 和注解:这是 Spring 的灵魂,前端没有完全对应的概念。
  3. 多动手少看视频 :直接跟着官方 Guides(spring.io/guides)写代码。
  4. 善用 Postman / Apifox 调接口:在没有前端的情况下用它验证后端逻辑。
  5. 理解 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


祝你学习顺利!记住:后端学习的关键不是记住所有注解,而是理解"分层"和"解耦"的思想。 🚀

相关推荐
狗头大军之江苏分军8 小时前
Python 协程进化史:从 yield 到 async/await 的底层实现
前端·后端
jay神8 小时前
基于YOLOv8的交通标志识别Web系统
前端·人工智能·深度学习·yolo·机器学习·毕业设计
CAD老兵8 小时前
一张 HTML 走天下:CAD-Viewer 首创的「离线 CAD 看图」
前端·javascript·github
程序员榴莲8 小时前
Python 中的 @property:像访问属性一样调用方法
开发语言·前端·python
yingyima9 小时前
Linux定时任务:crontab vs systemd timer,到底谁更适合你的业务?
前端
有味道的男人9 小时前
1688 跨境 API:多语言、跨境代采、独立站商品同步方案
java·服务器·前端
索西引擎9 小时前
【实战】Changesets:Monorepo 版本管理与变更日志的实践
前端
Highcharts.js9 小时前
AI向量知识谱系图表创建示例代码|Highcharts网络图表(networkgraph)搭建案例
开发语言·前端·javascript·网络·信息可视化·编辑器·highcharts
zhangxingchao10 小时前
AI应用开发五:RAG高级技术与调优
前端·人工智能·后端