
第一次看到《网络程序设计》这门课的目录时我愣了一下第一章不聊网络也不写代码先把Web、JSP、Tomcat三个词摆在那里。这三个词拆开都认识合在一起却让很多人原地发懵。工作多年后再回头看这个安排一点都不奇怪Java方向的网络程序设计本质上就是用Java做Web开发而Web是我们要做的事JSP是当年最常用的Java服务器页面技术Tomcat则是让JSP跑起来的引擎。这三样东西不搞清楚后面所有实验、作业和考试题都会变成无头苍蝇。我会用最直白的方式把Web、JSP、Tomcat到底是什么、三者怎么配合、如何从零把一个JSP页面跑起来以及常见报错怎么排查一次性讲透。适合零基础入门、被课程作业卡住、以及想弄明白点下运行后到底发生了什么的人。1. 从打开网页这件事拆解Web1.1 你在浏览器里看到的一切只是Web的冰山一角打开浏览器输入网址、回车、页面出现这个过程很多人每天重复几十次但问到Web到底是什么能答清楚的人并不多。WebWorld Wide Web是基于HTTP协议的一整套资源网络核心是URL定位资源 浏览器发起请求 服务器返回内容。它不是互联网本身。互联网是底层网络Web只是跑在互联网上最著名的应用之一就像手机和运营商网络的关系。很多初学者把Web和前端划等号认为Web就是HTML、CSS、JavaScript。其实那只是浏览器拿到手之后的渲染层。真正的Web系统通常由三部分组成浏览器客户端、Web服务器、后端业务程序。浏览器负责把用户操作翻译成HTTP请求Web服务器负责接收请求并找到对应的资源后端程序才是一顿饭真正的大厨——读写数据库、处理登录、执行计算。JSP和Tomcat都住在服务器后端程序这一侧这也是《网络程序设计》课程和你想象中写网页不太一样的地方你写的东西不是被浏览器直接解释的而是被服务器先加工过的。从课程学习的角度把这三层分清比记住任何API都重要。因为后续你遇到的每一个404、每一个页面没有显示的Bug本质上都是在某一层断了。而这一章说的Web指的就是这套客户端-服务器对话机制。1.2 静态页面和动态页面JSP为什么被发明出来如果Web只是把服务器上的HTML文件原样发给浏览器那我们完全不需要JSP。一个叫Apache的静态服务器就能干这件事浏览器请求a.html服务器找到a.html把它放到HTTP响应里返回结束。这种页面叫静态页面内容固定不会因人因时变化。但真实的网站不是这样的。你打开购物网站首页推荐每个人都不一样你登录之后网页顶部会显示你的用户名你查快递时页面会根据快递单号显示物流状态。这些内容不可能为每个用户提前写一个静态HTML文件必须由程序在收到请求的瞬间临时把数据拼装成HTML返回。这种页面叫动态页面。JSP就是为了解决动态生成HTML这个问题而生的Java技术。它长得很像HTML但里面可以嵌Java代码Java代码在服务器端运行运行完之后把结果放回HTML里的对应位置再把完整的HTML返回给浏览器。类比静态HTML像印刷好的宣传单谁拿到的都一样JSP像带着模板的打印店你可以告诉老板你的名字、你想要的样式打印店现场把模板填好出一份专属传单。这也是为什么JSP一定要有个容器比如Tomcat来执行因为它不是普通文件它是一段需要运行的程序。1.3 HTTP请求-响应Web世界的基本对话方式无论静态还是动态浏览器和服务器之间的对话都要遵循同一个协议HTTP。一次HTTP交互可以拆成四段请求行、请求头、请求体以及响应行、响应头、响应体。请求行长这样GET /hello/index.jsp?nameTom HTTP/1.1。它告诉服务器三件事想执行什么操作GET/POST、想访问什么资源、用哪个HTTP版本。请求头里有浏览器类型、Cookie、期望的编码等附加信息。如果POST请求有表单数据就放在请求体里。服务器处理完返回时第一行是HTTP/1.1 200 OK200是状态码响应头里是服务器告诉浏览器的元信息比如Content-Type是text/html、charsetUTF-8响应体就是最终返回的HTML内容。你只需要记住Web开发中的所有技术包括JSP和Tomcat在内最终目标都是让服务器能够根据一个HTTP请求生成一个符合规范的HTTP响应。Tomcat管的是怎么把请求转交给Java程序再把结果封装回响应JSP管的是这个响应里的HTML正文怎么动态生成。分清楚这两个职责Tomcat和JSP之间的分工就非常明确了。2. JSP在HTML里写Java的老牌动态页面技术2.1 JSP其实就是加了Java代码的HTMLJSP的全称是JavaServer Pages翻译成中文就是Java服务器页面。我见过太多初学者把它当JavaScript因为后面都有一个JS。实际上它和JavaScript没有关系JavaScript在浏览器里跑JSP在服务器上跑两者唯一的共同点是名字里都有个J。一个最简单的JSP页面可以这样写% page contentTypetext/html;charsetUTF-8 languagejava % html head title我的第一个JSP/title /head body h1你好% request.getParameter(name) null ? 世界 : request.getParameter(name) %/h1 p服务器当前时间% new java.util.Date() %/p /body /html看到%和%之间的东西了吗那是Java代码。浏览器访问这个JSP时Tomcat会先执行这段Java代码把执行的结果插入到HTML模板的对应位置然后把整个HTML返回给浏览器。浏览器最终收到的页面里没有一行Java代码只有纯HTML这就是服务器端渲染。换句话说JSP页面的源代码只有服务器看得到用户永远看不到你写的Java逻辑这也顺便带来一个好处你不可能通过查看网页源代码来偷走服务端程序逻辑。这一点和纯前端页面的理念完全不同值得记一下。这里有个非常关键的区分如果在JSP里写script那段脚本是在浏览器执行的JavaScript如果写%那是在服务器执行完再输出结果。很多初学者把这两个混在一起明明是Java逻辑却想在浏览器端跑结果总是拿不到值。记住一句话凡是%开头的都正在服务器上运行浏览器看不见。2.2 JSP是怎么变成Servlet的翻译、编译、执行JSP不是直接被Tomcat运行的。Tomcat的底层是个Servlet容器它只认Servlet——一个Java类。所以JSP第一次被请求时Tomcat会先把JSP文件翻译成一个Java源文件这个源文件是Servlet的子类类名差不多是index_jsp里面有一个核心方法_jspService你写在JSP模板里的普通HTML会变成out.write(...)的输出语句你写在% %里的Java代码会被原样搬进方法体。接着Tomcat调用Java编译器把这个源文件编译成class再实例化、调用方法。这个过程完成后JSP就不再以页面的形式存在了它已经变成了一个Java程序。Tomcat把整个流程封装好对开发者来说几乎是透明的。第一次访问会稍微慢一点因为要翻译和编译第二次之后直接复用已经编译好的class速度就正常了。如果源码JSP文件被修改了Tomcat会通过时间戳发现变化自动再翻译、编译一次。你可以在Tomcat的work/Catalina/localhost/你的项目名/org/apache/jsp/目录下找到这些翻译出来的Java文件和class文件。我建议每个学JSP的人都去翻一次当你亲眼看到自己写的HTML模板被变成了out.write(html)这样的Java语句时JSP的本质就彻底理解了。这也是为什么说JSP就是Servlet的一种写法——本质上你是在用HTML页面的形式编写一个Servlet只是把繁琐的out.println换成了自然书写。2.3 JSP的三种常用角括号语法指令、脚本和表达式JSP语法看起来像HTML里长出了奇怪的角括号其实就三类完全不用怕。第一类是指令格式是% ... %。最常用的是page指令用来设置页面属性比如字符编码、是否开启Session、导入Java包。上面例子里的% page contentTypetext/html;charsetUTF-8 languagejava %就是一个page指令它告诉Tomcat这个页面输出的内容类型是HTML编码用UTF-8语言是Java。第二类是脚本段Scriptlet格式是% ... %。里面可以写任意Java代码比如定义变量、写if/for循环、调用方法。脚本段里的代码会被原样塞进_jspService方法所以你在里面定义的局部变量后面的HTML片段也能用。第三类是表达式格式是% ... %注意有一个等号。它的作用是把Java表达式的结果直接输出到页面当前位置等价于out.print(...)。上面例子里的% new java.util.Date() %就是在页面那个位置打印当前时间。很多教科书还会告诉你JSP里有声明、JSTL、EL表达式。入门阶段这三个语法够了。重点理解它们的执行顺序JSP翻译成Java后所有脚本段和表达式都按照书写顺序放在同一个方法里所以变量必须先定义后使用。逻辑不复杂但顺序很关键很多页面报500都是因为变量作用域和顺序问题。2.4 现在新项目都不主推JSP了为什么还要学它有人会问现在Java Web新项目早就不写JSP了Spring Boot项目默认甚至不用JSP做页面为什么《网络程序设计》第一课还在讲它我的看法是JSP是理解Java Web最不容易跳过的阶梯。Spring MVC也好Thymeleaf也好它们的核心思想和JSP完全一致服务端接收请求把数据塞进模板引擎最后生成HTML返回。你用Thymeleaf时写的那个模板本质上就是JSP的思想只是语法换成了更具约束的表达式。反过来如果你上来就学Spring Boot你会发现你配置了一堆注解和依赖却根本不知道请求是怎么进来的、页面是怎么出去的。而JSP把所有中间过程用最原始的方式暴露在你面前一个请求进来Tomcat把它交给ServletServlet执行Java代码把结果输出成HTML。这个过程一旦建立起来后面学任何框架都是顺水推舟。另一方面不是所有企业都有钱有闲把所有老项目重构掉。市面上仍有一大批运行了十年以上的老系统用JSP写页面这些系统维护需求长期存在。会JSP是真的能吃饭的手艺。当然我不是劝你抱着JSP啃一辈子而是说入门阶段它是最好的教学标本。3. Tomcat让JSP能跑起来的Web容器3.1 别把Tomcat和Apache/Nginx搞混提到Web服务器很多人会想到Apache、Nginx。Tomcat和它们很像但定位完全不同。Apache和Nginx是纯Web服务器擅长处理静态文件也常常被用作反向代理和负载均衡Tomcat是Servlet容器也叫Web容器核心职责是管理和运行Servlet与JSP。这里面的关键差异是Apache/Nginx不认识也不执行Java它拿到hello.jsp文件只会当普通文件返回浏览器打开后看到的是JSP源码Tomcat知道怎么把JSP翻译成Java并运行然后返回执行后的HTML。一个常见的生产架构是最外层架一台Nginx负责接收用户请求、处理静态资源图片、CSS、JS遇到JSP或后端API的请求时把它反向代理给内网某个Tomcat。Nginx在前台当接待Tomcat在后台当后厨各干各的。所以看到网上说Tomcat是网站服务器也不用反驳它确实是Web服务器的一种但准确说法是Java Web应用容器。Tomcat自己也能处理静态资源只是静态文件的传输性能和并发能力不如Nginx。学习阶段你只和一个Tomcat打交道完全够用不必管Nginx。但面试或工作中别人问起两者区别你得能像我刚才一样说出定位差异不要一听到Web服务器就以为只有Apache/Nginx。3.2 Tomcat的内部接待模式Connector与ContainerTomcat这个容器是怎么接待请求的它内部有两个核心组成部分Connector连接器和Container容器。Connector负责监听外部请求。Tomcat默认监听8080端口当你在浏览器输入http://localhost:8080/hello/index.jsp实际上是先连到8080这个端口TCP层握手成功HTTP请求数据被Connector读取并解析成内部请求对象。Container才是真正的业务处理中枢它内部又分四层Engine引擎、Host虚拟主机、Context上下文对应一个Web应用、Wrapper包装器对应一个Servlet。打个比方请求像是来到了酒店大堂。Connector是门童把客人领到前台Engine是酒店的运营中心决定这个客人去哪层Host是大堂经理根据域名比如localhost决定去哪栋楼Context是楼层管理员根据URL里的项目名找到具体哪个房间Wrapper是客房服务员负责Call某个Servlet起来工作。对于一个入门项目你不需要深入配置Host但一定要理解URL中的路径是怎么映射到Context和Wrapper的——后面你遇到访问项目却404十有八九就是Context路径根本没对上。3.3 安装和启动Tomcat新手最容易踩的坑Tomcat的安装本身不难难在版本和环境变量的配合。先用最简单的方式说去Apache Tomcat官网下载一个解压版zip或tar.gz不要下载安装版解压出来就能用。下载前确认你安装了JDKTomcat本质是Java程序没有Java环境它启动不了。一般Tomcat 9需要JDK 8Tomcat 10需要JDK 11下载前看一眼支持矩阵。解压后先设置JAVA_HOME环境变量指向你的JDK安装目录。Windows用户在环境变量里加一个JAVA_HOME再在Path里加上%JAVA_HOME%\bin。然后进入Tomcat的bin目录Windows双击startup.batLinux/Mac执行catalina.sh run。启动成功后在浏览器访问http://localhost:8080/能出现Tomcat默认首页新版是一只猫头鹰老版是一只黄色猫咪就代表成功了。新手最常见的坑有三个一是启动窗口一闪而过多半是JAVA_HOME没配或配错了在命令行手动执行startup.bat看报错二是8080端口被占用比如你电脑上装了其他服务三是Tomcat版本和IDEA版本不匹配导致IDEA里启动不了。端口占用的解决办法是用netstat -ano | findstr :8080Windows或lsof -i:8080Linux/Mac找到占用进程改Tomcat的conf/server.xml里Connector port8080改成其他端口比如8081再启动。生产环境可以在Linux上把Tomcat注册成systemd服务实现开机自启也可以调整JVM参数比如在setenv.sh里设置CATALINA_OPTS-Xms512m -Xmx1024m入门阶段先知道有这件事就行。我还见过有人把Tomcat装到C盘的Program Files下结果因为权限问题导致部署项目失败。这种坑真是防不胜防所以我建议安装在简单的路径下比如D:/tools/tomcat或/opt/tomcat路径里不要有中文和空格。3.4 部署JSP应用的两种方式目录和war包Tomcat里的部署概念很简单让Tomcat知道你有一个Web应用并给它一个访问路径。最原始的方式是把你的Web应用目录直接复制到Tomcat的webapps目录下。假设你有一个hello项目项目根目录下有一堆JSP文件和一个WEB-INF目录把这个hello文件夹拷进webapps启动Tomcat浏览器访问http://localhost:8080/hello/index.jspTomcat就会到webapps/hello目录下寻找并执行index.jsp。URL中那一层hello叫Context Path默认等于你放的目录名。这种目录结构式部署在开发阶段很方便改动之后服务器自动读取新文件。第二种方式是打包成war包。war包本质是一个Web应用的压缩包你可以用命令行jar -cvf hello.war .在项目目录下打成war或者用IDEA的Build Artifact功能。把hello.war扔进webapps目录Tomcat启动时会自动解开war并部署成目录。如果war已经解压过的目录还在Tomcat会把新的war重新解压覆盖生产环境热更新经常会用这个特性。对于入门者我强烈建议把项目做成完整的部署目录而不是只在IDE里运行。因为IDE会帮你隐藏很多细节比如Context Path怎么规定、WEB-INF里的web.xml有什么作用这些只有你手动部署过一次才会真正懂。手动把人家的JSP项目丢到webapps打开浏览器看到页面跑起来你才完成了一次真正意义上的Web部署。4. 从地址栏回车到页面显示一次完整旅行4.1 你输入的URL要经过哪些检查站把前面的概念串起来我们完整走一遍一次JSP请求。假设你访问的是http://localhost:8080/hello/index.jsp?nameTom浏览器拿到这个URL第一件事是拆解。协议是http主机是localhost端口是8080Context Path是hello资源路径是index.jsp后面跟一个参数nameTom。如果主机名不是IP浏览器先做DNS解析把域名转成IP再通过TCP三次握手和那个IP的8080端口建立连接。因为这里用的是localhost所以直接走本机回环地址127.0.0.1不需要真正跑到公网。连接建立后浏览器拼装一个HTTP请求报文大致长这样GET /hello/index.jsp?nameTom HTTP/1.1 Host: localhost:8080 User-Agent: Mozilla/5.0 ... Accept: text/html,application/xhtmlxml,... Cookie: JSESSIONIDxxxx注意Cookie行里的JSESSIONID可能还不存在如果这是一个新用户Tomcat会在响应头里通过Set-Cookie下发一个。Session机制是Web开发的重要基础你现在只需要知道JSP页面运行时Tomcat默认会帮你创建一个Session对象并通过Cookie维护它。以后你会看到登录状态、购物车数据都存在Session里而这些都始于这一次Set-Cookie。不过入门阶段不需要亲手操作Session只要知道Tomcat在背后做了这件事即可。4.2 Tomcat内部如何找到那个JSP并执行浏览器把请求报文发到8080端口Tomcat的Connector收到后把字节流解析成一个HttpServletRequest对象同时准备好一个HttpServletResponse对象然后把这两个对象交给Container处理。Container根据Host找到匹配的虚拟主机根据路径第一段hello找到对应的Context如果webapps下有hello这个应用目录再根据index.jsp找到对应的Wrapper。这里要理解Wrapper对应的Servlet可能还不存在。Tomcat发现index.jsp这个Wrapper是JSP类型就调用JSP引擎先检查work目录下有没有对应的index_jsp.class没有或者JSP文件比class新就执行翻译和编译步骤生成Servlet类然后实例化、调用_jspService方法。_jspService里的Java代码开始执行它读取你JSP里的Java表达式、处理业务逻辑、拼装HTML字符串最终把结果写进HttpServletResponse的输出流。当整段JSP代码执行完Tomcat把响应头和响应体封装成HTTP响应发回给浏览器。响应头里会包含Content-Type: text/html;charsetUTF-8响应体就是最终的HTML。浏览器拿到HTML后开始解析、加载CSS/JS、渲染页面你看到的是最终页面而不是index.jsp源码——这正是JSP和普通HTML文件的本质区别。整个过程看起来只在浏览器里按了一次回车但背后已经发生了这么多层工作也正是在这一层层的分工里Web、JSP和Tomcat各自的角色才真正串在了一起。4.3 这趟旅程中最容易翻车的三个环节这个流程看着不复杂但新手写代码时容易在三个环节翻车。第一个是404。URL中的Context Path写错、资源文件名写错、web.xml里映射配置出错都会导致Tomcat找不到资源。你访问http://localhost:8080/hello/index.jsp时如果回报404先确认webapps/hello目录下到底有没有index.jsp再确认Context Path是不是hello别想当然。第二个是500。JSP里Java代码执行异常比如调用了不存在的对象、类型转换失败、除零。500是服务器内部错误Tomcat会返回带有Stack Trace的页面。很多新手一看500就慌其实500比404好解决因为Tomcat直接把异常打印在页面上顺着at org.apache.jsp.index_jsp...那一行找就是代码出错的位置。第三个是中文乱码。最常见的情况是JSP文件本身是UTF-8Tomcat默认按ISO-8859-1处理又或者是response没有设置charset。解决办法我们在下一章讲但你要先有这个意识乱码是编码和解码不一致造成的和Web本身无关。这三个节点我建议你背下来因为整个学习过程会不断遇到它们。每次报错先问自己404是没找到500是程序崩了乱码是编码不对。对症下药效率会高很多。5. 自己动手在IDEA里建一个JSP项目并让它跑起来5.1 做项目前先把两样东西准备好JDK和Tomcat理论和乐趣讲完接下来动手。我推荐你在IDEA里完成第一步实操因为现在很多学校的实验环境都是IDEA而且IDEA能帮你管好编译和部署新手可以更专注在代码上。首先准备好JDK。JDK版本选什么以Tomcat 9为例JDK 8、11、17都能用但很多教程和课程默认JDK 8教材里的代码兼容性最好。如果你用的是较新版IDEA它自带JBRJetBrains Runtime能开发Java但Tomcat运行时走的是你系统环境变量里的JAVA_HOME。所以请先确认命令行输入java -version能正常显示版本。然后下载Tomcat。建议下载Tomcat 9.x的非安装版zip或者tar.gz解压到不带空格和中文的路径。这里我不推荐用Tomcat 10因为Tomcat 10把Java EE规范里的包名从javax.*改成了jakarta.*网上大量老教材、老Demo都还是javax.*初学者照抄会直接编译不过。Tomcat 9是兼容老教材和大部分课程要求的最稳选择。工具准备这种细节看似不重要实际决定了你能不能照着教程顺利走下去版本不匹配我给你打包票会踩坑。5.2 IDEA中新建项目的正确打开方式打开新版IDEA比如2024版本在New Project里选择Java Enterprise。这个选项就是专门用来创建企业级Web项目的。如果你的IDEA界面里没有它可能是社区版功能不全或者在More Actions里。选Java Enterprise之后需要做几件事Project SDK选JDK版本Additional Libraries里勾选Web ApplicationApplication Server选Tomcat Server指向你刚解压的Tomcat目录如果你需要web.xml勾选Create web.xml新版IDEA默认不勾选但课程作业往往需要建议勾上。点击Create之后IDEA会生成一个标准Java Web项目目录大致长这样myweb/ ├── src │ └── main │ ├── java │ └── webapp │ ├── WEB-INF │ │ └── web.xml │ └── index.jsp └── pom.xml如果你选择了Maven注意webapp这个目录名在旧版IDEA里可能是web本质一样。它才是Web应用的根目录你要把JSP、CSS、图片都放在这个目录下而不是放在src/main/java里。WEB-INF目录是受保护的浏览器无法直接访问里面的文件web.xml是Web应用的部署描述符用来配置首页、Servlet映射等。如果你选的是Maven项目还会有一个pom.xml里面需要添加依赖和打包插件。其实对入门来说不用Maven也可以直接IDEA的Web模板就够了但如果你想把项目打包成war方便部署Maven的package命令会省不少事。5.3 运行配置把Tomcat绑定到项目项目建好之后还要让IDEA知道怎么启动Tomcat、部署哪个项目。点击右上角运行菜单旁的Add Configuration选择Tomcat Server - Local在弹出的配置里Server选项卡Application Server选Tomcat目录Tomcat的HTTP port默认8080如果你的8080被占用改成8081。Deployment选项卡点击加号选择Artifact一般会有一个带:war exploded的选项选它。注意要选war exploded或war不要选其他。war exploded是解压态部署开发时修改文件能更快生效。在Deployment页面下方设置Application context比如填/hello。这个值决定了你运行后浏览器里访问的路径必须记清楚后面404基本都和它有关。设置好后点右上角的绿色运行按钮。IDEA会先编译项目然后把编译后的应用文件放到Tomcat的临时部署目录启动Tomcat最后打开浏览器。浏览器地址通常长这样http://localhost:8080/hello/index.jsp。如果你的默认首页配置了index.jsp访问http://localhost:8080/hello/就能直接看到页面。这里有个经验IDEA默认会在启动时使用一个临时的Tomcat实例不会动你下载的Tomcat的webapps目录。所以在IDEA里部署和在Tomcat的webapps里部署是两套逻辑但背后都是Tomcat在跑只是部署位置不同。做作业时如果想复现把war放webapps这回事你需要在IDEA里构建Artifact或者用Maven package再把产物复制到webapps。5.4 放一个JSP页面进去验证整条链路项目跑起来之后把你自己的JSP代码写进src/main/webapp/index.jsp或者新建一个hello.jsp。我建议先别急着写复杂业务就写一个能显示时间或参数的页面比如第2章的例子。运行后打开浏览器你应该能看到动态内容。如果你改动了JSP文件Tomcat会自动重新编译刷新浏览器就能看到变化不需要重启Tomcat。这是因为Tomcat对JSP有自动检测机制比对时间戳发现文件变了就会再次翻译。但如果你改的是Java类情况就不一样了IDEA的war exploded部署能做到Java类的热替换但很多时候要重启才稳妥。新手阶段建议果断重启省得踩热部署的坑。这一节的核心目标是让你亲眼看到动态页面和静态页面的区别你在JSP里写的% new java.util.Date() %浏览器里显示的不是这段代码而是具体的时间。这一眼胜过背十页概念。5.5 老式做法不用IDE记事本Tomcat一样能跑最后分享一个被很多人忽略但极其有效的练习脱离IDE用记事本写一个JSP手动放到Tomcat的webapps下跑一遍。操作是这样的在Tomcat的webapps目录下新建一个文件夹myweb往里新建一个index.jsp用记事本写第2章的那个例子保存为UTF-8编码。然后启动Tomcat访问http://localhost:8080/myweb/index.jsp。完成。这个方法不需要IDEA不需要配置也不需要打包但它逼着你面对Web部署最朴素的真相一个Web应用就是一个带特殊目录的文件夹Tomcat只是一个会执行JSP的程序。我自己的经验是用这个方法跑通一次之后你再回到IDEA里操作会觉得所有魔法都消失了。IDEA帮你做的事——编译、部署、启动、打开浏览器——你都能在脑子里翻译成Tomcat的一步步动作。这种理解带来的踏实感是任何IDE一键运行给不了的。6. Tomcat启动、404和中文乱码高频问题排查笔记6.1 启动失败黑窗一闪而过或提示端口占用我把入门阶段最高频的几个报错整理成清单你不一定现在都用得上但以后每次被卡住回头翻这一段比重新百度高效。第一个问题启动时窗口闪退。原因80%是JAVA_HOME没配好。你可以打开命令行手动执行Tomcat的bin/startup.bat窗口会停在报错信息不会闪退。看到类似Neither the JAVA_HOME nor the JRE_HOME environment variable is defined的提示就是JAVA_HOME的问题。Linux上执行echo $JAVA_HOME为空就去修改/etc/profile或~/.bashrc。第二个问题启动报端口占用。Tomcat默认8080端口被占用时日志里会看到java.net.BindException: Address already in use: JVM_Bind。解决办法是用netstat -ano | findstr 8080找到PID然后到任务管理器结束进程或者修改conf/server.xml里的端口号。我不建议随便关进程因为你学到后面装多个Tomcat时会发现改端口是家常便饭。第三个问题Tomcat能启动但访问不了先确认防火墙Linux下记得开放对应端口。6.2 浏览器一直404先分清Tomcat没启动还是应用没部署404大概是所有人遇到最多的报错而且它经常不是Tomcat的锅。判断思路很简单访问http://localhost:8080/如果能出现Tomcat默认首页说明Tomcat运行正常问题出在你的应用或URL如果默认首页都打不开那才是Tomcat本身有问题。URL访问应用404时请按照这个顺序排查先检查webapps目录下有没有你的项目文件夹再检查URL中是否带了正确的Context Path。比如你放的是webapps/hello/index.jsp要用http://localhost:8080/hello/index.jsp不能直接访问http://localhost:8080/index.jsp。在IDEA里也一样Deployment的Application context设置为/hello则URL必须带/hello。IDE里报源服务器未能找到目标资源的表示或者HTTP Status 404时我遇到过十次有八次都是这个原因。另外要注意WEB-INF目录。如果你不小心把JSP放在WEB-INF下面浏览器直接访问会404。WEB-INF不是给浏览器公共访问用的它存放web.xml、classes、lib等受保护资源。JSP页面应该放在webapp根目录或它的普通子目录下。最后如果项目里有web.xml检查里面有没有配置welcome-file-list。你要是不小心写成welcome-fileindex/welcome-file没有.jsp后缀Tomcat找index这个文件也找不到会404。6.3 中文乱码一次处理请求和响应两侧中文乱码有两大类一类是页面显示乱码一类是提交数据后乱码。它们的共同根源是一个字符在编码时用了A解码时用了B两边没对上。页面显示乱码最常见。解决办法从三个地方下手第一确保JSP文件本身以UTF-8保存IDEA右下角能看到文件编码第二在JSP第一行写% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %明确告诉Tomcat解析和输出都按UTF-8第三确保浏览器接收响应时按UTF-8解析response里已经通过contentType设置了charset浏览器能识别。POST表单提交中文乱码时因为Tomcat容器解码请求体的默认编码是ISO-8859-1你需要在读取参数之前先执行一句request.setCharacterEncoding(UTF-8);。GET请求的query参数中文乱码则一般通过修改server.xml里的Connector加一个URIEncodingUTF-8来解决。这些代码和配置都不难难的是理解乱码永远是编码两侧不匹配这个道理。记住这个原则遇到任何乱码都从数据是谁编码、谁解码入手一两分钟就能定位。6.4 看日志比瞎猜快Tomcat日志的打开姿势最后一个建议请学会看日志。Tomcat的所有运行信息都在logs目录下你不需要全部都懂但一定要知道几个文件catalina.日期.log或catalina.outTomcat的主日志启动、关闭、全局异常都在这里。localhost.日期.logWeb应用级别日志应用启动、Web应用异常基本都会输出到这里。JSP编译报错时Stack Trace经常出现在这个文件里。localhost_access_log.日期.txt访问日志记录每个请求的URL、IP、状态码排查404或响应时间很实用。在Windows上Tomcat控制台的输出会同时显示在startup.bat的窗口里在Linux上用tail -f logs/catalina.out实时看日志。IDEA里运行Tomcat时日志会输出到IDEA的Console窗口报错信息的颜色一般很醒目。我见过很多同学遇到500错误看一眼报错页面觉得看不懂就直接把整个报错贴到群里问。其实Tomcat已经可以很仁慈地告诉你第几行出错、异常类型是什么。你只需要逐行读从第一个Caused by开始找根因。这个习惯一旦养成你解决问题的能力会明显超过同阶段的人。我在辅导课程时经常让同学做一件看起来很傻的事先用记事本写一个JSP手动放到Tomcat的webapps目录下访问一次。如果这一步能自己独立完成你对Web/JSP/Tomcat的理解会高出周围人一大截。后续你要学的Servlet、过滤器、MVC框架全都是在这套基础上盖楼而地基就是今天这些内容。先跑通再问为什么网络程序设计这门课就不会难。