手写Tomcat + 自研IoC:我用AI一周实现了一个完整的Java Web框架

手写Tomcat + 自研IoC:我用AI一周实现了一个完整的Java Web框架 先给你看结果✅ 项目已跑通能处理 HTTP 请求、支持 IoC 依赖注入、返回动态页面✅ 全部核心代码 含注释代码仓库见文末✅ AI 贡献了100% 的代码我只负责提问、设计架构、测试验证这篇文章不只讲原理更会分享我是如何让 AI 在 7 天内从零搭出一个可用的 Java Web 框架。如果你也想用 AI 提升开发效率下面的内容可能会帮你省下几个月的时间。项目完全自研无Spring无Tomcat代码超3万行全部由AI辅助生成一、为什么要自己写Web框架“你疯了吗Spring Boot不香吗”——这是我决定动手时朋友的第一反应。确实Spring生态已经足够强大。但作为技术人总有一种“知其所以然”的执念。我想弄明白Tomcat到底怎么解析HTTP请求的IoC容器如何实现依赖注入Spring MVC的DispatcherServlet背后发生了什么传统做法是读源码、看书但效率太低。于是我有了一个大胆的想法让AI帮我写一个完整的Java Web框架在写的过程中理解原理。结果令人震惊一周时间AI生成了超过3万行代码一个功能完备、自研核心的Web框架诞生了。这就是CodeStats。项目开源地址https://gitee.com/zhouzuoli/code-stats二、CodeStats 框架概览CodeStats 不是“玩具”而是一个教学级的全栈开发平台包含以下模块模块说明自研Tomcat嵌入式Servlet容器支持Pipeline-Valve责任链IoC容器注解驱动Autowired依赖注入单例/原型作用域MVC框架Controller、RequestMapping、参数自动绑定JDBC与连接池SimpleDataSource连接池JdbcTemplateMyBatis风格Mapper代码分析引擎多线程统计代码行数、依赖图、循环依赖检测数据库客户端元数据浏览、表数据分页、ER图可视化目录管理文件上传下载、在线编辑器、路径安全校验AI Agent集成Ollama/DeepSeek内置知识库ngram降级重点是所有核心组件零依赖第三方框架——Tomcat是自己写的IoC是自己写的连日志框架都是自研的。三、手写Tomcat完整请求处理流程这是整个框架最硬核的部分。我们先看一次HTTP请求的完整旅程。3.1 Connector监听端口接收Socketjava// Connector.java public class Connector implements Lifecycle { private ServerSocket serverSocket; private ExecutorService threadPool; public void start() { serverSocket new ServerSocket(port); while (running) { Socket socket serverSocket.accept(); threadPool.submit(() - process(socket)); } } private void process(Socket socket) { Request request new Request(socket.getInputStream()); request.parse(); Response response new Response(socket.getOutputStream()); // 交给Pipeline处理 engine.getPipeline().invoke(request, response); } }Connector 使用线程池处理并发每个请求被包装成Request和Response对象然后进入Pipeline-Valve 责任链。3.2 Pipeline-Valve责任链模式解耦处理逻辑java// SimplePipeline.java public class SimplePipeline implements Pipeline { private ListValve valves new ArrayList(); private Valve basic; public void invoke(Request request, Response response) throws Exception { new ValveChainImpl().invokeNext(request, response); } private class ValveChainImpl implements Valve.ValveChain { private int index 0; public void invokeNext(Request req, Response resp) throws Exception { if (index valves.size()) { valves.get(index).invoke(req, resp, this); } else if (basic ! null) { basic.invoke(req, resp, this); } else { // 最终交给容器处理 container.getPipeline().invoke(req, resp); } } } }责任链依次经过Engine Valve → Host Valve → Context Valve → Wrapper ValveServlet。3.3 Context与WrapperServlet容器StandardContext维护了 Servlet 映射关系java// StandardContext.java public class StandardContext extends ContainerBase implements Context { private MapString, String servletMappings new HashMap(); public String findServletMapping(String uri) { // 精确匹配 if (servletMappings.containsKey(uri)) return servletMappings.get(uri); // 默认 /* 匹配 return defaultServletName; } }StandardWrapper负责加载并初始化 Servletjava// StandardWrapper.java public class StandardWrapper extends ContainerBase implements Wrapper { private Servlet servletInstance; public void init() { Class? clazz getLoader().loadClass(servletClass); servletInstance (Servlet) clazz.newInstance(); servletInstance.init(); } public void invokeServlet(Request request, Response response) { // 经过 FilterChain 后调用 service 方法 servletInstance.service(request, response); } }3.4 DispatcherServletMVC核心框架的DispatcherServlet继承自HttpServlet在init()时扫描所有Controller构建HandlerMapping正则表。java// DispatcherServlet.java private ListHandlerMapping handlerMappings new ArrayList(); public void init() { MapString, Object controllers beanFactory.getBeansOfType(Object.class); for (Object controller : controllers.values()) { String basePath controller.getClass().getAnnotation(RequestMapping.class).value(); for (Method method : controller.getClass().getMethods()) { RequestMapping rm method.getAnnotation(RequestMapping.class); String fullPath basePath rm.value(); String regex pathToRegex(fullPath, varNames); handlerMappings.add(new HandlerMapping(regex, controller, method)); } } }请求到达时匹配正则、提取路径变量、绑定参数、执行方法javaprotected void processRequest(HttpServletRequest req, HttpServletResponse res) { for (HandlerMapping hm : handlerMappings) { Matcher matcher Pattern.compile(hm.regex).matcher(uri); if (matcher.matches()) { // 提取路径变量 MapString, String pathVars extractPathVariables(matcher, hm.varNames); // 参数绑定支持 RequestParam, PathVariable, RequestBody Object[] args ParamBinder.resolveParameters(hm.method, req, res, pathVars); Object result hm.method.invoke(hm.controller, args); // 如果方法有 ResponseBody转JSON输出 if (hm.isResponseBody) { res.write(toJson(result)); } res.send(); return; } } }整个Tomcat流程可概括为textSocket accept → Connector → Request/Response 解析 → Pipeline-Valve 链 (Engine→Host→Context→Wrapper) → Servlet (DispatcherServlet) → HandlerMapping → Controller → 响应四、自研IoC容器从扫描到注入Spring 的 IoC 核心是BeanFactoryBeanDefinition。CodeStats 的实现同样清晰。4.1 BeanDefinition 与注册java// BeanDefinition.java public class BeanDefinition { private String beanClassName; private Class? beanClass; private String scope singleton; // singleton / prototype }AnnotationConfigApplicationContext在refresh()时扫描包将所有带Component、Service、Controller、Repository的类注册为BeanDefinition。4.2 依赖注入原理AbstractAutowireCapableBeanFactory的populateBean方法遍历字段遇到Autowired则解析依赖javaprotected void populateBean(Object bean, BeanDefinition bd) throws Exception { for (Field field : bean.getClass().getDeclaredFields()) { if (field.isAnnotationPresent(Autowired.class)) { field.setAccessible(true); Object dependency resolveDependency(field, bean); field.set(bean, dependency); } } } protected Object resolveDependency(Field field, Object bean) throws Exception { Class? requiredType field.getType(); MapString, ? candidates getBeansOfType(requiredType); if (candidates.size() 1) { return candidates.values().iterator().next(); } // 处理 Qualifier 和 Primary ... }支持循环依赖吗当前版本采用三级缓存机制类似Spring通过提前暴露ObjectFactory解决。五、AI一周实现3万行代码的秘诀5.1 我的工作流不是让AI直接生成全部代码而是分模块、分阶段提示阶段提示词示例AI产出第1天“实现一个嵌入式Tomcat包含Connector、Request、Response支持静态资源”基础Socket处理、HTTP解析第2天“实现Pipeline-Valve责任链让请求依次经过多个Valve”Pipeline接口、SimplePipeline实现第3天“实现IoC容器支持Component、Autowired单例缓存”BeanFactory、BeanDefinition、扫描注册第4天“实现DispatcherServlet支持RequestMapping和参数绑定”HandlerMapping、ParamBinder第5天“实现JDBC连接池SimpleDataSource使用Semaphore限流”连接池、JdbcTemplate第6天“实现MyBatis风格的Mapper代理自动执行SQL”MapperProxy、SqlParser第7天“整合所有模块添加前端界面”整合、调试、写文档5.2 AI生成代码的质量优点代码结构规范命名清晰大量注释AI习惯性写注释设计模式运用得当Pipeline、Builder、代理、工厂需要人工介入的地方复杂并发bug线程池关闭、连接泄漏循环依赖检测需手写三级缓存性能调优比如正则匹配HandlerMapping改用Trie树最终人工需要架构设计和调试但核心原理已全部通过AI代码体现。六、内置工具集亮点6.1 代码分析引擎Pipeline模式javaCollectStage → ParallelAnalyzeStage → AggregateStage → OutputStage每个文件分析时使用LanguageDetector识别30语言计算代码行、注释行、空行支持多线程并行处理。6.2 依赖分析与循环检测JavaDependencyExtractor通过词法分析提取类之间的依赖关系使用Tarjan算法检测循环依赖组。6.3 AI Agent项目助手内置知识库project_knowledge.json覆盖1000常见问题匹配不到时使用字符级3-gram语言模型降级生成回答——完全本地运行不依赖网络。七、如何快速上手体验7.1 环境要求JDK 8Maven 3.67.2 克隆与启动bashgit clone https://gitee.com/zhouzuoli/code-stats.git cd code-stats mvn clean compile java -cp target/classes com.omni.Bootstrap启动后访问http://localhost:28080/omni/demo/index.html7.3 核心配置application.propertiespropertiesserver.port28080 context.path/omni db.urljdbc:mysql://localhost:3306/test db.usernameroot db.password123456八、总结从造轮子到懂轮子一周时间借助AI我从零实现了一个Java Web框架。虽然它不适合生产环境但对于学习框架原理、理解Tomcat源码、掌握IoC设计思想价值巨大。这个项目可以给你带来彻底搞懂Spring Boot“黑盒”里发生了什么亲手实现Tomcat请求处理流程学习AI辅助编程的实战方法如果你也想挑战自己不妨试试用AI从零写一个框架。你会收获比读十本书更多的体验。项目地址Gitee - CodeStats欢迎Star、Fork、提Issue一起学习自研框架的乐趣。写在最后这篇文章从构思到完成AI 写代码我只负责提问和组装。我把它写出来不是为了炫耀而是想证明一件事借助 AI普通开发者也能在一周内完成以前需要一两个月的工作量。如果你觉得这篇文章对你有帮助或者让你看到了 AI 编程的真正潜力——请点个赞 这对我继续输出这类硬核实操内容非常重要。项目源码已开源有任何问题欢迎评论区交流。下篇预告敬请期待。