【Java Web02】WEB服务器内部实现技术揭秘

发布时间:2026/8/18 13:34:15
【Java Web02】WEB服务器内部实现技术揭秘 JAVA WEB内部实现技术揭秘一、XML1.1 xml简介1.2 DOM4J解析二、Tomcat102.1 Tomcat简介2.2 安装Tomcat2.3 WebApp的标准结构2.4 Tomcat部署项目的方式2.5 IDEA关联Tomcat2.6 创建、构建、部署JAVA WEB工程2.7 IDEA使用Tomcat运行java web项目的原理三、HTTP协议3.1 http简介3.2 HTTP请求和响应的报文格式3.2.1 请求报文3.2.2 响应报文3.3 响应状态码四、Servlet4.1 servlet简介4.2 HelloServlet4.3 注解方式配置servlet4.4 Servlet生命周期4.5 ServletConfig的使用4.7 ServletContext4.8 HttpServletRequest4.9 HttpServletResponse五、请求转发和响应重定向5.1 什么是请求转发和响应重定向5.2 请求转发5.3 响应重定向六、web乱码问题和路径问题总结6.1 乱码问题6.1.1 HTML乱码6.1.2 Tomcat控制台乱码6.1.3 suot乱码6.1.4 Get请求乱码6.1.5 Post请求乱码6.1.6 响应乱码问题6.2 路径问题6.2.1 前端相对路径问题6.2.2 前端绝对路径问题6.2.3 响应重定向的路径问题6.2.4 请求转发的路径问题6.2.5 不设置项目上下文路径七、MVC架构模式八、日程管理第二期8.1 项目搭建8.1.1 数据库准备8.1.2 实体类8.1.3 工具类8.1.4 DAO未来已来GPT4o也上线啦需要使用GPT镜像的可以私聊我哟可试用包稳定官方价格打骨折。接下来我们一起学习java web的内部实现技术本篇我们将介绍web服务器中的所有重要知识点和难点包括乱码问题的解决、路径问题的深入讲解重定向、请求转发的深入对比…一、XML1.1 xml简介简单来说xml就是在java中做配置文件的。擅长处理复杂的层级结构。回顾下常见的配置文件类型。对比下porperties和xmlxml有如下注意事项。比如下面就是一个约束为schema类型的xml文件。?xml version1.0 encodingUTF-8?web-appxmlnshttp://xmlns.jcp.org/xml/ns/javaeexmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsdversion4.0/web-app1.2 DOM4J解析使用DOM4J可以在java中进行xml解析。步骤如下。自己导入下dom4j的jar包。https://mvnrepository.com/artifact/org.dom4j/dom4j/2.1.4xml?xml version1.0 encodingUTF-8?jdbc-configdrivercom.mysql.cj.jdbc.Driver/driverurljdbc:mysql://localhost:3306/mydatabase/urlusernamemyuser/usernamepasswordmypassword/password/jdbc-config标记为资源目录代码packagecom.wangzhou;importorg.dom4j.Document;importorg.dom4j.DocumentException;importorg.dom4j.Element;importorg.dom4j.io.SAXReader;importorg.junit.jupiter.api.Test;importjava.io.InputStream;importjava.net.URL;publicclassTestDom4j{TestpublicvoidtestRead()throwsDocumentException{SAXReaderreadernewSAXReader();InputStreamresourceAsStreamTestDom4j.class.getClassLoader().getResourceAsStream(jdbc.xml);Documentdocumentreader.read(resourceAsStream);ElementrootElementdocument.getRootElement();System.out.println(rootElement.getName());rootElement.elements().forEach(element-{System.out.println(\telement.getName()element.getText());});}}运行结果如下。二、Tomcat102.1 Tomcat简介一句话说光有jreapp跑不起来。Tomcat可以让我们在服务器上的app跑起来。如果比喻app是子弹Tomcat就是一把枪。2.2 安装Tomcat官网https://tomcat.apache.org/解压到不带中文的路径下。注意tomcat也是使用java语言进行开发的因此需要匹配对应的jre运行环境。以Tomcat10为例我们需要使用java11。你要是还没有jdk自己下一个。https://www.oracle.com/cn/java/technologies/downloads/#jdk22-windows配置下系统环境变量。把JAVA_Home添加到Path变量中。确认下。运行tomcat试试。发现输出日志有中文乱码。问题不大后面解决。验证下是否启动成功访问http://localhost:8080/看到可爱的小猫就说明成功了。解决下日志中文乱码问题找到日志配置文件。更改如下配置windows窗口默认支持日志使用GBKjava.util.logging.ConsoleHandler.encoding GBK关掉重启一切就正常了。2.3 WebApp的标准结构总结下。补充下url组成部分和项目中资源的对应关系。2.4 Tomcat部署项目的方式2.5 IDEA关联TomcatIDEA和Tomcat有什么关系呢看看下图。我们使用IDEA编辑源代码这是一个JAVA WEB工程文件再构建成一个可以用于部署的APP将其部署到Tomcat。这都是用IDEA来做的。具体的过程如下。先建立tomcat和idea的关联。2.6 创建、构建、部署JAVA WEB工程新建项目设置jdk配置。为子模块增加tomcat 10依赖。新建子模块。转换为一个web项目。现在项目结构会变成下面这样。index.jsp咱们不用可以删除。接下来把java web项目构建成为一个web app。好了。来部署下。启动后会自动打开浏览器(没有你就手动打开)实际上上面构建这一步可以不用手动做。当你启动tomcat时IDEA会自动先完成构建。2.7 IDEA使用Tomcat运行java web项目的原理这里仅仅了解下就好。原来为了不污染原来的tomcatIDEA存了一个tomcat副本只保存一些和项目运行相关的配置。tomcat本体去根据副本tomcat中寸的配置信息运行web app。妙妙妙啊。三、HTTP协议3.1 http简介学习http无非就是学习下报文的数据格式。3.2 HTTP请求和响应的报文格式3.2.1 请求报文请求体3.2.2 响应报文响应行和响应头响应体3.3 响应状态码解释下。405比如只支持get方式访问但你客户端通过post方式访问url。500你服务器的代码运行出错了比如除0错误。304访问一个url获取图片后浏览器缓存了这个图片资源再次访问没有去服务器拿直接使用的缓存资源。注意1、有时候浏览器的缓存会干扰你的实验。可以按住ctrlshiftdel清理缓存2、使用下面图标可以热部署web项目无需重启项目。3、可以右键查看页面源代码确认浏览器是否更新了代码避免缓存影响。四、Servlet4.1 servlet简介动态资源和静态资源。servlet是啥。servlet运行流程如下。4.2 HelloServlet目标添加tomcat依赖。新建模块。变成web项目。删除index.jsp新建index.html。!DOCTYPEhtmlhtmllangenheadmetacharsetUTF-8titleTitle/title/headbodyformactionuserServletmethodget用户名inputtypetextnameusernamebrinputtypesubmitvalue校验/form/body/html编写UserServlet文件。packagecom.wangzhou.servlet;importjakarta.servlet.http.HttpServlet;importjakarta.servlet.http.HttpServletRequest;importjakarta.servlet.http.HttpServletResponse;importjava.io.IOException;publicclassUserServletextendsHttpServlet{Overridepublicvoidservice(HttpServletRequestreq,HttpServletResponseresp)throwsIOException{// 获取请求参数usernameStringusernamereq.getParameter(username);// 处理业务逻辑StringinfoYES;if(wang.equals(username)){infoNO;// 响应数据}// 响应数据resp.getWriter().write(info);}}更改web.xml。将部署项目设置下。改下项目url。启动项目(建议使用debug模式随时加断点)。点击校验。备注1、需要手工导入servlet的jar包吗2、一个servlet-name可以对应多个url-pattern3、url-pattern可以模糊匹配4.3 注解方式配置servlet就为了建立url路径和servlet文件之间的映射我们就写了下面这一段代码太麻烦了有什么简化的方法吗有上注解。原来的代码先注释掉。加一个WebServlet(/userservlet)到UserServlet 上WebServlet(/userservlet)publicclassUserServletextendsHttpServlet{Overridepublicvoidservice(HttpServletRequestreq,HttpServletResponseresp)throwsIOException{// 获取请求参数usernameStringusernamereq.getParameter(username);// 处理业务逻辑StringinfoYES;if(wang.equals(username)){infoNO;// 响应数据}// 响应数据resp.getWriter().write(info);}}4.4 Servlet生命周期你可以自己测试下。通过测试我们有如下总结。Tomcat还有一个defaultservlet,我们访问静态资源其实就是由defaultsevlet处理的。使用spring mvc也提供了defaultservlet会让tomcat中的defaultservlet失效。所以访问静态资源可能会访问不到。需要重新配置使其生效。具体内容这里先留个悬念。4.5 ServletConfig的使用创建项目servlet03重复上面两节内容转为java web项目。修改配置文件。当然你也可以通过注解进行配置。如下图在项目启动后tomcat会拿到config信息。因此我们可以通过servletConfig去获取这些配置信息。如果我们再配置一个servlet02那么它的相关配置会通过一个新的servletconfig对象去存储。4.7 ServletContextServletContext是单例的。编写配置信息。测试。servletcontext的其它api4.8 HttpServletRequest其实无非就是一些API。获取行相关的api。URL与URI有什么区别再来。为何会有客户端请求的端口号和应用所在容器的端口号的区别呢因为可能有代理。获取请求头相关api。获取请求中键值对参数相关API。先准备一个简单的表单。测试代码如下。4.9 HttpServletResponse了解下咯。五、请求转发和响应重定向5.1 什么是请求转发和响应重定向5.2 请求转发测试代码。可以加进行测试。5.3 响应重定向测试代码。六、web乱码问题和路径问题总结6.1 乱码问题6.1.1 HTML乱码6.1.2 Tomcat控制台乱码6.1.3 suot乱码解决办法设置虚拟机加载.class文件的字符集与编译时使用的字符集一致。6.1.4 Get请求乱码但是tomcat10解码默认是utf-8字符集。因此下面tomcat控制台出现了乱码。解决方法更改tomcat配置6.1.5 Post请求乱码解决办法设置请求体解码的字符集6.1.6 响应乱码问题解决。6.2 路径问题6.2.1 前端相对路径问题情况1目标资源所在路径与当前资源所在路径相同项目结构和demo代码如下。思考查找资源的过程是怎么完成的情况2目标资源所在路径与当前资源所在路径不相同没有请求转发情况2目标资源所在路径与当前资源所在路径不相同进行了请求转发下面代码访问不了。因为用户无法直接访问view.html。必须经过请求转发。分析过程。正确写法正确的思考过程资源的查找是客户端的事情而不是服务端做写相对路径从浏览器客户端的角度考虑6.2.2 前端绝对路径问题绝对路径怎么写需要先找到项目的固定路径出发点。可以做测试。比如在index.html写如下代码。请求index.html。打开开发者模式查看网络中对于png的请求点进去看看它请求图片的地址。正确写法如下。绝对路径也有缺点因为项目上下文路径可以改变。项目上下文路径一旦改变引用了这个路径的地方全都要修改如果有100个你要改100次有没有办法避免呢有的。后续将会介绍。6.2.3 响应重定向的路径问题6.2.4 请求转发的路径问题6.2.5 不设置项目上下文路径在开发过程中我们通常不设置项目上下文路径因为一台服务器就部署一个app(如下图)。这样写绝对路径就不用加上下文路径了省心。七、MVC架构模式到底啥是MVC模式啊通俗来说就是你在写代码时项目文件不能乱放乱来必须遵守一定的架构规则。不理解看图。八、日程管理第二期8.1 项目搭建8.1.1 数据库准备使用navicat连接到你的数据库。创建一个新的数据库。执行如下sql。SETNAMES utf8mb4;SETFOREIGN_KEY_CHECKS0;DROPTABLEIFEXISTSsys_schedule;CREATETABLEsys_schedule(sidintNOTNULLAUTO_INCREMENT,uidintNULLDEFAULTNULL,titleVARCHAR(20)CHARACTERSETutf8mb4COLLATEutf8mb4_0900_ai_ciNULLDEFAULTNULL,completedint(1)NULLDEFAULTNULL,PRIMARYKEY(sid)USINGBTREE)ENGINEInnoDBAUTO_INCREMENT1CHARACTERSETutf8mb4COLLATEutf8mb4_0900_ai_ci ROW_FORMATDynamic;DROPTABLEIFEXISTSsys_user;CREATETABLEsys_user(uidintNOTNULLAUTO_INCREMENT,usernameVARCHAR(10)CHARACTERSETutf8mb4COLLATEutf8mb4_0900_ai_ciNULLDEFAULTNULL,user_pwdVARCHAR(100)CHARACTERSETutf8mb4COLLATEutf8mb4_0900_ai_ciNULLDEFAULTNULL,PRIMARYKEY(uid)USINGBTREE,UNIQUEINDEXusername(username)USINGBTREE)ENGINEInnoDBCHARACTERSETutf8mb4COLLATEutf8mb4_0900_ai_ci ROW_FORMATDynamic;INSERTINTOsys_userVALUES(1,zhangsan,sxdfcgvhbjksdfghjk);INSERTINTOsys_userVALUES(2,lisi,sxdfcgvhbjksdfghjk);SETFOREIGN_KEY_CHECKS1;创建项目schedule_system,添加tomcat依赖添加java web framework组件支持。其实你也可以使用IDEA连接数据库无需再使用别的数据库工具。点击1 of 5选择需要展示的库。8.1.2 实体类检查是否安装了Lombok插件。Enable Annotation Processing创建实体类。AllArgsConstructorpublicclassSysUserimplementsSerializable{privateIntegeruid;privateStringusername;privateStringuserPwd;}下一个AllArgsConstructorNoArgsConstructorDatapublicclassSysSchedule{privateIntegersid;privateIntegeruid;privateStringtitle;privateIntegercompleted;}8.1.3 工具类导入druid的jar包。编写JDBC连接工具类。packagecom.wangzhou.schedule.util;importcom.alibaba.druid.pool.DruidDataSourceFactory;importjavax.sql.DataSource;importjava.io.IOException;importjava.io.InputStream;importjava.sql.Connection;importjava.sql.SQLException;importjava.util.Properties;publicclassJDBCUtil{privatestaticThreadLocalConnectionthreadLocalnewThreadLocal();privatestaticDataSourcedataSource;// 初始化连接池static{// 可以帮助我们读取.properties配置文件PropertiespropertiesnewProperties();InputStreamresourceAsStreamJDBCUtil.class.getClassLoader().getResourceAsStream(jdbc.properties);try{properties.load(resourceAsStream);}catch(IOExceptione){thrownewRuntimeException(e);}try{dataSourceDruidDataSourceFactory.createDataSource(properties);}catch(Exceptione){thrownewRuntimeException(e);}}/*1 向外提供连接池的方法*/publicstaticDataSourcegetDataSource(){returndataSource;}/*2 向外提供连接的方法*/publicstaticConnectiongetConnection(){ConnectionconnectionthreadLocal.get();if(nullconnection){try{connectiondataSource.getConnection();}catch(SQLExceptione){thrownewRuntimeException(e);}threadLocal.set(connection);}returnconnection;}/*定义一个归还连接的方法 (解除和ThreadLocal之间的关联关系) */publicstaticvoidreleaseConnection(){ConnectionconnectionthreadLocal.get();if(null!connection){threadLocal.remove();// 把连接设置回自动提交的连接try{connection.setAutoCommit(true);// 自动归还到连接池connection.close();}catch(SQLExceptione){thrownewRuntimeException(e);}}}}编写jdbc.properties。driverClassNamecom.mysql.cj.jdbc.Driver urljdbc:mysql://localhost:3306/schedule_system usernameroot passwordroot initialSize5 maxActive10 maxWait10008.1.4 DAOpublicTTbaseQueryObject(ClassTclazz,Stringsql,Object...args){Ttnull;ConnectionconnectionJDBCUtil.getConnection();PreparedStatementpreparedStatementnull;ResultSetresultSetnull;introws0;try{// 准备语句对象preparedStatementconnection.prepareStatement(sql);// 设置语句上的参数for(inti0;iargs.length;i){preparedStatement.setObject(i1,args[i]);}// 执行 查询resultSetpreparedStatement.executeQuery();if(resultSet.next()){t(T)resultSet.getObject(1);}}catch(Exceptione){e.printStackTrace();}finally{if(null!resultSet){try{resultSet.close();}catch(SQLExceptione){e.printStackTrace();}}if(null!preparedStatement){try{preparedStatement.close();}catch(SQLExceptione){e.printStackTrace();}}JDBCUtil.releaseConnection();}returnt;}