JavaWeb保姆级教程:从IDEA创建项目到Tomcat部署全流程

JavaWeb保姆级教程:从IDEA创建项目到Tomcat部署全流程
搞Java的尤其是做传统Web开发或者维护老系统的同学基本都绕不开JavaWeb和Tomcat这条线。很多学校的课程设计、企业内部的老项目、电商后台、报表系统跑的都是这套东西。我前阵子帮一个刚入行的朋友从零搭环境、建项目、连数据库、部署上线折腾了一圈下来发现网上的教程要么太老界面和流程跟IDEA 2024对不上要么只讲了其中一段从建项目到部署是割裂的照着做很容易卡在半路。这篇就把整个流程拆开揉碎了写一遍属于那种照着做就能跑通的保姆级教程覆盖项目创建、Tomcat配置、数据库连接、打包部署顺便把几个高频踩坑点也一并交代清楚。先说清楚这篇适合谁看零基础准备做JavaWeb课设的大学生、刚入职需要接手老项目的初级开发、以及想自己搭一套完整JavaWeb环境练手的自学党。如果你已经在用Spring Boot打天下这篇里的手工Servlet和JSP项目可能略显复古但Tomcat的部署原理和连接池的配置思路是通用的看看也不亏。1. 动手之前先搞明白这几个东西到底是干嘛的1.1 JavaWeb、Tomcat、数据库各司其职很多人一开始就被三个概念搅糊涂了JavaWeb是个什么东西Tomcat是个什么角色数据库又怎么和它扯上关系。其实用生活里的场景类比一下就清楚了。Tomcat可以理解成一个餐厅的店面它负责接待客人浏览器发来的HTTP请求然后把客人点的菜请求参数传给后厨你写的Servlet或者JSP代码去处理。后厨做完菜还要通过传菜窗口JDBC从仓库MySQL数据库里取食材数据最后把成品端到客人桌上生成HTML响应返回浏览器。所以JavaWeb不是一个具体的软件而是一套用Java语言开发Web应用的技术栈总称。Tomcat是这套技术栈里最常用的Web服务器它实现了JavaEE现在叫Jakarta EE中的Servlet和JSP规范负责把浏览器发来的HTTP请求转换成Java代码能处理的对象再把Java代码生成的结果转换成HTTP响应发回去。数据库则负责持久化存储业务数据Java代码通过JDBC这套标准接口来访问它不同的数据库厂商提供各自的驱动实现这样业务代码里就不需要关心底层数据库的具体差异。理解了这层关系你再看网上那一堆配置操作就不会觉得玄乎了。配置Tomcat本质上是让IDE知道怎么把编译好的项目塞给Tomcat去跑连接数据库本质上是让Java代码能通过JDBC驱动找到数据库、通过认证、执行SQL。理解了本质后面所有的操作都是“按规矩办事”而已。1.2 版本选型怎么避坑JDK、Tomcat、IDEA、MySQL版本选型是我最想强调的一部分因为新手踩的坑里有相当一部分不是操作问题而是版本不兼容的问题。先列一个我目前推荐的组合再解释为什么这么选。组件推荐版本说明JDK1.8 或 11JDK 8最稳定很多老项目还在用JDK 11对应Tomcat 9/10Tomcat9.0.x 或 10.1.x9是老牌稳定版10.1是Jakarta EE 10实现二者包名不同IDEA2024.1 及以上新版向导有变化但手动补Web支持的办法通用MySQL5.7 或 8.08.0默认认证插件是caching_sha2_password驱动版本要注意MySQL驱动5.1.49对应5.7 / 8.0.33对应8.0驱动版本和数据库版本要对上版本选型最大的坑在于Tomcat 10。Tomcat 10及更高版本把包名从javax.servlet换成了jakarta.servlet这意味着很多老教程里的import javax.servlet.http.HttpServlet在Tomcat 10下会直接报“程序包不存在”。如果你用的是Tomcat 10代码里必须写import jakarta.servlet.http.HttpServlet。这行改动虽然不大但网上一搜一大把的老代码全是javax开头的照抄就容易翻车。另外JDK版本和Tomcat版本也有对应关系。Tomcat 9.0要求JDK 8及以上Tomcat 10.1要求JDK 11及以上。如果你机器上装的是JDK 17那你最好选Tomcat 10.1因为Tomcat 9虽然也能在JDK 17下跑但有些反射相关的警告会刷屏看着心烦。新手我建议直接JDK 8 Tomcat 9 MySQL 5.7因为网上能找到的绝大多数JavaWeb教程都是这个组合查资料、抄代码都不会有兼容性问题。1.3 一个最小的请求是怎么跑通的在动手操作之前再花点时间理解请求的流转过程这比直接点鼠标更重要。当你在浏览器输入http://localhost:8080/hello并回车之后背后发生的事情是浏览器根据域名和端口向本机的8080端口发起一个HTTP GET请求Tomcat监听在8080端口接收到请求后根据URL中的上下文路径也就是项目名匹配到对应的Web应用Tomcat把请求信息封装成HttpServletRequest对象同时创建HttpServletResponse对象然后调用web.xml或注解中映射好的Servlet的doGet方法Servlet从HttpServletRequest里取出参数调用业务代码通过JDBC访问数据库取数Servlet把结果写入HttpServletResponseTomcat把响应对象转换成HTTP响应报文返回给浏览器浏览器解析HTML渲染页面。这个链路理解清楚之后排查问题就有一个清晰的思路浏览器请求没到Tomcat那是启动或端口的问题请求到了Tomcat但页面404那是上下文路径或Servlet映射的问题页面出来了但数据不对那是SQL或数据库连接的问题。把问题按链路节点去定位远比漫无目的地乱试高效。2. 从零创建JavaWeb项目IDEA 2024实操全记录2.1 新建项目别再选错项目类型IDEA 2024版的新建项目向导和之前的版本差别挺大很多教程里的截图已经对不上了。我按下拉菜单路径一步步说清楚。打开IDEA点击New Project这时候会看到左侧的选项列表。关键点来了这里不要选Spring Boot也不要选Jakarta EE直接选Java或者Generators里的Maven Archetype。如果你只想用最简单的纯Java项目结构手工补全Web能力选Java即可如果你想一步到位用Maven管理依赖选Maven Archetype然后在Archetype列表里找到org.apache.maven.archetypes:maven-archetype-webapp。这个Archetype会直接生成标准的Web项目目录结构包含src/main/webapp/WEB-INF/web.xml省去很多手工操作。我自己带新人的时候更推荐先用Maven Archetype的方式创建因为后面引入MySQL驱动、Druid连接池都要靠Maven管理依赖手工下载jar包再导入版本冲突和遗漏问题会让你怀疑人生。选好Archetype之后填好GroupId和ArtifactId。GroupId一般写公司域名倒序比如com.exampleArtifactId写项目名比如javaweb-demo。Java版本选择要和本机JDK版本一致我这边选的JDK 1.8。2.2 手动补全JavaWeb骨架如果你选的是Java类型的新建项目创建出来的只是一个普通Java工程没有src/main/webapp目录也没有WEB-INF/web.xml。这时候需要手动补全流程是按CtrlAltShiftS打开项目结构Project Structure左侧选择Modules选中当前模块点击上方的号选择Web弹窗里会让你指定Web资源目录把路径改成src/main/webapp确认后IDEA会为模块增加Web能力并在webapp目录下生成WEB-INF/web.xml如果你的版本没有自动生成就自己手动建这个目录和文件还要把src/main/java目录标记为Sources Rootsrc/main/resources标记为Resources Root这样IDEA才能正确编译和打包。这个手动补Web支持的过程是很多IDE版本迭代后依然通用的“保底方案”。不管向导怎么变项目结构的要求是不变的因此学会这一套比背菜单路径更有价值。对应的web.xml如果是Servlet 4.0规范Tomcat 9对应最精简的版本长这样?xml version1.0 encodingUTF-8? web-app xmlnshttp://xmlns.jcp.org/xml/ns/javaee xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd version4.0 display-namejavaweb-demo/display-name welcome-file-list welcome-fileindex.jsp/welcome-file welcome-fileindex.html/welcome-file /welcome-file-list /web-app如果你用的是Tomcat 10web.xml的命名空间要换成https://jakarta.ee/xml/ns/jakartaee不能照抄旧的。这个细节非常容易踩坑很多新手的Tomcat 10项目跑不起来就是web.xml头写错了。2.3 配置Tomcat把项目跑起来项目骨架就位后先把一个最简单的页面跑起来验证环境。在webapp目录下新建一个index.jsp内容随便写点东西比如% page contentTypetext/html;charsetUTF-8 languagejava % html head titleJavaWeb Demo/title /head body h2Hello JavaWeb!/h2 /body /html然后配置Tomcat运行环境。点击IDEA右上角的Add Configuration...在弹窗左上角点往下翻找到Tomcat Server选择Local。在Application server那里点Configure...选择你本地Tomcat的解压目录。注意这里的Tomcat目录是解压后的根目录比如D:\apache-tomcat-9.0.89不要选到bin或conf子目录。切到Deployment选项卡点选择Artifact然后选中javaweb-demo:war exploded。这个war exploded是“展开的war包”也就是目录形式的部署开发调试时用这种模式改代码可以热更新不用每次都重新打包。如果这里找不到Artifact说明前面Web支持没有配置好回到项目结构里检查Modules有没有Web Facet。Application context这一项默认是/项目名也可以改成/表示部署在根路径。我建议开发阶段就保留/项目名因为以后部署到服务器时这个上下文路径决定了URL怎么访问尽早养成带路径访问的习惯。配置完成后点击右上角的运行按钮IDEA会启动Tomcat并自动部署项目。启动日志出现INFO: Server startup in [xxx] milliseconds说明启动成功。打开浏览器访问http://localhost:8080/javaweb-demo/看到Hello JavaWeb!就说明整个开发环境彻底跑通了。2.4 顺带说说用Cursor创建Java项目最近不少人问用Cursor能不能创建Java项目。Cursor本质上是VS Code套壳加AI助手如果你非要用它写Java流程是先确认装了Extension Pack for Java扩展包然后在终端里执行mvn archetype:generate用Maven命令行生成项目骨架。或者更简单一点用IDEA创建好项目后再用Cursor打开项目目录让它辅助写代码、改配置。我的建议是Java开发还是老老实实用IDEACursor的AI能力可以通过IDEA自带的AI插件或者后端接入大模型的方案来弥补。编程工具选型稳定性和生态优先不要为了赶时髦把整个开发流程搞复杂。3. 连接数据库从JDBC到连接池3.1 认识JDBCJava和数据库之间的翻译官JDBCJava Database Connectivity是Java提供的一套数据库访问标准接口。它定义了一套统一的方法比如Connection连接、Statement执行SQL、ResultSet查询结果至于这套接口怎么实现由各家数据库厂商的驱动jar包来负责。你可以把JDBC理解成USB接口标准数据库是打印机驱动是打印机驱动程序。只要支持USB标准不管什么牌子的打印机都能插上就用只要数据库提供了JDBC驱动Java代码就能用同一套API去操作它。所以核心结论就是连接不同的数据库MySQL、Oracle、PostgreSQLJava业务代码的写法几乎一样区别仅仅在于引入的驱动jar包和连接URL不同。这也是为什么很多人会说“会了JDBC换数据库只是换驱动和URL的事”话虽夸张但基本属实。3.2 引入MySQL驱动和Druid连接池既然用了Maven引入依赖就是编辑pom.xml的事。在dependencies标签里加上MySQL驱动和数据库连接池的依赖dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency dependency groupIdcom.alibaba/groupId artifactIddruid/artifactId version1.2.20/version /dependency注意如果连接的是MySQL 5.7驱动版本建议用5.1.49不要直接用8.0.33因为8.0驱动在连接5.7时偶发时区相关的警告而且默认认证插件行为也不一样。如果连接的是MySQL 8.0驱动版本必须用8.x否则会报Public Key Retrieval is not allowed这种错误。阿里巴巴的Druid连接池是我在高并发和日常小项目中都用得比较顺手的选择。它不只是一个连接池还自带监控、SQL防注入、慢查询日志等功能。对于课程设计和中小型项目来说用Druid比直接手写DriverManager获取连接要规范得多因为频繁地创建和销毁Connection耗时且浪费资源连接池复用的思路能让程序在并发请求下的表现稳定很多。3.3 数据源配置与实战连接池的核心原理不复杂启动时预先创建一批数据库连接放在池子里请求来了就从池子里借一个连接用用完了还回去而不是关闭。这样省去了反复建立TCP连接、认证、断开的过程对性能的提升非常明显。在src/main/resources目录下新建druid.properties配置文件driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/javaweb_demo?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue usernameroot password123456 initialSize5 maxActive20 maxWait3000然后写一个工具类封装数据源获取逻辑package com.example.util; import com.alibaba.druid.pool.DruidDataSourceFactory; import javax.sql.DataSource; import java.io.InputStream; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; public class JdbcUtil { private static DataSource dataSource; static { try (InputStream in JdbcUtil.class.getClassLoader().getResourceAsStream(druid.properties)) { Properties props new Properties(); props.load(in); dataSource DruidDataSourceFactory.createDataSource(props); } catch (Exception e) { throw new ExceptionInInitializerError(初始化数据源失败: e.getMessage()); } } public static Connection getConnection() throws SQLException { return dataSource.getConnection(); } }写一个Servlet测试数据库连接比如UserServlet.javapackage com.example.servlet; import com.example.util.JdbcUtil; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; WebServlet(/user/list) public class UserServlet extends HttpServlet { Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType(text/html;charsetUTF-8); PrintWriter out resp.getWriter(); String sql SELECT id, name, age FROM t_user ORDER BY id; try (Connection conn JdbcUtil.getConnection(); PreparedStatement ps conn.prepareStatement(sql); ResultSet rs ps.executeQuery()) { out.println(table border1); out.println(trthID/thth姓名/thth年龄/th/tr); while (rs.next()) { out.println(tr); out.println(td rs.getInt(id) /td); out.println(td rs.getString(name) /td); out.println(td rs.getInt(age) /td); out.println(/tr); } out.println(/table); } catch (Exception e) { e.printStackTrace(); out.println(h3数据库查询出错: e.getMessage() /h3); } } }注意这里用的是WebServlet注解来注册Servlet省去了在web.xml里逐个配置的繁琐。这是Servlet 3.0之后推荐的用法。3.4 连接数据库的六个常见坑坑一驱动类找不到。报错ClassNotFoundException: com.mysql.jdbc.Driver多半是依赖没引入或者没刷新。检查pom.xml里的依赖坐标然后IDEA右侧Maven面板点刷新。另外MySQL 8.0的驱动类名是com.mysql.cj.jdbc.Driver不是老的com.mysql.jdbc.Driver这个很容易写错。坑二时区错误。报错The server time zone value й׼ʱ is unrecognized是因为连接URL里没有指定时区。在url参数后面加上serverTimezoneAsia/Shanghai即可。坑三SSL连接警告或错误。连接URL里加上useSSLfalse开发环境没必要用SSL省掉一堆告警。坑四Public Key Retrieval is not allowed。这个问题在MySQL 8.0 8.x驱动下很常见原因是8.0默认认证插件是caching_sha2_password需要先拿到服务器的公钥才能传输密码。解决方式是在连接URL加上allowPublicKeyRetrievaltrue或者把MySQL用户的认证插件改回mysql_native_password。坑五中文乱码。这个涉及三处连接URL里的characterEncodingutf8、页面响应的ContentType、数据库表的字符集。口诀是“URL、页面、库表三处统一UTF-8”。坑六连接池用Druid的DruidDataSourceFactory.createDataSource(props)时配置文件里字段名写错导致解析异常。比如把maxActive拼成maxActive大小写不对或者漏了driverClassName。配置文件字段名严格区分大小写而且必须是Druid能识别的属性名。4. 项目打包与部署从开发机到服务器4.1 两种部署方式怎么选部署到Linux服务器是JavaWeb项目的最终归宿。部署方式上常见的是两种一种是直接把打过包的项目放到Tomcat的webapps目录下启动Tomcat自动解压部署另一种是配置Tomcat的conf/server.xml在Host节点下加Context指定项目路径映射到外部目录。第一种方式最简单把war包或整个项目目录扔进webapps重启Tomcat就完事适合课程设计、小型项目。第二种方式可以把项目放在Tomcat之外好处是升级项目时不用动Tomcat安装目录重装Tomcat也不会丢项目文件适合稍微正规一点的环境。我个人的习惯是小项目用第一种省心如果服务器上同时跑多个项目或者有独立的发布目录用第二种更灵活。4.2 用IDEA打war包2024版本细节在IDEA里打war包先确保项目结构里配置了Web Artifact。打开Project Structure点Artifacts如果列表里没有点选择Web Application: Archive名字默认是项目名:war。确认Output directory是你要存放war包的路径。然后依次点击菜单Build - Build Artifacts - 项目名:war - Build。构建完成后到输出目录就能看到javaweb-demo.war。有一点要提醒IDEA 2024把Build Artifacts的入口藏得稍微深了一点一些魔改版本的IDEA可能在菜单里找不到这个选项。你可以在项目结构里直接把Artifacts的Output directory改到一个好找的目录或者用Maven的方式执行package命令来打war包。如果你用的是Maven Archetype创建的项目直接在IDEA右侧Maven面板双击package然后在target目录下找war包更直接。Maven打包war前记得在pom.xml里设置打包方式packagingwar/packaging4.3 Linux服务器部署Tomcat安装、上传、启动服务器这块我以CentOS 7环境为例其他发行版命令大同小异。基本流程是上传JDK和Tomcat的tar包到服务器解压到指定目录比如/usr/local/jdk8和/usr/local/tomcat配置环境变量JAVA_HOME、CATALINA_HOME并加入PATH把war包上传到/usr/local/tomcat/webapps目录启动Tomcat执行/usr/local/tomcat/bin/startup.sh确认启动成功访问http://服务器IP:8080/javaweb-demo/。启动后需要检查日志看/usr/local/tomcat/logs/catalina.out的输出。最常犯的错误是没看日志就急着访问结果报404或者连接拒绝然后又怀疑Tomcat装坏了。其实Tomcat启动是否成功日志里写得很清楚养成先看日志再判断的习惯排查问题会快很多。4.4 Linux部署的三个坑内存、端口、日志第一个坑是内存溢出。默认JVM堆内存太小项目稍微复杂一点就会出现OutOfMemoryError。解决办法是在Tomcat的bin目录下创建setenv.sh写入export JAVA_HOME/usr/local/jdk8 export JAVA_OPTS-Xms512m -Xmx1024m -XX:MaxMetaspaceSize256m-Xms是初始堆大小-Xmx是最大堆大小。-Xms和-Xmx设置成一样比较好避免运行中频繁扩容。MaxMetaspaceSize限制元空间大小防止类加载过多导致内存泄漏。第二个坑是端口不通。Tomcat启动成功但浏览器访问不到先检查服务器防火墙firewall-cmd --permanent --add-port8080/tcp firewall-cmd --reload如果用的是云服务器还要去安全组规则里放行8080端口。这个步骤经常被忽略很多人在本地跑得好好的一上云就访问不了99%是安全组没放端口。第三个坑是日志文件疯狂增长。Tomcat默认的日志机制会把所有输出写到catalina.out时间长了文件会变得巨大磁盘空间告急。可以配置日志轮转或者直接清空。开发环境的话我建议在setenv.sh里调整一下日志级别减少无用的DEBUG信息输出生产环境则要配合logrotate做自动切割。5. 常见问题排查实录5.1 Tomcat启动慢、卡住不动怎么办出现INFO: Deploying web application directory ...之后长时间没反应大概率是在初始化日志或安全相关组件时卡住。一个非常经典的场景是用JDK 8或JDK 9启动Tomcat在Linux上会卡在SecureRandom这个随机数生成器上因为它会阻塞等待系统熵池补充而云主机或虚拟机环境熵池通常很小。解决办法是在setenv.sh里加一行JVM参数export JAVA_OPTS$JAVA_OPTS -Djava.security.egdfile:/dev/./urandom这个参数告诉JVM使用/dev/urandom来代替/dev/random不走阻塞等待启动速度会明显改善。5.2 乱码问题全家桶乱码是JavaWeb新手遇到的最多的一类问题我这里按发生位置拆开来逐个说。控制台乱码一般是IDEA或Tomcat的日志编码问题。IDEA中打开Help - Edit Custom VM Options加上-Dfile.encodingUTF-8然后重启IDEA。Tomcat方面在bin/catalina.batWindows或setenv.shLinux里加上export JAVA_OPTS$JAVA_OPTS -Dfile.encodingUTF-8 -Dsun.jnu.encodingUTF-8页面乱码检查三点web.xml或JSP页面声明的字符集要UTF-8Servlet里resp.setContentType(text/html;charsetUTF-8)如果用了request.getParameter还要加上req.setCharacterEncoding(UTF-8)在读取参数之前设置。数据库乱码检查连接URL里的characterEncodingutf8同时确认数据库表字符集是utf8mb4。utf8mb4比utf8能存的字符更全推荐直接用utf8mb4。还有一个容易被忽略的点HTML页面本身的文件编码。IDEA右下角可以看到当前文件的编码如果文件本身是GBK编码但页面声明UTF-8中文必乱。统一把所有源码文件设置成UTF-8编码。5.3 IDEA启动后Tomcat生成一堆log文件这是一个让很多人都头疼的问题。IDEA配置Tomcat后每次运行项目都会在Tomcat的logs目录下追加日志本地调试频繁日志文件非常多。更烦的是tomcat9-stderr.log、tomcat9-stdout.log这些文件会不断变大。我的处理方式是在本地调试时把Tomcat的日志级别调低并且关闭不必要的日志输出。具体操作是修改conf/logging.properties把org.apache.jasper.level设为WARNING同时可以把localhost.log和manager.log去掉或降级。如果只是想让IDEA运行时不刷那么多日志可以在Run Configuration的VM options里加上-Djava.util.logging.config.fileD:/apache-tomcat-9.0.89/conf/logging.properties让Tomcat使用指定配置文件。真正常跑项目的服务器则建议用系统日志管理工具接管日志轮转甚至直接把标准输出重定向到/dev/null再配合专门的日志框架从源头控制文件增长。5.4 Linux配置setenv.sh后用systemctl启动失败这个坑我那年踩得印象特别深。服务器上配置了setenv.sh里面设置了JAVA_OPTS和JAVA_HOME然后写了一个systemd服务单元来管理Tomcat结果一执行systemctl start tomcat就失败但直接执行startup.sh却没问题。排查过程是这样的先看journalctl -u tomcat的日志发现报错是找不到JAVA_HOME或者环境变量没生效。原因在于systemd启动时不会加载/etc/profile里的环境变量而startup.sh在交互式shell中能读到的环境变量在systemd环境下是不存在的。另外如果在setenv.sh里用export设置的变量在直接执行startup.sh时会被继承但在systemd里如果脚本的执行目录或执行用户不对也可能读不到。解决办法有两个。一是在tomcat.service文件里显式指定环境变量[Service] EnvironmentJAVA_HOME/usr/local/jdk8 EnvironmentCATALINA_HOME/usr/local/tomcat ExecStart/usr/local/tomcat/bin/startup.sh二是用systemctl edit tomcat添加覆盖配置在[Service]段加上Environment。其实更标准的做法是用catalina.sh run作为ExecStart让Tomcat在前台运行由systemd托管进程生命周期而不是用startup.sh这种后台启动方式。这两个方式之间的区别对理解Linux服务管理非常有帮助。5.5 nginx反代Tomcat访问不到了怎么办很多项目前面会挡一层Nginx做反向代理静态资源由Nginx直接返回动态请求转发给Tomcat。Nginx配置的核心是location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }如果配好后访问Nginx的80端口出现404第一反应不是怀疑Nginx配置而是看上下文路径。假如你的项目部署在Tomcat的/javaweb-demo上下文中而Nginx的location /直接proxy_pass到http://127.0.0.1:8080那用户访问Nginx根路径时请求转发到Tomcat是/路径Tomcat返回404。解决方案是两种一是把项目的Application context改成/让项目部署在Tomcat根路径二是把Nginx的proxy_pass写成http://127.0.0.1:8080/javaweb-demo/或者给location配上proxy_pass http://127.0.0.1:8080/xxx/。还要注意如果location /后面proxy_pass的URL以路径结尾Nginx会将匹配的URL替换为该路径不写结尾斜杠则是原样拼接这个细节不改的话静态资源路径全都会错。另外如果只配置了一台TomcatNginx动静分离的意义主要在静态资源缓存和访问控制上如果配了多台Tomcat还要考虑upstream负载均衡和session共享问题。这属于进阶话题后面有机会再单独展开。5.6 端口被占用与安全组启动Tomcat时报Port 8080 required by Tomcat v9.0 Server at localhost is already in use十有八九是有其他进程占用了8080端口。Linux上排查方式netstat -tlnp | grep 8080找到占用端口的进程号再kill -9干掉它。Windows上可以用netstat -ano | findstr 8080查到PID再到任务管理器结束进程。改端口也可以。修改Tomcat的conf/server.xml里的Connector port8080 .../为其他端口比如8081。改完端口后要记得防火墙安全组都同步放行否则又是“怎么访问不了”的老问题。我自己平时本地调试习惯用8080到服务器上会把端口改成自定义端口然后再用Nginx把80转发过来既统一了对外访问入口又减少了端口暴露面积。写完这些想起第一次教实习生配环境时的场景一个Tomcat版本选错导致所有Servlet都爆红他盯着屏幕看了半小时没发现是javax和jakarta的差别。后来我把这段经历讲给每个新人听他们都觉得这个坑“早该知道”。实际上技术的每个坑都是这样踩过一遍就长记性了。希望这篇文章能让你少踩几个哪怕只踩一遍就能跑通我这份保姆级的心意就算到位了。

最新新闻

日新闻

周新闻

月新闻