引言
Spring框架是Java生态系统中最流行、最强大的企业级应用开发框架之一。自2003年首次发布以来,Spring已经发展成为一个庞大的生态系统,涵盖了从依赖注入到微服务架构的各个方面。本文将带你从Spring的基础概念开始,逐步深入到高级特性和实战技巧,帮助你系统地掌握Spring框架。
第一部分:Spring框架基础
1.1 Spring框架概述
Spring是一个开源的Java平台,它为Java应用程序提供了全面的基础设施支持。Spring的核心特性包括:
- 依赖注入(DI):通过控制反转(IoC)容器管理对象之间的依赖关系
- 面向切面编程(AOP):分离横切关注点,如日志、事务管理等
- 声明式事务管理:简化事务管理,无需编写复杂的事务代码
- 数据访问抽象:提供统一的API访问各种数据源
- Web框架:提供MVC模式的Web应用程序开发支持
1.2 Spring的核心模块
Spring框架由多个模块组成,每个模块都可以独立使用,也可以组合使用:
- Spring Core:提供IoC容器和依赖注入功能
- Spring AOP:提供面向切面编程支持
- Spring MVC:基于MVC模式的Web框架
- Spring Data:简化数据访问层的开发
- Spring Security:提供安全认证和授权
- Spring Boot:简化Spring应用的配置和部署
1.3 环境准备
在开始学习Spring之前,需要准备以下环境:
- Java Development Kit (JDK):推荐JDK 8或更高版本
- 构建工具:Maven或Gradle
- IDE:IntelliJ IDEA或Eclipse
- Spring版本:推荐Spring 5.x或Spring Boot 2.x
第二部分:Spring核心概念详解
2.1 依赖注入(DI)与控制反转(IoC)
2.1.1 基本概念
依赖注入(Dependency Injection)是Spring框架的核心机制。它通过控制反转(Inversion of Control)容器来管理对象之间的依赖关系。
传统方式:对象自己创建依赖
public class UserService {
private UserRepository userRepository;
public UserService() {
this.userRepository = new UserRepository(); // 自己创建依赖
}
}
依赖注入方式:依赖由外部容器提供
public class UserService {
private UserRepository userRepository;
// 依赖通过构造函数注入
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
2.1.2 Spring IoC容器
Spring IoC容器负责创建、配置和管理Bean。主要的容器接口是:
ApplicationContext:更高级的容器,提供更多企业级功能BeanFactory:基础容器,提供基本的IoC功能
配置Bean的三种方式:
- XML配置(传统方式)
<!-- beans.xml -->
<beans xmlns="http://www.springframework.org/schema/beans">
<bean id="userRepository" class="com.example.UserRepository"/>
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userRepository"/>
</bean>
</beans>
- 注解配置(推荐方式)
@Component
public class UserRepository {
// 数据访问逻辑
}
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
- Java配置(Spring Boot推荐)
@Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new UserRepository();
}
@Bean
public UserService userService() {
return new UserService(userRepository());
}
}
2.1.3 依赖注入的类型
- 构造函数注入(推荐)
@Service
public class OrderService {
private final PaymentService paymentService;
private final EmailService emailService;
@Autowired
public OrderService(PaymentService paymentService, EmailService emailService) {
this.paymentService = paymentService;
this.emailService = emailService;
}
}
- Setter方法注入
@Service
public class OrderService {
private PaymentService paymentService;
@Autowired
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}
- 字段注入(不推荐,但常见)
@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
}
2.2 Bean的作用域
Spring Bean有以下作用域:
- singleton(默认):每个容器中一个Bean实例
- prototype:每次请求都创建新实例
- request:每个HTTP请求一个实例(Web应用)
- session:每个HTTP会话一个实例(Web应用)
- global-session:全局HTTP会话(Portlet应用)
配置示例:
@Component
@Scope("prototype") // 每次获取都创建新实例
public class PrototypeBean {
// ...
}
2.3 Bean的生命周期
Spring Bean的生命周期包括以下阶段:
- 实例化:容器创建Bean实例
- 属性设置:注入依赖
- 初始化:调用初始化方法
- 使用:Bean被应用程序使用
- 销毁:容器销毁Bean时调用销毁方法
生命周期回调示例:
@Component
public class LifecycleBean implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化完成");
}
@Override
public void destroy() throws Exception {
System.out.println("销毁Bean");
}
@PostConstruct
public void init() {
System.out.println("使用@PostConstruct初始化");
}
@PreDestroy
public void cleanup() {
System.out.println("使用@PreDestroy清理");
}
}
第三部分:Spring AOP(面向切面编程)
3.1 AOP基本概念
AOP(Aspect-Oriented Programming)允许将横切关注点(如日志、事务、安全)从业务逻辑中分离出来。
核心术语:
- 切面(Aspect):横切关注点的模块化
- 连接点(Join Point):程序执行过程中的某个点
- 通知(Advice):切面在特定连接点执行的动作
- 切入点(Pointcut):匹配连接点的表达式
- 目标对象(Target):被通知的对象
3.2 Spring AOP实现
3.2.1 基于注解的AOP
// 1. 定义切面
@Aspect
@Component
public class LoggingAspect {
// 定义切入点:所有public方法
@Pointcut("execution(public * com.example.service.*.*(..))")
public void serviceMethods() {}
// 前置通知
@Before("serviceMethods()")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("开始执行方法: " + methodName);
}
// 后置通知
@After("serviceMethods()")
public void logAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("方法执行完成: " + methodName);
}
// 返回后通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
System.out.println("方法返回值: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
System.err.println("方法执行异常: " + ex.getMessage());
}
// 环绕通知
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
try {
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println("方法执行时间: " + (endTime - startTime) + "ms");
return result;
} catch (Exception e) {
System.err.println("方法执行异常: " + e.getMessage());
throw e;
}
}
}
3.2.2 切入点表达式
Spring AOP支持多种切入点表达式:
- execution:匹配方法执行
@Pointcut("execution(* com.example.service.*.*(..))")
- within:匹配类中的方法
@Pointcut("within(com.example.service.*)")
- this:匹配代理对象
@Pointcut("this(com.example.service.UserService)")
- target:匹配目标对象
@Pointcut("target(com.example.service.UserService)")
- args:匹配参数
@Pointcut("args(java.lang.String, java.lang.Integer)")
3.3 AOP应用场景
- 日志记录
- 事务管理
- 性能监控
- 权限验证
- 缓存管理
第四部分:Spring数据访问
4.1 Spring Data JPA
Spring Data JPA是Spring Data项目的一部分,简化了JPA的使用。
4.1.1 基本配置
Maven依赖:
<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>
实体类:
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String username;
@Column(nullable = false)
private String password;
@Column
private String email;
// 构造函数、getter、setter省略
}
Repository接口:
public interface UserRepository extends JpaRepository<User, Long> {
// 自定义查询方法
User findByUsername(String username);
// 使用JPQL查询
@Query("SELECT u FROM User u WHERE u.email = :email")
User findByEmail(@Param("email") String email);
// 分页查询
@Query("SELECT u FROM User u")
Page<User> findAllUsers(Pageable pageable);
// 更新操作
@Modifying
@Query("UPDATE User u SET u.password = :password WHERE u.id = :id")
int updatePassword(@Param("id") Long id, @Param("password") String password);
}
Service层使用:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public User createUser(User user) {
// 业务逻辑验证
if (userRepository.findByUsername(user.getUsername()) != null) {
throw new RuntimeException("用户名已存在");
}
return userRepository.save(user);
}
public Page<User> getUsers(int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("id").descending());
return userRepository.findAllUsers(pageable);
}
@Transactional
public void updatePassword(Long id, String newPassword) {
userRepository.updatePassword(id, newPassword);
}
}
4.2 Spring事务管理
4.2.1 声明式事务
Spring提供了声明式事务管理,通过注解或XML配置。
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private PaymentService paymentService;
@Autowired
private InventoryService inventoryService;
@Transactional
public Order createOrder(Order order) {
// 1. 创建订单
order = orderRepository.save(order);
// 2. 扣减库存
inventoryService.decreaseStock(order.getProductId(), order.getQuantity());
// 3. 处理支付
paymentService.processPayment(order);
return order;
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void logOrder(Order order) {
// 独立事务,即使主事务回滚,日志仍会保存
orderRepository.saveLog(order);
}
}
4.2.2 事务传播行为
Spring支持多种事务传播行为:
- REQUIRED(默认):如果当前存在事务,则加入;否则新建事务
- REQUIRES_NEW:总是新建事务,挂起当前事务
- SUPPORTS:如果当前存在事务,则加入;否则以非事务方式执行
- MANDATORY:必须在事务中执行,否则抛出异常
- NOT_SUPPORTED:以非事务方式执行,挂起当前事务
- NEVER:必须在非事务中执行,否则抛出异常
- NESTED:如果当前存在事务,则在嵌套事务中执行
第五部分:Spring Web开发
5.1 Spring MVC
5.1.1 基本结构
Spring MVC遵循MVC(Model-View-Controller)模式:
- Model:数据模型
- View:视图(如JSP、Thymeleaf)
- Controller:控制器,处理HTTP请求
5.1.2 RESTful API开发
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// GET /api/users/{id}
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
// POST /api/users
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = userService.createUser(user);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
// PUT /api/users/{id}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
user.setId(id);
User updatedUser = userService.updateUser(user);
return ResponseEntity.ok(updatedUser);
}
// DELETE /api/users/{id}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
// GET /api/users?page=0&size=10
@GetMapping
public ResponseEntity<Page<User>> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Page<User> users = userService.getUsers(page, size);
return ResponseEntity.ok(users);
}
}
5.1.3 请求参数处理
@RestController
@RequestMapping("/api/products")
public class ProductController {
// 路径参数
@GetMapping("/{id}")
public Product getProduct(@PathVariable Long id) {
// ...
}
// 查询参数
@GetMapping("/search")
public List<Product> searchProducts(
@RequestParam String keyword,
@RequestParam(required = false) Double minPrice,
@RequestParam(required = false) Double maxPrice) {
// ...
}
// 表单参数
@PostMapping("/create")
public Product createProduct(@RequestParam String name,
@RequestParam Double price,
@RequestParam String description) {
// ...
}
// 请求体参数
@PostMapping("/batch")
public List<Product> createProducts(@RequestBody List<Product> products) {
// ...
}
// 头部参数
@GetMapping("/info")
public String getProductInfo(@RequestHeader("Authorization") String token) {
// ...
}
}
5.2 Spring Boot
5.2.1 Spring Boot简介
Spring Boot是Spring框架的扩展,旨在简化Spring应用的配置和部署。主要特点:
- 自动配置:根据类路径自动配置Spring应用
- 独立运行:内置Tomcat等服务器,可打包为可执行JAR
- 生产就绪:提供健康检查、指标等生产特性
- 简化依赖管理:通过starter简化依赖配置
5.2.2 创建Spring Boot应用
方式一:使用Spring Initializr
# 通过命令行创建
curl https://start.spring.io/starter.zip \
-d dependencies=web,data-jpa,h2 \
-d groupId=com.example \
-d artifactId=demo \
-o demo.zip
方式二:使用IDE 在IntelliJ IDEA或Eclipse中选择Spring Initializr创建项目。
方式三:手动创建
<!-- pom.xml -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
</parent>
<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>
</dependencies>
主应用类:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
5.2.3 配置管理
application.properties:
# 服务器配置
server.port=8080
server.servlet.context-path=/api
# 数据源配置
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
# JPA配置
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
# 日志配置
logging.level.com.example=DEBUG
logging.level.org.springframework=WARN
application.yml(YAML格式,更结构化):
server:
port: 8080
servlet:
context-path: /api
spring:
datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
logging:
level:
com.example: DEBUG
org.springframework: WARN
配置类:
@Configuration
public class AppConfig {
@Value("${app.name}")
private String appName;
@Bean
public String appName() {
return appName;
}
@Bean
@Profile("dev")
public DataSource devDataSource() {
// 开发环境数据源配置
return new EmbeddedDatabaseBuilder()
.setType(EmbeddedDatabaseType.H2)
.addScript("classpath:schema-dev.sql")
.addScript("classpath:data-dev.sql")
.build();
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
// 生产环境数据源配置
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
}
第六部分:Spring Security
6.1 安全基础
Spring Security是Spring框架的安全解决方案,提供认证和授权功能。
6.2 基本配置
Maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
安全配置类:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/api/public/**").permitAll() // 公开接口
.antMatchers("/api/admin/**").hasRole("ADMIN") // 管理员接口
.anyRequest().authenticated() // 其他接口需要认证
.and()
.formLogin() // 表单登录
.loginPage("/login")
.defaultSuccessUrl("/dashboard")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.csrf().disable(); // 禁用CSRF(对于REST API)
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 内存用户
auth.inMemoryAuthentication()
.withUser("user")
.password("{noop}password") // {noop}表示明文密码
.roles("USER")
.and()
.withUser("admin")
.password("{noop}admin")
.roles("ADMIN", "USER");
}
}
6.3 自定义用户认证
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在: " + username);
}
return org.springframework.security.core.userdetails.User
.withUsername(user.getUsername())
.password(user.getPassword())
.roles(user.getRoles().toArray(new String[0]))
.build();
}
}
6.4 JWT认证(REST API)
// JWT工具类
@Component
public class JwtUtil {
@Value("${jwt.secret}")
private String secret;
@Value("${jwt.expiration}")
private long expiration;
public String generateToken(String username) {
Map<String, Object> claims = new HashMap<>();
return Jwts.builder()
.setClaims(claims)
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expiration))
.signWith(SignatureAlgorithm.HS256, secret)
.compact();
}
public String extractUsername(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getSubject();
}
public boolean validateToken(String token, UserDetails userDetails) {
final String username = extractUsername(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
private boolean isTokenExpired(String token) {
return extractExpiration(token).before(new Date());
}
private Date extractExpiration(String token) {
return Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getExpiration();
}
}
// JWT认证过滤器
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private JwtUtil jwtUtil;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
jwt = authorizationHeader.substring(7);
username = jwtUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
if (jwtUtil.validateToken(jwt, userDetails)) {
UsernamePasswordAuthenticationToken authenticationToken =
new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
}
}
chain.doFilter(request, response);
}
}
第七部分:Spring高级特性
7.1 Spring事件机制
Spring提供了强大的事件发布/订阅机制。
// 自定义事件
public class UserCreatedEvent extends ApplicationEvent {
private User user;
public UserCreatedEvent(Object source, User user) {
super(source);
this.user = user;
}
public User getUser() {
return user;
}
}
// 事件监听器
@Component
public class UserEventListener {
@EventListener
public void handleUserCreated(UserCreatedEvent event) {
System.out.println("用户创建事件: " + event.getUser().getUsername());
// 发送欢迎邮件、记录日志等
}
@Async // 异步处理
@EventListener
public void handleUserCreatedAsync(UserCreatedEvent event) {
System.out.println("异步处理用户创建事件");
// 耗时操作
}
}
// 事件发布者
@Service
public class UserService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Autowired
private UserRepository userRepository;
@Transactional
public User createUser(User user) {
User savedUser = userRepository.save(user);
// 发布事件
eventPublisher.publishEvent(new UserCreatedEvent(this, savedUser));
return savedUser;
}
}
7.2 Spring缓存
Spring Cache抽象提供了统一的缓存API。
// 启用缓存
@SpringBootApplication
@EnableCaching
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
// 缓存配置
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
// 使用ConcurrentMapCacheManager
ConcurrentMapCacheManager cacheManager = new ConcurrentMapCacheManager();
cacheManager.setCacheNames(Arrays.asList("users", "products"));
return cacheManager;
}
}
// 缓存使用
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 缓存方法结果
@Cacheable(value = "users", key = "#id")
public User getUserById(Long id) {
System.out.println("从数据库查询用户: " + id);
return userRepository.findById(id).orElse(null);
}
// 更新缓存
@CachePut(value = "users", key = "#user.id")
public User updateUser(User user) {
System.out.println("更新用户: " + user.getId());
return userRepository.save(user);
}
// 删除缓存
@CacheEvict(value = "users", key = "#id")
public void deleteUser(Long id) {
System.out.println("删除用户: " + id);
userRepository.deleteById(id);
}
// 组合注解
@Caching(
put = {@CachePut(value = "users", key = "#user.id")},
evict = {@CacheEvict(value = "userList", allEntries = true)}
)
public User updateUserWithCacheEvict(User user) {
return userRepository.save(user);
}
}
7.3 Spring异步处理
// 启用异步支持
@Configuration
@EnableAsync
public class AsyncConfig {
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(25);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
// 异步方法
@Service
public class EmailService {
@Async
public void sendWelcomeEmail(String email, String username) {
System.out.println("发送欢迎邮件到: " + email);
// 模拟耗时操作
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("欢迎邮件发送完成");
}
@Async
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void sendTransactionalEmail(String email, String content) {
// 独立事务的异步操作
System.out.println("发送事务性邮件");
}
}
第八部分:Spring实战技巧
8.1 统一异常处理
// 全局异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
ErrorResponse error = new ErrorResponse(
"RESOURCE_NOT_FOUND",
ex.getMessage(),
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error);
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {
List<String> errors = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.toList());
ErrorResponse error = new ErrorResponse(
"VALIDATION_ERROR",
"参数验证失败",
LocalDateTime.now(),
errors
);
return ResponseEntity.badRequest().body(error);
}
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGenericException(Exception ex) {
ErrorResponse error = new ErrorResponse(
"INTERNAL_SERVER_ERROR",
"服务器内部错误",
LocalDateTime.now()
);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
}
}
8.2 统一响应格式
// 统一响应包装类
public class ApiResponse<T> {
private boolean success;
private String message;
private T data;
private long timestamp;
// 构造函数、getter、setter省略
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> response = new ApiResponse<>();
response.setSuccess(true);
response.setData(data);
response.setTimestamp(System.currentTimeMillis());
return response;
}
public static <T> ApiResponse<T> error(String message) {
ApiResponse<T> response = new ApiResponse<>();
response.setSuccess(false);
response.setMessage(message);
response.setTimestamp(System.currentTimeMillis());
return response;
}
}
// 控制器使用
@RestController
@RequestMapping("/api")
public class UserController {
@GetMapping("/users/{id}")
public ApiResponse<User> getUser(@PathVariable Long id) {
User user = userService.getUserById(id);
return ApiResponse.success(user);
}
@PostMapping("/users")
public ApiResponse<User> createUser(@Valid @RequestBody User user) {
User createdUser = userService.createUser(user);
return ApiResponse.success(createdUser);
}
}
8.3 参数验证
// 实体类验证
public class User {
@NotNull(message = "用户名不能为空")
@Size(min = 3, max = 20, message = "用户名长度必须在3-20之间")
@Pattern(regexp = "^[a-zA-Z0-9_]+$", message = "用户名只能包含字母、数字和下划线")
private String username;
@NotNull(message = "密码不能为空")
@Size(min = 6, message = "密码长度至少6位")
private String password;
@Email(message = "邮箱格式不正确")
@NotNull(message = "邮箱不能为空")
private String email;
@Min(value = 18, message = "年龄必须大于等于18岁")
@Max(value = 100, message = "年龄不能超过100岁")
private Integer age;
// 构造函数、getter、setter省略
}
// 自定义验证注解
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = UniqueUsernameValidator.class)
public @interface UniqueUsername {
String message() default "用户名已存在";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 自定义验证器
@Component
public class UniqueUsernameValidator implements ConstraintValidator<UniqueUsername, String> {
@Autowired
private UserRepository userRepository;
@Override
public boolean isValid(String username, ConstraintValidatorContext context) {
if (username == null) {
return true;
}
return !userRepository.existsByUsername(username);
}
}
第九部分:Spring Boot高级特性
9.1 Spring Boot Actuator
Spring Boot Actuator提供了生产环境监控功能。
Maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
配置:
# 启用所有端点
management.endpoints.web.exposure.include=*
# 启用特定端点
management.endpoints.web.exposure.include=health,info,metrics
# 端点路径
management.endpoints.web.base-path=/actuator
# 健康检查详细信息
management.endpoint.health.show-details=always
自定义健康检查:
@Component
public class DatabaseHealthIndicator implements HealthIndicator {
@Autowired
private DataSource dataSource;
@Override
public Health health() {
try (Connection connection = dataSource.getConnection()) {
// 执行简单的查询
connection.createStatement().execute("SELECT 1");
return Health.up()
.withDetail("database", "H2")
.withDetail("status", "connected")
.build();
} catch (Exception e) {
return Health.down()
.withDetail("database", "H2")
.withDetail("error", e.getMessage())
.build();
}
}
}
9.2 Spring Boot测试
// 单元测试
@SpringBootTest
class UserServiceTest {
@Autowired
private UserService userService;
@MockBean
private UserRepository userRepository;
@Test
void shouldCreateUser() {
// 准备数据
User user = new User();
user.setUsername("testuser");
user.setPassword("password");
// 模拟Repository行为
when(userRepository.findByUsername("testuser")).thenReturn(null);
when(userRepository.save(any(User.class))).thenReturn(user);
// 执行测试
User result = userService.createUser(user);
// 验证结果
assertNotNull(result);
assertEquals("testuser", result.getUsername());
verify(userRepository).save(user);
}
}
// Web层测试
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void shouldGetUser() throws Exception {
User user = new User();
user.setId(1L);
user.setUsername("testuser");
when(userService.getUserById(1L)).thenReturn(user);
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("testuser"));
}
}
第十部分:Spring生态系统
10.1 Spring Cloud
Spring Cloud是Spring Cloud Netflix、Spring Cloud Config、Spring Cloud Gateway等项目的集合,用于构建分布式系统。
Spring Cloud Netflix:
- Eureka:服务注册与发现
- Ribbon:客户端负载均衡
- Hystrix:熔断器
- Zuul:API网关
Spring Cloud Config:配置中心
Spring Cloud Gateway:新一代API网关
10.2 Spring Data
Spring Data项目提供了统一的数据访问API:
- Spring Data JPA:JPA数据访问
- Spring Data MongoDB:MongoDB数据访问
- Spring Data Redis:Redis数据访问
- Spring Data Elasticsearch:Elasticsearch数据访问
10.3 Spring Batch
Spring Batch用于批处理作业,支持复杂的批处理任务。
10.4 Spring Integration
Spring Integration提供了企业集成模式的实现,用于消息驱动架构。
第十一部分:最佳实践
11.1 项目结构
推荐的Spring项目结构:
src/main/java/com/example/
├── config/ # 配置类
├── controller/ # 控制器
├── service/ # 服务层
├── repository/ # 数据访问层
├── entity/ # 实体类
├── dto/ # 数据传输对象
├── exception/ # 异常类
├── util/ # 工具类
└── Application.java # 主应用类
11.2 命名规范
- 包名:小写,使用点分隔,如
com.example.project - 类名:大驼峰,如
UserService - 方法名:小驼峰,如
getUserById - 常量:全大写,下划线分隔,如
MAX_SIZE - 变量名:小驼峰,如
userName
11.3 依赖管理
- 使用Spring Boot的starter简化依赖
- 保持依赖版本一致
- 定期更新依赖版本
- 避免传递依赖冲突
11.4 日志记录
// 使用SLF4J
@Service
public class OrderService {
private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
public void processOrder(Order order) {
logger.info("开始处理订单: {}", order.getId());
try {
// 业务逻辑
logger.debug("订单详情: {}", order);
// ...
logger.info("订单处理完成: {}", order.getId());
} catch (Exception e) {
logger.error("订单处理失败: {}", order.getId(), e);
throw new OrderProcessingException("订单处理失败", e);
}
}
}
11.5 性能优化
数据库优化:
- 使用连接池(HikariCP)
- 合理使用索引
- 避免N+1查询问题
缓存优化:
- 合理使用缓存策略
- 避免缓存穿透、缓存雪崩
异步处理:
- 耗时操作异步化
- 使用消息队列解耦
JVM优化:
- 合理配置堆内存
- 使用G1垃圾回收器
第十二部分:学习路径建议
12.1 初级阶段(1-2个月)
- 基础Java:掌握Java基础、集合、IO、多线程
- Spring Core:深入理解IoC、DI、Bean生命周期
- Spring MVC:掌握Web开发基础
- Spring Boot:学习自动配置、starter、配置管理
12.2 中级阶段(2-3个月)
- Spring Data JPA:掌握数据访问层开发
- Spring AOP:理解切面编程
- Spring Security:学习安全认证和授权
- Spring事务管理:掌握事务传播行为
12.3 高级阶段(3-6个月)
- Spring Cloud:学习微服务架构
- Spring Boot高级特性:Actuator、测试、性能优化
- 设计模式:在Spring中应用设计模式
- 项目实战:参与实际项目开发
12.4 持续学习
- 阅读源码:深入理解Spring内部机制
- 关注社区:Spring官方博客、GitHub
- 技术分享:参加技术会议、写博客
- 实践项目:不断实践,积累经验
结语
Spring框架是一个庞大而强大的生态系统,掌握它需要时间和实践。本文从基础概念到高级特性,从理论到实践,系统地介绍了Spring框架的各个方面。记住,学习Spring的最佳方式是实践——创建项目、解决问题、不断优化。
随着Spring 6和Spring Boot 3的发布,Spring生态系统正在向现代化、响应式编程和云原生方向发展。保持学习的热情,跟上技术发展的步伐,你将成为一名优秀的Spring开发者。
祝你学习顺利,早日成为Spring专家!
