引言:为什么选择Spring框架?
在Java企业级开发领域,Spring框架已经成为事实上的标准。根据2023年Stack Overflow开发者调查,Spring框架在最受欢迎的Java框架中稳居榜首,超过70%的Java开发者在工作中使用Spring。Spring不仅仅是一个框架,它是一个完整的生态系统,涵盖了从依赖注入到微服务架构的方方面面。
Spring框架的核心优势在于其控制反转(IoC)和面向切面编程(AOP)的设计理念。通过IoC容器管理对象生命周期,通过AOP实现横切关注点的分离,Spring让开发者能够专注于业务逻辑,而不是基础设施代码。此外,Spring Boot的出现极大地简化了Spring应用的配置和部署,使得从零开始构建一个生产级应用变得前所未有的简单。
第一部分:Spring核心概念详解
1.1 控制反转(IoC)与依赖注入(DI)
控制反转(Inversion of Control, IoC) 是Spring框架的基石。传统的编程模式中,对象负责创建和管理其依赖的对象。而在IoC模式下,对象的创建和依赖关系的管理由外部容器(Spring IoC容器)负责。
依赖注入(Dependency Injection, DI) 是实现IoC的具体方式。Spring通过三种主要方式实现依赖注入:
- 构造器注入(Constructor Injection)
- Setter方法注入(Setter Injection)
- 字段注入(Field Injection)
示例:构造器注入的实现
// 1. 定义服务接口
public interface UserService {
void saveUser(String username);
}
// 2. 实现服务接口
@Service
public class UserServiceImpl implements UserService {
private final UserRepository userRepository;
// 使用构造器注入
@Autowired
public UserServiceImpl(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public void saveUser(String username) {
// 业务逻辑
System.out.println("Saving user: " + username);
userRepository.save(username);
}
}
// 3. 定义数据访问层
@Repository
public class UserRepository {
public void save(String username) {
// 模拟数据库操作
System.out.println("Database: User " + username + " saved");
}
}
// 4. 主应用类
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
// 从容器中获取Bean
UserService userService = context.getBean(UserService.class);
userService.saveUser("John Doe");
context.close();
}
}
代码解析:
@Service和@Repository注解将类标记为Spring Bean@Autowired注解告诉Spring自动注入依赖- Spring容器在启动时会创建
UserServiceImpl实例,并自动注入UserRepository实例 - 这种方式实现了松耦合,便于单元测试和代码维护
1.2 Spring Bean的生命周期
Spring Bean的生命周期是理解Spring框架的关键。从Bean的创建到销毁,Spring提供了多个扩展点:
实例化 -> 属性赋值 -> 初始化 -> 使用 -> 销毁
示例:自定义Bean生命周期管理
@Component
public class CustomBean implements InitializingBean, DisposableBean {
public CustomBean() {
System.out.println("1. 构造函数调用");
}
@PostConstruct
public void postConstruct() {
System.out.println("3. @PostConstruct注解方法调用");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("4. InitializingBean.afterPropertiesSet()调用");
}
@PreDestroy
public void preDestroy() {
System.out.println("6. @PreDestroy注解方法调用");
}
@Override
public void destroy() throws Exception {
System.out.println("7. DisposableBean.destroy()调用");
}
// 自定义初始化方法
@Bean(initMethod = "customInit")
public void customInit() {
System.out.println("5. 自定义init-method调用");
}
// 自定义销毁方法
@Bean(destroyMethod = "customDestroy")
public void customDestroy() {
System.out.println("8. 自定义destroy-method调用");
}
}
生命周期执行顺序:
- 构造函数调用
- 属性赋值(通过setter或字段)
@PostConstruct注解方法InitializingBean.afterPropertiesSet()- 自定义init-method
- Bean就绪,可以使用
@PreDestroy注解方法DisposableBean.destroy()- 自定义destroy-method
1.3 面向切面编程(AOP)
AOP允许开发者将横切关注点(如日志、事务、安全)从业务逻辑中分离出来。Spring AOP基于代理模式实现。
示例:自定义日志切面
// 1. 定义切面
@Aspect
@Component
public class LoggingAspect {
// 定义切点:所有Service层的方法
@Pointcut("execution(* com.example.service.*.*(..))")
public void serviceMethods() {}
// 前置通知
@Before("serviceMethods()")
public void logBefore(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[LOG] 开始执行方法: " + methodName);
}
// 后置通知
@After("serviceMethods()")
public void logAfter(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[LOG] 方法执行完成: " + methodName);
}
// 返回通知
@AfterReturning(pointcut = "serviceMethods()", returning = "result")
public void logAfterReturning(JoinPoint joinPoint, Object result) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[LOG] 方法 " + methodName + " 返回结果: " + result);
}
// 异常通知
@AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {
String methodName = joinPoint.getSignature().getName();
System.out.println("[LOG] 方法 " + methodName + " 抛出异常: " + ex.getMessage());
}
// 环绕通知(最强大)
@Around("serviceMethods()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("[LOG] 环绕通知开始: " + joinPoint.getSignature().getName());
try {
// 执行目标方法
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
System.out.println("[LOG] 方法执行耗时: " + (endTime - startTime) + "ms");
return result;
} catch (Exception e) {
long endTime = System.currentTimeMillis();
System.out.println("[LOG] 方法执行异常,耗时: " + (endTime - startTime) + "ms");
throw e;
}
}
}
// 2. 业务服务类
@Service
public class OrderService {
public String createOrder(String orderId) {
System.out.println("正在创建订单: " + orderId);
return "Order " + orderId + " created successfully";
}
public void processOrder(String orderId) {
System.out.println("正在处理订单: " + orderId);
if (orderId == null) {
throw new IllegalArgumentException("订单ID不能为空");
}
}
}
// 3. 启用AOP
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
// 配置类
}
AOP执行流程:
- 环绕通知开始
- 前置通知
- 执行目标方法
- 后置通知
- 返回通知(如果正常返回)
- 异常通知(如果抛出异常)
- 环绕通知结束
第二部分:Spring Boot实战开发
2.1 Spring Boot快速入门
Spring Boot通过约定优于配置的理念,极大地简化了Spring应用的开发。
示例:创建一个简单的REST API
// 1. 项目结构
/*
src/main/java/com/example/demo/
├── DemoApplication.java # 主启动类
├── controller/
│ └── UserController.java # 控制器
├── service/
│ └── UserService.java # 服务层
├── model/
│ └── User.java # 实体类
└── repository/
└── UserRepository.java # 数据访问层
*/
// 2. 主启动类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
// 3. 实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private String email;
}
// 4. 数据访问层(内存数据库)
@Repository
public class UserRepository {
private final Map<Long, User> users = new ConcurrentHashMap<>();
private final AtomicLong idGenerator = new AtomicLong(1);
public List<User> findAll() {
return new ArrayList<>(users.values());
}
public User findById(Long id) {
return users.get(id);
}
public User save(User user) {
if (user.getId() == null) {
user.setId(idGenerator.getAndIncrement());
}
users.put(user.getId(), user);
return user;
}
public void delete(Long id) {
users.remove(id);
}
}
// 5. 服务层
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
public User getUserById(Long id) {
User user = userRepository.findById(id);
if (user == null) {
throw new RuntimeException("User not found with id: " + id);
}
return user;
}
public User createUser(User user) {
return userRepository.save(user);
}
public User updateUser(Long id, User user) {
User existingUser = userRepository.findById(id);
if (existingUser == null) {
throw new RuntimeException("User not found with id: " + id);
}
user.setId(id);
return userRepository.save(user);
}
public void deleteUser(Long id) {
User user = userRepository.findById(id);
if (user == null) {
throw new RuntimeException("User not found with id: " + id);
}
userRepository.delete(id);
}
}
// 6. 控制器层
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public ResponseEntity<List<User>> getAllUsers() {
List<User> users = userService.getAllUsers();
return ResponseEntity.ok(users);
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
return ResponseEntity.ok(user);
}
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
User createdUser = userService.createUser(user);
return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
}
@PutMapping("/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
User updatedUser = userService.updateUser(id, user);
return ResponseEntity.ok(updatedUser);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.noContent().build();
}
}
// 7. 配置文件 application.properties
/*
server.port=8080
spring.application.name=user-service
logging.level.com.example.demo=DEBUG
*/
测试API:
# 创建用户
curl -X POST http://localhost:8080/api/users \
-H "Content-Type: application/json" \
-d '{"name":"张三","email":"zhangsan@example.com"}'
# 查询所有用户
curl http://localhost:8080/api/users
# 查询单个用户
curl http://localhost:8080/api/users/1
# 更新用户
curl -X PUT http://localhost:8080/api/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"张三更新","email":"zhangsan_updated@example.com"}'
# 删除用户
curl -X DELETE http://localhost:8080/api/users/1
2.2 Spring Data JPA与数据库集成
Spring Data JPA提供了对JPA(Java Persistence API)的抽象,使得数据库操作变得极其简单。
示例:使用Spring Data JPA操作MySQL
// 1. 添加依赖(pom.xml)
/*
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
*/
// 2. 实体类
@Entity
@Table(name = "products")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private BigDecimal price;
@Column(name = "category_id")
private Long categoryId;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt;
@PrePersist
protected void onCreate() {
this.createdAt = new Date();
}
}
// 3. Repository接口(无需实现)
public interface ProductRepository extends JpaRepository<Product, Long> {
// 自定义查询方法
List<Product> findByNameContaining(String name);
List<Product> findByPriceBetween(BigDecimal min, BigDecimal max);
List<Product> findByCategoryId(Long categoryId);
// 使用JPQL查询
@Query("SELECT p FROM Product p WHERE p.price > :minPrice")
List<Product> findProductsAbovePrice(@Param("minPrice") BigDecimal minPrice);
// 使用原生SQL查询
@Query(value = "SELECT * FROM products WHERE category_id = :categoryId", nativeQuery = true)
List<Product> findProductsByCategoryId(@Param("categoryId") Long categoryId);
// 分页查询
Page<Product> findByPriceBetween(BigDecimal min, BigDecimal max, Pageable pageable);
// 排序查询
List<Product> findByCategoryIdOrderByPriceDesc(Long categoryId);
}
// 4. 服务层
@Service
@Transactional
public class ProductService {
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
// 创建产品
public Product createProduct(Product product) {
return productRepository.save(product);
}
// 批量创建产品
public List<Product> createProducts(List<Product> products) {
return productRepository.saveAll(products);
}
// 查询所有产品
public List<Product> getAllProducts() {
return productRepository.findAll();
}
// 根据ID查询产品
public Product getProductById(Long id) {
return productRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Product not found with id: " + id));
}
// 根据名称模糊查询
public List<Product> searchProductsByName(String keyword) {
return productRepository.findByNameContaining(keyword);
}
// 根据价格范围查询
public List<Product> getProductsByPriceRange(BigDecimal min, BigDecimal max) {
return productRepository.findByPriceBetween(min, max);
}
// 分页查询
public Page<Product> getProductsByPage(int page, int size) {
Pageable pageable = PageRequest.of(page, size, Sort.by("price").descending());
return productRepository.findAll(pageable);
}
// 更新产品
public Product updateProduct(Long id, Product productDetails) {
Product product = getProductById(id);
product.setName(productDetails.getName());
product.setPrice(productDetails.getPrice());
product.setCategoryId(productDetails.getCategoryId());
return productRepository.save(product);
}
// 删除产品
public void deleteProduct(Long id) {
Product product = getProductById(id);
productRepository.delete(product);
}
// 统计产品数量
public long countProducts() {
return productRepository.count();
}
// 检查产品是否存在
public boolean productExists(Long id) {
return productRepository.existsById(id);
}
}
// 5. 控制器层
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final ProductService productService;
public ProductController(ProductService productService) {
this.productService = productService;
}
@PostMapping
public ResponseEntity<Product> createProduct(@RequestBody Product product) {
Product createdProduct = productService.createProduct(product);
return ResponseEntity.status(HttpStatus.CREATED).body(createdProduct);
}
@GetMapping
public ResponseEntity<List<Product>> getAllProducts() {
List<Product> products = productService.getAllProducts();
return ResponseEntity.ok(products);
}
@GetMapping("/{id}")
public ResponseEntity<Product> getProductById(@PathVariable Long id) {
Product product = productService.getProductById(id);
return ResponseEntity.ok(product);
}
@GetMapping("/search")
public ResponseEntity<List<Product>> searchProducts(@RequestParam String keyword) {
List<Product> products = productService.searchProductsByName(keyword);
return ResponseEntity.ok(products);
}
@GetMapping("/price-range")
public ResponseEntity<List<Product>> getProductsByPriceRange(
@RequestParam BigDecimal min,
@RequestParam BigDecimal max) {
List<Product> products = productService.getProductsByPriceRange(min, max);
return ResponseEntity.ok(products);
}
@GetMapping("/page")
public ResponseEntity<Page<Product>> getProductsByPage(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size) {
Page<Product> products = productService.getProductsByPage(page, size);
return ResponseEntity.ok(products);
}
@PutMapping("/{id}")
public ResponseEntity<Product> updateProduct(@PathVariable Long id, @RequestBody Product product) {
Product updatedProduct = productService.updateProduct(id, product);
return ResponseEntity.ok(updatedProduct);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
return ResponseEntity.noContent().build();
}
@GetMapping("/count")
public ResponseEntity<Long> countProducts() {
long count = productService.countProducts();
return ResponseEntity.ok(count);
}
}
// 6. 配置文件 application.properties
/*
spring.datasource.url=jdbc:mysql://localhost:3306/spring_demo?useSSL=false&serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
server.port=8080
logging.level.org.hibernate.SQL=DEBUG
*/
2.3 Spring Security安全集成
Spring Security提供了全面的安全解决方案,包括认证、授权、CSRF保护等。
示例:基于JWT的认证系统
// 1. 添加依赖
/*
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
*/
// 2. JWT工具类
@Component
public class JwtTokenUtil {
private static final String SECRET_KEY = "your-secret-key-should-be-long-and-secure";
private static final long EXPIRATION_TIME = 86400000; // 24小时
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
claims.put("authorities", userDetails.getAuthorities());
return Jwts.builder()
.setClaims(claims)
.setSubject(userDetails.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();
}
public String extractUsername(String token) {
return Jwts.parser()
.setSigningKey(SECRET_KEY)
.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 Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody()
.getExpiration()
.before(new Date());
}
}
// 3. 用户实体
@Entity
@Table(name = "users")
@Data
public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String username;
@Column(nullable = false)
private String password;
@Column(unique = true)
private String email;
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return roles.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
.collect(Collectors.toList());
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
// 4. 角色实体
@Entity
@Table(name = "roles")
@Data
public class Role {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(unique = true, nullable = false)
private String name;
}
// 5. 用户Repository
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByUsername(String username);
Optional<User> findByEmail(String email);
boolean existsByUsername(String username);
boolean existsByEmail(String email);
}
// 6. JWT认证过滤器
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserRepository userRepository;
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
final String token = authHeader.substring(7);
final String username = jwtTokenUtil.extractUsername(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new RuntimeException("User not found"));
if (jwtTokenUtil.validateToken(token, user)) {
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
}
// 7. 安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
@Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter;
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
// 8. 认证控制器
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
try {
Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
loginRequest.getUsername(),
loginRequest.getPassword()
)
);
SecurityContextHolder.getContext().setAuthentication(authentication);
User user = (User) authentication.getPrincipal();
String token = jwtTokenUtil.generateToken(user);
return ResponseEntity.ok(new JwtResponse(token, user.getUsername()));
} catch (BadCredentialsException e) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body("Invalid username or password");
}
}
@PostMapping("/register")
public ResponseEntity<?> register(@RequestBody RegisterRequest registerRequest) {
if (userRepository.existsByUsername(registerRequest.getUsername())) {
return ResponseEntity.badRequest().body("Username already exists");
}
if (userRepository.existsByEmail(registerRequest.getEmail())) {
return ResponseEntity.badRequest().body("Email already exists");
}
User user = new User();
user.setUsername(registerRequest.getUsername());
user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
user.setEmail(registerRequest.getEmail());
// 设置默认角色
Role userRole = new Role();
userRole.setName("USER");
user.getRoles().add(userRole);
userRepository.save(user);
return ResponseEntity.status(HttpStatus.CREATED).body("User registered successfully");
}
}
// 9. 请求/响应对象
@Data
class LoginRequest {
private String username;
private String password;
}
@Data
class RegisterRequest {
private String username;
private String password;
private String email;
}
@Data
class JwtResponse {
private String token;
private String username;
public JwtResponse(String token, String username) {
this.token = token;
this.username = username;
}
}
第三部分:高级主题与最佳实践
3.1 Spring事务管理
Spring提供了声明式事务管理,通过@Transactional注解简化事务处理。
示例:复杂的事务场景
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryService inventoryService;
@Autowired
private PaymentService paymentService;
@Autowired
private NotificationService notificationService;
// 1. 基本事务管理
@Transactional
public Order createOrder(Order order) {
// 1. 保存订单
Order savedOrder = orderRepository.save(order);
// 2. 扣减库存
inventoryService.decreaseStock(order.getProductId(), order.getQuantity());
// 3. 处理支付
paymentService.processPayment(order);
// 4. 发送通知
notificationService.sendOrderConfirmation(order);
return savedOrder;
}
// 2. 事务传播行为
@Transactional(propagation = Propagation.REQUIRED)
public void methodA() {
// 使用现有事务,如果没有则创建新事务
methodB(); // 在同一个事务中执行
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodB() {
// 总是创建新事务,挂起当前事务
// 适合记录日志等独立操作
}
// 3. 事务隔离级别
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void processConcurrentOrders() {
// 防止脏读、不可重复读
// 适合高并发场景
}
// 4. 事务回滚规则
@Transactional(
rollbackFor = {Exception.class},
noRollbackFor = {IllegalArgumentException.class}
)
public void complexTransaction() {
try {
// 业务逻辑
} catch (IllegalArgumentException e) {
// 不回滚
throw e;
} catch (Exception e) {
// 回滚
throw e;
}
}
// 5. 嵌套事务
@Transactional(propagation = Propagation.NESTED)
public void nestedTransaction() {
// 如果外部事务存在,则创建嵌套事务
// 如果外部事务回滚,嵌套事务也会回滚
// 但嵌套事务可以独立回滚
}
// 6. 只读事务
@Transactional(readOnly = true)
public List<Order> getOrdersByUser(Long userId) {
// 优化性能,避免不必要的锁
return orderRepository.findByUserId(userId);
}
// 7. 事务超时
@Transactional(timeout = 30)
public void timeSensitiveOperation() {
// 30秒超时,防止长时间事务
}
// 8. 手动事务管理
@Autowired
private PlatformTransactionManager transactionManager;
public void manualTransaction() {
TransactionStatus status = transactionManager.getTransaction(
new DefaultTransactionDefinition()
);
try {
// 业务逻辑
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
throw e;
}
}
}
3.2 异步处理与消息队列
Spring提供了@Async注解和消息队列集成,用于处理异步任务。
示例:异步任务处理
// 1. 启用异步支持
@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.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
// 2. 异步服务
@Service
public class EmailService {
@Async
public void sendEmail(String to, String subject, String body) {
// 模拟发送邮件的耗时操作
try {
Thread.sleep(3000); // 模拟3秒延迟
System.out.println("Email sent to: " + to);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Async
public CompletableFuture<String> sendEmailAsync(String to, String subject, String body) {
try {
Thread.sleep(2000);
return CompletableFuture.completedFuture("Email sent to " + to);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return CompletableFuture.failedFuture(e);
}
}
}
// 3. 消息队列集成(RabbitMQ示例)
@Configuration
public class RabbitMQConfig {
@Bean
public Queue queue() {
return new Queue("order.queue", true);
}
@Bean
public TopicExchange exchange() {
return new TopicExchange("order.exchange");
}
@Bean
public Binding binding(Queue queue, TopicExchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("order.*");
}
}
@Service
public class OrderMessageService {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendOrderMessage(Order order) {
rabbitTemplate.convertAndSend("order.exchange", "order.created", order);
}
@RabbitListener(queues = "order.queue")
public void processOrderMessage(Order order) {
System.out.println("Processing order: " + order.getId());
// 处理订单逻辑
}
}
3.3 Spring Cloud微服务架构
Spring Cloud提供了构建分布式系统的工具,包括服务发现、配置管理、API网关等。
示例:微服务架构示例
// 1. 服务注册中心(Eureka Server)
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
// 2. 服务提供者(Product Service)
@SpringBootApplication
@EnableEurekaClient
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
@RestController
@RequestMapping("/api/products")
public class ProductController {
// ... 产品相关接口
}
// 3. 服务消费者(Order Service)
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class, args);
}
}
// 4. Feign客户端
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/api/products/{id}")
Product getProductById(@PathVariable("id") Long id);
@PostMapping("/api/products")
Product createProduct(@RequestBody Product product);
}
// 5. API网关(Spring Cloud Gateway)
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
// 6. 配置文件 application.yml
/*
spring:
cloud:
gateway:
routes:
- id: product-service
uri: lb://product-service
predicates:
- Path=/api/products/**
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
*/
// 7. 配置中心(Spring Cloud Config)
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
第四部分:性能优化与调试技巧
4.1 性能优化策略
示例:缓存优化
// 1. 启用缓存
@Configuration
@EnableCaching
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory())
.cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(10))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())))
.build();
return cacheManager;
}
}
// 2. 使用缓存注解
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
// 缓存结果,key为"product::" + id
@Cacheable(value = "products", key = "#id")
public Product getProductById(Long id) {
System.out.println("从数据库查询产品: " + id);
return productRepository.findById(id).orElse(null);
}
// 更新缓存
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
System.out.println("更新产品: " + product.getId());
return productRepository.save(product);
}
// 删除缓存
@CacheEvict(value = "products", key = "#id")
public void deleteProduct(Long id) {
System.out.println("删除产品: " + id);
productRepository.deleteById(id);
}
// 复杂缓存逻辑
@Cacheable(value = "products", key = "#categoryId + '_' + #page + '_' + #size")
public Page<Product> getProductsByCategory(Long categoryId, int page, int size) {
Pageable pageable = PageRequest.of(page, size);
return productRepository.findByCategoryId(categoryId, pageable);
}
}
4.2 调试与监控
示例:Spring Boot Actuator监控
// 1. 添加依赖
/*
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
*/
// 2. 配置 application.properties
/*
management.endpoints.web.exposure.include=health,info,metrics,loggers
management.endpoint.health.show-details=always
management.endpoint.health.show-details=when_authorized
management.endpoint.health.group.readiness.include=ping,db
management.endpoint.health.group.liveness.include=ping
management.info.env.enabled=true
*/
// 3. 自定义健康检查
@Component
public class CustomHealthIndicator implements HealthIndicator {
@Autowired
private DataSource dataSource;
@Override
public Health health() {
try (Connection connection = dataSource.getConnection()) {
if (connection.isValid(2)) {
return Health.up()
.withDetail("database", "MySQL")
.withDetail("status", "Connected")
.build();
} else {
return Health.down()
.withDetail("database", "MySQL")
.withDetail("status", "Connection timeout")
.build();
}
} catch (Exception e) {
return Health.down()
.withDetail("database", "MySQL")
.withDetail("error", e.getMessage())
.build();
}
}
}
// 4. 自定义指标
@Component
public class CustomMetrics {
private final MeterRegistry meterRegistry;
private final Counter orderCounter;
private final Timer orderProcessingTimer;
public CustomMetrics(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
this.orderCounter = Counter.builder("orders.total")
.description("Total number of orders")
.register(meterRegistry);
this.orderProcessingTimer = Timer.builder("orders.processing.time")
.description("Time taken to process orders")
.register(meterRegistry);
}
public void recordOrder() {
orderCounter.increment();
}
public void recordOrderProcessingTime(Runnable task) {
orderProcessingTimer.record(task);
}
}
第五部分:学习路径与资源推荐
5.1 学习路径建议
基础阶段(1-2周)
- 掌握Java基础(集合、多线程、IO)
- 理解Spring核心概念(IoC、DI、AOP)
- 学习Spring Boot基础配置
进阶阶段(2-4周)
- 深入学习Spring Data JPA
- 掌握Spring Security
- 学习REST API设计
高级阶段(4-6周)
- 学习Spring事务管理
- 掌握异步处理与消息队列
- 理解Spring Cloud微服务架构
实战阶段(持续)
- 参与开源项目
- 构建个人项目
- 学习性能优化与调试
5.2 推荐学习资源
官方文档
- Spring Framework官方文档:https://spring.io/projects/spring-framework
- Spring Boot官方文档:https://spring.io/projects/spring-boot
书籍推荐
- 《Spring实战》(Craig Walls著)
- 《Spring Boot编程思想》(小马哥著)
- 《Spring Cloud微服务实战》(翟永超著)
在线课程
- Spring官方教程:https://spring.io/guides
- Baeldung Spring教程:https://www.baeldung.com/spring-tutorial
- Spring Boot官方示例:https://github.com/spring-projects/spring-boot/tree/main/spring-boot-samples
社区与论坛
- Spring官方论坛:https://spring.io/community
- Stack Overflow Spring标签:https://stackoverflow.com/questions/tagged/spring
- GitHub Spring项目:https://github.com/spring-projects
5.3 实战项目建议
个人博客系统
- 技术栈:Spring Boot + Spring Data JPA + Thymeleaf
- 功能:用户管理、文章发布、评论系统
电商后台管理系统
- 技术栈:Spring Boot + Spring Security + Vue.js
- 功能:商品管理、订单处理、用户管理
微服务架构项目
- 技术栈:Spring Cloud + Docker + Kubernetes
- 功能:服务注册、配置中心、API网关、分布式事务
实时数据处理系统
- 技术栈:Spring Boot + Kafka + Redis + Elasticsearch
- 功能:数据采集、实时分析、可视化展示
结语
Spring框架的学习是一个循序渐进的过程,从理解核心概念到掌握实战技巧,需要持续的学习和实践。本文从零基础开始,详细介绍了Spring的核心概念、Spring Boot的实战开发、高级主题以及性能优化技巧。
关键要点回顾:
- IoC和DI是Spring的基石,理解它们是掌握Spring的关键
- Spring Boot通过约定优于配置的理念,极大地简化了开发
- Spring Data JPA让数据库操作变得简单高效
- Spring Security提供了全面的安全解决方案
- 事务管理和异步处理是企业级应用的核心能力
- Spring Cloud为微服务架构提供了完整的解决方案
学习建议:
- 从简单的REST API开始,逐步增加复杂度
- 多写代码,多调试,多思考
- 阅读优秀开源项目的源码
- 参与社区讨论,解决实际问题
Spring生态系统庞大而强大,掌握它将为你的Java开发之路打开新的大门。祝你学习顺利,早日成为Spring专家!
