Spring Boot入门教程:60分钟快速上手

日志观察员
2025-12-18 19:07
阅读 717

上周五晚上十一点半,我正窝在沙发上远程调试一个订单超时关闭的定时任务——没错,又是线上告警。这破逻辑上线前测试说“没问题”,结果双11大促刚过,用户投诉就炸了锅。我当时一边啃着冷掉的外卖(对,就是我们美团自己的),一边盯着日志里那堆 NullPointerException,心里默念:要是当初用 Spring Boot 重构这个老项目就好了。

我是美团外卖干了快4年的 Java 开发,主攻高并发场景下的订单和配送系统。这几年从手动配 XML 到全栈注解化,踩过的坑比吃过的饭还多。最近组里来了几个实习生,一问连 Spring Boot 都没跑起来过,我心想:得,干脆写篇接地气的入门教程吧。不是那种“Hello World + 理论八股”的假大空,而是真能帮你60分钟内把服务跑起来、接前端、连数据库、还能扛点流量的实战路线。


为啥是 Spring Boot?别被“脚手架”骗了

很多人以为 Spring Boot 就是个“快速生成项目”的工具,其实大错特错。它真正的价值在于自动装配(Auto Configuration)+ 生产就绪(Production Ready)。你想想,在我们这种天天面对百万级 QPS 的外卖平台,谁还有时间手动配 DataSource、TransactionManager、RedisTemplate?

去年搞春节红包活动,产品凌晨三点甩过来一句:“明早十点上线,支持十万并发抢券”。我差点把咖啡喷屏幕上。但靠着 Spring Boot 的 spring-boot-starter-* 体系,半小时搭好骨架,集成 Redis 做库存扣减、RabbitMQ 做异步解耦,再加个 Sentinel 限流——核心代码不到200行。要搁以前手写 Spring XML,估计现在还在改配置文件。

所以别小看这玩意儿,它不是玩具,是高并发战场上的 AK47


60分钟实操:从零到可交付

Step 1:初始化项目(5分钟)

打开 start.spring.io,别用国内某些魔改镜像(容易拉不到依赖)。我一般这么选:

  • Project: Maven
  • Language: Java
  • Spring Boot: 3.2.x(别贪新,3.x 起要求 JDK17+,我们生产环境刚升)
  • Dependencies:
    • Spring Web
    • Spring Data JPA
    • MySQL Driver
    • Lombok(省去 getter/setter,程序员之光)
    • Validation(参数校验,前端传参不靠谱是常态)

📌 血泪教训:千万别勾 Thymeleaf!我们是后端,不是写页面的。前端兄弟用 React/Vue,咱只管提供 REST API。

下载解压,IDEA 打开(记得装 Lombok 插件),mvn clean install 跑通——搞定!

Step 2:写个接口给前端(15分钟)

假设前端要查用户订单列表。先定义 DTO:

@Data
public class OrderResponse {
    private Long id;
    private String merchantName;
    private BigDecimal amount;
    private LocalDateTime createTime;
}

Controller 层直接怼:

@RestController
@RequestMapping("/api/v1/orders")
@RequiredArgsConstructor // Lombok 自动生成构造器注入
public class OrderController {

    private final OrderService orderService;

    @GetMapping("/user/{userId}")
    public List<OrderResponse> getUserOrders(@PathVariable Long userId) {
        // 实际项目这里会加权限校验、分页、防刷...
        return orderService.findOrdersByUser(userId);
    }
}

前端看到这个 /api/v1/orders/user/123 接口,直接拿 Postman 测试(或者让前端兄弟联调)。注意路径规范,我们团队强制要求 /api/v{版本号},避免后期接口兼容爆炸。

Step 3:连数据库,别裸奔(20分钟)

建表语句(简化版):

CREATE TABLE `orders` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` bigint NOT NULL,
  `merchant_name` varchar(100) NOT NULL,
  `amount` decimal(10,2) NOT NULL,
  `create_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB;

Entity 写法:

@Entity
@Table(name = "orders")
@Data
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private Long userId;
    private String merchantName;
    private BigDecimal amount;
    
    @Column(name = "create_time")
    private LocalDateTime createTime;
}

Repository 直接继承:

public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByUserId(Long userId);
}

配置 application.yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/food_delivery?useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: your_password
    hikari:
      maximum-pool-size: 20  # 别设太大!我们生产默认20,太多反而锁竞争
  jpa:
    show-sql: false  # 上线必须关!否则日志爆炸
    hibernate:
      ddl-auto: validate  # 别用 create!血的教训

⚠️ 安全意识提醒

  • 密码别硬编码!用配置中心或环境变量
  • ddl-auto 在生产只能是 validatenone
  • 敏感字段(如用户手机号)记得脱敏,别直接返回

Step 4:启动 & 验证(5分钟)

运行 main 方法,看到:

Tomcat started on port(s): 8080 (http)

Postman 访问 GET http://localhost:8080/api/v1/orders/user/1,返回 JSON:

[
  {
    "id": 1001,
    "merchantName": "黄焖鸡米饭",
    "amount": 28.50,
    "createTime": "2024-04-01T12:30:00"
  }
]

前端拿到数据,页面渲染完成——前后端联调成功


实战经验:那些文档不会告诉你的坑

坑1:事务失效

实习生曾在一个 @Service 方法里用 this.saveOrder() 调自己,结果事务没生效。因为 Spring AOP 是基于代理的,内部调用绕过了代理对象。解决办法:注入自己,或者用 ApplicationContext 获取代理 bean。

坑2:连接池打满

有一次大促,DB 连接池爆了。查了半天发现是某个查询没加索引,慢 SQL 卡住连接。务必监控 HikariCP 的 active/total 连接数,配合 Arthas 看线程堆栈。

坑3:前端传参乱七八糟

前端传个 "userId": "abc",后端直接报 400。所以 Controller 参数加上 @Valid

@GetMapping("/user/{userId}")
public List<OrderResponse> getUserOrders(@PathVariable @Min(1) Long userId) {

配合全局异常处理,返回友好错误:

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public String handleTypeMismatch() {
        return "参数类型错误,请检查 userId 是否为数字";
    }
}

性能与运维:上线前必做三件事

检查项 开发环境 生产环境
Actuator 健康检查 ✅(但需鉴权)
日志级别 DEBUG WARN
数据库连接池 10 20~50(根据 DB 规格)
JVM 参数 默认 -Xms4g -Xmx4g -XX:+UseG1GC

我们美团内部有标准化的 Spring Boot Starter,集成了链路追踪(SkyWalking)、配置中心(Apollo)、熔断降级(Sentinel)。但即使没有这些,至少要暴露 /actuator/health/actuator/metrics,让运维能监控服务状态。


最后说两句

Spring Boot 真的不难,难的是在复杂业务中用对、用稳。我见过太多人把所有逻辑塞进 Controller,结果后期改不动;也见过盲目追求微服务,最后连本地调试都要起五个服务。

记住:框架是工具,不是银弹。60分钟上手只是起点,真正值钱的是你如何设计接口、规避并发问题、保障数据一致性——这些才是我们 Java 老兵吃饭的家伙。

哦对了,刚才那个订单超时 Bug,最后发现是 RabbitMQ 消息积压导致监听器没触发……不过那是另一个故事了。先去改代码,产品又在群里@我了 😅

本文代码已上传 GitHub(模拟),实际项目请遵守公司安全规范。
—— 一个在家撸代码、被线上告警追着跑的美团外卖 Java 开发

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝