Spring Boot 整合 Web 开发并不是一个复杂的操作,它主要依靠 spring-boot-starter-web 这个启动器来完成。当我们把该依赖加入项目后,Spring Boot 会借助自动配置机制将内嵌的 Tomcat 服务器、Spring MVC 框架和 JSON 处理组件全部装配好,开发者只需要关注业务代码即可。这种开箱即用的体验,让 Web 应用开发的门槛大幅降低。

理解 spring-boot-starter-web 的自动配置原理
spring-boot-starter-web 实际上是一个聚合依赖,它内部包含了 spring-web、spring-webmvc、jackson-databind、spring-boot-starter-tomcat 等核心组件。在传统的 Spring 项目中,开发者需要自己创建 Spring 容器、配置 DispatcherServlet、手动扫描 Controller,并且还要针对 JSON 转换器进行繁琐的设置。而在 Spring Boot 中,这些工作全部由自动配置类接管。其中 WebMvcAutoConfiguration 是最关键的配置类,它会在类路径上存在 spring-webmvc 时自动生效,并注册 DispatcherServlet、HandlerMapping、HandlerAdapter 等核心 Bean。
除了 WebMvcAutoConfiguration 之外,ServletWebServerFactoryAutoConfiguration 负责创建内嵌的 Web 服务器。默认情况下,直接运行 Spring Boot 应用,它就会在本机启动一个监听 8080 端口的 Tomcat。开发者可以通过 application.properties 文件修改端口、上下文路径等参数。比如设置 server.port=9090,应用就会在 9090 端口启动。这种自动化的装配方式,彻底摆脱了传统 SSH 工程中那些令人头疼的 web.xml 配置文件。
创建第一个 REST 接口
理解自动配置之后,我们就可以开始编写接口了。一个最简单的 Web 接口需要借助 @RestController 注解来标记类,并且通过 @GetMapping、@PostMapping 等注解声明请求路径。下面的代码演示了一个返回字符串的接口。注意这里使用了 @GetMapping 将 HTTP GET 请求映射到 /hello 路径。
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 Web!";
}
}
启动应用后,访问 http://localhost:8080/hello 就能在浏览器中看到返回的字符串。因为 @RestController 等同于 @Controller 加 @ResponseBody,所以方法返回的内容会直接写入 HTTP 响应体。如果使用 @Controller,则返回的是视图名称,需要配合模板引擎来渲染页面。这种区别在实际开发中非常关键,需要根据接口类型来选择。
除了返回字符串,方法同样可以直接返回 Java 对象。例如返回一个 Map 或者自定义实体类,Spring Boot 会利用 Jackson 库自动将一个对象转换为 JSON 格式。这个过程完全依赖 HttpMessageConverter 机制,是最常用的数据交互方式。下面我们来看一个返回实体对象的完整例子。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
@RestController
public class InfoController {
@GetMapping("/info")
public Map<String, Object> info() {
Map<String, Object> data = new HashMap<>();
data.put("appName", "demo");
data.put("time", LocalDateTime.now().toString());
return data;
}
}
这里返回的是一个 Map,但实际上项目里更推荐返回自定义的实体对象。因为实体对象具有更清晰的类型定义,也更便于维护和测试。Spring Boot 的自动配置会为 Jackson 选择合适的 ObjectMapper,使 LocalDateTime、Date 等类型也能按照配置的格式输出。
接收请求参数
Web 开发中,接口往往需要接收前端传来的参数。Spring MVC 提供了多种参数绑定方式,包括 @RequestParam、@PathVariable 和 @RequestBody。它们分别对应查询参数、路径变量和请求体。下面的接口演示了前两种方式的用法。
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/user")
public class UserController {
@GetMapping("/query")
public String query(@RequestParam("name") String name,
@RequestParam(value = "age", required = false) Integer age) {
return "查询用户:" + name + ", 年龄:" + age;
}
@GetMapping("/detail/{id}")
public String detail(@PathVariable("id") Long id) {
return "用户ID:" + id;
}
}
@RequestParam 用于获取 URL 中的查询参数,例如 /api/user/query?name=张三&age=20 会将 name 和 age 分别绑定到方法的参数上。默认情况下 @RequestParam 是必填参数,如果请求中没有携带,会抛出异常。我们可以通过 required = false 将其设置为可选参数。@PathVariable 则适合 RESTful 风格的设计,将 URL 路径中的一部分作为参数,例如 /api/user/detail/100 就会把 100 传给 id 参数。
当请求方式是 POST 且客户端发送 JSON 数据时,可以使用 @RequestBody 将请求体直接绑定到实体类。这个解析过程同样由 Jackson 完成。假设有一个 User 实体类,包含 name 和 age 字段,下面的代码可以接收 JSON 格式的请求体。注意实体类需要提供 getter 和 setter 方法,否则 Jackson 无法完成反序列化。
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserSaveController {
@PostMapping("/user")
public User save(@RequestBody User user) {
user.setId(1L);
return user;
}
static class User {
private Long id;
private String name;
private Integer age;
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 Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
}
}
这样一个简单的 POST 接口就完成了。当客户端向 /user 发送 JSON 数据时,Spring Boot 会自动将 JSON 中的字段映射到 User 对象的属性上。如果字段对应不上,我们还可以在实体类属性上添加 @JsonProperty 注解来指定 JSON 字段名,实现更灵活的数据绑定。
静态资源与模板引擎
Spring Boot Web 并不只能提供 JSON 接口,它同样支持静态资源和模板页面。默认情况下,classpath 下的 /static、/public、/resources 和 /META-INF/resources 目录都会被视为静态资源目录。开发者只需要将 HTML、CSS、JavaScript 文件放入这些目录,就可以通过对应的 URL 直接访问。例如把 index.html 放在 src/main/resources/static 目录下,访问 http://localhost:8080/index.html 即可看到页面。
如果需要渲染动态页面,可以引入模板引擎。Spring Boot 官方推荐使用 Thymeleaf。在 pom.xml 中添加 spring-boot-starter-thymeleaf 依赖后,Spring Boot 会自动配置 Thymeleaf 的视图解析器。开发者只需将 HTML 模板放在 templates 目录下,并在 Controller 中返回视图名称即可。下面展示了添加依赖时所需的部分配置。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
使用 @Controller 而不是 @RestController 时,在处理方法中返回的字符串会被当作视图名称,Spring Boot 会自动去 templates 目录下查找对应的模板文件。例如在 templates 目录下创建 index.html,然后在 Controller 中返回 index,就能渲染出一个完整的页面。此时如果需要返回 JSON 数据,可以在方法上单独添加 @ResponseBody 注解,这就实现了接口和页面灵活共存的开发模式。
定制 JSON 序列化
在实际项目中,后端返回给前端的 JSON 格式往往需要统一。比如日期字段要格式化为 yyyy-MM-dd HH:mm:ss,空值字段不输出等。Spring Boot 允许通过修改 application.properties 文件或编写配置类来调整 Jackson 的序列化行为。最常用的全局配置如下。
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss spring.jackson.time-zone=GMT+8 spring.jackson.default-property-inclusion=non_null
这段配置会将日期格式统一为中国的常用时间格式,同时忽略值为 null 的字段。于是返回的 JSON 中不会再出现大量无意义的字段,减轻了网络传输的压力。这些配置对 Spring Boot 自动配置的 Jackson 对象直接生效,无需额外实现任何代码。
如果需要更复杂的定制,比如关闭时间戳输出,或者注册自定义的序列化器,可以通过编写配置类实现 Jackson2ObjectMapperBuilderCustomizer。下面这段代码演示了如何关闭日期时间序列化为时间戳的功能。这种方式更灵活,也更容易维护。
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.fasterxml.jackson.databind.SerializationFeature;
@Configuration
public class JacksonConfig {
@Bean
public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
return builder -> builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
}
}
通过这种方式,我们可以在不影响 Spring Boot 自动配置的前提下,灵活调整 ObjectMapper 的行为。例如注册 JavaTimeModule、设置忽略未知属性,或者为特定类型添加自定义序列化器。掌握这些定制技巧,可以保证前后端交互的数据格式始终处于可控状态。
统一异常处理
Web 应用必须妥善处理异常,否则当程序抛出错误时,客户端会直接收到一堆堆栈信息,既不安全也不友好。Spring Boot Web 提供了 @RestControllerAdvice 注解,可以捕获全局异常并转换为统一的 JSON 错误响应。这是一个非常实用且高频使用的功能,能大大提升接口的健壮性。
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Map<String, Object> handleException(Exception e) {
Map<String, Object> result = new HashMap<>();
result.put("code", 500);
result.put("message", e.getMessage());
return result;
}
}
当任意 Controller 抛出异常时,只要异常类型匹配,就会进入这个方法。模拟一个除零异常,访问相应接口后,客户端收到的就不再是默认错误页,而是一段结构清晰的 JSON 数据。开发者还可以在方法上添加 @ResponseStatus(HttpStatus.NOT_FOUND) 这样的注解,动态改变 HTTP 状态码,让前端能够根据状态码进行更精确的处理。
除了捕获 Exception,我们还可以针对不同的异常类型定义多个处理方法。比如针对参数校验异常、业务自定义异常分别给出不同的提示。这样一来,接口既能返回统一的格式,又能区分具体错误类型,为前端调试和监控系统提供了极大的便利。统一异常处理是生产级 Spring Boot Web 应用必不可少的一环。
总结
本文梳理了 Spring Boot 整合 Web 开发的主要环节,从自动配置原理到 REST 接口编写,再到参数接收、模板渲染、JSON 定制和异常处理。spring-boot-starter-web 把繁琐的配置工作打包好,让开发者将注意力放到业务实现上。理解其自动配置机制,有助于我们在遇到问题时快速定位原因。同时,合理使用参数注解、模板引擎和全局异常处理,能够显著提高开发效率和接口质量。
Spring Boot Web 开发模式已经非常成熟,掌握这些基础技能后,再去探索更高级的拦截器、过滤器、跨域配置、统一返回体封装等内容,就会顺畅很多。希望读者能够在实际项目中不断实践,将文章中提到的技巧灵活应用,从而搭建出稳定、高效的 Web 应用。
Spring BootWeb开发Spring MVC修改时间:2026-08-23 20:01:57