
从零到能跑通第一个增删改查我的JavaWeb学习记录第一次看到“JavaWeb”这个词的时候我其实是一脸懵的。学完了JavaSE觉得自己面向对象写得还挺溜结果打开一个JavaWeb项目的教程什么Servlet、JSP、Tomcat、Maven、Filter、Listener一股脑全冒出来直接给我整不会了。后来硬着头皮把一个带MySQL数据库的完整案例从头到尾敲了三遍才算真正把这条链路打通。这篇文章就是我自己的JavaWeb学习记录从环境配置到完整案例从IDEA 2026里创建项目到把数据存进MySQL每一步都踩过坑。我会把整个学习过程里最关键的东西拆开讲适合刚学完JavaSE、准备进入Web开发这块的朋友也适合那种“照着教程能跑通但换个环境就不会了”的读者。这里没有高深的理论全是我自己一边踩坑一边总结出来的实操经验。1. JavaWeb到底在学什么——先搞懂这四层东西学习JavaWeb最大的障碍不是代码本身而是概念太多、不知道怎么串起来。我一开始死磕Servlet的doGet和doPost方法磕了两天感觉自己啥也没学到。后来我把整个JavaWeb拆成了四层思路瞬间就清楚了。1.1 客户端、容器、动态资源、数据存储用最直白的话说JavaWeb干的事情就是浏览器发一个HTTP请求过来服务器上跑的Java程序处理一下要么返回一个页面要么返回一段数据而数据往往存在MySQL这类数据库里。整个过程里最关键的是要分清几个角色。第一层是HTTP协议本身。浏览器和服务器之间的交流全靠它请求长什么样、响应长什么样、状态码是什么意思这些是基础中的基础。我之前一直理解不了为什么POST要处理乱码、为什么表单提交有两种方式后来看了HTTP协议的基本格式才明白get和post本质上就是数据放在URL里还是放在请求体里的区别。第二层是Web容器最常见的就是Tomcat。它的作用有点像“给Java程序提供一个能接收HTTP请求的环境”。没有Tomcat你的Servlet就是一个普通的Java类跑不起来有了Tomcat它才知道怎么把浏览器发来的请求交给你的Servlet处理再把结果返回给浏览器。我当时把Tomcat理解成一个“接线员”它负责把外面的电话HTTP请求转到对应的分机Servlet这个类比帮我解决了很大的困惑。第三层是动态资源也就是Servlet、JSP、Filter这些。Servlet说白了就是一个能处理HTTP请求的Java类JSP就是能在HTML里嵌Java代码的页面。到这一步你写的代码才真正开始“动起来”能根据用户的输入返回不同的内容。第四层是数据存储也就是JDBC和MySQL。JavaWeb项目做完增删改查最终都要落到数据库上。这一层要掌握的是JDBC的操作流程、连接池的使用以及怎么在DAO层避免SQL注入、怎么处理事务。把这四层分清楚之后我再回头看那些教程和笔记就发现学习路线其实非常清晰先学HTTP的基本概念然后配置Tomcat接着写Servlet处理请求再用JSP渲染页面最后通过JDBC操作MySQL一个完整的闭环就串起来了。1.2 很多人学JavaWeb用错的方法网上关于JavaWeb的学习资料多到爆炸尤其是很多人提到的“黑马程序员”系列笔记和视频确实很经典但我觉得有些地方的学习方式不太对。第一个误区是直接跳到框架。有些朋友学完Servlet的HelloWorld就急着去学SpringMVC和SpringBoot觉得Servlet太老了、没人用了。实际上框架是把Servlet的很多细节封装掉了你如果连请求是怎么分发到方法的、Filter在哪个环节起作用都搞不清楚后面出了问题连日志都看不懂。我自己是老老实实把Servlet的生命周期、请求转发和重定向的区别这些搞明白之后再回头看框架代码一下就通透多了。第二个误区是只抄代码不抄思路。JavaWeb完整案例的代码网上很多也有那种配好MySQL就能跑的源码。但如果你只是把代码下载下来、运行起来、看着页面能显示数据就觉得自己会了那下次换个需求你照样不会写。我学的时候做了一个决定每个案例都要自己从零建项目不看源码只看需求文档。第一遍写不出来就翻笔记第二遍写不出来再看答案等到第三遍能不看任何参考把整个流程默写下来的时候才算真正掌握了。第三个误区是忽略环境版本的问题。JavaWeb相关的组件版本更新速度很快JDK从8到17到21Tomcat从9到10到11Servlet规范对应的包名都变了。教程里写的是Tomcat 8.5 JDK 8你用IDEA 2026默认配的JDK 17去跑很可能连启动都启动不了。后面我会详细讲版本怎么选、怎么配对这也是我踩过最坑的地方。2. 环境搭建的真实流程——IDEA 2026 Tomcat Maven环境配置是第一道门槛也是最容易让人想摔键盘的一步。网上搜“idea2026 创建javaweb项目”能搜出一堆教程但很多都是旧版本的界面对照着操作根本对不上。我这里直接按照IDEA 2026的界面把每一步都写清楚。2.1 版本选型与对应关系别用太新的也别用太旧的先说版本搭配这是我在重装了四五次环境之后总结出来的稳定组合组件版本建议备注JDK17也可用21别用8了新工具链兼容性麻烦IDEA2026.x用最新稳定版社区版也够用Tomcat10.1.x内置Servlet 6.0规范注意包名是jakarta.*Maven3.8.x或3.9.xIDEA自带也可以单独装MySQL8.0.x认准mysql-connector-j的版本这条配置里最需要关注的是Tomcat 10及以上版本带来的变化。老教程里写的是import javax.servlet.*但在Tomcat 10里面包名统一改成了import jakarta.servlet.*。如果照抄旧代码编译的时候会直接报“程序包javax.servlet不存在”我一开始不知道这个坑还以为是依赖没配好折腾了半个小时才反应过来。如果你非要用Tomcat 9或更低的版本那JDK也最好用8或11并且代码里继续写javax.servlet。但新的IDEA 2026默认支持新特性我建议直接用新的这套组合踩的坑反而少。2.2 配置Maven镜像和本地仓库Maven这个东西刚开始学的时候会觉得它老在下载东西慢得让人想砸电脑。原因就是默认的中央仓库在国外国内访问很慢。解决办法是修改Maven的settings.xml配置阿里云镜像。打开Maven安装目录下的conf/settings.xml在mirrors标签里加上这段配置mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror配置好之后再在IDEA里确认一下Maven的路径和settings.xml指向的是你自己的这份文件否则改了等于白改。本地仓库的路径建议改成非系统盘的位置比如D:/maven-repo万一系统要重装依赖包还在省得重新下一次。Maven还有一个好处是它能把依赖的jar包统一管理起来。以前写JavaWeb要把各种jar手动复制到WEB-INF/lib目录下用Maven之后只需要在pom.xml里声明依赖就行。比如要用Servlet API加上这段dependency groupIdjakarta.servlet/groupId artifactIdjakarta.servlet-api/artifactId version6.0.0/version scopeprovided/scope /dependencyscope填provided是因为Tomcat自己带了Servlet的实现打包的时候不需要把它打进去否则可能和容器的实现冲突。2.3 IDEA 2026创建JavaWeb项目的完整步骤很多人卡在第一步不知道怎么建一个“Web项目”。IDEA 2026和旧版本有个差别它没有专门的“Java Web”项目模板了你建一个普通的Java项目再自己添加Web支持就行。我操作的过程是这样的打开IDEA选择New Project左侧选“Java”选择对应的JDK版本我用的17。不勾选任何附加模板直接点Create出来一个干净的空项目。右键项目名选择“Add Framework Support”在弹出的窗口里勾选“Web Application”IDEA会自动生成web/WEB-INF目录和index.jsp。在Project Structure里把项目的Artifact配置成Web Application Exploded这样后面就能直接部署到Tomcat。配置Tomcat点击右上角的Add Configuration点加号选“Tomcat Server” - “Local”在Application Server里选择Tomcat的安装目录。然后切到Deployment标签页点加号选Artifact把项目部署进去。这里有一个细节Tomcat的Application Server名称和版本IDEA会自动识别但如果你看到Server标签页下面有个大大的红字提示说什么“No artifacts marked for deployment”那就是你忘了在Deployment里加Artifact或者Artifact没建好。2.4 第一次运行Tomcat的踩坑现场我第一次把项目跑起来的时候满心欢喜地点了右上角的绿色三角结果浏览器打开localhost:8080直接给我来了个“404”。我当时以为是代码的问题后来发现根本原因是部署URL配置不对。这里普及一个知识点在Tomcat的Deployment配置里有一个“Application context”设置比如默认是/或者/项目名_war_exploded。如果你访问的地址和这个上下文路径对不上就会404。我建议把它改成/这样访问localhost:8080就能直接看到首页省得后面每次访问还要输入一串又长又难记的路径。还有个坑是端口被占用。Windows电脑上常见的情况是别的程序把8080占了报错信息通常是“Port 8080 is already in use”。解决方式要么关掉占用的进程要么在Tomcat的conf/server.xml里把端口改成8081或9090。我后来直接固定在9090上省心。最后是IDEA里控制台出现乱码的情况。启动Tomcat时如果日志里有中文的乱码需要看两处一是help - Edit Custom VM Options里加上-Dfile.encodingUTF-8二是Tomcat的conf/logging.properties里改java.util.logging.ConsoleHandler.encoding为UTF-8。这俩改完基本能解决。3. 从Servlet到完整案例——一个图书管理系统的拆解环境配好之后就要开始写真正的完整案例了。我做的是一个最典型的“图书管理系统”功能就是图书的增删改查外加一个分页列表。这个案例虽然简单但它把JavaWeb的每一层都串起来了做完之后整个链路就通了。3.1 案例需求与表结构设计动手前先做这一步正式写代码之前先把需求和表结构定下来这一步千万别省。我见过很多朋友上来就建项目就开始写Servlet写到一半才发现字段对不上、页面不知道要展示什么然后推倒重来。我这个图书管理系统的需求比较明确展示图书列表支持按书名模糊搜索支持添加图书、编辑图书、删除图书。数据库表设计就一张book表字段如下CREATE TABLE book ( id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT 主键ID, name VARCHAR(100) NOT NULL COMMENT 书名, author VARCHAR(50) NOT NULL COMMENT 作者, price DECIMAL(10, 2) NOT NULL COMMENT 价格, publish_date DATE DEFAULT NULL COMMENT 出版日期, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT图书表;这里有几个注意事项。第一字符集一定要用utf8mb4在MySQL 8.0里这已经是默认值了但如果你是从老项目拷过来的建表语句很可能是utf8那会导致表情符号存不进去中文在某些情况也会出现问题。第二主键用BIGINT AUTO_INCREMENT而不是String类型方便后续扩展。第三价格用DECIMAL(10,2)而不是DOUBLE避免浮点数精度问题在页面出现那种19.999999的尴尬情况。3.2 三层架构Servlet、Service、DAO代码结构我采用了最标准的Web三层架构Controller层Servlet负责接收请求和返回响应Service层负责业务逻辑DAO层负责和数据库打交道。当初我学这个案例的时候不理解为什么非要拆成三层全写在一个Servlet里不是更省事吗后来业务稍微复杂一点我就发现了如果不分层增删改查的小项目还好只要加一个用户登录、权限判断的需求代码就会乱成一锅粥。分层之后每一层只关心自己的事情出了问题也知道去哪查。比如添加图书的流程是这样的页面上填好图书信息提交表单Servlet收到请求之后调用BookService.addBook()Service里做了简单的参数校验比如书名叫什么、价格是不是负数校验通过后调用BookDAO.insert(book)DAO把数据存进MySQL。删除和修改的流程类似只是SQL语句不同。DAO方面我没有直接用最原始的JDBC而是用了Druid连接池搭配JDBCUtils工具类。连接池的作用可以理解成一个“数据库连接的快递柜”提前把连接准备好需要时直接取用完还回去而不是每次都重新创建和销毁连接。Druid的配置在druid.properties里driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/book_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse usernameroot password你的密码 initialSize5 maxActive10注意驱动的类名是com.mysql.cj.jdbc.Driver这是MySQL 8.0及以上用的。如果你用的还是老版的com.mysql.jdbc.Driver运行的时候会有一行警告虽然也能跑但还是改成新的稳妥。3.3 核心代码分页查询是这样实现的分页是整个案例里比较有含金量的一部分。网上很多JavaWeb完整案例用的是“查询全部数据然后传到前端自己分页”这种方式数据量小的时候看不出来问题数据一多页面就会卡。我用的是经典的SQL分页方式核心就两步先查总条数再查当前页的数据。查总条数SELECT COUNT(*) FROM book WHERE name LIKE CONCAT(%, ?, %)查当前页数据SELECT id, name, author, price, publish_date, create_time FROM book WHERE name LIKE CONCAT(%, ?, %) ORDER BY id DESC LIMIT ?, ?这里要重点说一个网上老教程容易写错的地方——LIKE模糊查询的参数拼接。很多人喜欢直接在Java代码里拼% keyword %然后拼到SQL字符串里这样有两个问题一是容易造成SQL注入二是如果keyword里本身包含%或者_查询结果会不符合预期。正确做法是在SQL里用CONCAT(%, ?, %)让MySQL来处理拼接。分页参数的传递也有讲究。前端页面通过currentPage参数告诉Servlet当前是第几页Servlet算出start (currentPage - 1) * pageSize然后把start和pageSize传给DAO层的LIMIT参数。把搜索关键字keyword也一起传下去保证翻页的时候搜索条件不会丢失。我这里把pageSize固定成5方便看效果实际项目里一般会让用户自己选每页几条。3.4 JSP页面怎么写才不显得笨重JSP这个技术在现在的开发里确实越来越少了但作为JavaWeb的学习过程它依然是绕不开的一环。我写的页面没有用任何前端框架纯HTML JSTL标签渲染列表。在pom.xml里加上JSTL依赖dependency groupIdjakarta.servlet.jsp.jstl/groupId artifactIdjakarta.servlet.jsp.jstl-api/artifactId version3.0.0/version /dependency dependency groupIdorg.glassfish.web/groupId artifactIdjakarta.servlet.jsp.jstl/artifactId version3.0.1/version /dependency列表页的核心部分大致长这样c:forEach items${page.records} varbook tr td${book.id}/td td${book.name}/td td${book.author}/td td${book.price}/td td a href${pageContext.request.contextPath}/book?actioneditid${book.id}编辑/a a href${pageContext.request.contextPath}/book?actiondeleteid${book.id} onclickreturn confirm(确定删除吗)删除/a /td /tr /c:forEach这里有个容易掉进去的坑${book.price}在页面上显示的时候如果数据库里是19.90Java里用BigDecimal接收再直接输出页面上可能会显示成19.90但如果经过了一些格式化处理或者转成double可能就变成19.9了。最好的办法是在实体类里直接定义成BigDecimal页面输出的时候用fmt:formatNumber格式化fmt:formatNumber value${book.price} pattern0.00/另外所有的链接前面我都加了${pageContext.request.contextPath}这个是老生常谈了。如果你在IDEA里直接访问localhost:8080/上下文路径是空的可能看不出来区别但一旦你部署到服务器上项目名带了路径不带这个前缀的话所有链接都会断掉。4. 调试、部署与常见问题排查实录写代码的时候最耗时间的不是写功能而是排查各种奇奇怪怪的问题。我把自己在学习过程中遇到过的、以及帮同学解决的典型问题整理一下这些都是搜索引擎能搜到但我希望能更直白说清的版本。4.1 ClassNotFoundException和NoClassDefFoundError这两个异常在JavaWeb里出现的频率极高尤其是第一次配置完环境之后。区别在于前者是类找不到后者是类在编译期有但运行期加载失败。我遇到的最典型的场景是代码里用了MySQL的驱动类运行的时候报ClassNotFoundException: com.mysql.cj.jdbc.Driver。原因通常是依赖没有正确打包到WEB-INF/lib下或者Maven依赖的scope配错了比如把mysql-connector-j配置成了provided。排查方式是在IDEA的Project Structure里查看Artifact的输出目录看lib下有没有对应的jar包没有的话就右键Artifact选择“Put into Output Root”或者重新Build。这里有个技巧Maven的dependency:tree命令能帮你看清楚依赖关系但IDEA图形界面里直接看External Libraries更直观。你在左侧的External Libraries里能看到所有引入的jar如果在运行时报类找不到说明运行时的classpath和编译时的classpath不一致重点检查Artifact的部署配置。4.2 中文乱码到底该怎么调中文乱码问题是JavaWeb里最磨人的问题之一因为它可能出现在请求参数、响应输出、数据库存储任何一个环节。我总结了一个检查顺序按这个顺序排查基本都能解决。第一步是页面本身的编码JSP文件顶部要有% page contentTypetext/html;charsetUTF-8 languagejava %同时HTML的meta charsetUTF-8也要有。第二步是POST请求的乱码。在Servlet里处理POST请求之前加一行request.setCharacterEncoding(UTF-8);这句话必须在获取任何参数之前执行否则无效。第三步是GET请求的乱码。GET请求的参数是在URL里的浏览器用什么编码编码、服务器用什么编码解码两边不一致就会乱。Tomcat 10里面GET请求的默认编码一般是UTF-8但如果你用的老版本Tomcat需要在server.xml的Connector里加上URIEncodingUTF-8。第四步是响应的乱码。Servlet往页面输出内容时response.setCharacterEncoding(UTF-8)和response.setContentType(text/html;charsetUTF-8)都要设置而且顺序要在getWriter()之前。第五步是数据库的乱码。连接数据库的URL里带上characterEncodingutf8同时建表时指定utf8mb4两头都保证才能最终不乱码。调试的时候我建议在页面输出的最前面临时加一句System.out.println打印一下参数的值先在控制台确认参数本身是不是乱的再决定往哪个方向去排查比瞎改一通有效得多。4.3 数据库连接池起不来的常见原因Druid连接池在启动时报错的情况我也遇到过好多次。最常见的原因是配置文件没加载到或者连接参数有问题。我现在的习惯是在工具类的静态代码块里加载配置文件并且把配置文件放在src/main/resources目录下static { try (InputStream in DruidUtils.class.getClassLoader().getResourceAsStream(druid.properties)) { Properties props new Properties(); props.load(in); dataSource DruidDataSourceFactory.createDataSource(props); } catch (Exception e) { e.printStackTrace(); } }注意getResourceAsStream(druid.properties)里面不要带/前缀这个路径是相对于classpath根目录的。如果报错信息是Could not load driverClass com.mysql.cj.jdbc.Driver那大概率是mysql-connector-j的jar没有引入或者版本和MySQL不对应。MySQL 8.0以上对应的驱动坐标是dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId version8.4.0/version /dependency老坐标mysql:mysql-connector-java虽然也能用但新项目建议直接用新坐标。还有种情况是连接报错Access denied for user那就检查druid.properties里的用户名和密码不要用root以外的账号却不授权。本地学习直接用root就行权限问题最少。4.4 端口被占用和热部署失效端口被占用这个属于理论简单、遇到闹心的。Windows下用netstat查netstat -ano | findstr 8080查出来PID之后在任务管理器里确认是能杀的进程再结束。如果不想每次都被占用问题烦我还是建议直接把Tomcat端口改成8081或者别的一劳永逸。热部署失效的问题也值得提一嘴。IDEA里在Tomcat配置页有个“On frame deactivation”选项可以选“Update classes and resources”这样修改代码后自动编译更新。但有时候你会发现改了JSP文件不生效刷新页面还是旧的那是因为Tomcat默认对JSP的修改检测有延迟或者部署方式是war包模式而不是exploded模式。我建议调试阶段用war exploded部署方式改代码之后IDEA会直接把编译好的文件和静态资源同步过去刷新页面就能看到变化。4.5 一张速查表报错信息对应什么问题报错信息问题方向处理建议404请求的资源不可用部署配置或URL路径不对检查Application context确认访问路径500Servlet execution threw an exception代码运行期异常看Tomcat日志堆栈定位具体行号ClassNotFoundException缺jar或scope不对检查Artifact的lib目录Port 8080 already in use端口被占用换端口或杀进程Access denied for user ‘root’数据库账号密码错误核对druid.propertiesUnknown database ‘xxx’数据库不存在在MySQL里建好库再连Table doesn’t exist表没建或连错库确认连接URL里库名和建表的库一致HTTP Status 405 - Method Not AllowedServlet没重写对应方法检查doGet/doPost方法签名和请求方法中文乱码编码不一致按第4.2节的顺序从上到下排查这个表看起来简单但真的能省不少时间。每次遇到问题先对号入座再去翻具体原因比漫无目的地搜索要高效得多。5. 学习过程的复盘与后续方向整个JavaWeb从环境配置到完整案例跑通我大概花了两周时间每天两三个小时。这个进度不算快但如果让我重新来一遍应该能缩短到四五天因为很多坑完全是可以提前避开的。5.1 回头再看几个关键概念Servlet一开始我以为是要写的后来才明白Servlet本质上是“Java世界里处理HTTP请求的一种约定”。你实现一个类继承HttpServlet重写doGet或者doPost容器就会在合适的时候调用你。所有Web框架的底层都在做这件事只是把代码组织得更好看而已。搞清楚这一点后面学SpringMVC会轻松非常多。JSP现在确实用得越来越少前后端分离的趋势下后端返回JSON数据已经成为主流。但学习阶段写JSP有它的价值你能直观地看到服务端的数据是怎么渲染到页面上的理解“动态网页”这个概念到底是什么意思。如果你以后做传统项目遇到老系统维护JSP的知识也不会白学。Maven是另一个值得早点掌握的工具。刚开始用的时候只是觉得它解决了依赖管理的问题后来才慢慢体会到它还能管理项目的生命周期打包、部署都可以用它来完成。而且现在几乎所有Java项目都在用Maven或Gradle这是绕不开的。Filter是一个当时觉得鸡肋后来觉得真香的东西。写登录校验的时候如果每个Servlet都去判断是否登录代码会非常冗余。用一个Filter统一拦下来没登录就重定向到登录页这个思路在后来的SpringMVC拦截器、SpringSecurity过滤器链里都能找到影子。5.2 从JavaWeb出发下一步该学什么学完Servlet和JSP之后你会面临一个选择是学框架还是继续深挖底层。我的建议是两手都要抓但顺序上先学框架明白框架解决什么问题再回头看源码理解它的实现。对应的学习路线大概是先学MyBatis把原来手写的DAO层换成ORM框架你会发现SQL还能这么管理再学Spring理解容器和依赖注入是怎么回事然后学SpringMVC这时候你会发现之前Servlet里做的那些事参数接收、请求映射、响应处理框架都帮你封装好了最后学SpringBoot它把前面所有东西整合在一起让项目的启动和配置变得极其简单。这个递进过程很自然。如果你直接学SpringBoot虽然也能快速做出东西但遇到问题会很难定位到具体是哪一个环节出了问题。5.3 给后来者的一些实在建议第一环境问题一定要自己独立解决一次。哪怕照着教程一步步做也把它当成“没有人帮我看、我一定能搞定”的心态去做。环境配置这种问题看起来琐碎但排查问题的思路是通用的看报错、查日志、分析原因、验证修复这套方法论在后面的开发中经常用到。第二完整案例一定要独立敲一遍。网上能找到的黑马JavaWeb笔记、教程项目源码可以看但看完一定要合上自己从空项目开始建。我做图书管理系统的时候第一遍完全照着敲第二遍看着表结构和需求写第三遍才是闭卷写。每多一遍都有新的收获。第三记录自己的踩坑日志。我建议准备一个自己的笔记文档遇到问题的时候不要只记录“怎么解决的”还要记录“为什么会导致这个问题”。比如乱码问题如果你只记录“加一行代码就好了”下次遇到还是不会排查但如果你记录了Tomcat 10包名变化、GET和POST请求的参数编码流程下次就不会再犯。第四不要追求完美再动手。有人说学JavaWeb要先学完HTML、CSS、JavaScript、HTTP、数据库才能开始这纯属扯淡不然永远都在准备阶段。边做边补知识反而更快因为你遇到了具体问题带着问题去学效率比盲学高得多。我最后还有个小技巧分享一下写完一个功能之后故意把代码改坏再去根据报错信息修复。比如故意把数据库密码改错、把Servlet的映射路径删掉、把连接池的驱动类写错然后观察各种异常长什么样。这种“主动制造故障”的训练方式特别锻炼排查能力等你把常见错误都见过一遍以后再遇到问题心里就有底了。JavaWeb的学习没有捷径但踩过的每一个坑都会变成你的经验这个阶段打牢了基础后面学框架就是水到渠成的事。