Java学习第34天 - 性能优化与系统监控

55 阅读11分钟

学习目标

掌握性能优化方法,学习系统监控与可观测性,理解安全认证机制,掌握测试方法,了解最佳实践,提升系统性能与稳定性。


1. 性能优化

1.1 JVM调优

JVM参数配置:

// JVM调优配置类
@Configuration
@Slf4j
public class JvmTuningConfig {
    
    // 堆内存配置
    // -Xms2g -Xmx2g:初始堆和最大堆大小
    // -XX:NewRatio=2:新生代与老年代比例
    // -XX:SurvivorRatio=8:Eden与Survivor比例
    
    // GC配置
    // -XX:+UseG1GC:使用G1垃圾收集器
    // -XX:MaxGCPauseMillis=200:最大GC暂停时间
    // -XX:G1HeapRegionSize=16m:G1区域大小
    
    @PostConstruct
    public void printJvmInfo() {
        Runtime runtime = Runtime.getRuntime();
        long maxMemory = runtime.maxMemory();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        
        log.info("最大内存: {} MB", maxMemory / 1024 / 1024);
        log.info("总内存: {} MB", totalMemory / 1024 / 1024);
        log.info("已用内存: {} MB", usedMemory / 1024 / 1024);
        log.info("可用内存: {} MB", freeMemory / 1024 / 1024);
        
        // 内存使用率
        double memoryUsage = (double) usedMemory / totalMemory * 100;
        log.info("内存使用率: {:.2f}%", memoryUsage);
    }
}

// 内存监控服务
@Service
@Slf4j
public class MemoryMonitorService {
    
    private final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
    
    // 获取堆内存使用情况
    public MemoryUsage getHeapMemoryUsage() {
        return memoryBean.getHeapMemoryUsage();
    }
    
    // 获取非堆内存使用情况
    public MemoryUsage getNonHeapMemoryUsage() {
        return memoryBean.getNonHeapMemoryUsage();
    }
    
    // 检查内存使用率
    public boolean isMemoryUsageHigh(double threshold) {
        MemoryUsage heapUsage = getHeapMemoryUsage();
        long used = heapUsage.getUsed();
        long max = heapUsage.getMax();
        double usage = (double) used / max * 100;
        
        log.info("堆内存使用率: {:.2f}%", usage);
        return usage > threshold;
    }
    
    // 触发GC
    public void triggerGC() {
        System.gc();
        log.info("手动触发GC");
    }
    
    // 获取GC信息
    public List<GarbageCollectorMXBean> getGCBeans() {
        return ManagementFactory.getGarbageCollectorMXBeans();
    }
    
    // 打印GC统计信息
    public void printGCStats() {
        List<GarbageCollectorMXBean> gcBeans = getGCBeans();
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            log.info("GC名称: {}", gcBean.getName());
            log.info("GC次数: {}", gcBean.getCollectionCount());
            log.info("GC总时间: {} ms", gcBean.getCollectionTime());
        }
    }
}

// 线程监控服务
@Service
@Slf4j
public class ThreadMonitorService {
    
    private final ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
    
    // 获取线程信息
    public ThreadInfo[] getAllThreadInfo() {
        long[] threadIds = threadBean.getAllThreadIds();
        return threadBean.getThreadInfo(threadIds);
    }
    
    // 打印线程统计信息
    public void printThreadStats() {
        int threadCount = threadBean.getThreadCount();
        int peakThreadCount = threadBean.getPeakThreadCount();
        long totalStartedThreadCount = threadBean.getTotalStartedThreadCount();
        
        log.info("当前线程数: {}", threadCount);
        log.info("峰值线程数: {}", peakThreadCount);
        log.info("总启动线程数: {}", totalStartedThreadCount);
        
        // 打印所有线程信息
        ThreadInfo[] threadInfos = getAllThreadInfo();
        for (ThreadInfo threadInfo : threadInfos) {
            if (threadInfo != null) {
                log.info("线程: {} - 状态: {} - CPU时间: {} ns",
                    threadInfo.getThreadName(),
                    threadInfo.getThreadState(),
                    threadBean.getThreadCpuTime(threadInfo.getThreadId())
                );
            }
        }
    }
    
    // 检测死锁
    public long[] detectDeadlocks() {
        return threadBean.findDeadlockedThreads();
    }
}

1.2 代码级优化

字符串优化:

// 字符串优化服务
@Service
@Slf4j
public class StringOptimizationService {
    
    // 使用StringBuilder代替字符串拼接
    public String buildString(List<String> items) {
        StringBuilder sb = new StringBuilder();
        for (String item : items) {
            sb.append(item);
        }
        return sb.toString();
    }
    
    // 使用String.join(Java 8+)
    public String joinStrings(List<String> items) {
        return String.join("", items);
    }
    
    // 字符串常量池优化
    public boolean compareStrings(String str1, String str2) {
        // 使用equals比较内容
        return str1.equals(str2);
        
        // 使用intern()利用常量池
        // return str1.intern() == str2.intern();
    }
    
    // 避免在循环中创建字符串
    public String processStrings(List<String> items) {
        StringBuilder result = new StringBuilder();
        for (String item : items) {
            // 避免在循环中创建临时字符串
            result.append(item.toUpperCase());
        }
        return result.toString();
    }
}

// 集合优化服务
@Service
@Slf4j
public class CollectionOptimizationService {
    
    // 指定集合初始容量
    public List<String> createList(int expectedSize) {
        return new ArrayList<>(expectedSize);
    }
    
    // 使用合适的集合类型
    public void useAppropriateCollection() {
        // 需要快速查找使用HashSet
        Set<String> uniqueItems = new HashSet<>();
        
        // 需要保持顺序使用LinkedHashSet
        Set<String> orderedItems = new LinkedHashSet<>();
        
        // 需要排序使用TreeSet
        Set<String> sortedItems = new TreeSet<>();
        
        // 需要键值对使用HashMap
        Map<String, String> keyValueMap = new HashMap<>();
        
        // 需要线程安全使用ConcurrentHashMap
        Map<String, String> concurrentMap = new ConcurrentHashMap<>();
    }
    
    // 使用Stream API优化集合操作
    public List<String> filterAndTransform(List<String> items) {
        return items.stream()
            .filter(item -> item.length() > 5)
            .map(String::toUpperCase)
            .collect(Collectors.toList());
    }
    
    // 避免不必要的迭代
    public boolean containsItem(List<String> items, String target) {
        // 使用contains方法而不是遍历
        return items.contains(target);
    }
}

// 对象创建优化
@Service
@Slf4j
public class ObjectCreationOptimizationService {
    
    // 使用对象池
    private final ObjectPool<StringBuilder> stringBuilderPool = new GenericObjectPool<>(
        new PooledObjectFactory<StringBuilder>() {
            @Override
            public PooledObject<StringBuilder> makeObject() {
                return new DefaultPooledObject<>(new StringBuilder());
            }
            
            @Override
            public void destroyObject(PooledObject<StringBuilder> p) {
                p.getObject().setLength(0);
            }
            
            @Override
            public boolean validateObject(PooledObject<StringBuilder> p) {
                return true;
            }
            
            @Override
            public void activateObject(PooledObject<StringBuilder> p) {
                p.getObject().setLength(0);
            }
            
            @Override
            public void passivateObject(PooledObject<StringBuilder> p) {
                p.getObject().setLength(0);
            }
        }
    );
    
    // 重用对象
    public StringBuilder getStringBuilder() {
        try {
            return stringBuilderPool.borrowObject();
        } catch (Exception e) {
            log.error("获取StringBuilder失败", e);
            return new StringBuilder();
        }
    }
    
    public void returnStringBuilder(StringBuilder sb) {
        try {
            stringBuilderPool.returnObject(sb);
        } catch (Exception e) {
            log.error("归还StringBuilder失败", e);
        }
    }
    
    // 使用不可变对象
    public final class ImmutableData {
        private final String name;
        private final int value;
        
        public ImmutableData(String name, int value) {
            this.name = name;
            this.value = value;
        }
        
        public String getName() {
            return name;
        }
        
        public int getValue() {
            return value;
        }
    }
}

1.3 数据库优化

数据库连接池优化:

// 数据库连接池配置
@Configuration
@Slf4j
public class DataSourceConfig {
    
    // HikariCP连接池配置(推荐)
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.hikari")
    public HikariDataSource dataSource() {
        HikariConfig config = new HikariConfig();
        
        // 连接池大小
        config.setMaximumPoolSize(20);
        config.setMinimumIdle(5);
        
        // 连接超时
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);
        config.setMaxLifetime(1800000);
        
        // 连接测试
        config.setConnectionTestQuery("SELECT 1");
        config.setValidationTimeout(5000);
        
        // 性能优化
        config.addDataSourceProperty("cachePrepStmts", "true");
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
        config.addDataSourceProperty("useServerPrepStmts", "true");
        config.addDataSourceProperty("useLocalSessionState", "true");
        config.addDataSourceProperty("rewriteBatchedStatements", "true");
        config.addDataSourceProperty("cacheResultSetMetadata", "true");
        config.addDataSourceProperty("cacheServerConfiguration", "true");
        config.addDataSourceProperty("elideSetAutoCommits", "true");
        config.addDataSourceProperty("maintainTimeStats", "false");
        
        return new HikariDataSource(config);
    }
}

// 数据库查询优化服务
@Service
@Slf4j
public class DatabaseOptimizationService {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    // 批量插入优化
    public void batchInsert(List<Map<String, Object>> dataList) {
        String sql = "INSERT INTO orders (order_id, user_id, amount) VALUES (?, ?, ?)";
        
        jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                Map<String, Object> data = dataList.get(i);
                ps.setString(1, (String) data.get("orderId"));
                ps.setLong(2, (Long) data.get("userId"));
                ps.setBigDecimal(3, (BigDecimal) data.get("amount"));
            }
            
            @Override
            public int getBatchSize() {
                return dataList.size();
            }
        });
    }
    
    // 使用索引优化查询
    public List<Map<String, Object>> queryWithIndex(Long userId) {
        // 确保userId字段有索引
        String sql = "SELECT * FROM orders WHERE user_id = ?";
        return jdbcTemplate.queryForList(sql, userId);
    }
    
    // 分页查询优化
    public List<Map<String, Object>> queryWithPagination(int page, int size) {
        // 使用LIMIT和OFFSET
        int offset = (page - 1) * size;
        String sql = "SELECT * FROM orders ORDER BY create_time DESC LIMIT ? OFFSET ?";
        return jdbcTemplate.queryForList(sql, size, offset);
    }
    
    // 避免N+1查询问题
    public List<OrderDTO> getOrdersWithUsers() {
        // 使用JOIN一次性查询
        String sql = "SELECT o.*, u.name as user_name " +
                     "FROM orders o " +
                     "JOIN users u ON o.user_id = u.id";
        
        return jdbcTemplate.query(sql, (rs, rowNum) -> {
            OrderDTO order = new OrderDTO();
            order.setId(rs.getLong("id"));
            order.setUserId(rs.getLong("user_id"));
            order.setUserName(rs.getString("user_name"));
            order.setAmount(rs.getBigDecimal("amount"));
            return order;
        });
    }
}

// MyBatis Plus查询优化
@Mapper
public interface OrderMapper extends BaseMapper<Order> {
    
    // 使用索引字段查询
    @Select("SELECT * FROM orders WHERE user_id = #{userId} AND status = #{status}")
    List<Order> findByUserIdAndStatus(@Param("userId") Long userId, 
                                      @Param("status") String status);
    
    // 批量插入
    @Insert("<script>" +
            "INSERT INTO orders (order_id, user_id, amount) VALUES " +
            "<foreach collection='orders' item='order' separator=','>" +
            "(#{order.orderId}, #{order.userId}, #{order.amount})" +
            "</foreach>" +
            "</script>")
    void batchInsert(@Param("orders") List<Order> orders);
    
    // 使用分页插件
    IPage<Order> selectPage(IPage<Order> page, 
                           @Param("userId") Long userId);
}

2. 系统监控

2.1 APM应用性能监控

Spring Boot Actuator监控:

// Actuator配置
@Configuration
@Slf4j
public class ActuatorConfig {
    
    // 自定义健康检查
    @Component
    @Slf4j
    public static class CustomHealthIndicator implements HealthIndicator {
        
        @Autowired
        private DataSource dataSource;
        
        @Override
        public Health health() {
            try {
                // 检查数据库连接
                try (Connection connection = dataSource.getConnection()) {
                    if (connection.isValid(1)) {
                        return Health.up()
                            .withDetail("database", "可用")
                            .build();
                    }
                }
            } catch (Exception e) {
                log.error("健康检查失败", e);
                return Health.down()
                    .withDetail("database", "不可用")
                    .withException(e)
                    .build();
            }
            
            return Health.down().build();
        }
    }
    
    // 自定义指标
    @Component
    @Slf4j
    public static class CustomMetrics {
        
        private final MeterRegistry meterRegistry;
        private final Counter requestCounter;
        private final Timer requestTimer;
        private final Gauge activeUsers;
        
        public CustomMetrics(MeterRegistry meterRegistry) {
            this.meterRegistry = meterRegistry;
            this.requestCounter = Counter.builder("custom.requests")
                .description("自定义请求计数")
                .register(meterRegistry);
            this.requestTimer = Timer.builder("custom.request.duration")
                .description("自定义请求耗时")
                .register(meterRegistry);
            this.activeUsers = Gauge.builder("custom.active.users", 
                () -> getActiveUserCount())
                .description("活跃用户数")
                .register(meterRegistry);
        }
        
        public void incrementRequest() {
            requestCounter.increment();
        }
        
        public void recordRequestTime(Duration duration) {
            requestTimer.record(duration);
        }
        
        private double getActiveUserCount() {
            // 获取活跃用户数
            return 100.0;
        }
    }
}

// 监控拦截器
@Component
@Slf4j
public class MonitoringInterceptor implements HandlerInterceptor {
    
    @Autowired
    private CustomMetrics customMetrics;
    
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
        request.setAttribute("startTime", System.currentTimeMillis());
        customMetrics.incrementRequest();
        return true;
    }
    
    @Override
    public void afterCompletion(HttpServletRequest request, 
                               HttpServletResponse response, 
                               Object handler, 
                               Exception ex) {
        Long startTime = (Long) request.getAttribute("startTime");
        if (startTime != null) {
            long duration = System.currentTimeMillis() - startTime;
            customMetrics.recordRequestTime(Duration.ofMillis(duration));
            
            log.info("请求路径: {}, 耗时: {} ms", 
                request.getRequestURI(), duration);
        }
    }
}

2.2 日志管理

日志配置与优化:

// 日志配置类
@Configuration
@Slf4j
public class LoggingConfig {
    
    // Logback配置(logback-spring.xml)
    /*
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration>
        <springProfile name="dev">
            <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
                <encoder>
                    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
                </encoder>
            </appender>
            <root level="INFO">
                <appender-ref ref="CONSOLE" />
            </root>
        </springProfile>
        
        <springProfile name="prod">
            <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
                <file>logs/application.log</file>
                <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                    <fileNamePattern>logs/application.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
                    <maxFileSize>100MB</maxFileSize>
                    <maxHistory>30</maxHistory>
                    <totalSizeCap>3GB</totalSizeCap>
                </rollingPolicy>
                <encoder>
                    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
                </encoder>
            </appender>
            <root level="INFO">
                <appender-ref ref="FILE" />
            </root>
        </springProfile>
    </configuration>
    */
}

// 结构化日志服务
@Service
@Slf4j
public class StructuredLoggingService {
    
    // 使用MDC添加上下文信息
    public void logWithContext(String userId, String operation) {
        MDC.put("userId", userId);
        MDC.put("operation", operation);
        MDC.put("requestId", UUID.randomUUID().toString());
        
        try {
            log.info("执行操作: {}", operation);
            // 业务逻辑
        } finally {
            MDC.clear();
        }
    }
    
    // 异步日志
    public void logAsync(String message) {
        CompletableFuture.runAsync(() -> {
            log.info("异步日志: {}", message);
        });
    }
    
    // 日志采样(降低日志量)
    private final AtomicLong logCounter = new AtomicLong(0);
    private static final int SAMPLE_RATE = 100; // 每100条记录1条
    
    public void logWithSampling(String message) {
        if (logCounter.incrementAndGet() % SAMPLE_RATE == 0) {
            log.info("采样日志: {}", message);
        }
    }
}

// ELK日志收集配置
@Configuration
@Slf4j
public class ElkLoggingConfig {
    
    // Logstash配置
    /*
    <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
        <destination>logstash-server:5000</destination>
        <encoder class="net.logstash.logback.encoder.LogstashEncoder">
            <customFields>{"application":"order-service"}</customFields>
        </encoder>
    </appender>
    */
}

2.3 指标监控

Prometheus指标监控:

// Prometheus配置
@Configuration
@Slf4j
public class PrometheusConfig {
    
    // 自定义指标
    @Component
    @Slf4j
    public static class BusinessMetrics {
        
        private final Counter orderCounter;
        private final Timer orderProcessingTime;
        private final Gauge activeOrders;
        private final Summary orderAmount;
        
        public BusinessMetrics(MeterRegistry meterRegistry) {
            this.orderCounter = Counter.builder("orders.total")
                .description("订单总数")
                .tag("type", "business")
                .register(meterRegistry);
            
            this.orderProcessingTime = Timer.builder("orders.processing.time")
                .description("订单处理时间")
                .register(meterRegistry);
            
            this.activeOrders = Gauge.builder("orders.active", 
                () -> getActiveOrderCount())
                .description("活跃订单数")
                .register(meterRegistry);
            
            this.orderAmount = Summary.builder("orders.amount")
                .description("订单金额")
                .register(meterRegistry);
        }
        
        public void recordOrder(String orderType) {
            orderCounter.increment(
                Tags.of("order_type", orderType)
            );
        }
        
        public void recordProcessingTime(Duration duration) {
            orderProcessingTime.record(duration);
        }
        
        public void recordOrderAmount(BigDecimal amount) {
            orderAmount.record(amount.doubleValue());
        }
        
        private double getActiveOrderCount() {
            // 获取活跃订单数
            return 50.0;
        }
    }
}

// Grafana仪表板配置
@RestController
@RequestMapping("/api/metrics")
@Slf4j
public class MetricsController {
    
    @Autowired
    private MeterRegistry meterRegistry;
    
    @GetMapping("/custom")
    public Map<String, Object> getCustomMetrics() {
        Map<String, Object> metrics = new HashMap<>();
        
        // 获取计数器值
        Counter counter = meterRegistry.find("orders.total").counter();
        if (counter != null) {
            metrics.put("ordersTotal", counter.count());
        }
        
        // 获取计时器统计
        Timer timer = meterRegistry.find("orders.processing.time").timer();
        if (timer != null) {
            metrics.put("avgProcessingTime", timer.mean(TimeUnit.MILLISECONDS));
            metrics.put("maxProcessingTime", timer.max(TimeUnit.MILLISECONDS));
        }
        
        return metrics;
    }
}

3. 安全与认证

3.1 JWT认证

JWT工具类:

// JWT工具类
@Component
@Slf4j
public class JwtUtil {
    
    @Value("${jwt.secret:mySecretKey}")
    private String secret;
    
    @Value("${jwt.expiration:86400000}")
    private Long expiration;
    
    // 生成Token
    public String generateToken(UserDetails userDetails) {
        Map<String, Object> claims = new HashMap<>();
        claims.put("sub", userDetails.getUsername());
        claims.put("roles", userDetails.getAuthorities().stream()
            .map(GrantedAuthority::getAuthority)
            .collect(Collectors.toList()));
        claims.put("iat", new Date());
        
        return createToken(claims, userDetails.getUsername());
    }
    
    private String createToken(Map<String, Object> claims, String subject) {
        return Jwts.builder()
            .setClaims(claims)
            .setSubject(subject)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + expiration))
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
    }
    
    // 验证Token
    public Boolean validateToken(String token, UserDetails userDetails) {
        final String username = getUsernameFromToken(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }
    
    // 从Token获取用户名
    public String getUsernameFromToken(String token) {
        return getClaimFromToken(token, Claims::getSubject);
    }
    
    // 从Token获取过期时间
    public Date getExpirationDateFromToken(String token) {
        return getClaimFromToken(token, Claims::getExpiration);
    }
    
    // 从Token获取指定Claim
    public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaimsFromToken(token);
        return claimsResolver.apply(claims);
    }
    
    // 从Token获取所有Claims
    private Claims getAllClaimsFromToken(String token) {
        return Jwts.parser()
            .setSigningKey(secret)
            .parseClaimsJws(token)
            .getBody();
    }
    
    // 检查Token是否过期
    private Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDateFromToken(token);
        return expiration.before(new Date());
    }
    
    // 刷新Token
    public String refreshToken(String token) {
        final Claims claims = getAllClaimsFromToken(token);
        claims.setIssuedAt(new Date());
        return createToken(claims, claims.getSubject());
    }
}

// JWT认证过滤器
@Component
@Slf4j
public class JwtAuthenticationFilter extends OncePerRequestFilter {
    
    @Autowired
    private JwtUtil jwtUtil;
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, 
                                   HttpServletResponse response, 
                                   FilterChain filterChain) 
            throws ServletException, IOException {
        
        String token = getTokenFromRequest(request);
        
        if (token != null && jwtUtil.validateToken(token, 
            userDetailsService.loadUserByUsername(
                jwtUtil.getUsernameFromToken(token)))) {
            
            String username = jwtUtil.getUsernameFromToken(token);
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            
            UsernamePasswordAuthenticationToken authentication = 
                new UsernamePasswordAuthenticationToken(
                    userDetails, null, userDetails.getAuthorities());
            authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
            
            SecurityContextHolder.getContext().setAuthentication(authentication);
        }
        
        filterChain.doFilter(request, response);
    }
    
    private String getTokenFromRequest(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (bearerToken != null && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7);
        }
        return null;
    }
}

3.2 OAuth2认证

OAuth2配置:

// OAuth2资源服务器配置
@Configuration
@EnableResourceServer
@Slf4j
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter {
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/api/public/**").permitAll()
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();
    }
    
    @Bean
    public JwtDecoder jwtDecoder() {
        return NimbusJwtDecoder.withJwkSetUri("http://auth-server/.well-known/jwks.json")
            .build();
    }
}

// OAuth2授权服务器配置
@Configuration
@EnableAuthorizationServer
@Slf4j
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
    @Autowired
    private AuthenticationManager authenticationManager;
    
    @Autowired
    private DataSource dataSource;
    
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource);
    }
    
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints
            .authenticationManager(authenticationManager)
            .tokenStore(tokenStore())
            .accessTokenConverter(accessTokenConverter());
    }
    
    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }
    
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("mySecretKey");
        return converter;
    }
}

3.3 Spring Security配置

Spring Security配置:

// Spring Security配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private UserDetailsService userDetailsService;
    
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authorizeRequests()
            .antMatchers("/api/auth/**").permitAll()
            .antMatchers("/api/public/**").permitAll()
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .antMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }
    
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}

// 用户详情服务
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username)
            .orElseThrow(() -> new UsernameNotFoundException("用户不存在: " + username));
        
        List<GrantedAuthority> authorities = user.getRoles().stream()
            .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
            .collect(Collectors.toList());
        
        return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            authorities
        );
    }
}

4. 测试与质量

4.1 单元测试

JUnit 5单元测试:

// 服务层单元测试
@ExtendWith(MockitoExtension.class)
@Slf4j
class OrderServiceTest {
    
    @Mock
    private OrderRepository orderRepository;
    
    @Mock
    private UserRepository userRepository;
    
    @InjectMocks
    private OrderService orderService;
    
    @Test
    @DisplayName("创建订单成功")
    void testCreateOrderSuccess() {
        // Given
        CreateOrderRequest request = new CreateOrderRequest();
        request.setUserId(1L);
        request.setAmount(new BigDecimal("100.00"));
        
        User user = new User();
        user.setId(1L);
        user.setName("测试用户");
        
        Order order = new Order();
        order.setId(1L);
        order.setUserId(1L);
        order.setAmount(new BigDecimal("100.00"));
        
        when(userRepository.findById(1L)).thenReturn(Optional.of(user));
        when(orderRepository.save(any(Order.class))).thenReturn(order);
        
        // When
        OrderDTO result = orderService.createOrder(request);
        
        // Then
        assertNotNull(result);
        assertEquals(1L, result.getId());
        assertEquals(new BigDecimal("100.00"), result.getAmount());
        verify(orderRepository, times(1)).save(any(Order.class));
    }
    
    @Test
    @DisplayName("用户不存在时创建订单失败")
    void testCreateOrderUserNotFound() {
        // Given
        CreateOrderRequest request = new CreateOrderRequest();
        request.setUserId(999L);
        
        when(userRepository.findById(999L)).thenReturn(Optional.empty());
        
        // When & Then
        assertThrows(UserNotFoundException.class, () -> {
            orderService.createOrder(request);
        });
    }
    
    @ParameterizedTest
    @ValueSource(doubles = {100.0, 200.0, 500.0})
    @DisplayName("不同金额的订单创建")
    void testCreateOrderWithDifferentAmounts(double amount) {
        // Given
        CreateOrderRequest request = new CreateOrderRequest();
        request.setUserId(1L);
        request.setAmount(new BigDecimal(String.valueOf(amount)));
        
        User user = new User();
        user.setId(1L);
        
        when(userRepository.findById(1L)).thenReturn(Optional.of(user));
        when(orderRepository.save(any(Order.class))).thenAnswer(invocation -> {
            Order order = invocation.getArgument(0);
            order.setId(1L);
            return order;
        });
        
        // When
        OrderDTO result = orderService.createOrder(request);
        
        // Then
        assertNotNull(result);
        assertEquals(new BigDecimal(String.valueOf(amount)), result.getAmount());
    }
}

4.2 集成测试

Spring Boot集成测试:

// 集成测试
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
@Transactional
@Slf4j
class OrderControllerIntegrationTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    @DisplayName("创建订单集成测试")
    void testCreateOrderIntegration() throws Exception {
        // Given
        User user = new User();
        user.setUsername("testuser");
        user.setPassword("password");
        user = userRepository.save(user);
        
        CreateOrderRequest request = new CreateOrderRequest();
        request.setUserId(user.getId());
        request.setAmount(new BigDecimal("100.00"));
        
        // When
        MvcResult result = mockMvc.perform(post("/api/orders")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(request)))
            .andExpect(status().isOk())
            .andReturn();
        
        // Then
        String responseContent = result.getResponse().getContentAsString();
        OrderDTO orderDTO = objectMapper.readValue(responseContent, OrderDTO.class);
        
        assertNotNull(orderDTO);
        assertEquals(user.getId(), orderDTO.getUserId());
        assertEquals(new BigDecimal("100.00"), orderDTO.getAmount());
        
        // 验证数据库
        Optional<Order> savedOrder = orderRepository.findById(orderDTO.getId());
        assertTrue(savedOrder.isPresent());
    }
}

4.3 性能测试

JMeter性能测试:

// 性能测试工具类
@Service
@Slf4j
public class PerformanceTestService {
    
    // 压力测试
    public void stressTest(String url, int threads, int iterations) {
        ExecutorService executor = Executors.newFixedThreadPool(threads);
        CountDownLatch latch = new CountDownLatch(threads);
        AtomicLong successCount = new AtomicLong(0);
        AtomicLong failCount = new AtomicLong(0);
        List<Long> responseTimes = new CopyOnWriteArrayList<>();
        
        for (int i = 0; i < threads; i++) {
            executor.submit(() -> {
                try {
                    for (int j = 0; j < iterations; j++) {
                        long startTime = System.currentTimeMillis();
                        
                        try {
                            // 发送HTTP请求
                            RestTemplate restTemplate = new RestTemplate();
                            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
                            
                            if (response.getStatusCode().is2xxSuccessful()) {
                                successCount.incrementAndGet();
                            } else {
                                failCount.incrementAndGet();
                            }
                        } catch (Exception e) {
                            failCount.incrementAndGet();
                        }
                        
                        long responseTime = System.currentTimeMillis() - startTime;
                        responseTimes.add(responseTime);
                    }
                } finally {
                    latch.countDown();
                }
            });
        }
        
        try {
            latch.await();
            executor.shutdown();
            
            // 统计结果
            log.info("成功请求数: {}", successCount.get());
            log.info("失败请求数: {}", failCount.get());
            log.info("平均响应时间: {} ms", 
                responseTimes.stream().mapToLong(Long::longValue).average().orElse(0));
            log.info("最大响应时间: {} ms", 
                responseTimes.stream().mapToLong(Long::longValue).max().orElse(0));
            log.info("最小响应时间: {} ms", 
                responseTimes.stream().mapToLong(Long::longValue).min().orElse(0));
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

5. 最佳实践

5.1 代码规范

代码规范检查:

// 使用Checkstyle、PMD、SpotBugs等工具
// 代码规范示例

// 1. 命名规范
public class OrderService {  // 类名使用大驼峰
    private static final int MAX_RETRY_COUNT = 3;  // 常量使用大写下划线
    
    private Long orderId;  // 变量名使用小驼峰
    
    public void createOrder() {  // 方法名使用小驼峰
        // 方法实现
    }
}

// 2. 注释规范
/**
 * 订单服务类
 * 
 * @author YourName
 * @version 1.0
 * @since 2024-01-01
 */
public class OrderService {
    
    /**
     * 创建订单
     * 
     * @param request 创建订单请求
     * @return 订单DTO
     * @throws UserNotFoundException 用户不存在异常
     */
    public OrderDTO createOrder(CreateOrderRequest request) {
        // 实现
        return null;
    }
}

// 3. 异常处理规范
public class OrderService {
    
    public OrderDTO createOrder(CreateOrderRequest request) {
        try {
            // 业务逻辑
            return processOrder(request);
        } catch (UserNotFoundException e) {
            log.error("用户不存在: {}", request.getUserId(), e);
            throw e;
        } catch (Exception e) {
            log.error("创建订单失败", e);
            throw new OrderCreationException("创建订单失败", e);
        }
    }
}

5.2 设计模式应用

常用设计模式:

// 策略模式
public interface PaymentStrategy {
    void pay(BigDecimal amount);
}

@Component
public class AlipayStrategy implements PaymentStrategy {
    @Override
    public void pay(BigDecimal amount) {
        // 支付宝支付逻辑
    }
}

@Component
public class WechatPayStrategy implements PaymentStrategy {
    @Override
    public void pay(BigDecimal amount) {
        // 微信支付逻辑
    }
}

@Service
public class PaymentService {
    private final Map<String, PaymentStrategy> strategies;
    
    public PaymentService(List<PaymentStrategy> strategyList) {
        this.strategies = strategyList.stream()
            .collect(Collectors.toMap(
                s -> s.getClass().getSimpleName().replace("Strategy", "").toLowerCase(),
                Function.identity()
            ));
    }
    
    public void pay(String paymentType, BigDecimal amount) {
        PaymentStrategy strategy = strategies.get(paymentType.toLowerCase());
        if (strategy == null) {
            throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
        }
        strategy.pay(amount);
    }
}

// 观察者模式
public interface OrderObserver {
    void onOrderCreated(Order order);
}

@Component
public class EmailNotificationObserver implements OrderObserver {
    @Override
    public void onOrderCreated(Order order) {
        // 发送邮件通知
    }
}

@Component
public class InventoryObserver implements OrderObserver {
    @Override
    public void onOrderCreated(Order order) {
        // 更新库存
    }
}

@Service
public class OrderService {
    private final List<OrderObserver> observers = new ArrayList<>();
    
    public void addObserver(OrderObserver observer) {
        observers.add(observer);
    }
    
    public void createOrder(Order order) {
        // 创建订单
        // 通知观察者
        observers.forEach(observer -> observer.onOrderCreated(order));
    }
}