引言

Spring框架是Java企业级应用开发的事实标准,它通过依赖注入(DI)和面向切面编程(AOP)等核心概念,极大地简化了企业级应用的开发。本指南将从基础概念讲起,逐步深入到高级特性,并通过实战案例帮助你掌握Spring框架的核心技能。

第一部分:Spring基础概念

1.1 什么是Spring框架?

Spring是一个开源的Java开发框架,由Rod Johnson在2003年创建。它的核心特性包括:

  • 依赖注入(DI):通过控制反转(IoC)容器管理对象之间的依赖关系
  • 面向切面编程(AOP):分离横切关注点,如日志、事务、安全等
  • 声明式事务管理:简化事务处理
  • MVC框架:提供Web应用开发的MVC架构

1.2 Spring的核心模块

Spring框架由多个模块组成,主要包括:

  • Spring Core:提供IoC容器和DI功能
  • Spring Context:提供配置和上下文支持
  • Spring AOP:提供面向切面编程支持
  • Spring JDBC:简化JDBC操作
  • Spring ORM:集成ORM框架如Hibernate
  • Spring Web:提供Web应用支持
  • Spring MVC:提供MVC架构支持

1.3 依赖注入(DI)详解

依赖注入是Spring框架的核心概念。它通过IoC容器将对象的依赖关系从代码中移出,由容器负责创建和管理对象。

示例:使用XML配置的DI

// 定义接口
public interface MessageService {
    String getMessage();
}

// 实现类
public class EmailService implements MessageService {
    @Override
    public String getMessage() {
        return "Hello via Email";
    }
}

// 使用类
public class NotificationService {
    private MessageService messageService;
    
    // 通过setter方法注入
    public void setMessageService(MessageService messageService) {
        this.messageService = messageService;
    }
    
    public void sendNotification() {
        System.out.println(messageService.getMessage());
    }
}
<!-- beans.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- 定义MessageService的实现 -->
    <bean id="emailService" class="com.example.EmailService"/>
    
    <!-- 定义NotificationService并注入依赖 -->
    <bean id="notificationService" class="com.example.NotificationService">
        <property name="messageService" ref="emailService"/>
    </bean>
</beans>
// 使用Spring容器
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        NotificationService notificationService = context.getBean("notificationService", NotificationService.class);
        notificationService.sendNotification();
    }
}

示例:使用注解的DI

// 使用@Component注解标记组件
@Component
public class EmailService implements MessageService {
    @Override
    public String getMessage() {
        return "Hello via Email";
    }
}

// 使用@Service注解标记服务层
@Service
public class NotificationService {
    @Autowired
    private MessageService messageService;
    
    public void sendNotification() {
        System.out.println(messageService.getMessage());
    }
}
// 配置类
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
    // 可以在这里定义额外的bean
}
// 使用Java配置
public class MainApp {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        NotificationService notificationService = context.getBean(NotificationService.class);
        notificationService.sendNotification();
    }
}

1.4 Spring IoC容器

Spring IoC容器负责创建、配置和管理bean。主要的容器接口是ApplicationContext

容器类型:

  1. ClassPathXmlApplicationContext:从类路径加载XML配置
  2. FileSystemXmlApplicationContext:从文件系统加载XML配置
  3. AnnotationConfigApplicationContext:基于注解的配置

Bean的作用域:

  • singleton(默认):每个容器中一个bean实例
  • prototype:每次请求都创建新实例
  • request:每个HTTP请求一个实例(Web应用)
  • session:每个HTTP会话一个实例(Web应用)
  • global-session:全局HTTP会话(Portlet应用)

第二部分:Spring核心特性深入

2.1 面向切面编程(AOP)

AOP允许将横切关注点(如日志、事务、安全)从业务逻辑中分离出来。

AOP核心概念:

  • 切面(Aspect):横切关注点的模块化
  • 连接点(Join Point):程序执行过程中的点(如方法执行)
  • 通知(Advice):在特定连接点执行的动作
  • 切入点(Pointcut):匹配连接点的表达式
  • 目标对象(Target Object):被代理的对象
  • 代理(Proxy):Spring创建的AOP代理对象

示例:使用注解的AOP

// 定义切面
@Aspect
@Component
public class LoggingAspect {
    
    // 定义切入点:所有service包下的方法
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceMethods() {}
    
    // 前置通知
    @Before("serviceMethods()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before executing: " + joinPoint.getSignature().getName());
    }
    
    // 后置通知
    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After executing: " + joinPoint.getSignature().getName());
    }
    
    // 返回通知
    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        System.out.println("Method " + joinPoint.getSignature().getName() + 
                          " returned: " + result);
    }
    
    // 异常通知
    @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable ex) {
        System.out.println("Method " + joinPoint.getSignature().getName() + 
                          " threw exception: " + ex.getMessage());
    }
    
    // 环绕通知
    @Around("serviceMethods()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("Around before: " + joinPoint.getSignature().getName());
        Object result = joinPoint.proceed(); // 执行目标方法
        System.out.println("Around after: " + joinPoint.getSignature().getName());
        return result;
    }
}
// 启用AOP
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}

2.2 Spring事务管理

Spring提供了声明式事务管理,通过AOP实现。

事务传播行为:

  • REQUIRED(默认):如果当前存在事务,则加入;否则创建新事务
  • REQUIRES_NEW:总是创建新事务,挂起当前事务
  • MANDATORY:必须在现有事务中执行
  • SUPPORTS:如果存在事务则加入,否则以非事务方式执行
  • NOT_SUPPORTED:以非事务方式执行,挂起当前事务
  • NEVER:必须在非事务中执行

示例:声明式事务管理

// 服务类
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    
    @Transactional(propagation = Propagation.REQUIRED, 
                   rollbackFor = Exception.class)
    public void createUser(User user) {
        userRepository.save(user);
        // 如果这里抛出异常,事务会回滚
        if (user.getAge() < 18) {
            throw new RuntimeException("User must be at least 18 years old");
        }
    }
    
    @Transactional(readOnly = true)
    public User findUserById(Long id) {
        return userRepository.findById(id).orElse(null);
    }
}
// 配置事务管理器
@Configuration
@EnableTransactionManagement
public class TransactionConfig {
    
    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }
}

2.3 Spring数据访问

Spring提供了统一的数据访问抽象,支持JDBC、JPA、Hibernate等。

示例:Spring Data JPA

// 实体类
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "username", nullable = false, unique = true)
    private String username;
    
    @Column(name = "email")
    private String email;
    
    @Column(name = "age")
    private Integer age;
    
    // 构造函数、getter、setter省略
}

// Repository接口
public interface UserRepository extends JpaRepository<User, Long> {
    
    // 自定义查询方法
    User findByUsername(String username);
    
    List<User> findByAgeGreaterThan(Integer age);
    
    // 使用JPQL查询
    @Query("SELECT u FROM User u WHERE u.email LIKE %:domain%")
    List<User> findByEmailDomain(@Param("domain") String domain);
    
    // 原生SQL查询
    @Query(value = "SELECT * FROM users WHERE age > :minAge", nativeQuery = true)
    List<User> findUsersByMinAge(@Param("minAge") Integer minAge);
    
    // 分页查询
    Page<User> findByAgeGreaterThan(Integer age, Pageable pageable);
    
    // 自定义更新
    @Modifying
    @Query("UPDATE User u SET u.email = :email WHERE u.id = :id")
    int updateUserEmail(@Param("id") Long id, @Param("email") String email);
}
// 使用Repository
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    
    public User createUser(User user) {
        return userRepository.save(user);
    }
    
    public User findByUsername(String username) {
        return userRepository.findByUsername(username);
    }
    
    public List<User> findUsersByAge(Integer age) {
        return userRepository.findByAgeGreaterThan(age);
    }
    
    public Page<User> findUsersByAgeWithPagination(Integer age, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("username"));
        return userRepository.findByAgeGreaterThan(age, pageable);
    }
}

第三部分:Spring Web开发

3.1 Spring MVC架构

Spring MVC是基于MVC模式的Web框架,核心组件包括:

  • DispatcherServlet:前端控制器
  • HandlerMapping:请求映射处理器
  • Controller:处理请求的控制器
  • ModelAndView:模型和视图
  • ViewResolver:视图解析器

示例:RESTful API开发

// Controller类
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @Autowired
    private UserService userService;
    
    // 创建用户
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        User createdUser = userService.createUser(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
    
    // 获取用户
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        User user = userService.findUserById(id);
        if (user == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(user);
    }
    
    // 获取所有用户
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        List<User> users = userService.findAllUsers();
        return ResponseEntity.ok(users);
    }
    
    // 更新用户
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        User existingUser = userService.findUserById(id);
        if (existingUser == null) {
            return ResponseEntity.notFound().build();
        }
        user.setId(id);
        User updatedUser = userService.updateUser(user);
        return ResponseEntity.ok(updatedUser);
    }
    
    // 删除用户
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResponseEntity.noContent().build();
    }
    
    // 分页查询
    @GetMapping("/search")
    public ResponseEntity<Page<User>> searchUsers(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(required = false) Integer minAge) {
        
        Pageable pageable = PageRequest.of(page, size);
        Page<User> users;
        
        if (minAge != null) {
            users = userService.findUsersByAge(minAge, pageable);
        } else {
            users = userService.findAllUsers(pageable);
        }
        
        return ResponseEntity.ok(users);
    }
}

3.2 请求参数绑定

Spring MVC支持多种参数绑定方式:

// 路径参数
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) { ... }

// 查询参数
@GetMapping("/users")
public List<User> getUsers(@RequestParam String name) { ... }

// 表单参数
@PostMapping("/users")
public User createUser(@RequestParam String username, @RequestParam String email) { ... }

// JSON请求体
@PostMapping("/users")
public User createUser(@RequestBody User user) { ... }

// 多部分文件上传
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) { ... }

// 复杂对象绑定
@PostMapping("/users")
public User createUser(@Valid @RequestBody UserDTO userDTO) { ... }

3.3 数据验证

Spring支持JSR-303/JSR-349数据验证:

// DTO类
public class UserDTO {
    @NotBlank(message = "用户名不能为空")
    @Size(min = 3, max = 20, message = "用户名长度必须在3-20之间")
    private String username;
    
    @Email(message = "邮箱格式不正确")
    @NotBlank(message = "邮箱不能为空")
    private String email;
    
    @Min(value = 18, message = "年龄必须大于等于18")
    @Max(value = 120, message = "年龄不能超过120")
    private Integer age;
    
    // getter和setter省略
}

// Controller中使用验证
@RestController
@RequestMapping("/api/users")
public class UserController {
    
    @PostMapping
    public ResponseEntity<?> createUser(@Valid @RequestBody UserDTO userDTO, 
                                       BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            List<String> errors = bindingResult.getAllErrors().stream()
                    .map(DefaultMessageSourceResolvable::getDefaultMessage)
                    .collect(Collectors.toList());
            return ResponseEntity.badRequest().body(errors);
        }
        
        // 处理业务逻辑
        User user = convertToUser(userDTO);
        User createdUser = userService.createUser(user);
        return ResponseEntity.status(HttpStatus.CREATED).body(createdUser);
    }
}

3.4 异常处理

Spring提供了全局异常处理机制:

// 全局异常处理器
@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().getAllErrors().stream()
                .map(DefaultMessageSourceResolvable::getDefaultMessage)
                .collect(Collectors.toList());
        
        ErrorResponse error = new ErrorResponse(
            "VALIDATION_ERROR",
            "Validation failed",
            LocalDateTime.now(),
            errors
        );
        return ResponseEntity.badRequest().body(error);
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGenericException(Exception ex) {
        ErrorResponse error = new ErrorResponse(
            "INTERNAL_SERVER_ERROR",
            "An unexpected error occurred",
            LocalDateTime.now()
        );
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
    }
}

// 自定义异常
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

// 错误响应DTO
public class ErrorResponse {
    private String code;
    private String message;
    private LocalDateTime timestamp;
    private List<String> details;
    
    // 构造函数、getter、setter省略
}

第四部分:Spring Boot实战

4.1 Spring Boot简介

Spring Boot是Spring框架的扩展,旨在简化Spring应用的初始搭建和开发过程。

Spring Boot特性:

  • 自动配置:根据类路径自动配置Spring应用
  • 起步依赖:简化依赖管理
  • 内嵌服务器:无需单独部署Tomcat等服务器
  • 生产就绪特性:健康检查、指标监控等
  • 无需XML配置:基于Java配置和注解

4.2 创建Spring Boot项目

使用Spring Initializr创建项目

# 使用curl创建项目
curl https://start.spring.io/starter.zip \
  -d dependencies=web,data-jpa,h2,devtools,lombok \
  -d groupId=com.example \
  -d artifactId=spring-boot-demo \
  -d name=spring-boot-demo \
  -d description="Demo project for Spring Boot" \
  -d packageName=com.example.demo \
  -d packaging=jar \
  -d javaVersion=11 \
  -o spring-boot-demo.zip

项目结构

spring-boot-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/demo/
│   │   │       ├── DemoApplication.java
│   │   │       ├── controller/
│   │   │       ├── service/
│   │   │       ├── repository/
│   │   │       └── entity/
│   │   └── resources/
│   │       ├── application.properties
│   │       └── static/
│   └── test/
│       └── java/
│           └── com/example/demo/
├── pom.xml
└── README.md

4.3 Spring Boot核心配置

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.demo=DEBUG
logging.level.org.springframework.web=INFO

# 开发工具配置
spring.devtools.restart.enabled=true
spring.devtools.livereload.enabled=true

# Actuator配置
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always

application.yml配置

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
  devtools:
    restart:
      enabled: true
    livereload:
      enabled: true

logging:
  level:
    com.example.demo: DEBUG
    org.springframework.web: INFO

management:
  endpoints:
    web:
      exposure:
        include: health,info,metrics
  endpoint:
    health:
      show-details: always

4.4 Spring Boot自动配置原理

Spring Boot通过@SpringBootApplication注解启用自动配置:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@SpringBootApplication注解组合了以下注解:

  • @SpringBootConfiguration:标记该类为配置类
  • @EnableAutoConfiguration:启用自动配置
  • @ComponentScan:扫描组件

自动配置通过spring.factories文件和条件注解实现:

// 自定义自动配置示例
@Configuration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class})
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class CustomDataSourceAutoConfiguration {
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource(DataSourceProperties properties) {
        return properties.initializeDataSourceBuilder().build();
    }
}

4.5 Spring Boot Starter

Spring Boot Starter是一组依赖描述符,简化了依赖管理。

常用Starter:

  • spring-boot-starter-web:Web开发
  • spring-boot-starter-data-jpa:JPA数据访问
  • spring-boot-starter-security:安全控制
  • spring-boot-starter-test:测试支持
  • spring-boot-starter-actuator:生产监控

创建自定义Starter

<!-- 自定义Starter的pom.xml -->
<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>custom-spring-boot-starter</artifactId>
    <version>1.0.0</version>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project>
// 自动配置类
@Configuration
@ConditionalOnClass(CustomService.class)
@EnableConfigurationProperties(CustomProperties.class)
public class CustomAutoConfiguration {
    
    @Bean
    @ConditionalOnMissingBean
    public CustomService customService(CustomProperties properties) {
        return new CustomService(properties.getMessage());
    }
}

// 配置属性类
@ConfigurationProperties(prefix = "custom")
public class CustomProperties {
    private String message = "Hello";
    
    // getter和setter省略
}

// 自定义服务
public class CustomService {
    private final String message;
    
    public CustomService(String message) {
        this.message = message;
    }
    
    public String getMessage() {
        return message;
    }
}
// 在META-INF/spring.factories中注册
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.CustomAutoConfiguration

第五部分:Spring高级特性

5.1 Spring Security

Spring Security是强大的安全框架,提供认证和授权功能。

基本配置

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .antMatchers("/api/public/**").permitAll()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/dashboard")
                .permitAll()
            .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout")
                .permitAll()
            .and()
            .exceptionHandling()
                .accessDeniedPage("/403");
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

JWT认证示例

// JWT工具类
@Component
public class JwtTokenUtil {
    
    private static final String SECRET_KEY = "your-secret-key";
    private static final long EXPIRATION_TIME = 86400000; // 24小时
    
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("roles", userDetails.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList()));
        
        return Jwts.builder()
                .setClaims(claims)
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                .compact();
    }
    
    public String extractUsername(String token) {
        return extractClaim(token, Claims::getSubject);
    }
    
    public Date extractExpiration(String token) {
        return extractClaim(token, Claims::getExpiration);
    }
    
    public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = extractAllClaims(token);
        return claimsResolver.apply(claims);
    }
    
    private Claims extractAllClaims(String token) {
        return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
    }
    
    private Boolean isTokenExpired(String token) {
        return extractExpiration(token).before(new Date());
    }
    
    public Boolean validateToken(String token, UserDetails userDetails) {
        final String username = extractUsername(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
}

// JWT认证过滤器
@Component
public class JwtRequestFilter extends OncePerRequestFilter {
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @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 = jwtTokenUtil.extractUsername(jwt);
        }
        
        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
            
            if (jwtTokenUtil.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);
    }
}

5.2 Spring Cloud微服务

Spring Cloud是基于Spring Boot的微服务框架。

服务注册与发现(Eureka)

// Eureka Server
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}

// Eureka Client
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserServiceApplication.class, args);
    }
}

// 服务调用(RestTemplate)
@Service
public class OrderService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    public Order createOrder(Order order) {
        // 通过服务名调用,Eureka会自动解析为实际地址
        User user = restTemplate.getForObject(
            "http://user-service/api/users/" + order.getUserId(), 
            User.class
        );
        
        // 创建订单逻辑...
        return order;
    }
}

配置中心(Config Server)

// Config Server
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class, args);
    }
}

// 配置文件(application.yml)
server:
  port: 8888

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/your-repo/config-repo
          search-paths: config
          username: your-username
          password: your-password

API网关(Spring Cloud Gateway)

// Gateway配置
@Configuration
public class GatewayConfig {
    
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
            .route("user-service", r -> r.path("/api/users/**")
                .uri("lb://user-service"))
            .route("order-service", r -> r.path("/api/orders/**")
                .uri("lb://order-service"))
            .route("auth-service", r -> r.path("/api/auth/**")
                .uri("lb://auth-service"))
            .build();
    }
}

5.3 Spring响应式编程

Spring WebFlux是Spring的响应式Web框架。

响应式控制器

@RestController
@RequestMapping("/api/reactive")
public class ReactiveUserController {
    
    @Autowired
    private ReactiveUserService userService;
    
    // 返回Mono(单个对象)
    @GetMapping("/{id}")
    public Mono<User> getUser(@PathVariable String id) {
        return userService.findById(id);
    }
    
    // 返回Flux(多个对象)
    @GetMapping
    public Flux<User> getAllUsers() {
        return userService.findAll();
    }
    
    // 创建用户
    @PostMapping
    public Mono<User> createUser(@RequestBody User user) {
        return userService.save(user);
    }
    
    // 流式响应
    @GetMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<User> streamUsers() {
        return userService.findAll()
            .delayElements(Duration.ofSeconds(1))
            .doOnNext(user -> System.out.println("Sending user: " + user.getId()));
    }
}

响应式服务

@Service
public class ReactiveUserService {
    
    @Autowired
    private ReactiveMongoTemplate mongoTemplate;
    
    public Mono<User> findById(String id) {
        return mongoTemplate.findById(id, User.class);
    }
    
    public Flux<User> findAll() {
        return mongoTemplate.findAll(User.class);
    }
    
    public Mono<User> save(User user) {
        return mongoTemplate.save(user);
    }
    
    public Mono<Void> deleteById(String id) {
        return mongoTemplate.remove(Query.query(Criteria.where("_id").is(id)), User.class);
    }
}

第六部分:Spring测试

6.1 单元测试

// 使用JUnit 5和Mockito
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
    
    @Mock
    private UserRepository userRepository;
    
    @InjectMocks
    private UserService userService;
    
    @Test
    void shouldCreateUser() {
        // 准备数据
        User user = new User();
        user.setUsername("testuser");
        user.setEmail("test@example.com");
        
        // 模拟行为
        when(userRepository.save(any(User.class))).thenReturn(user);
        
        // 执行测试
        User result = userService.createUser(user);
        
        // 验证结果
        assertNotNull(result);
        assertEquals("testuser", result.getUsername());
        verify(userRepository, times(1)).save(user);
    }
    
    @Test
    void shouldThrowExceptionWhenUsernameExists() {
        // 准备数据
        User user = new User();
        user.setUsername("existinguser");
        
        // 模拟行为
        when(userRepository.findByUsername("existinguser"))
            .thenReturn(Optional.of(user));
        
        // 执行测试并验证异常
        assertThrows(RuntimeException.class, () -> {
            userService.createUser(user);
        });
    }
}

6.2 集成测试

@SpringBootTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
@TestPropertySource(locations = "classpath:application-test.properties")
class UserServiceIntegrationTest {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    @Transactional
    void shouldCreateAndRetrieveUser() {
        // 创建用户
        User user = new User();
        user.setUsername("integrationtest");
        user.setEmail("integration@test.com");
        
        User savedUser = userService.createUser(user);
        
        // 验证保存
        assertNotNull(savedUser.getId());
        
        // 查询用户
        User foundUser = userService.findUserById(savedUser.getId());
        
        // 验证查询结果
        assertNotNull(foundUser);
        assertEquals("integrationtest", foundUser.getUsername());
    }
    
    @Test
    void shouldReturnEmptyWhenUserNotFound() {
        User user = userService.findUserById(999L);
        assertNull(user);
    }
}

6.3 Web层测试

@WebMvcTest(UserController.class)
class UserControllerWebTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private UserService userService;
    
    @Test
    void shouldGetUserById() throws Exception {
        // 准备数据
        User user = new User();
        user.setId(1L);
        user.setUsername("testuser");
        user.setEmail("test@example.com");
        
        // 模拟行为
        when(userService.findUserById(1L)).thenReturn(user);
        
        // 执行请求
        mockMvc.perform(get("/api/users/1")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(jsonPath("$.id").value(1))
                .andExpect(jsonPath("$.username").value("testuser"));
    }
    
    @Test
    void shouldReturn404WhenUserNotFound() throws Exception {
        when(userService.findUserById(999L)).thenReturn(null);
        
        mockMvc.perform(get("/api/users/999")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isNotFound());
    }
}

第七部分:Spring性能优化

7.1 连接池优化

// HikariCP配置
@Configuration
public class DataSourceConfig {
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public HikariDataSource dataSource(DataSourceProperties properties) {
        HikariDataSource dataSource = properties.initializeDataSourceBuilder()
                .type(HikariDataSource.class)
                .build();
        
        // 优化配置
        dataSource.setMaximumPoolSize(20);
        dataSource.setMinimumIdle(5);
        dataSource.setConnectionTimeout(30000);
        dataSource.setIdleTimeout(600000);
        dataSource.setMaxLifetime(1800000);
        dataSource.setLeakDetectionThreshold(60000);
        
        return dataSource;
    }
}

7.2 缓存优化

// 启用缓存
@Configuration
@EnableCaching
public class CacheConfig {
    
    @Bean
    public CacheManager cacheManager() {
        RedisCacheManager cacheManager = RedisCacheManager.builder(redisConnectionFactory())
                .cacheDefaults(RedisCacheConfiguration.defaultCacheConfig()
                        .entryTtl(Duration.ofMinutes(10))
                        .disableCachingNullValues())
                .build();
        return cacheManager;
    }
    
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration("localhost", 6379);
        return new JedisConnectionFactory(config);
    }
}

// 使用缓存
@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Cacheable(value = "users", key = "#id")
    public User findUserById(Long id) {
        System.out.println("Fetching user from database...");
        return userRepository.findById(id).orElse(null);
    }
    
    @CachePut(value = "users", key = "#user.id")
    public User updateUser(User user) {
        return userRepository.save(user);
    }
    
    @CacheEvict(value = "users", key = "#id")
    public void deleteUser(Long id) {
        userRepository.deleteById(id);
    }
}

7.3 异步处理

// 启用异步支持
@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 sendEmail(String to, String subject, String body) {
        // 模拟耗时操作
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("Email sent to: " + to);
    }
}

// 异步控制器
@RestController
@RequestMapping("/api/async")
public class AsyncController {
    
    @Autowired
    private EmailService emailService;
    
    @PostMapping("/send-email")
    public ResponseEntity<String> sendEmail(@RequestParam String to) {
        emailService.sendEmail(to, "Test Subject", "Test Body");
        return ResponseEntity.ok("Email will be sent asynchronously");
    }
}

第八部分:Spring企业级应用实战

8.1 项目结构设计

enterprise-app/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/company/enterprise/
│   │   │       ├── config/           # 配置类
│   │   │       ├── controller/       # 控制器层
│   │   │       ├── service/          # 服务层
│   │   │       │   ├── impl/         # 服务实现
│   │   │       │   └── interface/    # 服务接口
│   │   │       ├── repository/       # 数据访问层
│   │   │       ├── entity/           # 实体类
│   │   │       ├── dto/              # 数据传输对象
│   │   │       ├── exception/        # 异常处理
│   │   │       ├── util/             # 工具类
│   │   │       └── aspect/           # 切面
│   │   └── resources/
│   │       ├── application.yml       # 主配置
│   │       ├── application-dev.yml   # 开发环境配置
│   │       ├── application-prod.yml  # 生产环境配置
│   │       ├── static/               # 静态资源
│   │       └── templates/            # 模板文件
│   └── test/
│       └── java/
│           └── com/company/enterprise/
│               ├── unit/              # 单元测试
│               └── integration/       # 集成测试
├── pom.xml
└── README.md

8.2 分层架构实现

实体层(Entity)

@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "order_number", unique = true, nullable = false)
    private String orderNumber;
    
    @Column(name = "total_amount", precision = 10, scale = 2)
    private BigDecimal totalAmount;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "status")
    private OrderStatus status;
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "customer_id")
    private Customer customer;
    
    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List<OrderItem> orderItems = new ArrayList<>();
    
    @Column(name = "created_at")
    @CreationTimestamp
    private LocalDateTime createdAt;
    
    @Column(name = "updated_at")
    @UpdateTimestamp
    private LocalDateTime updatedAt;
    
    // 构造函数、getter、setter省略
}

// 枚举类
public enum OrderStatus {
    PENDING, PROCESSING, SHIPPED, DELIVERED, CANCELLED
}

数据传输对象(DTO)

// 请求DTO
public class OrderRequestDTO {
    @NotBlank(message = "Customer ID is required")
    private String customerId;
    
    @NotEmpty(message = "Order items cannot be empty")
    private List<OrderItemDTO> items;
    
    // getter和setter省略
}

// 响应DTO
public class OrderResponseDTO {
    private String orderNumber;
    private BigDecimal totalAmount;
    private OrderStatus status;
    private String customerName;
    private List<OrderItemDTO> items;
    private LocalDateTime createdAt;
    
    // getter和setter省略
}

Repository层

@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    
    // 自定义查询
    Optional<Order> findByOrderNumber(String orderNumber);
    
    List<Order> findByStatus(OrderStatus status);
    
    // 分页查询
    Page<Order> findByCustomerId(Long customerId, Pageable pageable);
    
    // 复杂查询
    @Query("SELECT o FROM Order o WHERE o.createdAt BETWEEN :start AND :end")
    List<Order> findOrdersByDateRange(@Param("start") LocalDateTime start, 
                                      @Param("end") LocalDateTime end);
    
    // 原生SQL查询
    @Query(value = "SELECT * FROM orders WHERE status = :status ORDER BY created_at DESC", 
           nativeQuery = true)
    List<Order> findOrdersByStatusNative(@Param("status") String status);
    
    // 自定义更新
    @Modifying
    @Query("UPDATE Order o SET o.status = :status WHERE o.id = :id")
    int updateOrderStatus(@Param("id") Long id, @Param("status") OrderStatus status);
}

Service层

// 接口
public interface OrderService {
    OrderResponseDTO createOrder(OrderRequestDTO request);
    OrderResponseDTO getOrder(String orderNumber);
    Page<OrderResponseDTO> getOrdersByCustomer(Long customerId, int page, int size);
    void cancelOrder(Long orderId);
}

// 实现
@Service
@Transactional
public class OrderServiceImpl implements OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private CustomerRepository customerRepository;
    
    @Autowired
    private OrderItemRepository orderItemRepository;
    
    @Autowired
    private ModelMapper modelMapper;
    
    @Override
    public OrderResponseDTO createOrder(OrderRequestDTO request) {
        // 验证客户
        Customer customer = customerRepository.findById(Long.parseLong(request.getCustomerId()))
                .orElseThrow(() -> new ResourceNotFoundException("Customer not found"));
        
        // 创建订单
        Order order = new Order();
        order.setOrderNumber(generateOrderNumber());
        order.setCustomer(customer);
        order.setStatus(OrderStatus.PENDING);
        
        // 计算总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<OrderItem> orderItems = new ArrayList<>();
        
        for (OrderItemDTO itemDTO : request.getItems()) {
            OrderItem item = new OrderItem();
            item.setOrder(order);
            item.setProductId(itemDTO.getProductId());
            item.setQuantity(itemDTO.getQuantity());
            item.setUnitPrice(itemDTO.getUnitPrice());
            item.setTotalPrice(itemDTO.getUnitPrice().multiply(BigDecimal.valueOf(itemDTO.getQuantity())));
            
            totalAmount = totalAmount.add(item.getTotalPrice());
            orderItems.add(item);
        }
        
        order.setTotalAmount(totalAmount);
        order.setOrderItems(orderItems);
        
        // 保存订单
        Order savedOrder = orderRepository.save(order);
        
        // 转换为DTO
        return convertToResponseDTO(savedOrder);
    }
    
    @Override
    @Transactional(readOnly = true)
    public OrderResponseDTO getOrder(String orderNumber) {
        Order order = orderRepository.findByOrderNumber(orderNumber)
                .orElseThrow(() -> new ResourceNotFoundException("Order not found"));
        
        return convertToResponseDTO(order);
    }
    
    @Override
    @Transactional(readOnly = true)
    public Page<OrderResponseDTO> getOrdersByCustomer(Long customerId, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("createdAt").descending());
        Page<Order> orders = orderRepository.findByCustomerId(customerId, pageable);
        
        return orders.map(this::convertToResponseDTO);
    }
    
    @Override
    public void cancelOrder(Long orderId) {
        Order order = orderRepository.findById(orderId)
                .orElseThrow(() -> new ResourceNotFoundException("Order not found"));
        
        if (order.getStatus() != OrderStatus.PENDING) {
            throw new IllegalStateException("Only pending orders can be cancelled");
        }
        
        order.setStatus(OrderStatus.CANCELLED);
        orderRepository.save(order);
    }
    
    private String generateOrderNumber() {
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = String.format("%04d", new Random().nextInt(10000));
        return "ORD-" + timestamp + "-" + random;
    }
    
    private OrderResponseDTO convertToResponseDTO(Order order) {
        OrderResponseDTO dto = modelMapper.map(order, OrderResponseDTO.class);
        dto.setCustomerName(order.getCustomer().getName());
        
        List<OrderItemDTO> itemDTOs = order.getOrderItems().stream()
                .map(item -> modelMapper.map(item, OrderItemDTO.class))
                .collect(Collectors.toList());
        dto.setItems(itemDTOs);
        
        return dto;
    }
}

Controller层

@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
    
    @Autowired
    private OrderService orderService;
    
    @PostMapping
    public ResponseEntity<OrderResponseDTO> createOrder(@Valid @RequestBody OrderRequestDTO request) {
        OrderResponseDTO response = orderService.createOrder(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(response);
    }
    
    @GetMapping("/{orderNumber}")
    public ResponseEntity<OrderResponseDTO> getOrder(@PathVariable String orderNumber) {
        OrderResponseDTO order = orderService.getOrder(orderNumber);
        return ResponseEntity.ok(order);
    }
    
    @GetMapping("/customer/{customerId}")
    public ResponseEntity<Page<OrderResponseDTO>> getOrdersByCustomer(
            @PathVariable Long customerId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        Page<OrderResponseDTO> orders = orderService.getOrdersByCustomer(customerId, page, size);
        return ResponseEntity.ok(orders);
    }
    
    @PutMapping("/{orderId}/cancel")
    public ResponseEntity<Void> cancelOrder(@PathVariable Long orderId) {
        orderService.cancelOrder(orderId);
        return ResponseEntity.noContent().build();
    }
}

8.3 企业级特性实现

1. 日志管理

// 使用SLF4J和Logback
@Service
public class OrderService {
    
    private static final Logger logger = LoggerFactory.getLogger(OrderService.class);
    
    public OrderResponseDTO createOrder(OrderRequestDTO request) {
        logger.info("Creating order for customer: {}", request.getCustomerId());
        
        try {
            // 业务逻辑
            OrderResponseDTO response = processOrder(request);
            logger.info("Order created successfully: {}", response.getOrderNumber());
            return response;
        } catch (Exception e) {
            logger.error("Failed to create order for customer: {}", request.getCustomerId(), e);
            throw new OrderCreationException("Failed to create order", e);
        }
    }
}

2. 监控和指标

// 使用Micrometer和Prometheus
@Configuration
public class MetricsConfig {
    
    @Bean
    public MeterRegistryCustomizer<MeterRegistry> metricsCommonTags() {
        return registry -> registry.config().commonTags("application", "enterprise-app");
    }
    
    @Bean
    public TimedAspect timedAspect(MeterRegistry registry) {
        return new TimedAspect(registry);
    }
    
    @Bean
    public CountedAspect countedAspect(MeterRegistry registry) {
        return new CountedAspect(registry);
    }
}

// 在Service中使用
@Service
public class OrderService {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    @Timed(value = "order.creation.time", description = "Time taken to create an order")
    @Counted(value = "order.creation.count", description = "Number of orders created")
    public OrderResponseDTO createOrder(OrderRequestDTO request) {
        // 业务逻辑
        return processOrder(request);
    }
}

3. 配置管理

// 使用Spring Cloud Config
@Configuration
public class DynamicConfig {
    
    @Value("${app.feature.flag.new-payment:false}")
    private boolean newPaymentFeature;
    
    @Value("${app.max.orders.per.day:100}")
    private int maxOrdersPerDay;
    
    @Value("${app.email.sender:notifications@company.com}")
    private String emailSender;
    
    // 动态刷新配置
    @RefreshScope
    @Bean
    public FeatureFlagService featureFlagService() {
        return new FeatureFlagService(newPaymentFeature);
    }
}

4. 安全加固

// 安全配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .cors().and()
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
                .antMatchers("/api/public/**").permitAll()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/api/v1/orders/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
    }
    
    @Bean
    public JwtAuthenticationFilter jwtAuthenticationFilter() {
        return new JwtAuthenticationFilter();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

8.4 部署和运维

Docker化部署

# Dockerfile
FROM openjdk:11-jre-slim

# 设置工作目录
WORKDIR /app

# 复制JAR文件
COPY target/enterprise-app.jar app.jar

# 暴露端口
EXPOSE 8080

# 设置环境变量
ENV JAVA_OPTS="-Xmx512m -Xms256m"

# 启动应用
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Kubernetes部署

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: enterprise-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: enterprise-app
  template:
    metadata:
      labels:
        app: enterprise-app
    spec:
      containers:
      - name: enterprise-app
        image: your-registry/enterprise-app:latest
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: JAVA_OPTS
          value: "-Xmx512m -Xms256m"
        resources:
          requests:
            memory: "512Mi"
            cpu: "250m"
          limits:
            memory: "1Gi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: enterprise-app-service
spec:
  selector:
    app: enterprise-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: LoadBalancer

第九部分:最佳实践和常见问题

9.1 代码组织最佳实践

  1. 遵循单一职责原则:每个类只负责一个功能
  2. 使用接口编程:依赖抽象而非具体实现
  3. 合理分层:Controller、Service、Repository职责清晰
  4. 避免循环依赖:使用依赖注入解决
  5. 使用DTO进行数据传输:避免直接暴露实体类

9.2 性能优化建议

  1. 数据库优化

    • 使用索引
    • 避免N+1查询问题
    • 使用分页查询
    • 合理使用缓存
  2. JVM优化

    • 合理设置堆内存大小
    • 使用G1垃圾收集器
    • 监控GC日志
  3. 连接池优化

    • 合理设置连接池大小
    • 使用HikariCP
    • 监控连接泄漏

9.3 常见问题及解决方案

问题1:循环依赖

// 错误示例
@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;
}

@Service
public class ServiceB {
    @Autowired
    private ServiceA serviceA;
}

// 解决方案1:使用@Lazy
@Service
public class ServiceA {
    @Autowired
    @Lazy
    private ServiceB serviceB;
}

// 解决方案2:重构代码,提取公共逻辑
@Service
public class CommonService {
    // 公共逻辑
}

@Service
public class ServiceA {
    @Autowired
    private CommonService commonService;
}

@Service
public class ServiceB {
    @Autowired
    private CommonService commonService;
}

问题2:事务失效

// 错误示例:同类方法调用
@Service
public class OrderService {
    
    @Transactional
    public void createOrder(Order order) {
        // 保存订单
        saveOrder(order);
        // 调用另一个方法(事务失效)
        updateInventory(order);
    }
    
    public void updateInventory(Order order) {
        // 更新库存
    }
}

// 解决方案1:使用自调用
@Service
public class OrderService {
    
    @Autowired
    private OrderService self; // 自己注入自己
    
    @Transactional
    public void createOrder(Order order) {
        saveOrder(order);
        self.updateInventory(order); // 通过代理调用
    }
    
    @Transactional
    public void updateInventory(Order order) {
        // 更新库存
    }
}

// 解决方案2:提取到另一个Service
@Service
public class InventoryService {
    @Transactional
    public void updateInventory(Order order) {
        // 更新库存
    }
}

@Service
public class OrderService {
    @Autowired
    private InventoryService inventoryService;
    
    @Transactional
    public void createOrder(Order order) {
        saveOrder(order);
        inventoryService.updateInventory(order);
    }
}

问题3:N+1查询问题

// 错误示例
@Entity
public class Order {
    @OneToMany(mappedBy = "order")
    private List<OrderItem> orderItems;
}

// 查询订单时,每个订单都会额外查询其订单项
List<Order> orders = orderRepository.findAll();
for (Order order : orders) {
    // 这里会触发N+1查询
    order.getOrderItems().size();
}

// 解决方案1:使用JOIN FETCH
@Query("SELECT o FROM Order o JOIN FETCH o.orderItems WHERE o.id = :id")
Optional<Order> findByIdWithItems(@Param("id") Long id);

// 解决方案2:使用EntityGraph
@EntityGraph(attributePaths = {"orderItems"})
List<Order> findAll();

// 解决方案3:使用DTO投影
@Query("SELECT new com.example.OrderDTO(o.id, o.orderNumber, oi.productId, oi.quantity) " +
       "FROM Order o JOIN o.orderItems oi WHERE o.id = :id")
List<OrderDTO> findOrderWithItems(@Param("id") Long id);

9.4 安全最佳实践

  1. 输入验证:对所有用户输入进行验证
  2. SQL注入防护:使用参数化查询
  3. XSS防护:对输出进行HTML转义
  4. CSRF防护:使用Spring Security的CSRF保护
  5. 敏感信息保护:不在日志中记录密码、令牌等
  6. 使用HTTPS:生产环境必须使用HTTPS
  7. 定期更新依赖:及时更新Spring和依赖库

第十部分:学习资源和进阶路线

10.1 推荐学习资源

  1. 官方文档

  2. 书籍推荐

    • 《Spring实战》(Craig Walls著)
    • 《Spring Boot实战》(Craig Walls著)
    • 《Spring Cloud微服务实战》(翟永超著)
  3. 在线课程

    • Spring官方培训课程
    • Udemy上的Spring Boot课程
    • Coursera上的Spring框架课程
  4. 社区资源

    • Spring官方博客
    • Stack Overflow的Spring标签
    • GitHub上的Spring项目

10.2 进阶学习路线

阶段1:基础掌握(1-2个月)

  • 掌握Spring Core、AOP、事务管理
  • 熟悉Spring MVC开发
  • 理解依赖注入原理

阶段2:Spring Boot精通(2-3个月)

  • 深入理解自动配置原理
  • 掌握Spring Boot Starter开发
  • 熟悉Spring Boot Actuator

阶段3:企业级开发(3-4个月)

  • 掌握Spring Security
  • 熟悉Spring Data JPA
  • 了解Spring Cache、消息队列集成

阶段4:微服务架构(3-4个月)

  • 掌握Spring Cloud组件
  • 理解服务注册发现、配置中心
  • 熟悉API网关、熔断器

阶段5:高级特性(持续学习)

  • 响应式编程(Spring WebFlux)
  • 云原生开发(Kubernetes、Docker)
  • 性能调优和监控

10.3 实战项目建议

  1. 电商系统:用户管理、商品管理、订单管理、支付集成
  2. 博客系统:文章管理、评论系统、用户认证
  3. 任务管理系统:任务分配、进度跟踪、报表统计
  4. API网关:路由、限流、认证、监控
  5. 微服务架构:拆分多个服务,使用Spring Cloud集成

结语

Spring框架是Java企业级开发的基石,掌握Spring框架需要理论与实践相结合。本指南从基础概念到高级实战,涵盖了Spring框架的核心知识点和企业级应用开发的关键技能。

学习Spring框架的关键在于:

  1. 理解核心原理:依赖注入、AOP、事务管理
  2. 动手实践:通过实际项目巩固知识
  3. 持续学习:关注Spring生态的发展
  4. 参与社区:与其他开发者交流经验

希望本指南能帮助你系统地掌握Spring框架,成为一名优秀的企业级Java开发者。记住,编程是一门实践的艺术,只有不断编码、调试、优化,才能真正掌握Spring框架的精髓。

祝你学习顺利!