Spring Boot 的 “约定大于配置” 特性能大幅简化开发流程。这篇 “一课一得” 博客,会带你从 0 到 1 掌握 Spring Boot 基础,每个知识点都附实操代码,学完就能落地项目!
一、开发入门:5 分钟搭建第一个 Spring Boot 项目
1. 环境准备
- JDK:推荐 1.8 及以上(Spring Boot 2.x + 对 JDK 版本有明确要求)
- 构建工具:Maven 3.6+ 或 Gradle(本文用 Maven)
- 开发工具:IDEA(社区版 / 旗舰版均可)
2. 快速创建项目(Spring Initializr)
方式 1:IDEA 内置工具创建
- 打开 IDEA → 新建项目 → 选择 “Spring Initializr”
- 配置项目信息:
-
- Group/Artifact:自定义(如 ***.example/demo)
-
- 打包方式:Jar(Spring Boot 推荐,无需部署到 Tomcat)
-
- Java 版本:对应本地 JDK 版本
- 选择依赖(入门仅需选 2 个):
-
- Spring Web(支持 Web 开发)
-
- Lombok(简化实体类代码,减少 get/set)
- 确认项目路径,完成创建。
方式 2:官网创建(适合无 IDEA 场景)
访问Spring Initializr 官网,按上述步骤配置后下载压缩包,解压后用 IDEA 打开即可。
3. 第一个 Hello World
项目创建后,默认生成DemoApplication主启动类(带@SpringBootApplication注解,是 Spring Boot 的核心注解),我们只需新增一个 Controller:
// 引入Lombok和Spring Web注解
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController // 组合注解:@Controller + @ResponseBody(返回JSON/字符串)
@Slf4j // Lombok注解,自动生成日志对象log
public class HelloController {
// 处理GET请求,路径为/hello
@GetMapping("/hello")
public String hello() {
log.info("Hello Spring Boot请求已接收");
return "Hello Spring Boot! 这是我的第一个项目";
}
}
启动DemoApplication(直接运行 main 方法),访问http://localhost:8080/hello,就能看到返回结果,入门完成!
二、Spring Boot 配置:告别繁琐 XML
Spring Boot 通过application系列配置文件实现配置,支持两种格式:properties(键值对)和yml(层级结构,更简洁),推荐用yml。
1. 核心配置文件(src/main/resources 下)
示例:application.yml
# 1. 服务器配置
server:
port: 8081 # 自定义端口(默认8080)
servlet:
context-path: /demo # 项目上下文路径(访问需加/demo,如http://localhost:8081/demo/hello)
# 2. Spring核心配置(以数据库为例,后续数据访问会用到)
spring:
datasource:
driver-class-name: ***.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
username: root
password: 123456
2. 自定义配置与取值
如果需要自定义配置(如项目版本、文件路径),可通过两种方式取值:
方式 1:@Value 注解(适合单个配置)
# 自定义配置
app:
version: 1.0.0
upload-path: /usr/local/upload
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConfigController {
// 直接注入自定义配置
@Value("${app.version}")
private String appVersion;
@GetMapping("/config/version")
public String getVersion() {
return "当前项目版本:" + appVersion;
}
}
方式 2:@ConfigurationProperties(适合批量配置,推荐)
- 新建配置类:
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.***ponent;
// 前缀匹配app开头的配置
@ConfigurationProperties(prefix = "app")
@***ponent // 注入到Spring容器
public class AppConfig {
private String version;
private String uploadPath;
// Lombok的@Data可省略get/set,这里手动写便于理解
public String getVersion() { return version; }
public void setVersion(String version) { this.version = version; }
public String getUploadPath() { return uploadPath; }
public void setUploadPath(String uploadPath) { this.uploadPath = uploadPath; }
}
- 使用配置类:
@RestController
public class ConfigController {
// 注入配置类
private final AppConfig appConfig;
// 构造器注入(Spring Boot推荐,避免空指针)
public ConfigController(AppConfig appConfig) {
this.appConfig = appConfig;
}
@GetMapping("/config/all")
public String getAllConfig() {
return "版本:" + appConfig.getVersion() + ",上传路径:" + appConfig.getUploadPath();
}
}
3. 多环境配置(开发 / 测试 / 生产)
实际项目需区分环境,Spring Boot 通过profile实现:
- 创建多环境配置文件:
-
- 开发环境:application-dev.yml(本地开发用,端口 8080)
-
- 测试环境:application-test.yml(测试服用,端口 8082)
-
- 生产环境:application-prod.yml(线上用,端口 80)
- 激活指定环境(3 种方式):
-
- 配置文件激活(在 application.yml 中):
spring:
profiles:
active: dev # 激活开发环境
-
- 启动参数激活(IDEA 中:Run → Edit Configurations → VM options 添加-Dspring.profiles.active=test)
-
- 命令行激活(打包后运行:java -jar demo.jar --spring.profiles.active=prod)
三、Spring Boot Web 应用支持:快速开发接口
Spring Boot 内置 Spring MVC,无需额外配置即可开发 Web 接口,核心是 Controller 层的注解使用。
1. 常用 Controller 注解
| 注解 |
作用 |
示例 |
| @RestController |
返回 JSON / 字符串(适合接口开发) |
上文 HelloController 示例 |
| @Controller |
返回页面(适合前后端不分离,需配合 @ResponseBody) |
- |
| @GetMapping |
处理 GET 请求(查询数据) |
@GetMapping("/user/{id}") |
| @PostMapping |
处理 POST 请求(新增数据) |
@PostMapping("/user") |
| @PutMapping |
处理 PUT 请求(更新数据) |
@PutMapping("/user/{id}") |
| @DeleteMapping |
处理 DELETE 请求(删除数据) |
@DeleteMapping("/user/{id}") |
2. 参数绑定实战
以用户接口为例,演示不同参数的接收方式:
import ***.example.demo.entity.User;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/user") // 类级路径,所有接口前缀都是/user
public class UserController {
// 1. 路径参数(@PathVariable):/user/1
@GetMapping("/{id}")
public String getUserById(@PathVariable Long id) {
return "查询用户ID:" + id;
}
// 2. 请求参数(@RequestParam):/user?name=张三&age=20
@GetMapping
public String getUserByParam(
@RequestParam(required = false) String name, // required=false表示非必传
@RequestParam(defaultValue = "0") Integer age) { // 默认值0
return "查询用户:姓名=" + name + ",年龄=" + age;
}
// 3. 请求体(@RequestBody):接收JSON格式参数(POST/PUT常用)
@PostMapping
public String addUser(@RequestBody User user) {
return "新增用户:" + user.getName() + ",年龄=" + user.getAge();
}
}
注:User类需用 Lombok 的@Data或手动写 get/set,否则 JSON 参数无法绑定。
3. 静态资源访问
Spring Boot 默认静态资源路径(优先级从高到低):
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/(推荐,新建 static 文件夹放图片、JS、CSS)
- classpath:/public/
示例:在static文件夹放logo.png,访问http://localhost:8081/demo/logo.png即可查看。
四、Spring Boot 数据访问:重点讲 JPA 与 MyBatis
数据访问是项目核心,Spring Boot 对 JPA(JPA 是规范,Hibernate 是实现)和 MyBatis 都有良好支持,两者各有优势:
- JPA:简化 CRUD,无需写 SQL,适合快速开发
- MyBatis:SQL 完全可控,适合复杂查询场景
1. Spring Data JPA(重点)
步骤 1:引入依赖(pom.xml)
<dependencies>
<!-- JPA依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
步骤 2:配置 JPA(application.yml)
spring:
datasource: # 数据库配置(前文已写,此处省略)
jpa:
hibernate:
ddl-auto: update # 自动建表策略:update(表存在则更新,不存在则创建)
show-sql: true # 控制台打印SQL语句
properties:
hibernate:
format_sql: true # 格式化SQL(便于查看)
database-platform: org.hibernate.dialect.MySQL8Dialect # 数据库方言(适配MySQL8)
步骤 3:定义实体类(与数据库表映射)
import lombok.Data;
import javax.persistence.*;
import java.time.LocalDateTime;
@Data // Lombok注解,生成get/set/toString等
@Entity // 标记为JPA实体类(对应数据库表)
@Table(name = "t_user") // 指定数据库表名(默认是类名小写,这里自定义为t_user)
public class User {
@Id // 主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增策略(MySQL推荐)
private Long id;
@Column(name = "user_name", length = 50, nullable = false) // 对应表字段:非空,长度50
private String name;
@Column(nullable = false)
private Integer age;
@Column(unique = true) // 唯一约束
private String email;
// 自动填充创建时间(无需手动设置)
@Column(updatable = false) // 禁止更新
private LocalDateTime createTime;
// 自动填充更新时间
private LocalDateTime updateTime;
// JPA生命周期注解:保存前执行
@PrePersist
public void prePersist() {
this.createTime = LocalDateTime.now();
this.updateTime = LocalDateTime.now();
}
// 保存/更新前执行
@PreUpdate
public void preUpdate() {
this.updateTime = LocalDateTime.now();
}
}
步骤 4:定义 Repository 接口(核心,无需写实现)
Spring Data JPA 提供JpaRepository接口,内置 CRUD 方法,我们只需继承即可:
import ***.example.demo.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
// JpaRepository<实体类, 主键类型>
public interface UserRepository extends JpaRepository<User, Long> {
// 1. 方法命名规则查询(无需写SQL,JPA自动解析)
// 需求:根据姓名查询用户(精确匹配)
User findByName(String name);
// 需求:根据年龄大于指定值查询(模糊匹配,关键字GreaterThan)
List<User> findByAgeGreaterThan(Integer age);
// 2. 自定义JPQL查询(类似HQL,面向实体类)
@Query("SELECT u FROM User u WHERE u.name LIKE %:name% AND u.age = :age")
List<User> findByNameLikeAndAge(@Param("name") String name, @Param("age") Integer age);
// 3. 原生SQL查询(面向数据库表,需加nativeQuery = true)
@Query(value = "SELECT * FROM t_user WHERE email = :email", nativeQuery = true)
User findByEmail(@Param("email") String email);
}
步骤 5:使用 Repository(Service 层示例)
import ***.example.demo.entity.User;
import ***.example.demo.repository.UserRepository;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
private final UserRepository userRepository;
// 构造器注入
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 1. 新增用户
public User addUser(User user) {
return userRepository.save(user); // JpaRepository内置save方法
}
// 2. 查询所有用户
public List<User> getAllUser() {
return userRepository.findAll(); // 内置查询所有
}
// 3. 根据ID查询
public User getUserById(Long id) {
// findById返回Optional,orElseThrow抛异常(用户不存在时)
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("用户不存在"));
}
// 4. 自定义查询(根据姓名模糊查询+年龄匹配)
public List<User> getByNameLikeAndAge(String name, Integer age) {
return userRepository.findByNameLikeAndAge(name, age);
}
// 5. 删除用户
public void deleteUser(Long id) {
userRepository.deleteById(id); // 内置删除
}
}
2. MyBatis(重点,SQL 可控)
MyBatis 是半 ORM 框架,需手动写 SQL,适合复杂查询(如多表联查)。Spring Boot 通过mybatis-spring-boot-starter简化整合。
步骤 1:引入依赖(pom.xml)
<dependencies>
<!-- MyBatis Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version> <!-- 版本需与Spring Boot匹配 -->
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
步骤 2:配置 MyBatis(application.yml)
spring:
datasource: # 数据库配置(同JPA,省略)
# MyBatis配置
mybatis:
mapper-locations: classpath:mapper/**/*.xml # Mapper XML文件路径(推荐放resources/mapper下)
type-aliases-package: ***.example.demo.entity # 实体类别名(XML中可直接用类名,无需全路径)
configuration:
map-underscore-to-camel-case: true # 开启下划线转驼峰(如数据库user_name → 实体类userName)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL
步骤 3:定义 Mapper 接口(两种方式:注解式、XML 式)
方式 1:注解式(适合简单 SQL,无需 XML)
import ***.example.demo.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
// @Mapper:标记为MyBatis Mapper接口(也可在主启动类加@MapperScan("***.example.demo.mapper")批量扫描)
@Mapper
public interface UserMapper {
// 新增用户(@Insert注解写SQL)
@Insert("INSERT INTO t_user (user_name, age, email, create_time, update_time) " +
"VALUES (#{name}, #{age}, #{email}, NOW(), NOW())")
// @Options:获取自增主键(keyProperty对应实体类主键字段)
@Options(useGeneratedKeys = true, keyProperty = "id")
void insert(User user);
// 根据ID查询(@Select)
@Select("SELECT * FROM t_user WHERE id = #{id}")
User selectById(Long id);
// 根据姓名模糊查询(@Select,#{}防SQL注入)
@Select("SELECT * FROM t_user WHERE user_name LIKE CONCAT('%', #{name}, '%')")
List<User> selectByNameLike(String name);
// 更新用户(@Update)
@Update("UPDATE t_user SET user_name = #{name}, age = #{age}, email = #{email}, update_time = NOW() " +
"WHERE id = #{id}")
void update(User user);
// 删除用户(@Delete)
@Delete("DELETE FROM t_user WHERE id = #{id}")
void delete(Long id);
}
方式 2:XML 式(适合复杂 SQL,推荐)
- 定义 Mapper 接口(仅需方法签名,无注解):
@Mapper
public interface UserMapper {
void insert(User user);
User selectById(Long id);
List<User> selectByNameLike(String name);
void update(User user);
void delete(Long id);
// 复杂查询示例:多表联查(假设关联t_order表)
List<User> selectUserWithOrder();
}
- 创建 XML 文件(resources/mapper/UserMapper.xml):
<?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">
<!-- namespace必须与Mapper接口全路径一致 -->
<mapper namespace="***.example.demo.mapper.UserMapper">
<!-- 1. 结果映射(解决字段名与实体类属性名不一致,或复杂对象映射) -->
<resultMap id="UserResultMap" type="User"> <!-- type用别名(配置了type-aliases-package) -->
<id column="id" property="id"/> <!-- 主键映射 -->
<result column="user_name" property="name"/> <!-- 下划线转驼峰已开启,也可显式映射 -->
<result column="age" property="age"/>
<result column="email" property="email"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<!-- 2. 新增用户 -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO t_user (user_name, age, email, create_time, update_time)
VALUES (#{name}, #{age}, #{email}, NOW(), NOW())
</insert>
<!-- 3. 根据ID查询(resultMap引用上面定义的映射) -->
<select id="selectById" resultMap="UserResultMap">
SELECT * FROM t_user WHERE id = #{id}
</select>
<!-- 4. 复杂查询:多表联查(用户+订单) -->
<resultMap id="UserWithOrderResultMap" type="User">
<resultMap ref="UserResultMap"/> <!-- 继承基础映射 -->
<!-- 关联订单列表(假设User类有List<Order> orders属性) -->
<collection property="orders" ofType="Order"> <!-- ofType是集合元素类型 -->
<id column="order_id" property="id"/>
<result column="order_no" property="orderNo"/>
<result column="total_amount" property="totalAmount"/>
</collection>
</resultMap>
<select id="selectUserWithOrder" resultMap="UserWithOrderResultMap">
SELECT u.*, o.id AS order_id, o.order_no, o.total_amount
FROM t_user u
LEFT JOIN t_order o ON u.id = o.user_id
</select>
</mapper>
步骤 4:使用 Mapper(Service 层示例)
import ***.example.demo.entity.User;
import ***.example.demo.mapper.UserMapper;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
private final UserMapper userMapper;
// 构造器注入
public UserService(UserMapper userMapper) {
this.userMapper = userMapper;
}
// 新增用户
public void addUser(User user) {
userMapper.insert(user);
System.out.println("新增用户ID:" + user.getId()); // 自增主键已回显到user对象
}
// 复杂查询:用户+订单
public List<User> getUserWithOrder() {
return userMapper.selectUserWithOrder();
}
}
3. JPA vs MyBatis:怎么选?
| 对比维度 |
Spring Data JPA |
MyBatis |
| SQL 控制度 |
低(自动生成,复杂 SQL 需 JPQL) |
高(手动写 SQL,灵活) |
| 开发效率 |
高(无需写 CRUD SQL) |
中(需写 SQL,但有代码生成工具) |
| 学习成本 |
中(需理解 JPA 规范、Hibernate) |
低(SQL 基础好即可上手) |
| 适用场景 |
快速开发、简单 CRUD 项目 |
复杂查询、SQL 优化需求高的项目 |
五、整合缓存:提升接口性能
缓存能减少数据库访问次数,大幅提升接口响应速度。Spring Boot 内置缓存抽象,支持多种缓存(默认 ConcurrentMap、Redis、EhCache 等)。
1. 基础缓存(默认 ConcurrentMap,适合单机)
步骤 1:开启缓存
在主启动类加@EnableCaching注解:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching // 开启缓存支持
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
步骤 2:使用缓存注解(核心)
常用缓存注解:
| 注解 |
作用 |
关键属性 |
| @Cacheable |
查询时缓存(有缓存则返回,无则查库并缓存) |
value(缓存名称)、key(缓存键) |
| @CachePut |
更新时更新缓存(先查库,再更新缓存) |
value、key |
| @CacheEvict |
删除时清除缓存(支持单个 / 全部清除) |
value、key、allEntries(是否全清) |
示例(在 UserService 中加缓存):
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 1. 查询缓存:根据ID查询用户,缓存键为"user::1"(value=user,key=id)
@Cacheable(value = "user", key = "#id")
public User getUserById(Long id) {
System.out.println("查询数据库,ID:" + id); // 首次执行会打印,缓存后不打印
return userRepository.findById(id).orElseThrow(() -> new RuntimeException("用户不存在"));
}
// 2. 更新缓存:更新用户后,同步更新缓存(key与查询缓存一致)
@CachePut(value = "user", key = "#user.id")
public User updateUser(User user) {
User oldUser = getUserById(user.getId());
oldUser.setName(user.getName());
oldUser.setAge(user.getAge());
return userRepository.save(oldUser);
}
// 3. 清除缓存:删除用户后,清除对应缓存;allEntries=true会清除"user"下所有缓存
@CacheEvict(value = "user", key = "#id")
public void deleteUser(Long id) {
userRepository.deleteById(id);
}
}
2. 整合 Redis 缓存(推荐,适合分布式)
默认 ConcurrentMap 缓存是内存级缓存,重启后失效,分布式环境下需用 Redis。
步骤 1:引入 Redis 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
步骤 2:配置 Redis(application.yml)
spring:
redis:
host: localhost # Redis地址
port: 6379 # 端口(默认6379)
password: 123456 # Redis密码(无则省略)
database: 0 # 数据库索引(默认0)
timeout: 3000ms # 连接超时时间
lettuce: # Redis客户端(Spring Boot 2.x默认用Lettuce,替代Jedis)
pool:
max-active: 8 # 最大连接数
max-idle: 8 # 最大空闲连接数
min-idle: 2 # 最小空闲连接数
max-wait: -1ms # 最大等待时间(-1表示无限制)
# 缓存配置(可选,自定义缓存过期时间)
spring.cache:
redis:
time-to-live: 3600000ms # 缓存默认过期时间(1小时)
cache-null-values: false # 是否缓存null值(防止缓存穿透,按需开启)
步骤 3:使用 Redis 缓存
无需修改之前的缓存注解!Spring Boot 会自动将缓存实现从 ConcurrentMap 切换为 Redis,缓存数据会存储到 Redis 中(键格式:user::1,值为 JSON 格式)。
六、安全管理:Spring Security 入门
Spring Security 是 Spring 生态的安全框架,支持认证(登录)、授权(权限控制)、防 CSRF 等功能,Spring Boot 通过spring-boot-starter-security简化整合。
1. 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
引入依赖后,Spring Security 会自动生效:
- 所有接口默认需要登录
- 默认生成随机密码(控制台打印,格式:Using generated security password: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
- 默认用户名:user
2. 自定义安全配置(核心)
新建配置类,继承WebSecurityConfigurerAdapter(Spring Boot 2.7 + 已弃用,改用SecurityFilterChain,这里用兼容写法):
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity // 开启Web安全
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 1. 密码编码器(Spring Security 5.x+强制要求,推荐BCrypt)
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 2. 配置认证(用户信息):这里用内存用户(实际项目需从数据库查询)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin") // 用户名
.password(passwordEncoder().encode("123456")) // 密码(需加密)
.roles("ADMIN") // 角色(ADMIN)
.and()
.withUser("user")
.password(passwordEncoder().encode("123456"))
.roles("USER"); // 角色(USER)
}
// 3. 配置授权(接口访问权限)
@Override
protected void configure(HttpSecurity http) throws Exception {
http
// 关闭CSRF(前后端分离项目常用,非分离项目建议开启)
.csrf().disable()
// 配置请求授权规则
.authorizeRequests()
// 1. 放行无需登录的接口(如登录页、静态资源)
.antMatchers("/login", "/static/**").permitAll()
// 2. ADMIN角色才能访问的接口(/admin/**路径)
.antMatchers("/admin/**").hasRole("ADMIN")
// 3. USER角色或ADMIN角色能访问的接口(/user/**路径)
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
// 4. 其他所有接口都需要登录
.anyRequest().authenticated()
.and()
// 配置登录(自定义登录页和登录接口)
.formLogin()
.loginPage("/login") // 自定义登录页路径(前后端分离可省略,用默认)
.loginProcessingUrl("/doLogin") // 登录请求接口(默认是/login)
.defaultSu***essUrl("/index") // 登录成功后跳转的路径
.failureUrl("/login?error") // 登录失败后跳转的路径
.and()
// 配置退出登录
.logout()
.logoutUrl("/logout") // 退出登录接口
.logoutSu***essUrl("/login") // 退出成功后跳转的路径
.invalidateHttpSession(true); // 退出后销毁Session
}
}
3. 权限控制实战(基于角色)
示例:ADMIN 能删除用户,USER 只能查询用户:
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
// 所有登录用户(USER/ADMIN)都能访问
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userService.getUserById(id);
}
// 只有ADMIN角色能访问(方法级权限控制,需加@PreAuthorize)
@PreAuthorize("hasRole('ADMIN')") // 需在主启动类加@EnableGlobalMethodSecurity(prePostEnabled = true)
@DeleteMapping("/{id}")
public String deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return "删除成功";
}
}
注:方法级权限控制需在主启动类加@EnableGlobalMethodSecurity(prePostEnabled = true)注解开启。
七、一课一得:Spring Boot 基础核心总结
- 入门核心:通过 Spring Initializr 快速创建项目,@SpringBootApplication是主入口,Jar 包部署更便捷。
- 配置核心:application.yml管理配置,@ConfigurationProperties批量取值,多环境用profile切换。
- Web 核心:@RestController+@GetMapping等注解快速开发接口,参数绑定支持路径、请求体、请求参数。
- 数据访问:JPA 适合快速 CRUD,MyBatis 适合复杂 SQL;两者都需配置数据源,JPA 靠 Repository,MyBatis 靠 Mapper。
- 缓存核心:@EnableCaching开启缓存,@Cacheable/@CacheEvict控制缓存,Redis 适合分布式场景。
- 安全核心:Spring Security 控制认证授权,PasswordEncoder加密密码,hasRole控制角色权限。
Spring Boot 的核心是 “简化”,通过 “约定大于配置” 减少重复工作。建议大家动手敲一遍代码,遇到问题多查官方文档(Spring Boot 官方文档),很快就能掌握!