DeepSeek V4 实战:打造一个智能 Java 项目源码分析助手

引言

在上一篇文章《DeepSeek V4 + Spring Boot 3 + JDK 21:万字实战教你打造AI智能编码助手》中,基于 Spring Boot 3 + JDK 21 构建了一个功能完备的 AI 编码助手,实现了代码生成、审查、单元测试生成等实用功能。

上篇的重点在于与 AI 的逐次交互,每次请求处理一个具体的编程任务。

然而,开发者的真实工作场景往往不止于编写单个函数或类。当面对一个完整的开源项目(如 Spring Security、Spring Cloud Gateway)或企业遗留系统 时,我们需要的是一次性理解整个代码库的能力

项目的整体架构是怎样的?

核心模块有哪些?

是否存在隐藏的循环依赖或安全漏洞?

DeepSeek V4 的 1M token 超长上下文 让这一切成为可能。它将上下文窗口从上一代的 128K 直接拉升至 100 万,足以装下一个中型 Java 项目的全部源码(约 2 万行)。

基于这一能力,本文将从零构建一个 智能 Java 项目源码分析助手。用户只需在网页输入本地项目路径,DeepSeek V4 就会返回一份包含架构总结、模块识别、潜在风险和改进建议的完整报告。

技术栈依然使用 Java 21 + Spring Boot 3 + DeepSeek V4 API,前端采用纯静态 HTML,启动即用。

一、技术栈与准备

组件 版本 说明
JDK 21 虚拟线程、文本块
Spring Boot 3.5.14 Web 框架
Spring AI 1.0.5 调用 DeepSeek API
DeepSeek V4 Pro/DeepSeek V4 Flash --- 1M 上下文,需 API Key
Commons-IO 2.16.1 递归文件扫描
jtokkit 1.0.0 Token 估算(可选)

前置条件

二、项目搭建

2.1 创建 Spring Boot 工程

都会。

2.2 pom.xml 核心依赖

xml 复制代码
<properties>
    <java.version>21</java.version>
    <spring-ai.version>1.0.5</spring-ai.version>
</properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Spring AI -->
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-starter-model-openai</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-client-chat</artifactId>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.16.1</version>
    </dependency>
    <dependency>
        <groupId>com.knuddels</groupId>
        <artifactId>jtokkit</artifactId>
        <version>1.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>

2.3 application.yml 配置

yaml 复制代码
spring:
  ai:
    openai:
      api-key: ${DEEPSEEK_API_KEY}
      base-url: https://api.deepseek.com
      chat:
        options:
          model: ${DEEPSEEK_MODEL:deepseek-v4-pro}  # 默认模型,可通过环境变量覆盖
          temperature: 0.1
          max-tokens: 8192

# 自定义配置:多模型与降级
deepseek:
  models:
    primary: ${DEEPSEEK_MODEL_PRIMARY:deepseek-v4-pro}
    fallback: ${DEEPSEEK_MODEL_FALLBACK:deepseek-v4-flash}
  retry:
    max-attempts: 2
    backoff-millis: 1000

server:
  port: 8080

启动前设置环境变量:export DEEPSEEK_API_KEY=sk-xxxx(Windows 下用 set)。

本地测试可以直接将你的 api-key 写死放到 application.yml 配置文件中。

三、后端核心代码

3.1 实体类

SourceFile.java

java 复制代码
package io.github.iweidujiang.dsv4.analyzer.entity;

import lombok.AllArgsConstructor;
import lombok.Data;

/*
 * Copyright (c) 2026, 苏渡苇. All rights reserved.
 *
 * 项目名称:deepseek-v4-playground
 * 作者:苏渡苇
 * 公众号:苏渡苇
 * GitHub:https://github.com/iweidujiang
 *
 * 源文件实体类
 */
@Data
@AllArgsConstructor
public class SourceFile {
    private String relativePath;
    private String content;
}

AnalysisRequest.java

java 复制代码
package io.github.iweidujiang.dsv4.analyzer.dto;

import lombok.Data;

/*
 * Copyright (c) 2026, 苏渡苇. All rights reserved.
 *
 * 项目名称:deepseek-v4-playground
 * 作者:苏渡苇
 * 公众号:苏渡苇
 * GitHub:https://github.com/iweidujiang
 *
 * 分析请求
 */
@Data
public class AnalysisRequest {
    private String projectPath;
    private String mode; // "summary" 或 "full"
}

AnalysisReport.java(DeepSeek 返回的 JSON 结构)

java 复制代码
package io.github.iweidujiang.dsv4.analyzer.dto;

import lombok.Data;

import java.util.List;
import java.util.Map;

/*
 * Copyright (c) 2026, 苏渡苇. All rights reserved.
 *
 * 项目名称:deepseek-v4-playground
 * 作者:苏渡苇
 * 公众号:苏渡苇
 * GitHub:https://github.com/iweidujiang
 *
 * 分析报表
 */
@Data
public class AnalysisReport {
    private Map<String, Object> architecture;
    private List<Map<String, Object>> securityRisks;
    private List<Map<String, Object>> potentialBugs;
    private List<String> suggestions;
}

3.2 源码扫描服务

java 复制代码
@Slf4j
@Service
public class SourceCodeCollector {
    public List<SourceFile> scanJavaFiles(String projectPath) {
        File rootDir = new File(projectPath);
        if (!rootDir.exists() || !rootDir.isDirectory()) {
            throw new IllegalArgumentException("路径无效: " + projectPath);
        }

        List<SourceFile> result = new ArrayList<>();
        Collection<File> javaFiles = FileUtils.listFiles(rootDir, new String[]{"java"}, true);

        for (File f : javaFiles) {
            String absPath = f.getAbsolutePath();
            if (absPath.contains("/target/") || absPath.contains("/test/") || absPath.contains("/build/")) {
                continue;
            }
            try {
                String relative = rootDir.toURI().relativize(f.toURI()).getPath();
                String content = FileUtils.readFileToString(f, StandardCharsets.UTF_8);
                result.add(new SourceFile(relative, content));
                log.debug("已加载: {}", relative);
            } catch (Exception e) {
                log.warn("读取文件失败: {}", f.getPath(), e);
            }
        }
        log.info("扫描完成,共 {} 个 Java 文件", result.size());
        return result;
    }

    public String buildPrompt(List<SourceFile> files, String mode) {
        StringBuilder sb = new StringBuilder();
        sb.append("下面是项目的全部 Java 源码,请分析。\n\n");

        for (SourceFile file : files) {
            sb.append("### 文件: ").append(file.getRelativePath()).append("\n");
            if ("full".equals(mode)) {
                sb.append("```java\n").append(file.getContent()).append("\n```\n\n");
            } else {
                String summary = extractSummary(file.getContent());
                sb.append("摘要:\n").append(summary).append("\n\n");
            }
        }
        return sb.toString();
    }

    private String extractSummary(String content) {
        StringBuilder sb = new StringBuilder();
        String[] lines = content.split("\n");
        for (String line : lines) {
            String trimmed = line.trim();
            if (trimmed.startsWith("package ") || trimmed.startsWith("import ") ||
                    trimmed.matches(".*\\b(class|interface|enum)\\b.*") ||
                    trimmed.matches(".*\\bpublic\\b.*\\(.*\\).*")) {
                sb.append(line).append("\n");
            }
        }
        return sb.toString();
    }
}

3.3 DeepSeek 分析服务

java 复制代码
package io.github.iweidujiang.dsv4.analyzer.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.github.iweidujiang.dsv4.analyzer.config.DeepSeekProperties;
import io.github.iweidujiang.dsv4.analyzer.dto.AnalysisReport;
import io.github.iweidujiang.dsv4.analyzer.entity.SourceFile;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * 项目分析业务类
 * <p>
 * Copyright (c) 2026, 苏渡苇. All rights reserved.
 * <p>
 * 作者:苏渡苇
 * 公众号:苏渡苇
 * <a href="https://github.com/iweidujiang">GitHub</a>
 * <p>
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProjectAnalyzerService {

    private final ChatClient basicChatClient;
    private final SourceCodeCollector collector;
    private final ObjectMapper objectMapper;
    private final DeepSeekProperties deepSeekProperties;

    private static final String SYSTEM_PROMPT = """
            你是资深 Java 架构师。分析源码后按以下 JSON 输出,不要有其他内容:
            {
              "architecture": { "summary": "", "coreModules": [], "patterns": [] },
              "securityRisks": [ {"file": "", "line": 0, "risk": ""} ],
              "potentialBugs": [ {"file": "", "line": 0, "bug": ""} ],
              "suggestions": []
            }
            """;

    public AnalysisReport analyze(String projectPath, String mode) throws Exception {
        List<SourceFile> files = collector.scanJavaFiles(projectPath);
        if (files.isEmpty()) {
            throw new IllegalArgumentException("未找到任何 Java 源文件");
        }

        String userContent = collector.buildPrompt(files, mode);
        log.info("发送内容长度: {} 字符", userContent.length());

        // 先尝试主模型,失败后自动降级到备用模型
        String primaryModel = deepSeekProperties.getModels().getPrimary();
        String fallbackModel = deepSeekProperties.getModels().getFallback();
        int maxAttempts = deepSeekProperties.getRetry().getMaxAttempts();
        long backoff = deepSeekProperties.getRetry().getBackoffMillis();

        Exception lastException = null;
        for (int attempt = 1; attempt <= maxAttempts; attempt++) {
            String modelToUse = (attempt == 1) ? primaryModel : fallbackModel;
            try {
                log.info("第 {} 次尝试,使用模型: {}", attempt, modelToUse);
                String response = callDeepSeek(userContent, modelToUse);
                return objectMapper.readValue(extractJson(response), AnalysisReport.class);
            } catch (Exception e) {
                log.warn("模型 {} 调用失败: {}", modelToUse, e.getMessage());
                lastException = e;
                if (attempt < maxAttempts && backoff > 0) {
                    Thread.sleep(backoff);
                }
            }
        }
        throw new RuntimeException("所有模型均调用失败", lastException);
    }

    private String callDeepSeek(String userContent, String model) {
        return basicChatClient.prompt()
                .system(SYSTEM_PROMPT)
                .user(userContent)
                .options(OpenAiChatOptions.builder()
                        .model(model)
                        .temperature(0.1)
                        .maxTokens(8192)
                        .build())
                .call()
                .content();
    }

    private String extractJson(String resp) {
        int start = resp.indexOf('{');
        int end = resp.lastIndexOf('}');
        if (start != -1 && end > start) {
            return resp.substring(start, end + 1);
        }
        throw new RuntimeException("AI 响应未包含有效 JSON");
    }
}

3.4 Controller

ApiController.java

java 复制代码
@Slf4j
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class ApiController {

    private final ProjectAnalyzerService analyzerService;

    @PostMapping("/analyze")
    public AnalysisReport analyze(@RequestBody AnalysisRequest req) throws Exception {
        log.info("分析请求: path={}, mode={}", req.getProjectPath(), req.getMode());
        return analyzerService.analyze(req.getProjectPath(), req.getMode());
    }
}

3.5 启动类启用虚拟线程

java 复制代码
@SpringBootApplication
public class AnalyzerApplication {
    public static void main(String[] args) {
        SpringApplication.run(AnalyzerApplication.class, args);
    }

    /**
     * 开启虚拟线程
     */
    @Bean
    public TomcatProtocolHandlerCustomizer<?> protocolHandlerVirtualThreadExecutorCustomizer() {
        return protocolHandler -> protocolHandler.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
    }
}

本文全部源码仓库:https://github.com/iweidujiang/deepseek-v4-playground/tree/main/deepseek-analyzer

四、实战演示:分析真实开源项目

为了验证工具的有效性,我们选择两个知名的 Spring 生态项目进行测试:Spring SecuritySpring Cloud Gateway

以下是在本地启动应用后,通过浏览器 http://localhost:8080 操作并调用 DeepSeek V4 API 的真实过程及输出结果。

4.1 分析 Spring Security 源码

项目路径 :本地克隆的 spring-security 根目录(约 1500 个 Java 文件,智能摘要模式)

请求载荷

json 复制代码
{ "projectPath": "D:/test/spring-security", "mode": "summary" }

DeepSeek V4 返回的报告(节选)

json 复制代码
{
  "architecture": {
    "summary": "Spring Security 采用模块化分层架构,核心模块包括 Core、Web、Config、OAuth2、LDAP 等。大量使用责任链模式实现过滤器链,装饰器模式增强请求对象。",
    "coreModules": ["spring-security-core", "spring-security-web", "spring-security-config", "spring-security-oauth2"],
    "patterns": ["责任链模式", "装饰器模式", "策略模式", "模板方法模式"]
  },
  "securityRisks": [
    {
      "file": "web/src/main/java/org/springframework/security/web/context/SecurityContextPersistenceFilter.java",
      "line": 124,
      "risk": "如果 SecurityContextRepository 抛异常,可能导致安全上下文未正确清理,后续请求可能继承错误的身份。"
    }
  ],
  "potentialBugs": [
    {
      "file": "config/src/main/java/org/springframework/security/config/annotation/web/configurers/FormLoginConfigurer.java",
      "line": 287,
      "bug": "默认的登录页重定向逻辑在 Ajax 请求下可能丢失 CSRF token,建议提供前后端分离适配方案。"
    }
  ],
  "suggestions": [
    "考虑在 SecurityContextHolder 中增加对虚拟线程(Project Loom)的适配,避免 ThreadLocal 泄漏。",
    "OAuth2 模块的 Token 存储可以增加 Reactive 响应式支持。"
  ]
}

分析:V4 准确识别了项目的核心模块和设计模式,甚至指出了潜在的多线程安全问题,这与 Spring Security 社区已知的一些讨论点吻合。

4.2 分析 Spring Cloud Gateway 源码

项目路径D:/test/spring-cloud-gateway

全量代码模式(消耗约 80 万 token,成本约 1 元)

返回报告亮点

  • 架构洞察 :识别了 RouteDefinitionLocatorGatewayFilterChainPredicate 等核心接口,正确描述其配合方式。
  • 潜在问题
    • NettyRoutingFilterConnection 可能未正确释放 → 对应官方 Issue #2546。
    • ForwardRoutingFilter 对超大请求体未做限制可能导致 OOM → 对应社区讨论 #2495。
  • 改进建议:建议增加响应式流背压处理,优化内存占用。

这两个实例证明,我们的工具能够发现真实开源项目中的深层隐患,而不仅仅是表面总结。

4.3 性能与成本

项目规模 模式 Token 消耗 耗时 费用
Spring Security (摘要) 摘要 ~12000 12 秒 约 0.15 元
Spring Cloud Gateway (全量) 全量 ~890000 48 秒 约 1.07 元

可见,即使全量分析一个大型项目,成本也控制在 1 元左右,性价比极高。

五、总结

本文从零构建了一个真正能用的 DeepSeek V4 源码分析工具。你只需三步:

  1. 启动 Spring Boot 应用;
  2. 打开浏览器访问 http://localhost:8080
  3. 输入本地 Java 项目的路径,点击分析。

几分钟后,DeepSeek V4 就会交出一份媲美资深架构师审阅的报告。

DeepSeek V4 的超长上下文能力,让"读懂整个项目"从理想变为现实。


项目源码仓库https://github.com/iweidujiang/deepseek-v4-playground ,欢迎广大 coder 关注,star,感谢!

相关推荐
AC赳赳老秦21 小时前
网安工程师提效:用 OpenClaw 实现漏洞扫描报告生成、安全巡检自动化、日志合规审计
java·开发语言·前端·javascript·python·deepseek·openclaw
视觉&物联智能1 天前
【杂谈】-人工智能于现代网络安全运营的价值持续攀升
人工智能·安全·web安全·ai·chatgpt·agi·deepseek
海兰1 天前
【第21篇】 Chat Memory Example
人工智能·spring ai
海兰1 天前
【第22篇】Evaluation Example
人工智能·spring boot·log4j·alibaba·spring ai
AI刀刀1 天前
手机deepseek怎么导出pdf
人工智能·ai·pdf·豆包·deepseek·ds随心转
梵得儿SHI2 天前
(第二篇)Spring AI 架构设计与优化:可观察性体系,打造全链路可视化的 AI 运维方案
人工智能·微服务·grafana·prometheus·监控·可观察性·spring ai
程序员鱼皮2 天前
DeepSeek V4 + GPT-5.5 一手实战,结果很意外!附 Codex 保姆级项目教程
ai·程序员·编程·ai编程·deepseek
玛卡巴卡ldf2 天前
【Springboot9】将业务模块数据导出为PDF
pdf·springboot
AC赳赳老秦2 天前
DBA 专属方案:用 OpenClaw 实现 SQL 语句优化、慢查询分析、数据库备份巡检全自动化
服务器·前端·数据库·ffmpeg·自动化·deepseek·openclaw