SpringBoot 极速上手:从零到一构建Web应用
本文章为SpringBoot 极速上手:从零到一构建Web应用视频的整理稿件,略有修补。
SpringBoot 极速上手:从零到一构建Web应用
1. SpringBoot 简介与核心优势
1.1 什么是 SpringBoot?
SpringBoot 并非一个全新的框架,而是基于 Spring Framework 的基础上进行的一系列增强和自动化配置。其核心目标是简化 Spring 应用的初始搭建以及开发过程。 它通过“约定优于配置”(Convention over Configuration)的原则,大量减少了开发人员需要编写的样板代码和 XML 配置,从而大幅提升开发效率。 具体来说,SpringBoot 提供了以下关键特性:
- 自动配置(Auto-Configuration): SpringBoot 根据项目依赖(如 classpath 中存在的 JAR 包)自动配置 Spring 应用,例如,如果检测到
spring-boot-starter-web
依赖,它会自动配置 Tomcat 和 Spring MVC。 - 起步依赖(Starters): SpringBoot 提供了一系列“起步依赖”(Starters),这些依赖是一组预先配置好的依赖描述符,可以简化构建配置。例如,
spring-boot-starter-data-jpa
包含了使用 JPA 进行数据访问所需的所有依赖。 - 内嵌式容器(Embedded Servers): SpringBoot 默认内嵌了 Tomcat、Jetty 或 Undertow 等 Web 服务器,无需单独部署 WAR 文件。
- Actuator: 提供生产级别的特性,例如健康检查、指标收集、外部化配置等。
1.2 SpringBoot 的优势
相比传统的 Spring 应用开发,SpringBoot 带来了显著的优势:
- 简化配置: 大幅减少了 XML 配置和注解配置,大多数情况下,只需要使用默认配置即可。
- 快速开发: 借助起步依赖和自动配置,可以快速搭建项目原型并进行业务逻辑开发。
- 易于部署: 内嵌式容器使得应用可以打包成一个可执行的 JAR 文件,简化了部署流程。
- 微服务友好: SpringBoot 的轻量级和快速启动特性非常适合构建微服务架构。
- 提高生产力: 开发人员无需过多关注底层配置,可以专注于业务逻辑的实现,显著提高开发效率。
- 强大的社区支持: Spring Framework 拥有庞大的社区和丰富的文档,SpringBoot 也因此受益。
1.3 SpringBoot 与 Spring 的关系
理解 SpringBoot 与 Spring 的关系至关重要。 SpringBoot 不是 Spring 的替代品,而是 Spring 的增强和扩展。 它构建在 Spring 的核心概念(如依赖注入、面向切面编程)之上,简化了 Spring 应用的开发和部署。 可以将 SpringBoot 视为一个“脚手架”,它预先搭建好了 Spring 应用的基础设施,让开发者可以更专注于业务逻辑的实现。 Spring 依然是核心,SpringBoot 只是提供了一种更加便捷的使用方式。
2. 快速搭建 SpringBoot 项目
2.1 环境准备
在开始之前,确保已安装以下软件:
- Java Development Kit (JDK): JDK 23 。
- Maven 或 Gradle: 作为项目构建工具,我推荐使用 Maven(Gradle太难用了)。
- IDE (集成开发环境): IntelliJ IDEA 或 Vscode。
2.2 使用 Spring Initializr 创建项目
Spring Initializr 是一个 Web 应用程序,可以帮助我们快速生成 SpringBoot 项目的基础结构。 访问 https://start.spring.io/。
- Project: 选择 “Maven Project”。
- Language: 选择 “Java”。
- Spring Boot: 选择一个稳定的 SpringBoot 版本。
- Group: 输入你的组织或项目的 Group ID(默认,
com.example
)。 - Artifact: 输入你的项目名称(默认,
demo
)。 - Packaging: 选择 “Jar”。
- Java: 选择你的 JDK 版本(23)。
- Dependencies: 点击 “Add Dependencies” 按钮,添加所需的依赖。 对于一个简单的 Web 应用,添加 “Spring Web” 依赖。 如果需要使用数据库,可以添加 “Spring Data JPA” 和相应的数据库驱动(例如,“H2 Database” 用于内存数据库)。
点击 “Generate” 按钮,下载生成的 ZIP 文件,解压并导入到你的 IDE 中。
2.3 项目结构
生成的项目结构通常如下:
demo/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── demo/
│ │ │ └── DemoApplication.java // 主程序入口
│ │ └── resources/
│ │ └── application.properties // 配置文件
│ └── test/
│ └── java/
│ └── com/
│ └── example/
│ └── demo/
│ └── DemoApplicationTests.java // 测试类
├── pom.xml // Maven 项目描述文件
└── mvnw // Maven Wrapper (可选)
└── mvnw.cmd // Maven Wrapper (可选)
DemoApplication.java
: 包含main
方法,是 SpringBoot 应用的启动入口。它通常包含@SpringBootApplication
注解。application.properties
: 用于配置应用的属性,例如数据库连接、服务器端口等。也可以使用application.yml
文件(YAML 格式)。pom.xml
: Maven 项目的配置文件,包含了项目的依赖、插件等信息。
2.4 @SpringBootApplication 注解
@SpringBootApplication
是一个组合注解,它等同于同时使用 @Configuration
、@EnableAutoConfiguration
和 @ComponentScan
。
@Configuration
: 表明该类是一个配置类,可以包含@Bean
注解的方法来定义 Spring Beans。@EnableAutoConfiguration
: 启用 SpringBoot 的自动配置机制。@ComponentScan
: 告诉 Spring 扫描当前包及其子包中的组件(例如,@Controller
、@Service
、@Repository
等)。
3. 创建一个简单的 RESTful API
3.1 创建 Controller
在 com.example.demo
包下创建一个名为 HelloController
的类:
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
@RestController
: 一个组合注解,等同于@Controller
和@ResponseBody
。它表明该类是一个 RESTful 控制器,其方法的返回值将直接作为 HTTP 响应体。@GetMapping("/hello")
: 将 HTTP GET 请求映射到/hello
路径。
3.2 运行应用
在 IDE 中运行 DemoApplication
类的 main
方法,或者在项目根目录下执行 Maven 命令:
mvn spring-boot:run
应用启动后,默认会在 8080 端口监听请求。 在浏览器中访问 http://localhost:8080/hello
,你将看到 “Hello, Spring Boot!"。
3.3 添加请求参数
我们可以通过 @RequestParam
注解获取请求参数:
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
return "Hello, " + name + "!";
}
}
@RequestParam(value = "name", defaultValue = "World")
: 获取名为name
的请求参数。如果请求中没有提供name
参数,则使用默认值 “World”。
现在访问 http://localhost:8080/hello?name=SpringBoot
,你将看到 “Hello, SpringBoot!"。
3.4 使用 @PathVariable 获取路径变量
除了使用@RequestParam
获取请求参数,还可以使用@PathVariable
来获取URL路径中的变量。
package com.example.demo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
return "Hello, " + name + "!";
}
@GetMapping("/greet/{username}")
public String greet(@PathVariable("username") String username) {
return "Greetings, " + username + "!";
}
}
@PathVariable("username")
: 将 URL 路径中的{username}
部分映射到username
参数。
访问 http://localhost:8080/greet/User
,你将看到 “Greetings, User!"。
4. 数据库集成 (以 H2 为例)
4.1 添加依赖
在 pom.xml
文件中添加 Spring Data JPA 和 H2 Database 的依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
4.2 配置数据源
在 application.properties
文件中配置 H2 数据库:
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
spring.datasource.url
: 指定 H2 数据库的连接 URL。jdbc:h2:mem:testdb
表示使用内存数据库,数据库名为testdb
。spring.jpa.hibernate.ddl-auto=create-drop
: 表示在应用启动时创建数据库表,在应用关闭时删除数据库表。 在生产环境中,通常使用update
或validate
。
4.3 创建实体类
创建一个 User
实体类:
package com.example.demo;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
// Getters and setters
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;
}
}
@Entity
: 表明该类是一个 JPA 实体,对应数据库中的一张表。@Id
: 表明该字段是主键。@GeneratedValue
: 指定主键的生成策略。
Oracle将Java EE(Java Enterprise Edition)交给了Eclipse基金会管理,Eclipse基于Apache 2.0协议开发了新的版本,并将其重命名为Jakarta,以避免与Oracle的商标冲突,javax更名为jakarta。
在JPA中,如果实体类的属性或字段名是SQL保留字(如
user
),会引发问题。
4.4 创建 Repository
创建一个 UserRepository
接口,继承 JpaRepository
:
package com.example.demo;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
JpaRepository
提供了许多常用的数据库操作方法,例如 save()
, findById()
, findAll()
, delete()
等。 我们无需编写任何实现代码,SpringBoot 会自动生成实现。
4.5 在 Controller 中使用 Repository
修改 HelloController
,注入 UserRepository
并使用它来操作数据库:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class HelloController {
@Autowired
private UserRepository userRepository;
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", defaultValue = "World") String name) {
User user = new User();
user.setName(name);
userRepository.save(user);
return "Hello, " + name + "!";
}
@GetMapping("/users")
public List<User> listUsers() {
return userRepository.findAll();
}
@GetMapping("/greet/{username}")
public String greet(@PathVariable("username") String username) {
return "Greetings, " + username + "!";
}
}
@Autowired
: 自动注入UserRepository
的实例。
现在访问 http://localhost:8080/hello?name=TestUser
,会将一个名为 “TestUser” 的用户保存到数据库中。
访问 http://localhost:8080/users
,将返回所有用户的列表。
5. 测试
5.1 单元测试
SpringBoot 提供了强大的测试支持。 spring-boot-starter-test
依赖包含了 JUnit、Spring Test、AssertJ、Hamcrest 等测试框架。
在 src/test/java
目录下,DemoApplicationTests.java
已经包含了一个基本的测试类:
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class DemoApplicationTests {
@Test
void contextLoads() {
}
}
@SpringBootTest
: 表明这是一个 SpringBoot 测试类,它会加载 Spring 应用上下文。
我们可以添加更多的测试方法来测试我们的 Controller、Service、Repository 等组件。
5.2 集成测试
集成测试用于测试多个组件之间的协作。我们可以使用@SpringBootTest
和@AutoConfigureMockMvc
来模拟HTTP请求。
package com.example.demo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class DemoApplicationTests {
@Autowired
private MockMvc mockMvc;
@Test
void contextLoads() {
}
@Test
void testHelloEndpoint() throws Exception {
mockMvc.perform(get("/hello"))
.andExpect(status().isOk())
.andExpect(content().string("Hello, World!"));
}
@Test
void testGreetEndpoint() throws Exception {
mockMvc.perform(get("/greet/TestUser"))
.andExpect(status().isOk())
.andExpect(content().string("Greetings, TestUser!"));
}
}
@AutoConfigureMockMvc
: 自动配置MockMvc
实例,MockMvc
可以模拟HTTP请求。mockMvc.perform(get("/hello"))
: 模拟发送一个GET请求到/hello
。.andExpect(status().isOk())
: 期望HTTP状态码为200 OK。.andExpect(content().string("Hello, World!"))
: 期望响应内容为"Hello, World!"。
运行mvn test
进行测试。
小结
今天介绍了 SpringBoot 的基本概念、核心优势以及如何快速搭建一个 SpringBoot 应用,并集成了 H2 数据库和进行了简单的测试。 SpringBoot 的强大之处在于其自动化配置、起步依赖和内嵌式容器,这些特性极大地简化了 Spring 应用的开发和部署。
未来,可以进一步探索 SpringBoot 的高级特性:
- Spring Security: 用于实现应用的安全性。
- Spring Cloud: 用于构建分布式系统和微服务。
- Spring Boot Actuator: 用于监控和管理应用。
- 使用不同的数据库: 例如 MySQL、PostgreSQL、MongoDB 等。
- 异步处理: 使用
@Async
注解和CompletableFuture
。 - 缓存: 使用
@Cacheable
、@CachePut
、@CacheEvict
等注解。
SpringBoot 是一个非常强大且灵活的框架,值得深入学习和掌握,虽然我不喜欢。
接下来进行一些美化工作,麻雀虽小五脏俱全。
为了让 SpringBoot 返回一个包含 CSS 和 JavaScript 的网页,我们需要做以下几处修改:
- 静态资源处理: SpringBoot 默认会将
/src/main/resources/static
目录下的文件作为静态资源(如 CSS、JavaScript、图片等)提供。 - Thymeleaf 模板引擎): 为了更方便地构建动态 HTML 页面,我们可以使用 Thymeleaf 模板引擎。当然,也可以直接返回静态 HTML 文件。
- Controller 修改: 修改 Controller,让其返回一个视图名称(View Name),而不是直接返回字符串。 SpringBoot 会根据视图名称查找对应的模板文件(如果使用了模板引擎)或静态 HTML 文件。
- 创建HTML,CSS,JS文件 在
/src/main/resources/static
目录下分别创建。
使用 Thymeleaf 模板引擎):
1. 添加 Thymeleaf 依赖 (pom.xml):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2. 修改 HelloController:
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller; // 注意:这里改为 @Controller
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@Controller // 使用 @Controller,而不是 @RestController
public class HelloController {
@Autowired
private UserRepository userRepository;
@GetMapping("/hello")
public String hello(@RequestParam(value = "name", defaultValue = "World") String name, Model model) {
User user = new User();
user.setName(name);
userRepository.save(user);
model.addAttribute("name", name); // 将 name 属性添加到 Model 中
return "hello"; // 返回视图名称 "hello"
}
@GetMapping("/users")
public String listUsers(Model model) {
List<User> users = userRepository.findAll();
model.addAttribute("users", users);
return "users"; // 返回视图名称 "users"
}
@GetMapping("/greet/{username}")
public String greet(@PathVariable("username") String username, Model model) {
model.addAttribute("username", username);
return "greet"; //返回视图名称 "greet"
}
}
@Controller
: 使用@Controller
注解,表明该类是一个控制器,用于处理 Web 请求并返回视图。Model
:Model
对象用于将数据传递给视图。return "hello";
: 返回视图名称 “hello”。 Thymeleaf 会在/src/main/resources/templates
目录下查找名为hello.html
的模板文件。
3. 创建 Thymeleaf 模板文件 (hello.html):
在 /src/main/resources/templates
目录下创建 hello.html
文件:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Hello, Spring Boot!</title>
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}">
</head>
<body>
<h1 th:text="'Hello, ' + ${name} + '!'"></h1>
<p>This is a beautiful webpage powered by Spring Boot, Thymeleaf, CSS, and JavaScript.</p>
<button onclick="showAlert()">Click Me!</button>
<script th:src="@{/js/script.js}"></script>
</body>
</html>
xmlns:th="http://www.thymeleaf.org"
: 声明 Thymeleaf 命名空间。th:href="@{/css/style.css}"
: 使用 Thymeleaf 的th:href
属性和@
语法来引用静态资源。SpringBoot 会自动处理/css/style.css
路径。th:text="'Hello, ' + ${name} + '!'"
: 使用 Thymeleaf 的th:text
属性来显示动态内容。${name}
会被替换为 Model 中name
属性的值。<script th:src="@{/js/script.js}"></script>
: 引用外部JavaScript文件。
4. 创建 CSS 文件 (style.css):
在 /src/main/resources/static/css
目录下创建 style.css
文件:
body {
font-family: sans-serif;
background-color: #f0f0f0;
text-align: center;
padding: 50px;
}
h1 {
color: #333;
}
button {
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
cursor: pointer;
}
5. 创建 JavaScript 文件 (script.js):
在 /src/main/resources/static/js
目录下创建 script.js
文件:
function showAlert() {
alert("Hello from JavaScript!");
}
6. 创建 users.html (用于 /users 路径):
在 /src/main/resources/templates
目录下创建 users.html
:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>User List</title>
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}">
</head>
<body>
<h1>User List</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.id}"></td>
<td th:text="${user.name}"></td>
</tr>
</tbody>
</table>
<script th:src="@{/js/script.js}"></script>
</body>
</html>
th:each="user : ${users}"
: Thymeleaf 的循环指令,用于遍历users
列表。th:text="${user.id}"
和**th:text="${user.name}"
**: 显示用户的id和name。
7. 创建 greet.html (用于 /greet/{username} 路径):
在 /src/main/resources/templates
目录下创建 greet.html
:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Greetings</title>
<link rel="stylesheet" type="text/css" th:href="@{/css/style.css}">
</head>
<body>
<h1 th:text="'Greetings, ' + ${username} + '!'"></h1>
<script th:src="@{/js/script.js}"></script>
</body>
</html>
8. 运行和测试:
运行 DemoApplication
,然后在浏览器中访问:
http://localhost:8080/hello
http://localhost:8080/hello?name=DNG
http://localhost:8080/users
http://localhost:8080/greet/TestUser
现在,你应该能看到一个包含 CSS 样式和 JavaScript 功能的精美网页。
点击 “Click Me!” 按钮会弹出一个 JavaScript 警告框。
小结
- 静态资源: 将 CSS、JavaScript 和图片等静态资源放在
/src/main/resources/static
目录下。 - Thymeleaf (可选): 使用 Thymeleaf 模板引擎可以更方便地构建动态 HTML 页面,并使用
@
语法引用静态资源。 @Controller
: 使用@Controller
注解处理 Web 请求并返回视图。Model
: 使用Model
对象将数据传递给视图。- 视图名称: Controller 方法返回视图名称,SpringBoot 会根据视图名称查找对应的模板文件或静态 HTML 文件。
- 文件结构: 确保文件结构符合SpringBoot的规范。
/src/main/resources/static
用于静态资源,/src/main/resources/templates
用于Thymeleaf模板。