Spring Boot 全面使用教程 本文将从常见的 Spring Boot 项目实践出发,逐步讲解各个关键点的 注解、用法和配置 ,涵盖以下方面:
控制器 Controller
Service 层
Mapper 与 MyBatis XML
自定义配置注入
依赖注入 & IoC
Lombok 使用
日志记录(Slf4j + logback.xml)
全局异常处理
1. 控制器 Controller 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @RestController @RequestMapping("/user") public class UserController { private final UserService userService; // 构造器注入推荐(避免循环依赖 & 测试方便) public UserController(UserService userService) { this.userService = userService; } @PostMapping("/register") public ResponseEntity<String> register(@RequestBody UserDTO userDTO) { userService.register(userDTO); return ResponseEntity.ok("用户注册成功!"); } }
常用注解
@RestController:组合注解 = @Controller + @ResponseBody,返回 JSON。
@RequestMapping:定义类或方法的访问路径。
@PostMapping / @GetMapping:请求方法映射。
@RequestBody:接收 JSON 请求体并绑定到对象。
2. Service 层 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Service public class UserService { private final UserMapper userMapper; public UserService(UserMapper userMapper) { this.userMapper = userMapper; } public void register(UserDTO userDTO) { User user = new User(); user.setUsername(userDTO.getUsername()); user.setPassword(userDTO.getPassword()); userMapper.insertUser(user); } }
常用注解
@Service:标记业务逻辑层 Bean。
@Transactional:事务管理(可用于方法或类)。
3. Mapper 与 MyBatis XML Mapper 接口 1 2 3 4 5 @Mapper public interface UserMapper { void insertUser(User user); User findByUsername(String username); }
Mapper XML(resources/mapper/UserMapper.xml) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.demo.mapper.UserMapper"> <insert id="insertUser" parameterType="com.example.demo.model.User"> INSERT INTO user (username, password) VALUES (#{username}, #{password}) </insert> <select id="findByUsername" parameterType="String" resultType="com.example.demo.model.User"> SELECT id, username, password FROM user WHERE username = #{username} </select> </mapper>
4. 自定义配置注入 application.yml 1 2 3 app: name: MySpringApp version: 1.0.0
配置类 1 2 3 4 5 6 7 @Component @ConfigurationProperties(prefix = "app") @Data public class AppConfig { private String name; private String version; }
使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @RestController public class ConfigController { private final AppConfig appConfig; public ConfigController(AppConfig appConfig) { this.appConfig = appConfig; } @GetMapping("/config") public String getConfig() { return appConfig.getName() + " - " + appConfig.getVersion(); } }
5. 依赖注入 & IoC Spring Boot 的 IoC 容器 (ApplicationContext)负责管理 Bean 的生命周期。
常见注入方式
构造器注入(推荐)
Setter 注入
字段注入(@Autowired)
6. Lombok 使用 在 pom.xml 中加入:
1 2 3 4 5 <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>provided</scope> </dependency>
常用注解 1 2 3 4 5 @Data // 生成 getter/setter/toString/hashCode/equals @NoArgsConstructor @AllArgsConstructor @Builder // 链式构建对象 @Slf4j // 日志
示例 1 2 3 4 5 6 7 8 9 @Data @AllArgsConstructor @NoArgsConstructor @Builder public class User { private Long id; private String username; private String password; }
7. Slf4j 日志记录 & logback.xml 配置 使用日志 1 2 3 4 5 6 7 @Slf4j @Service public class UserService { public void register(UserDTO userDTO) { log.info("注册用户: {}", userDTO.getUsername()); } }
logback-spring.xml 配置(resources/ 下) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="LOG_PATH" value="logs"/> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <file>${LOG_PATH}/app.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_PATH}/app.%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>7</maxHistory> </rollingPolicy> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="FILE"/> </root> </configuration>
8. 全局异常处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleException(Exception e) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("服务器异常: " + e.getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<String> handleValidationException(MethodArgumentNotValidException e) { return ResponseEntity.badRequest() .body("参数错误: " + e.getBindingResult().getFieldError().getDefaultMessage()); } }
常用注解
@RestControllerAdvice:全局异常处理 + JSON 返回。
@ExceptionHandler:指定异常类型处理。
9. AOP 编程 AOP 概念
AOP (Aspect Oriented Programming,面向切面编程) :通过预编译方式和运行期动态代理实现程序功能的统一维护。
核心思想:把与业务逻辑无关的功能(如日志、事务、安全检查)从业务代码中分离出来,形成独立的切面。
核心术语
切面 (Aspect) :横切关注点的模块化,如日志切面、权限切面。
连接点 (JoinPoint) :程序执行的某个点,如方法调用、异常抛出。
切点 (Pointcut) :定义哪些连接点需要织入,如指定某个包下的所有方法。
通知 (Advice) :切面在连接点执行的操作,包括:
@Before:方法执行前
@After:方法执行后(无论是否异常)
@AfterReturning:方法返回后
@AfterThrowing:方法抛出异常时
@Around:环绕通知(可控制方法执行前后逻辑)
织入 (Weaving) :将切面应用到目标对象的过程。
代理对象 :Spring AOP 基于 JDK 动态代理 或 CGLIB 生成代理对象。
Spring Boot 中启用 AOP
引入依赖:
1 2 3 4 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-aop</artifactId > </dependency >
启用 AOP(可选,默认已启用):
1 2 3 @EnableAspectJAutoProxy @SpringBootApplication public class DemoApplication {}
定义切面 日志切面示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 @Aspect @Component @Slf4j public class LoggingAspect { @Pointcut("execution(* com.example.demo.service..*(..))") public void serviceMethods () {} @Before("serviceMethods()") public void logBefore (JoinPoint joinPoint) { log.info("调用方法: {}" , joinPoint.getSignature().toShortString()); } @AfterReturning(pointcut = "serviceMethods()", returning = "result") public void logAfterReturning (JoinPoint joinPoint, Object result) { log.info("方法返回: {} -> {}" , joinPoint.getSignature().toShortString(), result); } @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex") public void logAfterThrowing (JoinPoint joinPoint, Exception ex) { log.error("方法异常: {} -> {}" , joinPoint.getSignature().toShortString(), ex.getMessage()); } @Around("serviceMethods()") public Object logAround (ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object result = pjp.proceed(); long time = System.currentTimeMillis() - start; log.info("方法耗时: {} ms" , time); return result; } }
切点表达式常见写法
execution(* com.example..*(..)):匹配 com.example 包及子包下所有方法。
execution(public * *(..)):匹配所有 public 方法。
@annotation(org.springframework.web.bind.annotation.GetMapping):匹配带有特定注解的方法。
within(com.example.service..*):匹配某个包下的所有类。
常见应用场景
日志记录 (方法调用、入参、返回值、耗时)
权限控制 (在方法调用前检查权限)
事务管理 (Spring 已内置 @Transactional 基于 AOP)
异常统一处理 (捕获异常,转换成统一响应格式)
性能监控 (统计方法执行时间)
高级用法 1. 自定义注解 + AOP 1 2 3 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface RequireLogin {}
切面实现:
1 2 3 4 5 6 7 8 9 10 11 @Aspect @Component public class AuthAspect { @Before("@annotation(com.example.demo.annotation.RequireLogin)") public void checkLogin () { if (!SecurityContext.isLogin()) { throw new RuntimeException ("未登录" ); } } }
2. Order 控制切面优先级 1 2 3 4 @Aspect @Component @Order(1) public class FirstAspect {}
AOP vs 拦截器
特点
AOP
Spring MVC 拦截器
粒度
方法级
URL 请求级
使用场景
日志、事务、权限
认证、跨域、限流
灵活性
支持注解、自定义切点
针对请求生命周期
Spring Boot 参数绑定与返回结果教程 1. 参数绑定方式 Spring Boot 提供了多种方式将请求参数绑定到方法参数上。
1.1 路径参数(PathVariable) 1 2 3 4 @GetMapping("/user/{id}") public ResponseEntity<String> getUserById(@PathVariable Long id) { return ResponseEntity.ok("用户ID: " + id); }
@PathVariable:绑定路径中的 {} 参数。
支持 可选参数 (可用 required=false 或 Optional)。
1 2 3 4 @GetMapping("/user/{id}") public ResponseEntity<String> getUserOptional(@PathVariable Optional<Long> id) { return ResponseEntity.ok("用户ID: " + id.orElse(-1L)); }
1.2 查询参数(RequestParam) 1 2 3 4 @GetMapping("/search") public ResponseEntity<String> search(@RequestParam String keyword) { return ResponseEntity.ok("搜索关键词: " + keyword); }
默认是 必填 ,否则会报 400。
可设置 required=false 或提供默认值:
1 2 3 4 5 @GetMapping("/search") public ResponseEntity<String> search( @RequestParam(required = false, defaultValue = "default") String keyword) { return ResponseEntity.ok("搜索关键词: " + keyword); }
1 2 3 4 @GetMapping("/search2") public ResponseEntity<String> search2(@RequestParam Optional<String> keyword) { return ResponseEntity.ok("搜索关键词: " + keyword.orElse("未提供")); }
1.3 请求体 JSON(RequestBody) 1 2 3 4 @PostMapping("/user") public ResponseEntity<String> createUser(@RequestBody UserDTO user) { return ResponseEntity.ok("创建用户: " + user.getUsername()); }
@RequestBody:绑定请求体 JSON → 对象。
需要 spring-boot-starter-web 自动配置的 Jackson 序列化。
1 2 3 4 5 @PostMapping("/login") public ResponseEntity<String> login(@RequestParam String username, @RequestParam String password) { return ResponseEntity.ok("登录用户: " + username); }
1.5 文件上传(MultipartFile) 1 2 3 4 @PostMapping("/upload") public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) throws IOException { return ResponseEntity.ok("文件名: " + file.getOriginalFilename() + " 大小: " + file.getSize()); }
需要 spring.servlet.multipart.enabled=true(默认已启用)。
多文件上传:
1 2 3 4 @PostMapping("/upload-multi") public ResponseEntity<String> uploadMultiple(@RequestParam("files") List<MultipartFile> files) { return ResponseEntity.ok("上传文件数: " + files.size()); }
1 2 3 4 @GetMapping("/header") public ResponseEntity<String> getHeader(@RequestHeader("User-Agent") String userAgent) { return ResponseEntity.ok("请求头 UA: " + userAgent); }
可设置 required=false 或 Optional:
1 2 3 4 @GetMapping("/header2") public ResponseEntity<String> getHeaderOptional(@RequestHeader(value = "X-Token", required = false) Optional<String> token) { return ResponseEntity.ok("Token: " + token.orElse("未提供")); }
1.7 Cookie 参数(CookieValue) 1 2 3 4 @GetMapping("/cookie") public ResponseEntity<String> getCookie(@CookieValue("SESSIONID") String sessionId) { return ResponseEntity.ok("SessionID: " + sessionId); }
2. 返回结果的常见方式
2.1 返回 JSON 1 2 3 4 @GetMapping("/json") public UserDTO getUserJson() { return new UserDTO("Tom", "123456"); }
Spring Boot 自动将对象 → JSON(Jackson)。
若要自定义序列化,可用 @JsonProperty、@JsonIgnore。
2.2 返回 ResponseEntity(推荐) 1 2 3 4 5 6 7 @GetMapping("/entity") public ResponseEntity<UserDTO> getEntity() { return ResponseEntity .status(HttpStatus.CREATED) // 设置状态码 .header("X-Custom-Header", "demo") // 设置响应头 .body(new UserDTO("Tom", "123456")); // 设置响应体 }
2.3 返回文件下载 1 2 3 4 5 6 7 8 9 @GetMapping("/download") public ResponseEntity<byte[]> downloadFile() throws IOException { byte[] content = Files.readAllBytes(Paths.get("example.txt")); HttpHeaders headers = new HttpHeaders(); headers.setContentDispositionFormData("attachment", "example.txt"); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return new ResponseEntity<>(content, headers, HttpStatus.OK); }
2.4 返回纯文本 1 2 3 4 5 6 @GetMapping("/text") public ResponseEntity<String> getText() { return ResponseEntity.ok() .contentType(MediaType.TEXT_PLAIN) .body("Hello Spring Boot!"); }
2.5 返回流(大文件) 1 2 3 4 5 6 7 8 9 @GetMapping("/stream") public void streamFile(HttpServletResponse response) throws IOException { response.setContentType("application/octet-stream"); response.setHeader("Content-Disposition", "attachment; filename=data.txt"); try (OutputStream os = response.getOutputStream()) { os.write("Stream Content".getBytes()); os.flush(); } }
3. 小结 参数绑定
路径参数 :@PathVariable
查询参数 :@RequestParam
请求体 JSON :@RequestBody
表单参数 :@RequestParam
文件上传 :MultipartFile
请求头 :@RequestHeader
Cookie :@CookieValue
可选参数 :Optional<T>
返回结果
JSON :对象 → 自动序列化
ResponseEntity :可设置状态码/头/体
文件 :byte[] / 流
文本 :MediaType.TEXT_PLAIN
流式返回 :写入 HttpServletResponse