1. 教程概述

本教程面向零基础或刚接触 Spring Boot 的开发者,从环境部署、Maven 配置、项目创建、代码编写到运行验证,一步步带你跑通一个完整的入门实战项目。教程以 Windows 系统为例,其他操作系统操作步骤基本一致。

2. 环境部署

2.1 JDK 安装与配置

Spring Boot 3.x 要求 JDK 17 及以上版本,本教程以 JDK 17 为例。

  1. 前往 Oracle 官网或 Adoptium 下载 JDK 17 安装包。
  2. 双击安装包,按提示完成安装,建议安装到默认路径。
  3. 配置环境变量:右键「此电脑」→「属性」→「高级系统设置」→「环境变量」。
  4. 新建系统变量 JAVA_HOME,值为 JDK 安装路径,例如 C:\Program Files\Java\jdk-17
  5. 编辑 Path 变量,新增 %JAVA_HOME%\bin
  6. 打开命令行,输入 java -version 验证安装是否成功。

2.2 IDE 安装

推荐使用 IntelliJ IDEA 社区版(免费)或 Eclipse。本教程以 IntelliJ IDEA 为例。

  1. 前往 JetBrains 官网下载 IntelliJ IDEA Community 版。
  2. 双击安装包,按提示完成安装。
  3. 首次启动时,选择主题并导入设置即可。

3. Maven 配置

3.1 Maven 下载与安装

  1. 前往 Maven 官网下载二进制压缩包,例如 apache-maven-3.9.6-bin.zip
  2. 解压到本地目录,例如 D:\apache-maven-3.9.6
  3. 新建系统变量 MAVEN_HOME,值为 Maven 解压路径。
  4. 编辑 Path 变量,新增 %MAVEN_HOME%\bin
  5. 命令行输入 mvn -version 验证安装是否成功。

3.2 配置阿里云镜像

国内访问 Maven 中央仓库较慢,建议配置阿里云镜像加速依赖下载。编辑 Maven 安装目录下 conf/settings.xml,在 <mirrors> 节点内添加以下内容:

<mirror>
    <id>aliyunmaven</id>
    <mirrorOf>central</mirrorOf>
    <name>阿里云公共仓库</name>
    <url>https://maven.aliyun.com/repository/public</url>
</mirror>

3.3 在 IDEA 中配置 Maven

  1. 打开 IDEA,进入 File → Settings → Build, Execution, Deployment → Build Tools → Maven
  2. Maven home path 指向本地 Maven 安装目录。
  3. User settings file 指向 conf/settings.xml
  4. 点击 ApplyOK 保存配置。

4. 创建 Spring Boot 项目

4.1 使用 Spring Initializr 创建项目

  1. 打开 IDEA,选择 New Project
  2. 左侧选择 Spring Initializr,填写项目信息:Group 为 com.example,Artifact 为 demo,Type 选择 Maven,Java 版本选择 17
  3. 点击 Next,在依赖选择页面勾选 Spring Web
  4. 点击 Finish,等待 IDEA 自动下载依赖并完成项目初始化。

4.2 项目结构说明

创建完成后,项目结构如下:

  • src/main/java:存放 Java 源码。
  • src/main/resources:存放配置文件和静态资源。
  • src/test/java:存放测试代码。
  • pom.xml:Maven 项目配置文件。

5. 代码展示与实操

5.1 编写启动类

项目会自动生成一个启动类 DemoApplication.java,代码如下:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

5.2 编写实体类

com.example.demo 包下新建 entity 子包,然后创建 User.java 实体类:

package com.example.demo.entity;

public class User {

    private Long id;
    private String name;
    private String email;

    public User() {
    }

    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

5.3 编写 Repository

com.example.demo 包下新建 repository 子包,然后创建 UserRepository.java,这里使用内存 Map 模拟数据存储:

package com.example.demo.repository;

import com.example.demo.entity.User;
import org.springframework.stereotype.Repository;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

@Repository
public class UserRepository {

    private final Map<Long, User> store = new ConcurrentHashMap<>();
    private final AtomicLong idGenerator = new AtomicLong(1);

    public User save(User user) {
        if (user.getId() == null) {
            user.setId(idGenerator.getAndIncrement());
        }
        store.put(user.getId(), user);
        return user;
    }

    public User findById(Long id) {
        return store.get(id);
    }

    public Map<Long, User> findAll() {
        return store;
    }

    public void deleteById(Long id) {
        store.remove(id);
    }
}

5.4 编写 Controller

com.example.demo 包下新建 controller 子包,然后创建 UserController.java,提供增删改查接口:

package com.example.demo.controller;

import com.example.demo.entity.User;
import com.example.demo.repository.UserRepository;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RestController
@RequestMapping("/users")
public class UserController {

    private final UserRepository userRepository;

    public UserController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @PostMapping
    public User create(@RequestBody User user) {
        return userRepository.save(user);
    }

    @GetMapping
    public Map<Long, User> list() {
        return userRepository.findAll();
    }

    @GetMapping("/{id}")
    public User getById(@PathVariable Long id) {
        return userRepository.findById(id);
    }

    @PutMapping("/{id}")
    public User update(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userRepository.save(user);
    }

    @DeleteMapping("/{id}")
    public void delete(@PathVariable Long id) {
        userRepository.deleteById(id);
    }
}

5.5 全局异常处理

为了让接口在出错时返回统一的错误信息,在 com.example.demo 包下新建 exception 子包,然后创建 GlobalExceptionHandler.java,使用 @RestControllerAdvice@ExceptionHandler 统一处理异常:

package com.example.demo.exception;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.util.Map;

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 用户不存在,返回 404
    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<Map<String, Object>> handleUserNotFound(UserNotFoundException e) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(Map.of("code", 404, "message", e.getMessage()));
    }

    // 请求参数错误,返回 400
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<Map<String, Object>> handleBadRequest(IllegalArgumentException e) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(Map.of("code", 400, "message", e.getMessage()));
    }
}

同时,在 exception 子包下创建自定义异常类 UserNotFoundException.java

package com.example.demo.exception;

public class UserNotFoundException extends RuntimeException {

    public UserNotFoundException(String message) {
        super(message);
    }
}

为了让查询和删除接口在用户不存在时抛出该异常,需要修改 UserController.java 中的 getByIddelete 方法:

@GetMapping("/{id}")
public User getById(@PathVariable Long id) {
    User user = userRepository.findById(id);
    if (user == null) {
        throw new UserNotFoundException("用户不存在,id: " + id);
    }
    return user;
}

@DeleteMapping("/{id}")
public void delete(@PathVariable Long id) {
    User user = userRepository.findById(id);
    if (user == null) {
        throw new UserNotFoundException("用户不存在,id: " + id);
    }
    userRepository.deleteById(id);
}

对应的错误响应 JSON 格式示例如下:

  • 用户不存在(404){"code":404,"message":"用户不存在,id: 99"}
  • 请求参数错误(400){"code":400,"message":"参数错误"}

5.6 配置 application.properties

在配置数据库连接之前,需要先在 MySQL 中创建数据库。打开命令行,登录 MySQL 后执行以下 SQL 语句创建数据库:

CREATE DATABASE demo DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

其中 demo 是数据库名称,需要与 application.properties 中的连接地址保持一致。执行成功后,可以在 src/main/resources 目录下的 application.properties 文件中配置服务端口、数据库连接等信息:

server.port=8080
spring.application.name=demo
数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
JPA 配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

同时,需要在 pom.xml 中添加 MySQL 驱动和 Spring Data JPA 依赖:

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

src/main/resources 目录下的 application.properties 文件中,可以配置服务端口等信息:

server.port=8080
spring.application.name=demo

5.7 数据库实体与 Repository

为了让数据持久化到 MySQL,需要改造实体类和 Repository。首先修改 User.java,添加 JPA 注解。注意 Spring Boot 3.x 使用 jakarta.persistence 包,且 user 是 MySQL 保留字,表名使用 t_user 避免冲突:

package com.example.demo.entity;

import jakarta.persistence.*;

@Entity
@Table(name = "t_user")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String email;

    public User() {
    }

    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }
}

然后修改 UserRepository.java,继承 JpaRepository 接口:

package com.example.demo.repository;

import com.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

由于 JpaRepository 已提供 savefindByIdfindAlldeleteById 等方法,Controller 中的代码无需改动即可正常工作。

5.8 前端页面

src/main/resources/static 目录下创建 index.html,通过简单的 JavaScript 调用后端接口,实现用户管理页面:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>用户管理</title>
</head>
<body>
    <h1>用户管理</h1>

    <form id="userForm">
        <input type="text" id="name" placeholder="姓名" required>
        <input type="email" id="email" placeholder="邮箱" required>
        <button type="submit">新增用户</button>
    </form>

    <ul id="userList"></ul>

    <script>
        const api = 'http://localhost:8080/users';

        async function loadUsers() {
            const res = await fetch(api);
            const users = await res.json();
            const list = document.getElementById('userList');
            list.innerHTML = '';
            Object.values(users).forEach(user => {
                const li = document.createElement('li');
                li.textContent = user.id + ' - ' + user.name + ' (' + user.email + ')';
                list.appendChild(li);
            });
        }

        document.getElementById('userForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            const name = document.getElementById('name').value;
            const email = document.getElementById('email').value;
            await fetch(api, {
                method: 'POST',
                headers: {'Content-Type': 'application/json'},
                body: JSON.stringify({name, email})
            });
            document.getElementById('name').value = '';
            document.getElementById('email').value = '';
            loadUsers();
        });

        loadUsers();
    </script>
</body>
</html>

启动项目后,在浏览器访问 http://localhost:8080/index.html 即可看到用户管理页面,实现新增和查看用户的功能。

6. 运行与验证

6.1 启动项目

在 IDEA 中直接运行 DemoApplicationmain 方法,控制台出现以下日志表示启动成功:

Tomcat started on port(s): 8080 (http) with context path ''
Started DemoApplication in 2.5 seconds

6.2 访问接口验证

项目启动成功后,可以通过浏览器或 Postman 等工具访问以下接口进行验证:

  • 新增用户:向 http://localhost:8080/users 发送 POST 请求,请求体为 JSON,例如 {"name":"张三","email":"zhangsan@example.com"},返回新增后的用户信息。
  • 查询用户列表:访问 http://localhost:8080/users,页面返回所有用户信息。
  • 查询单个用户:访问 http://localhost:8080/users/1,返回 id 为 1 的用户信息。
  • 更新用户:向 http://localhost:8080/users/1 发送 PUT 请求,请求体为 JSON,例如 {"name":"李四","email":"lisi@example.com"},返回更新后的用户信息。
  • 删除用户:向 http://localhost:8080/users/1 发送 DELETE 请求,删除 id 为 1 的用户。

例如,在浏览器中访问 http://localhost:8080/users,页面显示 {} 表示当前没有用户数据;新增用户后再访问,即可看到刚添加的用户信息。

7. 常见问题与总结

7.1 常见问题

  • 端口被占用:修改 application.properties 中的 server.port 为其他端口。
  • 依赖下载缓慢:确认阿里云镜像配置是否正确。
  • JDK 版本不匹配:确认项目 JDK 版本与本地安装版本一致。

7.2 总结

本教程带你完成了 Spring Boot 入门实战的完整流程:从 JDK 和 IDE 的环境部署,到 Maven 的安装与镜像配置,再到项目的创建、代码编写和运行验证。掌握这些基础后,你可以继续深入学习 Spring Boot 的数据库操作、接口开发、热部署等进阶内容。

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐