30岁转行,我用Spring Boot在杭州搭了个Hello World

程序员阿远
2025-12-29 08:30
阅读 1522

去年十月,我还在一家传统制造企业做供应链管理。每天和Excel、ERP系统斗智斗勇,直到某天看到杭州某大厂的Java岗JD写着“欢迎有业务背景的转行者”。那一刻,我仿佛看到了人生的第二个窗口——于是,白天上班,晚上啃《Spring实战》,周末泡在网易蜗牛读书里刷LeetCode,三个月后,真就拿到了offer。

如今坐在杭州文一西路的工位上,每天8点准时打开IDEA,咖啡还没凉,产品经理已经在钉钉@我:“这个需求双11前必须上线”。上周五晚上十一点,我还在改一个诡异的NullPointerException,起因居然是YAML缩进错了两个空格。那一刻我真的想砸电脑——但转念一想,这不就是我当初拼命想进来的世界吗?

今天这篇教程,就是写给和我一样从非科班杀进后端战场的兄弟们。别怕,Spring Boot没那么玄乎,60分钟,带你跑通第一个能打接口的服务。


为什么是 Spring Boot?Go 不香吗?

刚入职时,团队技术栈讨论会上,有个年轻同事提议:“现在云原生这么火,不如直接上 Go 写微服务?”
架构师笑了笑:“Go 是好,但咱们系统要对接老ERP、老CRM,一堆历史包袱,还得和阿里云中间件深度集成。Spring Boot 生态成熟,社区资源多,出了问题 Stack Overflow 上八成有人踩过坑。”

这话我深有体会。我在学 Go 的时候也折腾过 Gin 框架,确实轻量、启动快,但一旦涉及事务管理、JPA、MyBatis、OAuth2 这些企业级功能,Spring 家族的整合能力简直降维打击。更重要的是——资源。中文文档、视频教程、开源项目、招聘需求,Spring Boot 的生态护城河太深了。

所以,别纠结“Go 还是 Java”,先解决眼前的问题。我们组现在主力还是 Spring Boot 2.7 + MySQL + Redis,稳定压倒一切。


60 分钟实战:从零到能打接口

第一步:环境准备(5分钟)

确保你装了:

  • JDK 17(别用8了,新项目都17+)
  • Maven 或 Gradle(我用 Maven,公司统一规范)
  • 一个趁手的 IDE(IntelliJ IDEA 社区版足够)

然后去 start.spring.io —— Spring 官方脚手架,堪称新手福音。填好 Group、Artifact,依赖勾上:

  • Spring Web(必须)
  • Spring Data JPA(如果你要用数据库)
  • MySQL Driver(或 H2 用于本地测试)
  • Lombok(省掉 getter/setter,爽到飞起)

点击 Generate,解压导入 IDEA。搞定!比 Go 的 go mod init 还快(别打我)。


第二步:写个 Controller(10分钟)

新建一个类:

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String sayHello() {
        return "Hello, I'm a 30-year-old newbie in Hangzhou!";
    }
}

别笑,这就是你的第一个 API。启动主类(带 @SpringBootApplication 的那个),访问 http://localhost:8080/hello,看到字符串就算成功。

🚨 坑点提醒:
我第一次启动报错 Web server failed to start,原因是 8080 被占用了。后来学会加配置:

# application.yml
server:
  port: 8081

第三步:连数据库(20分钟)

公司项目当然不能只返回字符串。假设我们要存用户信息。

  1. 建表(本地用 H2 方便,生产用 MySQL):
CREATE TABLE user (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE
);
  1. 实体类(配合 Lombok):
@Entity
@Table(name = "user")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    private String email;
}
  1. Repository 接口
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByEmail(String email);
}
  1. Service 层(简单示例):
@Service
@Transactional
public class UserService {
    
    @Autowired
    private UserRepository userRepository;

    public User createUser(String name, String email) {
        if (userRepository.findByEmail(email).isPresent()) {
            throw new RuntimeException("Email already exists");
        }
        User user = new User();
        user.setName(name);
        user.setEmail(email);
        return userRepository.save(user);
    }
}
  1. Controller 调用
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody CreateUserRequest request) {
    User user = userService.createUser(request.getName(), request.getEmail());
    return ResponseEntity.ok(user);
}

💡 小技巧:
我用 Postman 测试接口时,经常忘加 Content-Type: application/json,结果报 415 Unsupported Media Type。血泪教训!


第四步:配置与日志(10分钟)

生产环境不能裸奔。至少要配:

# application-prod.yml
spring:
  datasource:
    url: jdbc:mysql://prod-db:3306/myapp?useSSL=false&serverTimezone=Asia/Shanghai
    username: ${DB_USER}
    password: ${DB_PASSWORD}
  jpa:
    hibernate:
      ddl-auto: validate  # 千万别用 create!会丢数据!
    show-sql: false

logging:
  level:
    com.mycompany: INFO
    org.springframework.web: DEBUG

我们组规定:开发环境可以 show-sql: true,生产必须关掉。上次有个实习生没关,日志把磁盘打满了,运维半夜打电话骂人。


第五步:打包与部署(15分钟)

Maven 项目执行:

./mvnw clean package -DskipTests

生成 target/*.jar,直接运行:

java -jar myapp.jar --spring.profiles.active=prod

公司用 Jenkins + Docker 自动化部署,但我本地调试就靠这条命令。Go 编译成二进制确实方便,但 Java 的 -jar 也不差,尤其配上 Spring Boot 的内嵌 Tomcat,一个文件搞定所有依赖,运维都说省心。


性能与稳定性:别只顾跑起来

新人容易犯的错:只关注功能是否实现,忽略性能和健壮性。

我们在压测时发现,JPA 默认的 fetch 策略会导致 N+1 查询。比如查订单列表,每条订单再查用户信息,100 条订单就是 101 次 SQL!解决方案:

  • @EntityGraph 显式声明关联加载
  • 或直接写 JPQL / Native Query

另外,接口设计要有防御性

  • 参数校验(用 @Valid + JSR-303)
  • 统一异常处理(@ControllerAdvice
  • 返回格式标准化(别一会儿 Map 一会儿 JSON)
@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(RuntimeException e) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(new ErrorResponse(e.getMessage()));
    }
}

资源推荐:少走弯路

类型 推荐
官方文档 spring.io/projects/spring-boot
中文教程 B站“狂神说Java”Spring Boot系列(虽然有点啰嗦但适合入门)
书籍 《Spring Boot编程思想》(小马哥著,深度够)
实战项目 GitHub 搜 “spring-boot-best-practice”

别迷信“三天精通”,我花了两个月才敢独立接需求。但只要你每天坚持敲代码,60分钟能跑通,60天就能上线


最后说两句

从供应链转行做程序员,最大的感悟是:技术没有魔法,只有细节堆砌。Spring Boot 之所以流行,不是因为它多酷,而是它把企业开发中最繁琐的配置、集成、部署问题,用“约定优于配置”的理念封装好了。

上周双11大促,我们的服务扛住了峰值 5000 QPS,零故障。项目经理请全组喝喜茶,我坐在西湖边,看着手机里 curl http://localhost:8080/hello 的输出,突然觉得——这行字,真好看。

如果你也在转行路上,别怕慢。杭州的春天很短,但每个敲代码的清晨,都值得期待。

P.S. 本文所有代码已整理到 GitHub,搜 “springboot-newbie-hangzhou” 就能找到。Go 的教程我也在写,下次聊聊 Go 如何调用 Java 写的遗留系统——毕竟,现实世界哪有纯技术选型,都是缝合怪罢了。

评论 0

最热最新
暂无评论
程序员阿远Lv.1
0
影响力
0
文章
0
粉丝