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

#徐洋
2025-12-14 15:19
阅读 5202

大家好,我是老K。前某中型电商公司的技术总监,现在已经从996的牢笼里跳出来,在成都这座“巴适得板”的城市准备搞自己的小创业项目。每天早上8点准时泡上一壶茉莉花茶,打开VS Code,开始写代码——不是为了赶双11大促的上线 deadline,而是为了自己真正想做的东西。

上周五晚上,我一边刷BOSS直聘(别笑,简历还在悄悄更新),一边翻自己以前写的项目,突然想起一个事儿:去年带新人的时候,有个实习生问我:“K哥,Spring Boot到底怎么用啊?我看网上教程要么太浅,要么直接上微服务、Nacos、Sentinel那一套,头都大了。” 当时我随口回了句“照着官方文档走就行”,结果那小子三天后跑来跟我说:“K哥,你这‘照着走’三个字,差点让我在公司过夜。”

于是今天,趁着创业还没正式开干、咖啡还没凉,我决定写一篇真正能60分钟上手的Spring Boot实战教程。不讲八股文,不堆概念,就聚焦一件事:让你写个能跑起来的后端接口,顺便还能爬点数据玩玩。

为啥要结合爬虫?因为我自己最近就在用Go写一个竞品监控工具(对,就是那种偷偷看对手价格变没变的玩意儿),但有些轻量级任务,用Java+Spring Boot反而更快搭原型。而且,很多同学学Spring Boot就是为了做毕设或者加到简历里充门面——那不如直接做个带爬虫功能的API服务,面试时还能多聊两句。


背景:为什么是现在?

去年双11前,我们团队被产品经理逼着三天内上线一个“商品舆情分析”模块。需求很简单:抓取某宝评论,分析情绪。当时我第一反应是“用Python啊!”,但运维老王一脸苦相:“K哥,Python服务部署起来太麻烦了,日志、监控、告警全要单独配,能不能用Java?咱们K8s集群都是Java应用……”

行吧,那就Spring Boot。结果发现,其实用Spring Boot写个HTTP爬虫服务,比想象中简单得多。而且性能还行——毕竟Netty底子在那儿。

所以这篇教程的核心目标很明确:

  • 60分钟内,用Spring Boot搭建一个RESTful API服务
  • 集成一个简单的网页爬虫(比如抓取某个公开页面)
  • 能把数据存到数据库(哪怕只是H2内存库)
  • 最终打包成jar,本地能跑,部署也不慌

准备工作:别被环境劝退

先确认你装了这些:

  • JDK 17(别问为啥不是8,2024年了兄弟)
  • Maven 或 Gradle(我用Maven,但Gradle党也别急,差别不大)
  • 一个IDE(IntelliJ IDEA 社区版就行,别再用Eclipse了,真的)
  • Postman 或 curl(测试接口用)

然后,去 https://start.spring.io 生成项目。我选的配置如下:

选项 值
Project Maven
Language Java
Spring Boot 3.2.x
Group com.example
Artifact springboot-crawler-demo
Dependencies Spring Web, Spring Data JPA, H2 Database, Lombok

Lombok 是个好东西,省掉一堆getter/setter。别听那些“影响可读性”的老古董BB,现代Java开发没Lombok就像吃火锅不蘸油碟——难受。

点击“Generate”,下载zip,解压导入IDE。搞定,项目骨架就有了。


第一步:写个Hello World,先让服务跑起来

打开 DemoApplication.java,它长这样:

@SpringBootApplication
public class SpringbootCrawlerDemoApplication {
    public static void void main(String[] args) {
        SpringApplication.run(SpringbootCrawlerDemoApplication.class, args);
    }
}

没错,就这。现在直接运行 main 方法,你会看到控制台输出:

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

访问 http://localhost:8080,应该会返回404——正常,因为我们还没写任何接口。

新建一个Controller:

@RestController
@RequestMapping("/api")
public class HelloController {

    @GetMapping("/hello")
    public String sayHello() {
        return "Hello from Chengdu! ☕️";
    }
}

重启,访问 http://localhost:8080/api/hello,看到那句成都问候,恭喜你,Spring Boot服务跑起来了!

划重点:@RestController = @Controller + @ResponseBody,直接返回JSON或字符串,不用写视图层。我们做API服务,基本都用这个。


第二步:加个爬虫,别光说不练

现在,我们要实现一个接口:GET /api/crawl?url=xxx,传入一个URL,返回该页面的标题。

先加依赖。编辑 pom.xml,加上Jsoup(Java里最友好的HTML解析库):

<dependency>
    <groupId>org.jsoup</groupId>
    <artifactId>jsoup</artifactId>
    <version>1.17.2</version>
</dependency>

然后写爬虫逻辑:

@Service
@Slf4j // Lombok注解,自动注入logger
public class WebCrawlerService {

    public String extractTitle(String url) {
        try {
            Document doc = Jsoup.connect(url)
                    .userAgent("Mozilla/5.0 (compatible; CrawlerBot/1.0)")
                    .timeout(5000)
                    .get();
            return doc.title();
        } catch (IOException e) {
            log.error("Failed to crawl URL: {}", url, e);
            throw new RuntimeException("Crawl failed: " + e.getMessage());
        }
    }
}

再写个Controller调用它:

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

    private final WebCrawlerService crawlerService;

    @GetMapping("/crawl")
    public ResponseEntity<Map<String, String>> crawl(@RequestParam String url) {
        String title = crawlerService.extractTitle(url);
        Map<String, String> result = Map.of("url", url, "title", title);
        return ResponseEntity.ok(result);
    }
}

启动服务,试试:

curl "http://localhost:8080/api/crawl?url=https://www.zhihu.com"

如果返回类似:

{"url":"https://www.zhihu.com","title":"知乎 - 有问题,就会有答案"}

那就说明爬虫跑通了!注意:有些网站会反爬(比如加验证码、限流),这里只是演示原理。生产环境请遵守robots.txt,别乱爬!

吐槽一句:之前有个测试同事拿这个接口去爬我们自家后台,结果触发了风控,运维半夜打电话问我“谁在DDoS?”——我当时真的想砸电脑。


第三步:把数据存下来,简历才有料

光爬不存,等于白干。现在加个实体,把每次爬取记录存到数据库。

先定义Entity:

@Entity
@Table(name = "crawl_record")
@Data // Lombok:getter/setter/toString等
@NoArgsConstructor
@AllArgsConstructor
public class CrawlRecord {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String url;
    private String title;
    private LocalDateTime crawledAt;
}

Repository接口(Spring Data JPA的魔法):

public interface CrawlRecordRepository extends JpaRepository<CrawlRecord, Long> {
}

修改Service,保存记录:

@Service
@Slf4j
@RequiredArgsConstructor
public class WebCrawlerService {

    private final CrawlRecordRepository recordRepo;

    public String extractTitle(String url) {
        try {
            Document doc = Jsoup.connect(url)
                    .userAgent("Mozilla/5.0")
                    .timeout(5000)
                    .get();
            String title = doc.title();

            // 保存记录
            CrawlRecord record = new CrawlRecord();
            record.setUrl(url);
            record.setTitle(title);
            record.setCrawledAt(LocalDateTime.now());
            recordRepo.save(record);

            return title;
        } catch (IOException e) {
            log.error("Crawl failed for URL: {}", url, e);
            throw new RuntimeException("Crawl error: " + e.getMessage());
        }
    }
}

重启应用,再调一次 /api/crawl,然后访问H2控制台:

  • 浏览器打开 http://localhost:8080/h2-console
  • JDBC URL 填 jdbc:h2:mem:testdb
  • 用户名 sa,密码留空
  • 点击 Connect

执行 SELECT * FROM crawl_record;,就能看到你的爬取记录!

小贴士:H2是内存数据库,重启就丢数据。但作为开发阶段的快速验证,足够了。真要上线,换成MySQL或PostgreSQL,只需改两行配置(后面说)。


第四步:配置优化 & 生产准备

虽然我们目标是60分钟上手,但别把demo当生产。这里分享几个我在职时踩过的坑:

1. 配置文件别硬编码

application.yml 里加点配置:

app:
  crawler:
    timeout: 5000
    user-agent: "MyCrawler/1.0"

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    driver-class-name: org.h2.Driver
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: false # 开发可以开true,生产务必关!

然后在Service里用 @Value 注入:

@Value("${app.crawler.timeout}")
private int timeout;

@Value("${app.crawler.user-agent}")
private String userAgent;

2. 异常处理要优雅

现在如果URL无效,会返回500错误。加个全局异常处理器:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<Map<String, String>> handleRuntime(RuntimeException ex) {
        Map<String, String> error = Map.of("error", ex.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }
}

这样,非法请求会返回400 + 友好提示,而不是堆栈信息(线上千万别暴露堆栈!)。

3. 打包部署

在项目根目录执行:

./mvnw clean package

生成 target/springboot-crawler-demo-0.0.1-SNAPSHOT.jar

运行:

java -jar target/*.jar

搞定!这个jar自带Tomcat,不需要额外装Web服务器。这才是Spring Boot的精髓:开箱即用。

我们之前上线新服务,运维老王再也不用求爷爷告奶奶配Nginx了,直接丢jar包,systemd托管,日志用logback按天切割——香得很。


性能与扩展:别只顾跑通

虽然这是入门教程,但作为前技术总监,我得提两句架构上的事:

  • 爬虫别阻塞主线程:现在的实现是同步的,高并发下会卡死。生产环境要用 @Async 或消息队列(比如RabbitMQ)解耦。
  • 限流防刷:加个Redis计数器,防止被人当免费代理用。
  • 连接池:Jsoup默认没有连接池,高频请求建议用OkHttp + 连接池管理。
  • 监控:加上Actuator,暴露 /actuator/health,方便K8s探活。

不过这些,等你60分钟上手之后再考虑吧。先跑起来,再优化。


为什么我要写这篇教程?

说实话,我见过太多人学Spring Boot,卡在“环境配不通”、“依赖冲突”、“启动报错看不懂”上,最后放弃。而实际上,Spring Boot的设计哲学就是“约定优于配置” ——你只要按它的套路走,大部分事情它都帮你搞定了。

我离职前最后一周,帮一个想转Java的前端同事搭环境。他之前用Go写过爬虫(Go确实快,goroutine天生适合IO密集型任务),但公司要求用Java。我花了20分钟带他跑通上面这个demo,他眼睛一亮:“原来Java也能这么轻量?”

所以,别被“企业级”、“微服务”、“分布式事务”吓到。Spring Boot的起点,就是一个main方法 + 一个Controller。


最后:关于简历和Go

我知道很多人学Spring Boot是为了丰富简历。那我建议:别只写“熟悉Spring Boot”,而是写“使用Spring Boot开发了XX爬虫服务,支持日均10万次请求,QPS 200+”。

至于Go?我自己的创业项目后端主力语言就是Go——简洁、高效、部署方便。但技术选型要看场景。如果你团队全是Java栈,硬上Go反而增加维护成本。

Spring Boot依然是国内Java后端的事实标准。掌握它,不是为了卷,而是为了拥有选择权。


好了,60分钟到了吗?希望你已经跑起了自己的第一个Spring Boot服务。

代码我放GitHub了(搜 k-chengdu/springboot-crawler-demo),欢迎star(虽然我现在不靠这个找工作了 😄)。

下次见。我得去改我的BP了——创业狗的日子,也不比996轻松多少啊。

成都的太阳出来了,该去人民公园喝杯盖碗茶了。代码可以等,生活不能。

评论 0

最热最新
暂无评论
#徐洋Lv.1
0
影响力
0
文章
0
粉丝