接手老项目最头疼的往往不是代码本身,而是环境怎么搭起来。前两天同事扔给我一个压缩包,说“帮我看下这个项目怎么跑不起来”,我解压一看,好家伙,整个项目里连个pom.xml都没有,src、web、WEB-INF、lib 倒是齐整,典型的老式 Java Web 项目结构。用 IDEA 打开,满屏红标,右键没有 Run,配置无从下手,很多新手在这一步就直接心态崩了。
这篇文章就专门解决这个问题:不用 Maven,怎么把一个传统的非 Maven Web 项目导入 IntelliJ IDEA,编译、部署到 Tomcat,然后正常跑起来。我会把从 Open 项目到 Tomcat 启动的完整路径走一遍,每一步都讲清楚“为什么这么做”,顺带把常见的坑也一并列出来。不管你拿到的是 Eclipse 老项目、学校实验课项目,还是别人从 SVN 上拉下来的祖传代码,这套流程都通用。
1. 拿到项目先别急着 Open,花两分钟认清它的“出身”
很多人在这一步就栽了跟头。拿到压缩包直接解压,然后用 IDEA 的File -> Open选中文件夹,结果 IDEA 完全没有识别出这是个 Web 项目,所有的源码目录和资源目录都变成了普通文件夹,右键没有Run,更没有Tomcat部署选项。你以为是你操作错了,其实问题出在第一步:你得先搞清楚这个项目的结构属于哪一种类型的非 Maven Web 项目。
1.1 传统 Java Web 项目长什么样
非 Maven 的 Web 项目通常被称为“传统 Web 项目”,它和现在主流的 Spring Boot + Maven 项目结构差异非常大。典型的目录结构一般是这样的:
src/:存放 Java 源码web/(也可能是WebContent/、WebRoot/):存放网页资源,里面通常会有WEB-INF/目录WEB-INF/web.xml:Web 项目部署描述符WEB-INF/classes/:编译后的 class 文件输出目录(手动部署时用)WEB-INF/lib/:项目第三方依赖的 jar 包
注意,这里没有pom.xml,没有.idea/目录,也没有.classpath和.project。如果是 Eclipse 老项目,倒是很可能有.classpath和.project这两个文件,但 IDEA 并不会依靠这两个文件来自动还原 Web 项目配置。这也是为什么打开之后 IDAE 表现得像个“傻子”一样,完全不知道这些目录该干什么。
1.2 先检查 JDK 和 web.xml,心里有个底
在动手配置之前,我先建议你做三件小事:
第一,用文本编辑器打开WEB-INF/web.xml,确认项目使用的是哪个 Servlet 版本规范。比如web-app的version="3.0"或者2.5等,这个直接决定了你后面选择 Tomcat 版本时的兼容性。
第二,看看src目录里有没有package路径,最好能对应找到一个带有@WebServlet注解或者extends HttpServlet的类,确认项目本身是一个 Servlet 项目,还是 Spring MVC 那种基于分发器的项目,这决定了部署后能不能正确访问到核心入口。
第三,看看WEB-INF/lib下都有哪些 jar。如果里面有spring-webmvc,说明这是个 Spring MVC 老项目,后面启动时如果报 ContextLoader 相关的错,你也知道该往哪个方向查。如果只有servlet-api和几个工具包,那可能就是最简单的 Servlet + JSP 项目。
提示:老项目如果编码是 GBK,而 IDEA 默认是 UTF-8,导入后打开文件就是乱码。这一步可以先顺手在
Settings -> File Encodings里把 Global Encoding、Project Encoding 都改成 UTF-8,再在Properties Files下面勾上Transparent native-to-ascii conversion,避免后面乱码问题反复折磨。
2. 用 IDEA 打开目录:用对方式,一步到位
拿到结构之后,就该把项目放进 IDEA 了。这里有一个很多人没想明白的点:打开项目并不等于导入项目。你如果只是在 IDEA 里Open了一个普通目录,IDEA 会默认把它当一个普通工程来对待,而我们要做的事情,其实是在这个普通目录之上,手动告诉 IDEA:“这地方的 src 是源码目录,这地方的 web 是网页根目录”。
2.1 Open 和 New Project 的区别
千万不要用New -> Project from Existing Sources里的 Maven 选项硬导。有些新手一看没有 Maven,就想着“我帮他建一个 Maven 壳子”,这个方法不是不行,但会给老项目引入一堆兼容性问题,比如依赖坐标缺失、包名冲突等。
正确做法是:File -> Open,选择项目根目录,IDEA 会弹出一个提示,问你是要Open as Project还是Open as File,选前者。此时 IDEA 大概率会识别为一个空项目,没关系,你看到的也就是一个光秃秃的目录树,这时候我们才开始动手构建项目骨架。
2.2 识别并标记源码目录
打开项目后,如果src目录没有变成蓝色,说明 IDEA 没有把它识别为源码根目录。
- 右键点击
src目录 - 选择
Mark Directory as -> Sources Root
标记后,目录会变为蓝色。这一步非常关键,不标记的话,你后面的import com.xxx.xxx全部都会标红,找不到类。
2.3 把 web 目录标记为 Web 资源目录
如果说上面只是开胃菜,这一步才是让项目“Web 化”的关键:
- 右键点击
web目录(也可能是WebContent、webapp等名字) - 选择
Add Framework Support...(如果没有的话,可以先右键检查) - 在弹出的对话框里选择Java EE -> Web Application
如果你用的是较新版的 IDEA,也可以直接右键web目录,选择Mark Directory as -> Web Resources Directory,然后指定 Web Resource Directory 的路径为 web 根目录。设置完成之后,web目录图标上会显示一个中间带小圆点的地球图标,这才是 IDEA 认可用它作为 Web 部署根目录的标志。
注意:如果项目里没有 web.xml(比如 Servlet 3.0+ 以后用注解),IDEA 的 Add Framework Support 可能会自动生成一个空的 web.xml。没关系,你可以加上,也可以不加,但加了往往更保险,后面配置 Artifact 时也会用到这个目录结构。
3. 依赖处理:没有 Maven,那就手动把 jar“请”进来
Maven 项目的依赖管理很方便,pom.xml 里面加几行依赖,编译器就自动帮你下载 jar。但非 Maven 项目没有这个机制,所有的依赖都只存在于WEB-INF/lib里。IDEA 不会自动把这些 jar 加到编译路径中,你需要手动完成这一步。
3.1 批量将 lib 目录添加为库
右键WEB-INF/lib目录,选择Add as Library...。弹出对话框里有一个 Level,这地方我一般选择Project Library,这样项目里所有模块都能引用到。
添加之后,你在左侧的 Project 窗口展开 lib 目录,会发现每个 jar 前面都多了一个小黑色箭头,表示它已经被识别为项目依赖的一部分。这一步做完,大部分import xxx的红线都会消失,但要注意:servlet-api.jar这类由 Tomcat 容器提供的 jar,很多时候并不在 lib 里,所以关于 Servlet 的类找不到是正常的,下一步解决。
3.2 给项目加上 Tomcat 的类库
很多传统 Web 项目里没有servlet-api.jar,因为部署到 Tomcat 时,这个 jar 是容器自己提供的。但是在编译阶段,IDEA 不知道你后面会用哪个 Tomcat,所以编译时HttpServletRequest这一类的符号会全部标红。
解决办法有两个:
- 在
File -> Project Structure -> Libraries里添加一个Java类型的库,然后指向你本地 Tomcat 的lib/servlet-api.jar(以及jsp-api.jar) - 或者更推荐的方式:等到配置完 Tomcat Server 后,
File -> Project Structure -> Modules -> 当前模块 -> Dependencies,点击+,选择Library,然后从 Tomcat 的依赖列表里勾选。
第二种方式的好处是它和具体的 Tomcat 版本绑定,后面切换 Tomcat 时类库也会跟着切换,比较符合实际部署环境。
3.3 留意 jar 包冲突和缺失
传统项目最常见的问题是 lib 里的 jar 非常“乱”,同一个类可能出现多个不同版本的 jar,或者某些 jar 是网上随便下的残缺版本。导入完成后,你可以抽时间编译一遍,如果发现某个类找不到,先不要慌,大概率不是你的代码错了,而是 lib 里缺依赖,需要上网下载对应 jar 补进 lib。这个过程没有 Maven 那么自动化,但熟练之后也就是几分钟的事。
实操心得:我一般会使用
Ctrl + Shift + Alt + S打开 Project Structure,然后在Libraries里统一管理所有 jar。如果一个 lib 超过 50 个 jar,而且项目用了 Spring,那我会建议你检查一下是不是有多个版本的 spring-core、spring-context 混在一起,这种情况通常在运行时会出现一些很诡异的 NoSuchMethodError,排查起来非常费劲。
4. 配置编译输出与 Artifacts:让 IDEA 知道怎么“打包”
到了这一步,项目源码能识别了,依赖也能找到了,但 IDEA 依然不知道如何把这个 Web 项目“打包”成一个可部署的目录结构。这一步的核心就是 Artifact,中文叫“工件”,你可以简单理解为:它定义了最终要产出什么样的部署物,是打成 war 包,还是生成一个部署目录。
4.1 先讲清楚 Exploded 和 Archive 的区别
在添加 Artifact 时,IDEA 会给你两个选项:Web Application: Exploded和Web Application: Archive。
Exploded:目录形式,相当于解压后的项目,Tomcat 直接指向这个开发目录,改完代码,IDEA 会把 class 文件同步编译进去,浏览器刷新即可生效,开发调试时最方便。Archive:就是打成 war 包,每次改代码都要重新打包,适合最终交付部署,不适合开发调试。
我强烈建议你开发阶段选择 Exploded,这也是 IDEA 比较推荐的一种方式。你自己开发的时候用 Exploded,最终要发包了再在命令行或 IDEA 里 Build Artifact。
4.2 新建 Artifact 并调整输出布局
操作路径:File -> Project Structure -> Artifacts -> + -> Web Application -> Exploded -> From Module,然后选择你的项目模块。
生成之后,你会看到 Output Layout 面板,这里面的内容非常关键。正常的结构应该是:
- 根目录下有一个
WEB-INF/classes,IDEA 会把编译后的 class 文件放进去 - 有一个
WEB-INF/lib,里面应该是你刚刚 Add as Library 的所有 jar 包 - 如果有
web.xml,它应该出现在WEB-INF目录下
如果这些内容缺失,可以右键 Output Layout 里的目录树,选择Create Directory来补建;如果 lib 里没有 jar 包,就点击+,选择Library Files,把你的项目库加进去。这一步非常重要,稍有不慎,部署启动时就会报ClassNotFoundException或者 404。
4.3 编译输出位置与模块依赖顺序的坑
非 Maven 项目最容易踩的坑就是编译输出位置。在File -> Project Structure -> Project里面的Compiler output设置如果不对,IDEA 把编译后的 class 文件输出了别的地方,那么你的 Artifact 的WEB-INF/classes里可能就是空的,启动项目时所有类都找不到。
我通常的做法是:在Project Structure -> Modules -> 当前模块 -> Paths里面,选择Use module compile output path,然后把输出目录设置为项目目录下的out或者target/classes。只要编译输出位置和 Artifact 里指定的目录一致,运行才不会有问题。如果看到 Tomcat 启动后报了NoClassDefFoundError,先别急着查代码,大概率是这一步没对上。
提示:老项目可能同时存在
src目录下多个资源文件,比如.xml、.properties,这些要确保在编译时被复制到输出目录。Project Structure -> Modules -> Sources标签下,你可以把这些资源文件标记为Resources,IDEA 在编译时会自动复制到 classes 目录,否则运行时读不到配置文件会一直报空指针。
5. 配置 Tomcat 并启动:把项目跑到浏览器里
依赖、Artifact 都准备好了,剩下的就是配置本地 Tomcat 然后启动。这一步属于“临门一脚”,很多人卡在这一步,其实不知道 Tomcat 配置的本质:它需要知道两件事——去哪儿拿项目(Artifact),以及访问时用哪个 URL 前缀(Application context)。
5.1 添加本地 Tomcat Server
运行配置入口在右上角的下拉框,点击Edit Configurations,然后左上角+,选择Tomcat Server -> Local。
如果你之前没配置过 Tomcat,IDEA 会要求你指定 Tomcat 的安装目录,也就是你解压 Tomcat 后包含bin、conf、lib的根目录。配置好之后,IDEA 会自动帮你关联 Tomcat 的类库,之前第 3.2 节里说的servlet-api找不到的问题,在这一步也会一并解决。
有两个参数需要注意:
VM options:一般默认留空即可,必要时可以设置-Xmx512m -Xms256mJRE:选择 JDK 8 或 11,取决于你的项目,别选错版本,选错了启动报UnsupportedClassVersionError就是这里的问题
Tomcat 端口配置在HTTP port一栏,默认 8080,如果你的机器上 8080 被占了,改成 8081、8082 都行,但要记清楚,后面访问 URL 用的就是它。
5.2 Deployment 与 Application context 设置
切到Deployment标签页,点+,选Artifact,然后选择你刚刚创建的 Exploded 工件。这里会有一个Application context字段,默认是/项目名或者/,它代表你访问这个项目时 URL 里的上下文路径。
你访问项目的完整地址就是:http://localhost:8080/Application context/资源路径。
举个例子,如果 Application context 是/myweb,那么访问首页 Servlet 映射为/hello时,地址就是http://localhost:8080/myweb/hello。这里很容易踩坑——很多人部署完之后访问,Tomcat 正常启动了也不报错,但访问总是 404,十有八九是 Application context 和 URL 没对上。可以先用根路径/试一下,能跑通再改成自己习惯的上下文路径。
5.3 启动与热部署
配置完成后,点击右上角绿色三角形,IDEA 会帮你启动 Tomcat 并部署项目。正常启动后,在 IDEA 的 Run 窗口里能看到 Tomcat 的日志输出,最后会有一行Server startup in [xxxx] milliseconds,表示启动成功。
开发阶段我建议把On frame deactivation设置为Update classes and resources(在 Tomcat 运行配置的 Server 标签页),这样你切回 IDEA 或保存代码时,IDEA 会自动把修改过的 class 文件和资源同步到部署目录,实现热部署。改完 JSP 刷新页面直接生效,改完 Java 代码编译后也会自动更新,省去反复重启 Tomcat 的时间。
6. 跑不通别慌:常见报错与排查速查表
传统 Web 项目在 IDEA 里部署运行,从来没有“一次成功”的说法。我这里把几年下来碰到最多的几个问题整理成一个速查表,你可以先收藏,遇到问题直接按图索骥。
| 现象 | 可能原因 | 排查与解决办法 |
|---|---|---|
| 启动时大量红色报错,找不到 servlet-api 相关类 | Tomcat Library未关联 | 确认 Tomcat Server 配置无误,Project Structure -> Libraries 里能看到 Tomcat 的类库 |
| Tomcat 启动成功,但请求全部 404 | Artifact 没部署成功,或者 Application context 不对 | 检查 Deployment 标签页是否有你的 Artifact,用/根路径访问试试 |
启动时报ClassNotFoundException | 依赖 jar 没有打进 Artifact 的 WEB-INF/lib | Project Structure -> Artifacts -> 布局里添加所有 Library Files |
| 页面中文乱码 | 编码不一致 | 检查项目 File Encodings,统一 UTF-8;Tomcat 配置 VM options 加-Dfile.encoding=UTF-8 |
访问页面提示 500,控制台报NoClassDefFoundError | 编译输出位置和 Artifact 目录不一致 | 检查 Modules 的编译输出路径,确保 class 文件生成到了正确位置 |
| 端口被占用,Tomcat 启动后立即退出 | 8080 被其他程序占用 | 改 Tomcat HTTP port,或释放占用端口 |
编译时提示cannot find symbol,但是依赖明明有 | jar 冲突或者缺失 | 检查 lib 下是否有重复 jar,清理后再 Add as Library |
| 修改 Java 代码后重启也不生效 | 编译输出缓存 | Build -> Rebuild Project清空重新编译 |
如果你遇到的是上面表格之外的问题,我还想多提一个万能排查思路:先看控制台完整的异常堆栈,从最底下第一个Caused by开始读,而不是只看最上面那段。90% 的报错都能从这个思路里找到答案,很多看起来“莫名其妙”的问题,最后都是 lib 依赖、路径配置这种低级原因。
实操心得:我曾经处理过一个非常棘手的问题,项目在 Eclipse 里好好的,到了 IDEA 里就 404。查了半天,最后发现是 Artifact 里缺少
WEB-INF/classes这个目录,导致所有编译后的 class 文件没有被打进部署目录,Tomcat 启动时启动了,但所有 Servlet 全都不存在。这种问题光看 IDEA 的日志是看不出来的,要在启动日志里仔细看有没有Deployment failed或者Application context相关警告。
还有一个很容易被忽略的地方,就是 Tomcat 的conf/catalina.properties或conf/context.xml里如果有配置问题,也会导致部署失败,但这些都是环境级配置,非 Maven 项目几乎不会涉及到,一般不用动。
最后再说点掏心窝的话
这种非 Maven 的老式 Web 项目,说实话在现在这个年代已经属于“历史遗留物种”了,但就是这种项目,恰恰是很多业务系统的核心。你不可能为了图省事,非要把所有东西都强行改成 Maven 结构再跑,很多时候项目能稳定跑起来、能出页面能调接口,比什么都重要。
我在 IDEA 里折腾这种项目,少说也有几十个了。每次拿到一个新环境,我都会按同一个套路来:先看结构、再 Open、标记目录、添加依赖、配置 Artifact、配置 Tomcat、启动。这套流程一旦熟练,整个过程也就五分钟。反倒是每次图省事跳过某一步,后面往往会花更多时间去排查。
如果你拿到的是一个特别老的 Spring + SpringMVC 项目,配置方式可能会多一个 Spring 相关的 Facet,但核心逻辑和这里完全一样,无非是多告诉 IDEA 一句“这个项目的 Spring 配置文件在哪”。理解了原理,你就不会怕任何“非 Maven”项目了。