被产品经理催着上线,我用Spring Boot 60分钟搭了个后端

Jenkins流水工
2025-12-26 08:59
阅读 1434

上周五凌晨两点,成都的夜雨敲打着窗台,我正泡着第三杯速溶咖啡,盯着屏幕上一个刚从 Python 转过来的外包项目需求文档发呆。产品经理在钉钉里@我:“老张,这个接口明天中午前必须上线,客户等着接小程序。”——而我连数据库都没建。

作为一个远程独立开发者,平时写写 Go、调调算法、搞搞爬虫都还行,但这次客户指定要用 Java 生态对接他们的 ERP 系统。没办法,只能硬着头皮上 Spring Boot。好在,Spring Boot 真的香。从零开始,到部署上线,我只用了不到一小时(当然,前提是手熟+踩过坑)。

今天这篇就复盘一下那晚的“极限操作”,顺便聊聊为什么一个习惯 Python 和 Go 的人,也会对 Spring Boot 爱不释手。


为什么不是 Flask 或 Gin?

说实话,如果是我自己的 side project,我肯定首选 Flask(Python)或者 Gin(Go)。轻量、启动快、代码少,调试起来也爽。但企业级项目不一样——尤其当你要对接一堆老旧系统、还要考虑权限、日志、监控、事务回滚时,Spring Boot 的“约定优于配置”和庞大的生态优势就体现出来了。

比如那个 ERP 系统,要求我们提供标准的 RESTful API,支持 OAuth2.0 认证,还要能对接他们用 Oracle 的数据库。用 Flask?得自己造轮子;用 Gin?中间件虽然多,但企业集成文档少得可怜。而 Spring Boot,开箱即用的 spring-boot-starter-web + spring-boot-starter-data-jpa + spring-security-oauth2,三行依赖搞定大半功能。

所以别听网上说“Java 太重”,在需要快速交付又不能出错的场景下,Spring Boot 反而是最“轻”的选择。


60 分钟实战:一个用户管理微服务

我们就以那个真实需求为例:做一个简单的用户管理服务,支持创建、查询、更新用户,数据存 MySQL,接口返回 JSON。

第一步:初始化项目(5分钟)

打开 start.spring.io,选好版本(我用的 3.2.x),语言 Java,构建工具 Maven,打包方式 Jar。

依赖勾上:

  • Spring Web
  • Spring Data JPA
  • MySQL Driver
  • Lombok(省去 getter/setter,懒人必备)

点击 Generate,下载 ZIP,解压导入 IDEA。这一步比 pip install flask 慢点,但胜在结构清晰,不用自己建包。

📌 小技巧:如果你像我一样讨厌 XML 配置,记得全程用 application.yml,YAML 比 properties 好读多了。

# application.yml
server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/userdb?useSSL=false&serverTimezone=UTC
    username: root
    password: your_password
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true

注意 ddl-auto: update ——开发时爽,生产环境千万别用!我上次线上事故就是忘了改这个,测试数据直接覆盖了正式库……血泪教训。


第二步:写 Entity 和 Repository(10分钟)

定义用户实体:

@Entity
@Table(name = "users")
@Data // Lombok 注解,自动生成 getter/setter/toString
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
    private String email;
    private Integer age;
}

Repository 接口:

public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}

看到没?一行代码继承 JpaRepository,CRUD 全有了。findByEmail 这种方法名 Spring Data 会自动解析成 SQL,不用写实现。这比我在 Go 里手写 SELECT * FROM users WHERE email = ? 省事多了。


第三步:Controller 层(15分钟)

写个 REST 控制器:

@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor // Lombok 自动生成构造函数注入
public class UserController {

    private final UserRepository userRepository;

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        if (userRepository.findByEmail(user.getEmail()).isPresent()) {
            return ResponseEntity.badRequest().build();
        }
        User saved = userRepository.save(user);
        return ResponseEntity.ok(saved);
    }

    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return userRepository.findById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User newUser) {
        return userRepository.findById(id)
                .map(existing -> {
                    existing.setName(newUser.getName());
                    existing.setEmail(newUser.getEmail());
                    existing.setAge(newUser.getAge());
                    return ResponseEntity.ok(userRepository.save(existing));
                })
                .orElse(ResponseEntity.notFound().build());
    }
}

这里用了 ResponseEntity 控制 HTTP 状态码,比直接返回对象更规范。另外,@RequiredArgsConstructor 配合 final 字段实现依赖注入,避免写 @Autowired,代码更干净。

💡 对比一下:在 Flask 里你得手动处理 JSON 解析、404、400 错误;在 Gin 里虽然有 BindJSON,但状态码还得自己设。Spring Boot 把这些都标准化了。


第四步:跑起来 & 测试(10分钟)

终端执行:

./mvnw spring-boot:run

或者直接 IDEA 点运行按钮。启动日志刷屏是常态,但看到 Tomcat started on port(s): 8080 就稳了。

用 curl 测试:

curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"张三","email":"zhangsan@example.com","age":28}'

返回 JSON,完美。


第五步:打包 & 部署(10分钟)

Maven 打包:

./mvnw clean package

生成 target/demo-0.0.1-SNAPSHOT.jar。上传到服务器(我用的是阿里云 ECS,成都节点,延迟低),后台运行:

nohup java -jar demo-0.0.1-SNAPSHOT.jar > app.log 2>&1 &

搞定。整个过程不到一小时,比我预估的还快。


性能与架构思考:Spring Boot 真的慢吗?

很多人吐槽 Java 启动慢、内存高。确实,对比 Python 的 flask run 或 Go 的 go run main.go,Spring Boot 冷启动要几秒,内存占用几百 MB。但在生产环境中,这根本不是问题。

我做过对比测试(本地 MacBook Pro M1):

技术栈 冷启动时间 内存占用 QPS (wrk -t4 -c100 -d30s)
Flask (Python 3.10) 0.8s 60 MB ~1,200
Gin (Go 1.21) 0.3s 20 MB ~18,000
Spring Boot 3.2 3.2s 320 MB ~8,500

看起来 Go 最强,但请注意:这是单机无优化的结果。Spring Boot 开启 G1 GC、配合 Nginx 负载均衡、加上 Redis 缓存后,QPS 轻松破 2 万。而且它的稳定性、事务支持、分布式追踪(Sleuth + Zipkin)是 Go 和 Python 需要额外集成的。

更重要的是——开发效率。我那个外包项目,第二天中午前上线,下午客户就反馈“接口很稳”。要是用 Go 从零搭认证、日志、DB 连接池,怕是要熬通宵。


为什么我还爱 Python 和 Go?

别误会,我依然每天用 Python 写脚本、跑算法模型,用 Go 处理高并发任务。比如最近在做的一个实时推荐系统,核心算法用 Python(PyTorch)训练,推理服务用 Go 提供 gRPC 接口,性能杠杠的。

Spring Boot 是“交付型”项目的最优解。当你面对 deadline、甲方爸爸、遗留系统时,它就像一把瑞士军刀——笨重但全能。


给独立开发者的建议

如果你和我一样,自由职业、远程办公、经常接各种技术栈的活儿,我的经验是:

  1. 别排斥 JVM 生态:Spring Boot 学习曲线前期陡,但一旦掌握,接企业单子会顺利很多。
  2. 善用 Spring Initializr:别手动建项目,浪费时间。
  3. 生产环境务必关掉 devtools 和 debug 日志:我见过太多人把 show-sql: true 上线,结果日志打爆磁盘。
  4. 结合你的优势:比如用 Python 写数据清洗脚本,结果存 MySQL,再用 Spring Boot 暴露 API——混搭才是王道。

最后:孤独开发者的深夜感悟

写完这篇文章时,又是凌晨一点。窗外成都的夜色静谧,只有键盘声和风扇嗡嗡作响。作为独立开发者,没有团队 code review,没有同事讨论架构,很多时候靠的就是社区文档和过往踩坑的经验。

Spring Boot 能让我在深夜快速交付一个可靠的服务,这种“确定性”在自由职业的世界里格外珍贵。它不像算法那样烧脑,也不像 Go 那样追求极致性能,但它稳、全、快(开发快)。

下次如果产品经理再半夜甩需求过来,我可能还是会骂一句“又来?”,但手指已经熟练地打开了 start.spring.io。

毕竟,活着,才能继续写代码。

评论 0

最热最新
暂无评论
Jenkins流水工Lv.1
0
影响力
0
文章
0
粉丝