Java学习第30天 - 综合实战与项目总结

1. 综合项目实战 - 电商系统完整实现

1.1 项目架构设计

项目整体架构:

java 复制代码
// 项目结构
// com.example.ecommerce
//   ├── domain          // 领域层
//   │   ├── order       // 订单领域
//   │   ├── product     // 商品领域
//   │   └── user        // 用户领域
//   ├── application      // 应用层
//   │   ├── service     // 应用服务
//   │   └── dto         // 数据传输对象
//   ├── infrastructure  // 基础设施层
//   │   ├── repository  // 仓储实现
//   │   ├── cache       // 缓存
//   │   └── mq          // 消息队列
//   └── presentation    // 表现层
//       └── controller  // 控制器

// 领域模型 - 订单聚合根
@Entity
@Table(name = "t_order")
@Data
@Slf4j
public class Order {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String orderNumber;
    private Long userId;
    private BigDecimal totalAmount;
    private OrderStatus status;
    
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id")
    private List<OrderItem> items;
    
    @Embedded
    private Address shippingAddress;
    
    private Date createTime;
    private Date updateTime;
    
    // 领域行为
    public void confirm() {
        if (this.status != OrderStatus.PENDING) {
            throw new IllegalStateException("只有待确认订单才能确认");
        }
        this.status = OrderStatus.CONFIRMED;
        this.updateTime = new Date();
    }
    
    public void pay(BigDecimal amount) {
        if (this.status != OrderStatus.CONFIRMED) {
            throw new IllegalStateException("只有已确认订单才能支付");
        }
        if (amount.compareTo(this.totalAmount) != 0) {
            throw new IllegalArgumentException("支付金额不匹配");
        }
        this.status = OrderStatus.PAID;
        this.updateTime = new Date();
    }
    
    public void cancel(String reason) {
        if (this.status == OrderStatus.COMPLETED || this.status == OrderStatus.CANCELLED) {
            throw new IllegalStateException("订单状态不允许取消");
        }
        this.status = OrderStatus.CANCELLED;
        this.updateTime = new Date();
    }
    
    public BigDecimal calculateTotal() {
        if (this.items == null || this.items.isEmpty()) {
            return BigDecimal.ZERO;
        }
        return this.items.stream()
            .map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
}

// 订单项实体
@Entity
@Table(name = "t_order_item")
@Data
public class OrderItem {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private Long orderId;
    private Long productId;
    private String productName;
    private BigDecimal price;
    private Integer quantity;
    private BigDecimal subtotal;
}

// 订单状态枚举
public enum OrderStatus {
    PENDING("待确认"),
    CONFIRMED("已确认"),
    PAID("已支付"),
    SHIPPED("已发货"),
    COMPLETED("已完成"),
    CANCELLED("已取消");
    
    private final String description;
    
    OrderStatus(String description) {
        this.description = description;
    }
}

1.2 应用服务层实现

应用服务实现:

java 复制代码
// 订单应用服务
@Service
@Slf4j
@Transactional
public class OrderApplicationService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private ProductService productService;
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private PaymentService paymentService;
    
    @Autowired
    private EventPublisher eventPublisher;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    // 创建订单
    public OrderDTO createOrder(CreateOrderRequest request) {
        // 1. 参数验证
        validateCreateOrderRequest(request);
        
        // 2. 获取用户信息
        User user = userService.getUserById(request.getUserId());
        if (user == null) {
            throw new UserNotFoundException("用户不存在");
        }
        
        // 3. 验证商品和库存
        List<OrderItem> items = new ArrayList<>();
        for (CreateOrderItemRequest itemRequest : request.getItems()) {
            Product product = productService.getProductById(itemRequest.getProductId());
            if (product == null) {
                throw new ProductNotFoundException("商品不存在: " + itemRequest.getProductId());
            }
            
            // 检查库存
            boolean available = inventoryService.checkInventory(
                itemRequest.getProductId(), 
                itemRequest.getQuantity()
            );
            if (!available) {
                throw new InsufficientInventoryException("库存不足: " + product.getName());
            }
            
            // 创建订单项
            OrderItem item = new OrderItem();
            item.setProductId(product.getId());
            item.setProductName(product.getName());
            item.setPrice(product.getPrice());
            item.setQuantity(itemRequest.getQuantity());
            item.setSubtotal(product.getPrice().multiply(BigDecimal.valueOf(itemRequest.getQuantity())));
            items.add(item);
        }
        
        // 4. 创建订单
        Order order = new Order();
        order.setOrderNumber(generateOrderNumber());
        order.setUserId(request.getUserId());
        order.setItems(items);
        order.setTotalAmount(calculateTotal(items));
        order.setShippingAddress(convertAddress(request.getShippingAddress()));
        order.setStatus(OrderStatus.PENDING);
        order.setCreateTime(new Date());
        order.setUpdateTime(new Date());
        
        // 5. 保存订单
        order = orderRepository.save(order);
        
        // 6. 扣减库存
        for (OrderItem item : items) {
            inventoryService.deductInventory(item.getProductId(), item.getQuantity());
        }
        
        // 7. 发布领域事件
        eventPublisher.publish(new OrderCreatedEvent(order.getOrderNumber(), order.getUserId(), order.getTotalAmount()));
        
        log.info("创建订单成功: orderNumber={}, userId={}", order.getOrderNumber(), order.getUserId());
        
        return convertToDTO(order);
    }
    
    // 支付订单
    public PaymentResult payOrder(String orderNumber, PaymentRequest paymentRequest) {
        // 1. 获取订单
        Order order = orderRepository.findByOrderNumber(orderNumber);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderNumber);
        }
        
        // 2. 验证订单状态
        if (order.getStatus() != OrderStatus.CONFIRMED) {
            throw new IllegalStateException("订单状态不允许支付");
        }
        
        // 3. 使用分布式锁防止重复支付
        String lockKey = "order:pay:" + orderNumber;
        DistributedLock lock = distributedLockService.acquireLock(lockKey, 10, TimeUnit.SECONDS);
        
        try {
            // 双重检查
            order = orderRepository.findByOrderNumber(orderNumber);
            if (order.getStatus() != OrderStatus.CONFIRMED) {
                throw new IllegalStateException("订单状态已变更");
            }
            
            // 4. 调用支付服务
            PaymentResult result = paymentService.processPayment(
                order.getOrderNumber(),
                order.getTotalAmount(),
                paymentRequest
            );
            
            if (result.isSuccess()) {
                // 5. 更新订单状态
                order.pay(order.getTotalAmount());
                orderRepository.save(order);
                
                // 6. 发布支付成功事件
                eventPublisher.publish(new OrderPaidEvent(order.getOrderNumber(), order.getUserId(), order.getTotalAmount()));
                
                log.info("订单支付成功: orderNumber={}", orderNumber);
            }
            
            return result;
        } finally {
            lock.unlock();
        }
    }
    
    // 取消订单
    public void cancelOrder(String orderNumber, String reason) {
        Order order = orderRepository.findByOrderNumber(orderNumber);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderNumber);
        }
        
        // 使用分布式锁
        String lockKey = "order:cancel:" + orderNumber;
        DistributedLock lock = distributedLockService.acquireLock(lockKey, 10, TimeUnit.SECONDS);
        
        try {
            order = orderRepository.findByOrderNumber(orderNumber);
            order.cancel(reason);
            orderRepository.save(order);
            
            // 恢复库存
            for (OrderItem item : order.getItems()) {
                inventoryService.restoreInventory(item.getProductId(), item.getQuantity());
            }
            
            // 发布取消事件
            eventPublisher.publish(new OrderCancelledEvent(orderNumber, order.getUserId(), reason));
            
            log.info("订单取消成功: orderNumber={}, reason={}", orderNumber, reason);
        } finally {
            lock.unlock();
        }
    }
    
    // 查询订单
    public OrderDTO getOrder(String orderNumber) {
        Order order = orderRepository.findByOrderNumber(orderNumber);
        if (order == null) {
            throw new OrderNotFoundException("订单不存在: " + orderNumber);
        }
        return convertToDTO(order);
    }
    
    // 分页查询用户订单
    public Page<OrderDTO> getUserOrders(Long userId, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createTime"));
        Page<Order> orders = orderRepository.findByUserId(userId, pageable);
        return orders.map(this::convertToDTO);
    }
    
    // 工具方法
    private String generateOrderNumber() {
        return "ORD" + System.currentTimeMillis() + (int)(Math.random() * 1000);
    }
    
    private BigDecimal calculateTotal(List<OrderItem> items) {
        return items.stream()
            .map(OrderItem::getSubtotal)
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    
    private Address convertAddress(AddressDTO dto) {
        return new Address(dto.getProvince(), dto.getCity(), dto.getDistrict(), 
                          dto.getStreet(), dto.getZipCode());
    }
    
    private OrderDTO convertToDTO(Order order) {
        OrderDTO dto = new OrderDTO();
        dto.setId(order.getId());
        dto.setOrderNumber(order.getOrderNumber());
        dto.setUserId(order.getUserId());
        dto.setTotalAmount(order.getTotalAmount());
        dto.setStatus(order.getStatus());
        dto.setItems(order.getItems().stream()
            .map(this::convertItemToDTO)
            .collect(Collectors.toList()));
        dto.setCreateTime(order.getCreateTime());
        return dto;
    }
    
    private OrderItemDTO convertItemToDTO(OrderItem item) {
        OrderItemDTO dto = new OrderItemDTO();
        dto.setProductId(item.getProductId());
        dto.setProductName(item.getProductName());
        dto.setPrice(item.getPrice());
        dto.setQuantity(item.getQuantity());
        dto.setSubtotal(item.getSubtotal());
        return dto;
    }
    
    private void validateCreateOrderRequest(CreateOrderRequest request) {
        if (request.getUserId() == null) {
            throw new IllegalArgumentException("用户ID不能为空");
        }
        if (request.getItems() == null || request.getItems().isEmpty()) {
            throw new IllegalArgumentException("订单项不能为空");
        }
        if (request.getShippingAddress() == null) {
            throw new IllegalArgumentException("收货地址不能为空");
        }
    }
}

1.3 控制器层实现

RESTful API实现:

java 复制代码
// 订单控制器
@RestController
@RequestMapping("/api/orders")
@Slf4j
@Validated
public class OrderController {
    
    @Autowired
    private OrderApplicationService orderService;
    
    // 创建订单
    @PostMapping
    @RateLimit(limit = 100, windowSize = 60000)
    public ResponseEntity<ApiResponse<OrderDTO>> createOrder(
            @Valid @RequestBody CreateOrderRequest request) {
        try {
            OrderDTO order = orderService.createOrder(request);
            return ResponseEntity.ok(ApiResponse.success(order));
        } catch (Exception e) {
            log.error("创建订单失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error(e.getMessage()));
        }
    }
    
    // 支付订单
    @PostMapping("/{orderNumber}/pay")
    public ResponseEntity<ApiResponse<PaymentResult>> payOrder(
            @PathVariable String orderNumber,
            @Valid @RequestBody PaymentRequest request) {
        try {
            PaymentResult result = orderService.payOrder(orderNumber, request);
            return ResponseEntity.ok(ApiResponse.success(result));
        } catch (Exception e) {
            log.error("支付订单失败: orderNumber={}", orderNumber, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error(e.getMessage()));
        }
    }
    
    // 取消订单
    @PostMapping("/{orderNumber}/cancel")
    public ResponseEntity<ApiResponse<Void>> cancelOrder(
            @PathVariable String orderNumber,
            @RequestBody CancelOrderRequest request) {
        try {
            orderService.cancelOrder(orderNumber, request.getReason());
            return ResponseEntity.ok(ApiResponse.success(null));
        } catch (Exception e) {
            log.error("取消订单失败: orderNumber={}", orderNumber, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error(e.getMessage()));
        }
    }
    
    // 查询订单
    @GetMapping("/{orderNumber}")
    public ResponseEntity<ApiResponse<OrderDTO>> getOrder(@PathVariable String orderNumber) {
        try {
            OrderDTO order = orderService.getOrder(orderNumber);
            return ResponseEntity.ok(ApiResponse.success(order));
        } catch (OrderNotFoundException e) {
            return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ApiResponse.error(e.getMessage()));
        } catch (Exception e) {
            log.error("查询订单失败: orderNumber={}", orderNumber, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error(e.getMessage()));
        }
    }
    
    // 查询用户订单列表
    @GetMapping("/user/{userId}")
    public ResponseEntity<ApiResponse<Page<OrderDTO>>> getUserOrders(
            @PathVariable Long userId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        try {
            Page<OrderDTO> orders = orderService.getUserOrders(userId, page, size);
            return ResponseEntity.ok(ApiResponse.success(orders));
        } catch (Exception e) {
            log.error("查询用户订单失败: userId={}", userId, e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ApiResponse.error(e.getMessage()));
        }
    }
}

// 统一响应格式
@Data
@AllArgsConstructor
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    private long timestamp;
    
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "success", data, System.currentTimeMillis());
    }
    
    public static <T> ApiResponse<T> error(String message) {
        return new ApiResponse<>(500, message, null, System.currentTimeMillis());
    }
}

2. 系统设计实战 - 高并发秒杀系统

2.1 秒杀系统架构设计

秒杀系统核心实现:

java 复制代码
// 秒杀服务
@Service
@Slf4j
public class SeckillService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Autowired
    private ProductService productService;
    
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private RabbitTemplate rabbitTemplate;
    
    private static final String SECKILL_STOCK_KEY = "seckill:stock:";
    private static final String SECKILL_USER_KEY = "seckill:user:";
    private static final String SECKILL_QUEUE = "seckill.queue";
    
    // 初始化秒杀库存
    public void initSeckillStock(Long productId, Integer stock) {
        String key = SECKILL_STOCK_KEY + productId;
        redisTemplate.opsForValue().set(key, String.valueOf(stock));
        log.info("初始化秒杀库存: productId={}, stock={}", productId, stock);
    }
    
    // 秒杀下单(高并发优化)
    public SeckillResult seckill(Long userId, Long productId) {
        // 1. 参数验证
        if (userId == null || productId == null) {
            return SeckillResult.fail("参数错误");
        }
        
        // 2. 检查用户是否已参与(防刷)
        String userKey = SECKILL_USER_KEY + productId + ":" + userId;
        Boolean exists = redisTemplate.hasKey(userKey);
        if (Boolean.TRUE.equals(exists)) {
            return SeckillResult.fail("您已经参与过本次秒杀");
        }
        
        // 3. 预扣库存(Redis原子操作)
        String stockKey = SECKILL_STOCK_KEY + productId;
        Long stock = redisTemplate.opsForValue().decrement(stockKey);
        
        if (stock == null || stock < 0) {
            // 库存不足,恢复库存
            redisTemplate.opsForValue().increment(stockKey);
            return SeckillResult.fail("商品已抢完");
        }
        
        // 4. 标记用户已参与
        redisTemplate.opsForValue().set(userKey, "1", 3600, TimeUnit.SECONDS);
        
        // 5. 异步处理订单(消息队列)
        SeckillMessage message = new SeckillMessage(userId, productId);
        rabbitTemplate.convertAndSend(SECKILL_QUEUE, message);
        
        log.info("秒杀请求已提交: userId={}, productId={}", userId, productId);
        return SeckillResult.success("秒杀成功,订单处理中");
    }
    
    // 消息队列消费者处理订单
    @RabbitListener(queues = "seckill.queue")
    public void processSeckillOrder(SeckillMessage message) {
        Long userId = message.getUserId();
        Long productId = message.getProductId();
        
        try {
            // 1. 再次验证库存(数据库层面)
            Product product = productService.getProductById(productId);
            if (product == null || product.getStock() <= 0) {
                log.warn("库存不足,取消订单: userId={}, productId={}", userId, productId);
                // 恢复Redis库存
                redisTemplate.opsForValue().increment(SECKILL_STOCK_KEY + productId);
                return;
            }
            
            // 2. 创建订单
            CreateOrderRequest request = new CreateOrderRequest();
            request.setUserId(userId);
            
            CreateOrderItemRequest itemRequest = new CreateOrderItemRequest();
            itemRequest.setProductId(productId);
            itemRequest.setQuantity(1);
            request.setItems(Collections.singletonList(itemRequest));
            
            OrderDTO order = orderService.createOrder(request);
            
            log.info("秒杀订单创建成功: orderNumber={}, userId={}, productId={}", 
                    order.getOrderNumber(), userId, productId);
            
        } catch (Exception e) {
            log.error("处理秒杀订单失败: userId={}, productId={}", userId, productId, e);
            // 恢复Redis库存
            redisTemplate.opsForValue().increment(SECKILL_STOCK_KEY + productId);
        }
    }
    
    // 查询秒杀库存
    public Integer getSeckillStock(Long productId) {
        String stock = redisTemplate.opsForValue().get(SECKILL_STOCK_KEY + productId);
        return stock != null ? Integer.parseInt(stock) : 0;
    }
}

// 秒杀结果
@Data
@AllArgsConstructor
public class SeckillResult {
    private boolean success;
    private String message;
    
    public static SeckillResult success(String message) {
        return new SeckillResult(true, message);
    }
    
    public static SeckillResult fail(String message) {
        return new SeckillResult(false, message);
    }
}

// 秒杀消息
@Data
@AllArgsConstructor
public class SeckillMessage {
    private Long userId;
    private Long productId;
}

2.2 限流与防刷策略

防刷与限流实现:

java 复制代码
// 秒杀限流服务
@Service
@Slf4j
public class SeckillRateLimitService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    // IP限流
    public boolean checkIpLimit(String ip, Long productId) {
        String key = "seckill:ip:" + productId + ":" + ip;
        Long count = redisTemplate.opsForValue().increment(key);
        
        if (count == 1) {
            redisTemplate.expire(key, 60, TimeUnit.SECONDS);
        }
        
        // 每个IP每分钟最多10次请求
        return count <= 10;
    }
    
    // 用户限流
    public boolean checkUserLimit(Long userId, Long productId) {
        String key = "seckill:user:limit:" + productId + ":" + userId;
        Long count = redisTemplate.opsForValue().increment(key);
        
        if (count == 1) {
            redisTemplate.expire(key, 60, TimeUnit.SECONDS);
        }
        
        // 每个用户每分钟最多5次请求
        return count <= 5;
    }
    
    // 总请求限流
    public boolean checkTotalLimit(Long productId) {
        String key = "seckill:total:" + productId;
        Long count = redisTemplate.opsForValue().increment(key);
        
        if (count == 1) {
            redisTemplate.expire(key, 1, TimeUnit.SECONDS);
        }
        
        // 每秒最多1000个请求
        return count <= 1000;
    }
}

// 秒杀控制器(带限流)
@RestController
@RequestMapping("/api/seckill")
@Slf4j
public class SeckillController {
    
    @Autowired
    private SeckillService seckillService;
    
    @Autowired
    private SeckillRateLimitService rateLimitService;
    
    @PostMapping("/{productId}")
    public ResponseEntity<ApiResponse<SeckillResult>> seckill(
            @PathVariable Long productId,
            HttpServletRequest request) {
        
        // 获取用户ID(从Token中解析)
        Long userId = getUserIdFromToken(request);
        if (userId == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
                .body(ApiResponse.error("未登录"));
        }
        
        // 获取IP
        String ip = getClientIp(request);
        
        // 1. IP限流
        if (!rateLimitService.checkIpLimit(ip, productId)) {
            return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
                .body(ApiResponse.error("请求过于频繁,请稍后重试"));
        }
        
        // 2. 用户限流
        if (!rateLimitService.checkUserLimit(userId, productId)) {
            return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
                .body(ApiResponse.error("您操作过于频繁,请稍后重试"));
        }
        
        // 3. 总请求限流
        if (!rateLimitService.checkTotalLimit(productId)) {
            return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
                .body(ApiResponse.error("系统繁忙,请稍后重试"));
        }
        
        // 4. 执行秒杀
        SeckillResult result = seckillService.seckill(userId, productId);
        
        if (result.isSuccess()) {
            return ResponseEntity.ok(ApiResponse.success(result));
        } else {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body(ApiResponse.error(result.getMessage()));
        }
    }
    
    @GetMapping("/stock/{productId}")
    public ResponseEntity<ApiResponse<Integer>> getStock(@PathVariable Long productId) {
        Integer stock = seckillService.getSeckillStock(productId);
        return ResponseEntity.ok(ApiResponse.success(stock));
    }
    
    private Long getUserIdFromToken(HttpServletRequest request) {
        // 从Token中解析用户ID
        String token = request.getHeader("Authorization");
        // 实现Token解析逻辑
        return 1L; // 示例
    }
    
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}

3. 性能调优实战

3.1 JVM调优实战

JVM参数配置与监控:

java 复制代码
// JVM监控服务
@Service
@Slf4j
public class JVMMonitorService {
    
    // 获取JVM内存信息
    public JVMMemoryInfo getMemoryInfo() {
        Runtime runtime = Runtime.getRuntime();
        long totalMemory = runtime.totalMemory();
        long freeMemory = runtime.freeMemory();
        long usedMemory = totalMemory - freeMemory;
        long maxMemory = runtime.maxMemory();
        
        JVMMemoryInfo info = new JVMMemoryInfo();
        info.setTotalMemory(totalMemory);
        info.setUsedMemory(usedMemory);
        info.setFreeMemory(freeMemory);
        info.setMaxMemory(maxMemory);
        info.setUsagePercent((double) usedMemory / maxMemory * 100);
        
        return info;
    }
    
    // 获取GC信息
    public List<GCInfo> getGCInfo() {
        List<GarbageCollectorMXBean> gcBeans = ManagementFactory.getGarbageCollectorMXBeans();
        List<GCInfo> gcInfos = new ArrayList<>();
        
        for (GarbageCollectorMXBean gcBean : gcBeans) {
            GCInfo info = new GCInfo();
            info.setName(gcBean.getName());
            info.setCollectionCount(gcBean.getCollectionCount());
            info.setCollectionTime(gcBean.getCollectionTime());
            gcInfos.add(info);
        }
        
        return gcInfos;
    }
    
    // 手动触发GC(仅用于测试)
    public void triggerGC() {
        System.gc();
        log.info("手动触发GC");
    }
    
    // 获取线程信息
    public ThreadInfo getThreadInfo() {
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        ThreadInfo info = new ThreadInfo();
        info.setThreadCount(threadBean.getThreadCount());
        info.setPeakThreadCount(threadBean.getPeakThreadCount());
        info.setTotalStartedThreadCount(threadBean.getTotalStartedThreadCount());
        info.setDaemonThreadCount(threadBean.getDaemonThreadCount());
        return info;
    }
}

// JVM内存信息
@Data
public class JVMMemoryInfo {
    private long totalMemory;      // 总内存
    private long usedMemory;       // 已用内存
    private long freeMemory;       // 空闲内存
    private long maxMemory;        // 最大内存
    private double usagePercent;   // 使用率
}

// GC信息
@Data
public class GCInfo {
    private String name;
    private long collectionCount;
    private long collectionTime;
}

// JVM监控控制器
@RestController
@RequestMapping("/api/monitor/jvm")
@Slf4j
public class JVMMonitorController {
    
    @Autowired
    private JVMMonitorService monitorService;
    
    @GetMapping("/memory")
    public ResponseEntity<ApiResponse<JVMMemoryInfo>> getMemoryInfo() {
        JVMMemoryInfo info = monitorService.getMemoryInfo();
        return ResponseEntity.ok(ApiResponse.success(info));
    }
    
    @GetMapping("/gc")
    public ResponseEntity<ApiResponse<List<GCInfo>>> getGCInfo() {
        List<GCInfo> infos = monitorService.getGCInfo();
        return ResponseEntity.ok(ApiResponse.success(infos));
    }
    
    @GetMapping("/thread")
    public ResponseEntity<ApiResponse<ThreadInfo>> getThreadInfo() {
        ThreadInfo info = monitorService.getThreadInfo();
        return ResponseEntity.ok(ApiResponse.success(info));
    }
}

// JVM调优建议
@Component
@Slf4j
public class JVMTuningAdvisor {
    
    public JVMTuningAdvice getTuningAdvice(JVMMemoryInfo memoryInfo) {
        JVMTuningAdvice advice = new JVMTuningAdvice();
        
        // 内存使用率过高
        if (memoryInfo.getUsagePercent() > 80) {
            advice.addWarning("内存使用率过高: " + String.format("%.2f%%", memoryInfo.getUsagePercent()));
            advice.addSuggestion("建议增加堆内存: -Xmx4g -Xms4g");
        }
        
        // 检查GC频率
        List<GCInfo> gcInfos = getGCInfo();
        for (GCInfo gcInfo : gcInfos) {
            if (gcInfo.getCollectionCount() > 1000) {
                advice.addWarning("GC频率过高: " + gcInfo.getName() + " 执行了 " + gcInfo.getCollectionCount() + " 次");
                advice.addSuggestion("建议使用G1GC: -XX:+UseG1GC -XX:MaxGCPauseMillis=200");
            }
        }
        
        return advice;
    }
    
    private List<GCInfo> getGCInfo() {
        // 实现获取GC信息
        return Collections.emptyList();
    }
}

3.2 数据库性能优化

数据库优化实践:

java 复制代码
// 数据库性能监控
@Service
@Slf4j
public class DatabasePerformanceService {
    
    @Autowired
    private DataSource dataSource;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    // 获取慢查询
    public List<SlowQuery> getSlowQueries() {
        // MySQL慢查询日志分析
        String sql = "SELECT * FROM mysql.slow_log ORDER BY start_time DESC LIMIT 100";
        // 实际实现需要根据数据库类型调整
        return Collections.emptyList();
    }
    
    // 分析SQL执行计划
    public ExecutionPlan analyzeExecutionPlan(String sql) {
        ExecutionPlan plan = new ExecutionPlan();
        
        try {
            // 获取执行计划
            String explainSql = "EXPLAIN " + sql;
            List<Map<String, Object>> results = jdbcTemplate.queryForList(explainSql);
            
            plan.setSql(sql);
            plan.setPlans(results);
            
            // 分析执行计划
            for (Map<String, Object> result : results) {
                String type = (String) result.get("type");
                if ("ALL".equals(type)) {
                    plan.addWarning("全表扫描,建议添加索引");
                }
                if ("index".equals(type)) {
                    plan.addWarning("全索引扫描,考虑优化查询条件");
                }
            }
            
        } catch (Exception e) {
            log.error("分析执行计划失败", e);
            plan.addError("分析失败: " + e.getMessage());
        }
        
        return plan;
    }
    
    // 索引优化建议
    public List<IndexSuggestion> getIndexSuggestions() {
        List<IndexSuggestion> suggestions = new ArrayList<>();
        
        // 查询未使用索引的表
        String sql = "SELECT table_name, index_name, seq_in_index, column_name " +
                    "FROM information_schema.statistics " +
                    "WHERE table_schema = DATABASE() " +
                    "ORDER BY table_name, index_name";
        
        // 分析索引使用情况
        // 实际实现需要查询数据库元数据
        
        return suggestions;
    }
}

// 执行计划
@Data
public class ExecutionPlan {
    private String sql;
    private List<Map<String, Object>> plans;
    private List<String> warnings = new ArrayList<>();
    private List<String> errors = new ArrayList<>();
    
    public void addWarning(String warning) {
        warnings.add(warning);
    }
    
    public void addError(String error) {
        errors.add(error);
    }
}

// 批量操作优化
@Service
@Slf4j
public class BatchOperationOptimizer {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    // 批量插入优化
    public void batchInsert(List<Order> orders) {
        String sql = "INSERT INTO t_order (order_number, user_id, total_amount, status, create_time) " +
                    "VALUES (?, ?, ?, ?, ?)";
        
        int batchSize = 1000;
        List<Object[]> batchArgs = new ArrayList<>();
        
        for (Order order : orders) {
            Object[] args = new Object[]{
                order.getOrderNumber(),
                order.getUserId(),
                order.getTotalAmount(),
                order.getStatus().name(),
                order.getCreateTime()
            };
            batchArgs.add(args);
            
            if (batchArgs.size() >= batchSize) {
                jdbcTemplate.batchUpdate(sql, batchArgs);
                batchArgs.clear();
            }
        }
        
        if (!batchArgs.isEmpty()) {
            jdbcTemplate.batchUpdate(sql, batchArgs);
        }
    }
    
    // 使用MyBatis Plus批量插入
    @Autowired
    private OrderMapper orderMapper;
    
    public void batchInsertWithMyBatisPlus(List<Order> orders) {
        // MyBatis Plus批量插入
        orderMapper.insertBatch(orders);
    }
}

4. 故障排查与监控

4.1 日志分析与监控

日志监控与分析:

java 复制代码
// 日志分析服务
@Service
@Slf4j
public class LogAnalysisService {
    
    // 分析错误日志
    public List<ErrorLog> analyzeErrorLogs(String logFile, Date startTime, Date endTime) {
        List<ErrorLog> errorLogs = new ArrayList<>();
        
        try {
            Path path = Paths.get(logFile);
            List<String> lines = Files.readAllLines(path);
            
            for (String line : lines) {
                if (line.contains("ERROR") || line.contains("Exception")) {
                    ErrorLog errorLog = parseErrorLog(line);
                    if (errorLog != null && isInTimeRange(errorLog.getTimestamp(), startTime, endTime)) {
                        errorLogs.add(errorLog);
                    }
                }
            }
            
        } catch (IOException e) {
            log.error("读取日志文件失败", e);
        }
        
        return errorLogs;
    }
    
    // 统计错误类型
    public Map<String, Integer> countErrorTypes(List<ErrorLog> errorLogs) {
        return errorLogs.stream()
            .collect(Collectors.groupingBy(
                ErrorLog::getErrorType,
                Collectors.collectingAndThen(Collectors.counting(), Long::intValue)
            ));
    }
    
    // 分析性能日志
    public List<PerformanceLog> analyzePerformanceLogs(String logFile) {
        List<PerformanceLog> performanceLogs = new ArrayList<>();
        
        // 解析性能日志
        // 实际实现需要根据日志格式解析
        
        return performanceLogs;
    }
    
    private ErrorLog parseErrorLog(String line) {
        // 解析错误日志
        // 实际实现需要根据日志格式解析
        return null;
    }
    
    private boolean isInTimeRange(Date timestamp, Date startTime, Date endTime) {
        return timestamp.after(startTime) && timestamp.before(endTime);
    }
}

// 错误日志
@Data
public class ErrorLog {
    private Date timestamp;
    private String level;
    private String errorType;
    private String message;
    private String stackTrace;
}

// 性能日志
@Data
public class PerformanceLog {
    private Date timestamp;
    private String method;
    private long executionTime;
    private String parameters;
}

// APM监控
@Component
@Slf4j
public class APMMonitor {
    
    // 方法执行时间监控
    @Around("@annotation(MonitorPerformance)")
    public Object monitorPerformance(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        String methodName = joinPoint.getSignature().toShortString();
        
        try {
            Object result = joinPoint.proceed();
            long executionTime = System.currentTimeMillis() - startTime;
            
            // 记录性能日志
            logPerformance(methodName, executionTime, true);
            
            // 如果执行时间过长,记录警告
            if (executionTime > 1000) {
                log.warn("方法执行时间过长: method={}, time={}ms", methodName, executionTime);
            }
            
            return result;
        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            logPerformance(methodName, executionTime, false);
            throw e;
        }
    }
    
    private void logPerformance(String methodName, long executionTime, boolean success) {
        // 发送到监控系统
        // 实际实现可以发送到Prometheus、InfluxDB等
    }
}

// 性能监控注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MonitorPerformance {
    String value() default "";
}

4.2 健康检查与告警

健康检查实现:

java 复制代码
// 健康检查服务
@Component
@Slf4j
public class HealthCheckService {
    
    @Autowired
    private DataSource dataSource;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    // 数据库健康检查
    public HealthStatus checkDatabase() {
        try {
            Connection connection = dataSource.getConnection();
            boolean valid = connection.isValid(5);
            connection.close();
            
            if (valid) {
                return HealthStatus.healthy("数据库连接正常");
            } else {
                return HealthStatus.unhealthy("数据库连接异常");
            }
        } catch (Exception e) {
            return HealthStatus.unhealthy("数据库健康检查失败: " + e.getMessage());
        }
    }
    
    // Redis健康检查
    public HealthStatus checkRedis() {
        try {
            String result = redisTemplate.execute((RedisCallback<String>) connection -> {
                return connection.ping();
            });
            
            if ("PONG".equals(result)) {
                return HealthStatus.healthy("Redis连接正常");
            } else {
                return HealthStatus.unhealthy("Redis连接异常");
            }
        } catch (Exception e) {
            return HealthStatus.unhealthy("Redis健康检查失败: " + e.getMessage());
        }
    }
    
    // 综合健康检查
    public Map<String, HealthStatus> checkAll() {
        Map<String, HealthStatus> statuses = new HashMap<>();
        statuses.put("database", checkDatabase());
        statuses.put("redis", checkRedis());
        // 添加其他检查项
        return statuses;
    }
}

// 健康状态
@Data
@AllArgsConstructor
public class HealthStatus {
    private boolean healthy;
    private String message;
    private Date checkTime;
    
    public static HealthStatus healthy(String message) {
        return new HealthStatus(true, message, new Date());
    }
    
    public static HealthStatus unhealthy(String message) {
        return new HealthStatus(false, message, new Date());
    }
}

// 告警服务
@Service
@Slf4j
public class AlertService {
    
    // 发送告警
    public void sendAlert(AlertLevel level, String message) {
        log.warn("告警: level={}, message={}", level, message);
        
        // 根据告警级别发送通知
        switch (level) {
            case CRITICAL:
                // 发送紧急通知(短信、电话等)
                sendCriticalAlert(message);
                break;
            case WARNING:
                // 发送警告通知(邮件、企业微信等)
                sendWarningAlert(message);
                break;
            case INFO:
                // 记录信息
                log.info("告警信息: {}", message);
                break;
        }
    }
    
    private void sendCriticalAlert(String message) {
        // 实现紧急告警逻辑
        log.error("紧急告警: {}", message);
    }
    
    private void sendWarningAlert(String message) {
        // 实现警告告警逻辑
        log.warn("警告告警: {}", message);
    }
}

enum AlertLevel {
    INFO, WARNING, CRITICAL
}

5. 面试准备

5.1 常见面试题

核心面试题解答:

java 复制代码
// 1. 如何实现线程安全的单例模式?
public class Singleton {
    // 双重检查锁定
    private static volatile Singleton instance;
    
    private Singleton() {}
    
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
    
    // 静态内部类方式(推荐)
    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }
    
    public static Singleton getInstance2() {
        return SingletonHolder.INSTANCE;
    }
}

// 2. 如何实现生产者消费者模式?
@Component
@Slf4j
public class ProducerConsumerExample {
    
    private final BlockingQueue<String> queue = new LinkedBlockingQueue<>(10);
    
    // 生产者
    @Async
    public void produce(String item) throws InterruptedException {
        queue.put(item);
        log.info("生产: {}", item);
    }
    
    // 消费者
    @Async
    public void consume() throws InterruptedException {
        String item = queue.take();
        log.info("消费: {}", item);
    }
}

// 3. 如何实现LRU缓存?
public class LRUCache<K, V> {
    
    private final int capacity;
    private final LinkedHashMap<K, V> cache;
    
    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.cache = new LinkedHashMap<K, V>(capacity, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
                return size() > capacity;
            }
        };
    }
    
    public synchronized V get(K key) {
        return cache.get(key);
    }
    
    public synchronized void put(K key, V value) {
        cache.put(key, value);
    }
}

// 4. 如何实现分布式锁?
// 见前面章节的Redis分布式锁实现

// 5. 如何设计一个高并发的秒杀系统?
// 见前面章节的秒杀系统实现

5.2 系统设计题

系统设计题解答框架:

java 复制代码
// 系统设计:设计一个短链接系统
@Service
@Slf4j
public class ShortUrlService {
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Autowired
    private ShortUrlRepository shortUrlRepository;
    
    private static final String SHORT_URL_PREFIX = "https://short.ly/";
    private static final String BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    // 生成短链接
    public String generateShortUrl(String longUrl) {
        // 1. 检查是否已存在
        String existingShortUrl = redisTemplate.opsForValue().get("long:" + longUrl);
        if (existingShortUrl != null) {
            return existingShortUrl;
        }
        
        // 2. 生成短链接
        String shortCode = generateShortCode();
        String shortUrl = SHORT_URL_PREFIX + shortCode;
        
        // 3. 保存映射关系
        ShortUrlMapping mapping = new ShortUrlMapping();
        mapping.setShortCode(shortCode);
        mapping.setLongUrl(longUrl);
        mapping.setCreateTime(new Date());
        shortUrlRepository.save(mapping);
        
        // 4. 缓存
        redisTemplate.opsForValue().set("short:" + shortCode, longUrl, 7, TimeUnit.DAYS);
        redisTemplate.opsForValue().set("long:" + longUrl, shortUrl, 7, TimeUnit.DAYS);
        
        return shortUrl;
    }
    
    // 获取原始链接
    public String getLongUrl(String shortCode) {
        // 1. 从缓存获取
        String longUrl = redisTemplate.opsForValue().get("short:" + shortCode);
        if (longUrl != null) {
            return longUrl;
        }
        
        // 2. 从数据库获取
        ShortUrlMapping mapping = shortUrlRepository.findByShortCode(shortCode);
        if (mapping != null) {
            // 更新缓存
            redisTemplate.opsForValue().set("short:" + shortCode, mapping.getLongUrl(), 7, TimeUnit.DAYS);
            return mapping.getLongUrl();
        }
        
        throw new ShortUrlNotFoundException("短链接不存在");
    }
    
    // 生成短码(Base62编码)
    private String generateShortCode() {
        // 使用雪花算法生成ID,然后Base62编码
        long id = snowflakeIdGenerator.nextId();
        return base62Encode(id);
    }
    
    private String base62Encode(long num) {
        StringBuilder sb = new StringBuilder();
        while (num > 0) {
            sb.append(BASE62.charAt((int) (num % 62)));
            num /= 62;
        }
        return sb.reverse().toString();
    }
}

6. 学习路径总结

6.1 知识体系梳理

30天学习成果总结:

java 复制代码
// 学习路径总结
/**
 * Java学习30天知识体系
 * 
 * 基础阶段(Day 1-10)
 * - Java基础语法
 * - 面向对象编程
 * - 集合框架
 * - 异常处理
 * - I/O流
 * - 多线程
 * 
 * 进阶阶段(Day 11-20)
 * - Spring框架
 * - Spring Boot
 * - 数据库操作(JDBC、MyBatis)
 * - RESTful API
 * - 事务管理
 * - 缓存技术
 * 
 * 高级阶段(Day 21-30)
 * - 微服务架构
 * - 分布式系统
 * - 消息队列
 * - 分布式事务
 * - 性能优化
 * - 系统设计
 * 
 * 核心技能点:
 * 1. Java基础扎实
 * 2. Spring生态熟练
 * 3. 数据库优化能力
 * 4. 分布式系统设计
 * 5. 性能调优经验
 * 6. 系统架构能力
 */

6.2 后续学习建议

继续学习方向:

java 复制代码
/**
 * 后续学习建议
 * 
 * 1. 深入学习
 *    - 深入理解JVM原理
 *    - 学习设计模式实战
 *    - 掌握更多中间件(Kafka、Elasticsearch等)
 * 
 * 2. 实践项目
 *    - 参与开源项目
 *    - 构建个人项目
 *    - 解决实际问题
 * 
 * 3. 技术拓展
 *    - 学习云原生技术(Kubernetes、Docker)
 *    - 了解前端技术(Vue、React)
 *    - 学习大数据技术(Hadoop、Spark)
 * 
 * 4. 软技能
 *    - 提升代码质量
 *    - 学习系统设计
 *    - 加强沟通能力
 */
相关推荐
梦未9 小时前
Spring控制反转与依赖注入
java·后端·spring
喜欢流萤吖~9 小时前
Lambda 表达式
java
ZouZou老师9 小时前
C++设计模式之适配器模式:以家具生产为例
java·设计模式·适配器模式
曼巴UE59 小时前
UE5 C++ 动态多播
java·开发语言
VX:Fegn08959 小时前
计算机毕业设计|基于springboot + vue音乐管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
程序员鱼皮9 小时前
刚刚,IDEA 免费版发布!终于不用破解了
java·程序员·jetbrains
Hui Baby10 小时前
Nacos容灾俩种方案对比
java
曲莫终10 小时前
Java单元测试框架Junit5用法一览
java
成富10 小时前
Chat Agent UI,类似 ChatGPT 的聊天界面,Spring AI 应用的测试工具
java·人工智能·spring·ui·chatgpt