当前位置: 首页 > news >正文

运城建设银行网站点从山海经取公司名

运城建设银行网站点,从山海经取公司名,wordpress主题网站模板,f3322免费域名申请1. 前言 先看一个小案例#xff0c; 引出对 Tomcat 底层实现思考 1.1 完成小案例 ● 快速给小伙伴完成这个小案例 0. 我们准备使用 Maven 来创建一个 WEB 项目, 老师先简单给小伙伴介绍一下 Maven 是什么, 更加详细的使用#xff0c;我们还会细讲, 现在先使用一把 先创建…1. 前言 先看一个小案例 引出对 Tomcat 底层实现思考 1.1 完成小案例 ● 快速给小伙伴完成这个小案例 0. 我们准备使用 Maven 来创建一个 WEB 项目, 老师先简单给小伙伴介绍一下 Maven 是什么, 更加详细的使用我们还会细讲, 现在先使用一把 先创建一个 Maven 的 Web 项目 hsp-tomcat 补充如何配置阿里 maven 镜像 (1) 把 maven的安装目录\conf\settings.xml 拷贝默认的 maven 配置目录 (2) C:\Users\Administrator.m2 目录 settings.xml (3) 修改 C:\Users\Administrator.m2\settings.xml , 增加如下的部分 mirrors !-- mirror | Specifies a repository mirror site to use instead of a given repository. The repository that | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used | for inheritance and direct lookup purposes, and must be unique across the set of mirrors. | mirror idmirrorId/id mirrorOfrepositoryId/mirrorOf nameHuman Readable Name for this Mirror./name urlhttp://my.repository.com/repo/path/url /mirror --mirroridalimaven/idnamealiyun maven/nameurlhttp://maven.aliyun.com/nexus/content/groups/public//urlmirrorOfcentral/mirrorOf/mirror /mirrors(4) 到此 ok 修改 pom.xml ?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersionpropertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.target/propertiesdependenciesdependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion4.11/versionscopetest/scope/dependency!--解读1. dependency 表示依赖, 也就是我们这个项目需要依赖的 jar 包2. groupId 和 artifactId 被统称为坐标, 是为了去定位这个项目/jar3. groupId: 一般是公司 比如 com.baidu , 这里是 avax.servlet4. artifactId 一般是项目名, 这里是 javax.servlet-api5. 这样的化就可以定位一个 jar 包6. version 表示你引入到我们项目的 jar 包的版本是 3.1.07. scope: 表示作用域也就是你引入的 jar 包的作用范围8. provided 表示在 tomcat 本身是有这个 jar 的因此在编译,测试使用但是在打包发布就不用要带上9. 在默认情况下, 引入的 jar 会到 中央仓库去下载 https://mvnrepository.com/10. 会下载到哪里到你指定的目录 C:\Users\Administrator\.m2\repository11. 有时为了下载更快, 往往配置镜像,12. 在 默 认 的 路 径 下 拷 贝 一 份 setting.xml 到C:\Users\Administrator\.m2\settings.xml13. 指定默认的阿里云镜像mirrorsmirroridalimaven/idnamealiyun maven/nameurlhttp://maven.aliyun.com/nexus/content/groups/public//urlmirrorOfcentral/mirrorOf/mirror/mirrors--dependencygroupIdjavax.servlet/groupIdartifactIdjavax.servlet-api/artifactIdversion3.1.0/versionscopeprovided/scope/dependency/dependencies创建 cal.html !DOCTYPE html html langen headmeta charsetUTF-8title计算器/title /head body h1计算器/h1 form action/calServlet methodgetnum1:input typetext namenum1br/num2:input typetext namenum2br/input typesubmit value提交 /form /body /html 创建 java 目录存放 java 源文件创建 CalServlet.java 修改 web.xml , 配置 Servlet !DOCTYPE web-app PUBLIC -//Sun Microsystems, Inc.//DTD Web Application 2.3//EN http://java.sun.com/dtd/web-app_2_3.dtd web-appdisplay-nameArchetype Created Web Application/display-nameservletservlet-nameCalServlet/servlet-nameservlet-classcom.hspedu.servlet.CalServlet/servlet-class/servletservlet-mappingservlet-nameCalServlet/servlet-nameurl-pattern/calServlet/url-pattern/servlet-mapping /web-app修改 CalServlet.java, 完成计算任务 public class CalServlet extends HttpServlet {protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {//接收提交的数据进行计算//复制当前行 ctrlalt下光标String strNum1 request.getParameter(num1);String strNum2 request.getParameter(num2);//把strNum1 和 strNum2 转成 intint num1 WebUtils.parseInt(strNum1, 0);int num2 WebUtils.parseInt(strNum2, 0);int result num1 num2;response.setContentType(text/html;charsetutf-8);PrintWriter writer response.getWriter();writer.print(h1 num1 num2 result h1);writer.flush();writer.close();}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response);} }创 建 工 具 类 WebUtils.java public class WebUtils {/*** 将一个字符串数字转成 int, 如果转换失败就返回传入 defaultVal* param strNum* param defaultVal* return*/public static int parseInt(String strNum, int defaultVal) {try {return Integer.parseInt(strNum);} catch (NumberFormatException e) {System.out.println(strNum 格式不对转换失败);}return defaultVal;}}配置 tomcat 略。。。启动 tomcat浏览器访问: http://localhost:8080/cal.html 完成测试 maven 中央仓库 : https://mvnrepository.com/ 1.2 思考 问题: Tomcat 底层实现 和 调用到 Servlet 流程? 我们的目标: 不用 Tomcat, 不用系统提供的 Servlet, 模拟 Tomcat 底层实现并能调用我们自己设计的 Servle, 也能完成相同的功能 1.3 Tomcat 整体架构分析 1.3.1 一图胜千言 ● 说明: Tomcat 有三种运行模式BIO, NIO, APR, 因为老师核心讲解的是 Tomcat 如何接收客户端请求解析请求, 调用 Servlet , 并返回结果的机制流程, 采用 BIO 线程模型来模拟.[绘图] 2. 手动实现 Tomcat 底层机制 自己设计 Servlet 2.1 实现任务阶段 1 编写自己 Tomcat, 能给浏览器返回 Hi, Hspedu 基于 socket 开发服务端-流程: 2.1.1 需求分析/图解 需求分析如图, 浏览器请求 http://localhost:8080/??, 服务端返回 hi , hspedu 2.1.2 分析代码实现 ● 分析示意图 ● 代码实现 创 建 TomcatV1.java /*** 这是第一个版本的tomcat ,可以完成接收浏览器的请求并返回信息*/ public class HspTomcatV1 {public static void main(String[] args) throws IOException {//1. 创建ServerSocket, 在 8080端口监听ServerSocket serverSocket new ServerSocket(8080);System.out.println(mytomcat在8080端口监听);while (!serverSocket.isClosed()) {//等待浏览器/客户端的连接//如果有连接来就创建一个socket//这个socket就是服务端和浏览器端的连接/通道Socket socket serverSocket.accept();//先接收浏览器发送的数据//inputStream 是字节流 BufferedReader(字符流)//java基础 IO , 第19章InputStream inputStream socket.getInputStream();BufferedReader bufferedReader new BufferedReader(new InputStreamReader(inputStream, utf-8));String mes null;System.out.println(接收到浏览器发送的数据);//循环的读取while ((mes bufferedReader.readLine()) ! null) {//判断mes的长度是否为0判断字符串长度是否为0的作用是为了处理HTTP请求头和请求体之间的空行。if (mes.length() 0) { break;//退出while}System.out.println(mes);}//我们的tomcat会送-http响应方式OutputStream outputStream socket.getOutputStream();//构建一个http响应的头//\r\n 表示换行//http响应体需要前面有两个换行 \r\n\r\nString respHeader HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n;String resp respHeader hi, hspedu 韩顺平教育;System.out.println(我们的tomcat 给浏览器会送的数据);System.out.println(resp);outputStream.write(resp.getBytes());//将resp字符串以byte[] 方式返回outputStream.flush();outputStream.close();inputStream.close();socket.close();}} }细节说明 1.判断字符串长度是否为0的作用是为了处理HTTP请求头和请求体之间的空行。 在HTTP请求中请求头和请求体之间必须要有一个空行表示请求头已经结束请求体开始。因此在读取HTTP请求时需要先读取请求头并解析出请求信息然后再读取请求体部分。而读取请求头时每个请求头字段都是以冒号和空格分隔的键值对形式出现的如果读取到的一行请求头字段的长度为0就表明请求头已经结束了。此时就可以退出循环继续处理请求体的内容了。 因此为了在读取HTTP请求时正确地处理请求头和请求体之间的空行需要添加判断字符串长度是否为0的逻辑。   2.在HTTP协议中每行信息都以\r\n回车换行作为结束符表示该行信息结束并让浏览器接收下一个信息。 所以在构造HTTP响应头部时需要在每行信息后添加\r\n。而在Java中“\n表示换行即使只写”\n在大多数情况下也能正常工作但是使用\r\n会更加规范和严谨因为在Windows系统中只用\n可能不会被认为是换行符而使用\r\n则能保证适用于所有操作系统。 因此这段代码中在回复客户端的HTTP响应头中使用了\r\n作为结束符号确保HTTP响应头的格式符合HTTP协议的规范。 测试 浏览器 http://localhost:8080/ 2.1.3 问题分析 没有使用 BIO 线程模型没有实现多线程性能差 2.2 实现任务阶段 2 使用 BIO 线程模型支持多线程 2.2.1 BIO 线程模型介绍 补充 1.BIO是阻塞式I/OBlocking I/O的缩写是Java网络编程中常用的一种I/O模型。它指的是在进行网络数据读写时当用户线程发起了一个I/O操作如读取数据该线程会一直等待直到操作完成并返回结果期间会一直阻塞在那里无法做其他事情。与之相对的是非阻塞式I/ONIO和异步I/OAIO两种模型。 BIO模型是传统的线程池模型即一个请求对应一个线程。在BIO模型中一个客户端请求到来时服务器会开启一个新的线程去处理这个请求直到整个请求处理完毕才会退出线程。这种模型实现简单易于理解但同时也会带来一些问题例如线程池大小的限制、线程上下文切换等问题。当线程池达到最大线程数时新的请求就会被拒绝或者阻塞降低系统的吞吐量和性能。 因此在高并发、大规模的网络编程场景中BIO不再适用而需要使用NIO和AIO等更加高效的I/O模型。   2.NIO是Java NIONew I/O的缩写指的是Java提供的一种高效的I/O处理方式。与传统的I/O操作如BIO不同NIO是基于事件驱动的模型可以在单线程中处理多个并发请求提升了性能和可扩展性。 通过使用NIO库Java应用程序可以实现非阻塞式I/O操作包括文件操作、套接字操作等。它的主要优势在于使用少量线程就能处理大量并发连接因此适用于高负载、高可靠性的网络应用程序。 2.2.2 需求分析/图解 需求分析如图, 浏览器请求 http://localhost:8080, 服务端返回 hi , hspedu, 后台hsptomcat 使用 BIO 线程模型,支持多线程 对前面的开发模式进行改造 2.2.3 分析代码实现 ● 分析示意图 ● 代码实现 HspTomcatV2.java public class HspTomcatV2 {public static void main(String[] args) throws IOException {//在8080端口监听ServerSocket serverSocket new ServerSocket(8080);System.out.println(hsptomcatV2 在8080监听);//只要 serverSocket没有关闭就一直等待浏览器/客户端的连接while (!serverSocket.isClosed()) {//1. 接收到浏览器的连接后如果成功就会得到socket//2. 这个socket 就是 服务器和 浏览器的数据通道Socket socket serverSocket.accept();//3. 创建一个线程对象并且把socket给该线程// 这个是java线程基础HspRequestHandler hspRequestHandler new HspRequestHandler(socket);new Thread(hspRequestHandler).start();}} }HspRequestHandler.java /*** 解读* 1. HspRequestHandler 对象是一个线程对象* 2. 处理一个http请求的*/ public class HspRequestHandler implements Runnable {//定义Socketprivate Socket socket null;public HspRequestHandler(Socket socket) {this.socket socket;}Overridepublic void run() {//这里我们可以对客户端/浏览器进行IO编程/交互try {InputStream inputStream socket.getInputStream();// 把inputStream - BufferedReader - 方便进行按行读取BufferedReader bufferedReader new BufferedReader(new InputStreamReader(inputStream, utf-8));// 不同的线程在和浏览器和客户端交互System.out.println(当前线程 Thread.currentThread().getName());System.out.println(hsptomcatv2 接收到的数据如下);String mes null;while ((mes bufferedReader.readLine()) ! null) {// 如果长度为0 if (mes.length() 0) {break; //退出}System.out.println(mes);}// 构建一下http响应头// 返回的http的响应体和响应头之间有两个换行 \r\n\r\nString respHeader HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n;String resp respHeader h1hello world!/h1;System.out.println(hsptomcatv2返回的数据是);System.out.println(resp);// 返回数据给我们的浏览器/客户端- 封装成http响应OutputStream outputStream socket.getOutputStream();resp.getBytes() 是把字符串转成字节数组outputStream.write(resp.getBytes());outputStream.flush();outputStream.close();inputStream.close();socket.close();} catch (IOException e) {e.printStackTrace();} finally {//最后一定确保socket要关闭,//否则如果连接数过多会造成客户端等待if (socket ! null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} }测试 浏览器 http://localhost:8080/ 2.2.4 问题分析 HspTomcat 只是简单返回结果没有和 Servlet、web.xml 关联 2.3 实现任务阶段 3 处理 Servlet 2.3.1 Servlet 生命周期-回顾 2.3.2 需求分析/图解 ● 需求分析如图, 浏览器请求 http://localhost:8080/hspCalServlet, 提交数据完成计算任务如果 servlet 不存在返回 404 2.3.3 分析代码实现 ● 分析示意图 架构图 2.3.3.1 优化1阶段 1.搭建结构 2.封装HttpServletRequest 1.模拟servlet HspServlet.java /*** 先搭建结构后面在写内容*/ public interface HspServlet {}HspHttpServlet.java public abstract class HspHttpServlet implements HspServlet {}HspCalServlet.java public class HspCalServlet extends HspHttpServlet {}2.模拟HttpServletRequest和HttpServletResponse HspRequest.java /*** 解读* 1. HspRequest 作用是封装http请求的数据* get /hspCalServlet?num110num230* 2. 比如 method(get) 、 uri(/hspCalServlet) 、 还有参数列表 (num110num230)* 3. HspRequest 作用就等价原生的servlet 中的HttpServletRequest* 4. 这里考虑的是GET请求*/ public class HspRequest {private String method;private String uri;//存放参数列表 参数名-参数值 HashMapprivate HashMapString, String parametersMapping new HashMap();private InputStream inputStream null;//构造器 对http请求进行封装 可以将老师写的代码封装成方法//inputStream 是和 对应http请求的socket关联public HspRequest(InputStream inputStream) {this.inputStream inputStream;//完成对http请求数据的封装..encapHttpRequest();}/*** 将http请求的相关数据进行封装,然后提供相关的方法进行获取*/private void encapHttpRequest() {System.out.println(HspRequest init());try {//inputstream - BufferedReaderBufferedReader bufferedReader new BufferedReader(new InputStreamReader(inputStream, utf-8));//读取第一行/*** GET /hspCalServlet?num110num230 HTTP/1.1* Host: localhost:8080* User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Fi*/String requestLine bufferedReader.readLine();//GET - /hspCalServlet?num110num230 - HTTP/1.1String[] requestLineArr requestLine.split( );//得到methodmethod requestLineArr[0];//解析得到 /hspCalServlet//1. 先看看uri 有没有参数列表int index requestLineArr[1].indexOf(?);if (index -1) { //说明没有参数列表uri requestLineArr[1];} else {//[0,index)uri requestLineArr[1].substring(0, index);//获取参数列表-parametersMapping//parameters num110num230String parameters requestLineArr[1].substring(index 1);//num110 , num230 .... parametersPair [num110,num230 ]String[] parametersPair parameters.split();//防止用户提交时 /hspCalServlet?if (null ! parametersPair !.equals(parametersPair)) {//再次分割 parameterPair num110for (String parameterPair : parametersPair) {//parameterVal [num1, 10]String[] parameterVal parameterPair.split();if (parameterVal.length 2) {//放入到 parametersMappingparametersMapping.put(parameterVal[0], parameterVal[1]);}}}}//这里不能关闭流 inputStream 和 socket关联//inputStream.close();} catch (Exception e) {e.printStackTrace();}}//request对象有一个特别重要方法public String getParameter(String name) {if (parametersMapping.containsKey(name)) {return parametersMapping.get(name);} else {return ;}}public String getMethod() {return method;}public void setMethod(String method) {this.method method;}public String getUri() {return uri;}public void setUri(String uri) {this.uri uri;}Overridepublic String toString() {return HspRequest{ method method \ , uri uri \ , parametersMapping parametersMapping };} }细节补充 在Java中Socket和流Stream通常是一起使用的用于进行网络数据传输。如果关闭与Socket相关联的流会导致Socket也关闭的问题取决于关闭流的方式。 如果使用Socket对象的close()方法关闭与其关联的输入流或输出流则会同时关闭该Socket因为这些流是通过Socket来创建的。例如 Socket socket new Socket(example.com, 80); OutputStream os socket.getOutputStream(); os.close(); // 关闭输出流同时也会关闭socketHspResponse /*** 老师解读* 1. HspResponse对象可以封装OutputStream(是socket关联)* 2. 即可以通过 HspResponse对象 返回Http响应给浏览器/客户端* 3. HspResponse对象 的作用等价于原生的servlet的 HttpServletResponse*/ public class HspResponse {}3.改进HspRequestHandler /*** 解读* 1. HspRequestHandler 对象是一个线程对象* 2. 处理一个http请求的*/ public class HspRequestHandler implements Runnable {//定义Socketprivate Socket socket null;public HspRequestHandler(Socket socket) {this.socket socket;}Overridepublic void run() {//这里我们可以对客户端/浏览器进行IO编程/交互try {//这里我们先死后活HspRequest hspRequest new HspRequest(socket.getInputStream());String num1 hspRequest.getParameter(num1);String num2 hspRequest.getParameter(num2);System.out.println(请求的参数num1 num1);System.out.println(请求的参数num2 num2);System.out.println(hspRequest hspRequest);// 构建一下http响应头// 返回的http的响应体和响应头之间有两个换行 \r\n\r\nString respHeader HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n;String resp respHeader h1hello world!/h1;System.out.println(hsptomcatv2返回的数据是);System.out.println(resp);OutputStream outputStream socket.getOutputStream();resp.getBytes() 是把字符串转成字节数组outputStream.write(resp.getBytes());outputStream.flush();outputStream.close();inputStream.close();socket.close();} catch (IOException e) {e.printStackTrace();} finally {//最后一定确保socket要关闭,//否则如果连接数过多会造成客户端等待if (socket ! null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} }2.3.3.2 优化2阶段 1.完善HspResponse 2.构建Servlet模型 3.创建Util工具类 4.优化HspRequestHandler处理器 补充:HspResponse.java /*** 老师解读* 1. HspResponse对象可以封装OutputStream(是socket关联)* 2. 即可以通过 HspResponse对象 返回Http响应给浏览器/客户端* 3. HspResponse对象 的作用等价于原生的servlet的 HttpServletResponse*/ public class HspResponse {private OutputStream outputStream null;//写一个http的响应头 先死后活public static final String respHeader HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n;//说明同学们如果有兴趣, 在编写更多的方法//比如 setContentType//在创建 HspResponse 对象时传入的outputStream是和Socket关联的public HspResponse(OutputStream outputStream) {this.outputStream outputStream;}//当我们需要给浏览器返回数据时可以通过HspResponse 的输出流完成//public OutputStream getOutputStream() {return outputStream;} }完善模拟的Servlet 1.补充Servlet的生命周期 /*** 先搭建结构后面在写内容* 老韩只保留了 三个核心方法声明*/ public interface HspServlet {void init() throws Exception;void service(HspRequest request, HspResponse response) throws IOException;void destroy(); }2.完善HttpServlet public abstract class HspHttpServlet implements HspServlet {Overridepublic void service(HspRequest request, HspResponse response) throws IOException {//老师说明 equalsIgnoreCase 比较字符串内容是相同不区别大小写if(GET.equalsIgnoreCase(request.getMethod())) {//这里会有动态绑定this.doGet(request,response);} else if(POST.equalsIgnoreCase(request.getMethod())) {this.doPost(request,response);}}//这里我们使用的了模板设计模式 java 基础的 抽象类专门讲过模板设计模式//让HspHttpServlet 子类 HspCalServlet 实现public abstract void doGet(HspRequest request, HspResponse response);public abstract void doPost(HspRequest request, HspResponse response); } 细节补充 在这段代码中this关键字和省略this关键字是没有区别的。因为在Java中当局部变量和实例变量同名时编译器会优先使用局部变量如果需要访问实例变量可以使用this关键字来代表当前对象。   因此使用this.doGet()和直接调用doGet()方法实际上是等价的不会影响程序的执行结果。只要doGet()方法已经定义在了当前类中都可以直接调用。   不过在实际开发中推荐使用this关键字来调用当前对象的方法或访问成员变量可以提高代码的可读性和可维护性。另外使用this关键字还有助于避免和局部变量或参数命名冲突的情况。   因此虽然this.doGet()和doGet()在语义上是一致的但是在实际开发中建议使用this.doGet()的方式来调用对象的方法。 3.实现HspCalServlet public class HspCalServlet extends HspHttpServlet {Overridepublic void doGet(HspRequest request, HspResponse response) {//java基础的 OOP 的动态绑定机制..//写业务代码完成计算任务int num1 WebUtils.parseInt(request.getParameter(num1), 0);int num2 WebUtils.parseInt(request.getParameter(num2), 0);int sum num1 num2;//返回计算结果给浏览器//outputStream 和 当前的socket关联OutputStream outputStream response.getOutputStream();String respMes HspResponse.respHeader h1 num1 num2 sum HspTomcatV3 - 反射xml创建/h1;try {outputStream.write(respMes.getBytes());outputStream.flush();outputStream.close();} catch (IOException e) {e.printStackTrace();}}Overridepublic void doPost(HspRequest request, HspResponse response) {this.doGet(request, response);}Overridepublic void init() throws Exception {}Overridepublic void destroy() {} } WebUtils.java public class WebUtils {//将字符串转成数字方法public static int parseInt(String strNum, int defaultVal) {try {return Integer.parseInt(strNum);} catch (NumberFormatException e) {System.out.println(strNum 不能转成数字);}return defaultVal;} }改进优化HspRequestHandler处理器 /*** 老师解读* 1. HspRequestHandler 对象是一个线程对象* 2. 处理一个http请求的*/ public class HspRequestHandler implements Runnable {//定义Socketprivate Socket socket null;public HspRequestHandler(Socket socket) {this.socket socket;}Overridepublic void run() {//这里我们可以对客户端/浏览器进行IO编程/交互try {//这里我们先死后活HspRequest hspRequest new HspRequest(socket.getInputStream());//这里我们可以同HspResponse对象返回数据给浏览器/客户端HspResponse hspResponse new HspResponse(socket.getOutputStream());//创建HspCalServlet对象- 一会我们再用反射来构建对象HspCalServlet hspCalServlet new HspCalServlet();hspCalServlet.doGet(hspRequest, hspResponse);socket.close();} catch (IOException e) {e.printStackTrace();} finally {//最后一定确保socket要关闭if (socket ! null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} } 2.3.3.3 优化3阶段 1.构造容器 2.配置web.xml 3.创建容器存放servlet和servlet-mapping 4.利用dom4j技术获取xml文件反射创建对象 思路分析 拷贝web.xml 引入dom4j的依赖 !--导入dom4j-- dependencygroupIddom4j/groupIdartifactIddom4j/artifactIdversion1.1/version /dependencyweb.xml !DOCTYPE web-app PUBLIC-//Sun Microsystems, Inc.//DTD Web Application 2.3//ENhttp://java.sun.com/dtd/web-app_2_3.dtd web-appdisplay-nameArchetype Created Web Application/display-name!--配置自己设计的Servlet提示 因为这是我们自己的servlet , 所以不识别, 没有关系, 直接忽略爆红..--servletservlet-nameHspCalServlet/servlet-nameservlet-classcom.hspedu.tomcat.servlet.HspCalServlet/servlet-class/servletservlet-mappingservlet-nameHspCalServlet/servlet-nameurl-pattern/hspCalServlet/url-pattern/servlet-mapping /web-appHspTomcatV3.java /*** 第3版的Tomcat, 实现通过xml反射来初始化容器*/ public class HspTomcatV3 {//1. 存放容器 servletMapping// -ConcurrentHashMap// -HashMap// key - value// ServletName 对应的实例public static final ConcurrentHashMapString, HspHttpServletservletMapping new ConcurrentHashMap();//2容器 servletUrlMapping// -ConcurrentHashMap// -HashMap// key - value// url-pattern ServletNamepublic static final ConcurrentHashMapString, StringservletUrlMapping new ConcurrentHashMap();//变强..public static void main(String[] args) {init();}//直接对两个容器进行初始化public static void init() {//读取web.xml dom4j //得到web.xml文件的路径 拷贝一份.String path HspTomcatV3.class.getResource(/).getPath();//System.out.println(path path);//使用dom4j技术完成读取SAXReader saxReader new SAXReader();//困难-真的掌握try {Document document saxReader.read(new File(path web.xml));System.out.println(document document);//得到根元素Element rootElement document.getRootElement();//得到根元素下面的所有元素ListElement elements rootElement.elements();//遍历并过滤到 servlet servlet-mappingfor (Element element : elements) {if (servlet.equalsIgnoreCase(element.getName())) {//这是一个servlet配置//System.out.println(发现 servlet);//使用反射将该servlet实例放入到servletMappingElement servletName element.element(servlet-name);Element servletClass element.element(servlet-class);servletMapping.put(servletName.getText(),(HspHttpServlet) Class.forName(servletClass.getText().trim()).newInstance());} else if (servlet-mapping.equalsIgnoreCase(element.getName())) {//这是一个servlet-mapping//System.out.println(发现 servlet-mapping);Element servletName element.element(servlet-name);Element urlPatter element.element(url-pattern);servletUrlMapping.put(urlPatter.getText(), servletName.getText());}}} catch (Exception e) {e.printStackTrace();}//验证这两个容器是否初始化成功System.out.println(servletMapping servletMapping);System.out.println(servletUrlMapping servletUrlMapping);} }2.3.3.4 优化4阶段 1.完善自定义Tomcat 2.修改优化代码 3.完善测试web.xml 改进HspTomcatV3 /*** 第3版的Tomcat, 实现通过xml反射来初始化容器*/ public class HspTomcatV3 {//1. 存放容器 servletMapping// -ConcurrentHashMap// -HashMap// key - value// ServletName 对应的实例public static final ConcurrentHashMapString, HspHttpServletservletMapping new ConcurrentHashMap();//2容器 servletUrlMapping// -ConcurrentHashMap// -HashMap// key - value// url-pattern ServletNamepublic static final ConcurrentHashMapString, StringservletUrlMapping new ConcurrentHashMap();//变强..public static void main(String[] args) {HspTomcatV3 hspTomcatV3 new HspTomcatV3();hspTomcatV3.init();//启动hsptomcat容器hspTomcatV3.run();}//启动HspTomcatV3容器public void run() {try {ServerSocket serverSocket new ServerSocket(8080);System.out.println(hsptomcatv3在8080监听);while (!serverSocket.isClosed()) {Socket socket serverSocket.accept();HspRequestHandler hspRequestHandler new HspRequestHandler(socket);new Thread(hspRequestHandler).start();}} catch (IOException e) {e.printStackTrace();}}//直接对两个容器进行初始化public void init() {//读取web.xml dom4j //得到web.xml文件的路径 拷贝一份.String path HspTomcatV3.class.getResource(/).getPath();//System.out.println(path path);//使用dom4j技术完成读取SAXReader saxReader new SAXReader();//困难-真的掌握try {Document document saxReader.read(new File(path web.xml));System.out.println(document document);//得到根元素Element rootElement document.getRootElement();//得到根元素下面的所有元素ListElement elements rootElement.elements();//遍历并过滤到 servlet servlet-mappingfor (Element element : elements) {if (servlet.equalsIgnoreCase(element.getName())) {//这是一个servlet配置//System.out.println(发现 servlet);//使用反射将该servlet实例放入到servletMappingElement servletName element.element(servlet-name);Element servletClass element.element(servlet-class);servletMapping.put(servletName.getText(),(HspHttpServlet) Class.forName(servletClass.getText().trim()).newInstance());} else if (servlet-mapping.equalsIgnoreCase(element.getName())) {//这是一个servlet-mapping//System.out.println(发现 servlet-mapping);Element servletName element.element(servlet-name);Element urlPatter element.element(url-pattern);servletUrlMapping.put(urlPatter.getText(), servletName.getText());}}} catch (Exception e) {e.printStackTrace();}//验证这两个容器是否初始化成功System.out.println(servletMapping servletMapping);System.out.println(servletUrlMapping servletUrlMapping);} } 改进HspRequestHandler /*** 1. HspRequestHandler 对象是一个线程对象* 2. 处理一个http请求的*/ public class HspRequestHandler implements Runnable {//定义Socketprivate Socket socket null;public HspRequestHandler(Socket socket) {this.socket socket;}Overridepublic void run() {//这里我们可以对客户端/浏览器进行IO编程/交互try {//这里我们先死后活HspRequest hspRequest new HspRequest(socket.getInputStream());//这里我们可以同HspResponse对象返回数据给浏览器/客户端HspResponse hspResponse new HspResponse(socket.getOutputStream());//1. 得到 uri 就是 servletUrlMapping 的 url-patternString uri hspRequest.getUri();String servletName HspTomcatV3.servletUrlMapping.get(uri);if (servletName null) {servletName ;}//2. 通过uri-servletName-servlet的实例 , 真正的运行类型是其子类 HspCalServletHspHttpServlet hspHttpServlet HspTomcatV3.servletMapping.get(servletName);//3. 调用service , 通过OOP的动态绑定机制调用运行类型的 doGet/doPostif (hspHttpServlet ! null) {//得到hspHttpServlet.service(hspRequest, hspResponse);} else {//没有这个servlet , 返回404的提示信息String resp HspResponse.respHeader h1404 Not Found/h1;OutputStream outputStream hspResponse.getOutputStream();outputStream.write(resp.getBytes());outputStream.flush();outputStream.close();}socket.close();} catch (IOException e) {e.printStackTrace();} finally {//最后一定确保socket要关闭if (socket ! null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} } 改进web.xml !DOCTYPE web-app PUBLIC-//Sun Microsystems, Inc.//DTD Web Application 2.3//ENhttp://java.sun.com/dtd/web-app_2_3.dtd web-appdisplay-nameArchetype Created Web Application/display-name!--配置自己设计的Servlet提示 因为这是我们自己的servlet , 所以不识别, 没有关系, 直接忽略爆红..--servletservlet-nameHspCalServlet/servlet-nameservlet-classcom.hspedu.tomcat.servlet.HspCalServlet/servlet-class/servletservlet-mappingservlet-nameHspCalServlet/servlet-nameurl-pattern/hspCalServlet/url-pattern/servlet-mapping!--多配置一个servlet--servletservlet-nameHsp6CalServlet/servlet-nameservlet-classcom.hspedu.tomcat.servlet.Hsp6CalServlet/servlet-class/servletservlet-mappingservlet-nameHsp6CalServlet/servlet-nameurl-pattern/hsp6CalServlet/url-pattern/servlet-mapping /web-app 增添Hsp6CalServlet public class Hsp6CalServlet extends HspHttpServlet {Overridepublic void doGet(HspRequest request, HspResponse response) {//java基础的 OOP 的动态绑定机制..//写业务代码完成计算任务int num1 WebUtils.parseInt(request.getParameter(num1), 0);int num2 WebUtils.parseInt(request.getParameter(num2), 0);int sum num1 * num2;//返回计算结果给浏览器//outputStream 和 当前的socket关联OutputStream outputStream response.getOutputStream();String respMes HspResponse.respHeader h1 num1 * num2 sum HspTomcatV3 - 反射xml创建/h1;try {outputStream.write(respMes.getBytes());outputStream.flush();outputStream.close();} catch (IOException e) {e.printStackTrace();}}Overridepublic void doPost(HspRequest request, HspResponse response) {}Overridepublic void init() throws Exception {}Overridepublic void destroy() {} } 2.4 小结 回顾 Tomcat 工作架构图 BIO线程模型 BIOBlocking I/O即同步阻塞 I/O是 Java 中最早使用的一种 I/O 模型。它的特点是使用传统的套接字Socket进行通信当服务端接收到客户端请求后为每个客户端连接创建一个新的线程进行处理因此这种模型也被称为“一请求一应答”模式。 BIO 线程模型的流程如下 服务端启动后通过 ServerSocket 等待客户端连接请求。客户端发起连接请求后服务端接收到请求并创建一个新的线程或使用线程池中的一个线程处理客户端的请求。服务端将接收到的数据存放到缓冲区中并处理客户端请求。服务端将处理结果返回给客户端并关闭连接。 需要注意的是BIO 模型中的线程数随着客户端连接数量的增加而增加如果客户端连接数量过多服务端可能会出现线程资源不足的情况。 NIO线程模型 NIONon-blocking I/O即非阻塞 I/O是 Java 中另一种 I/O 模型。相比于 BIO 模型它使用单个线程或少量线程来处理多个客户端的请求因此也被称为“多路复用”模式。 NIO 线程模型的流程如下 服务端启动后通过 ServerSocketChannel 等待客户端连接请求。客户端发起连接请求后服务端接收到请求并将其注册到 Selector 中由 Selector 监听客户端的事件。Selector 在监听到事件后将其分发给对应的线程进行处理例如读取客户端发送的数据。完成对客户端请求的处理后服务端将处理结果返回给客户端并关闭连接。 需要注意的是NIO 模型中使用单个线程或少量线程进行处理因此可以避免频繁创建线程造成的开销同时也能够提高系统的性能和吞吐量。但是在处理客户端请求时需要使用较为复杂的事件轮询机制。 3. 课后作业 cal.html !DOCTYPE html html langen headmeta charsetUTF-8title计算器/title /head body h1计算器/h1 form action/hspCalServlet methodgetnum1:input typetext namenum1br/num2:input typetext namenum2br/input typesubmit value提交 /form /body /htmlweb.xml servletservlet-nameHspCalServlet/servlet-nameservlet-classcom.hspedu.tomcat.servlet.HspCalServlet/servlet-class /servlet servlet-mappingservlet-nameHspCalServlet/servlet-nameurl-pattern/hspCalServlet/url-pattern /servlet-mappingWebUtils.java public class WebUtils {//将字符串转成数字方法public static int parseInt(String strNum, int defaultVal) {try {return Integer.parseInt(strNum);} catch (NumberFormatException e) {System.out.println(strNum 不能转成数字);}return defaultVal;}//判断uri是不是html文件public static boolean isHtml(String uri) {return uri.endsWith(.html);}//根据文件名来读取该文件-Stringpublic static String readHtml(String filename) {String path com.hspedu.utils.WebUtils.class.getResource(/).getPath();StringBuilder stringBuilder new StringBuilder();try {BufferedReader bufferedReader new BufferedReader(new FileReader(path filename));String buf ;while ((buf bufferedReader.readLine()) ! null) {stringBuilder.append(buf);}} catch (Exception e) {e.printStackTrace();}return stringBuilder.toString();} }HspRequestHandler.java /*** 老师解读* 1. HspRequestHandler 对象是一个线程对象* 2. 处理一个http请求的*/ public class HspRequestHandler implements Runnable {//定义Socketprivate Socket socket null;public HspRequestHandler(Socket socket) {this.socket socket;}Overridepublic void run() {//这里我们可以对客户端/浏览器进行IO编程/交互try {//这里我们先死后活HspRequest hspRequest new HspRequest(socket.getInputStream());//这里我们可以同HspResponse对象返回数据给浏览器/客户端HspResponse hspResponse new HspResponse(socket.getOutputStream());//1. 得到 uri 就是 servletUrlMapping 的 url-patternString uri hspRequest.getUri();//新增业务逻辑//(1) 判断uri是什么资源 工具方法//(2) 如果是静态资源,就读取该资源并返回给浏览器 content-type text/html//(3) 因为目前老师并没有起到tomcat, 不是一个标准的web项目//(4) 把读取的静态资源放到 target/classes/cal.html//拓展过滤拦截 , 权限等待 Handler.... 分发if(WebUtils.isHtml(uri)) {//就是静态页面String content WebUtils.readHtml(uri.substring(1));content HspResponse.respHeader content;//得到outputstream , 返回信息(静态页面)给浏览器OutputStream outputStream hspResponse.getOutputStream();outputStream.write(content.getBytes());outputStream.flush();outputStream.close();socket.close();return;}String servletName HspTomcatV3.servletUrlMapping.get(uri);if (servletName null) {servletName ;}//2. 通过uri-servletName-servlet的实例 , 真正的运行类型是其子类 HspCalServletHspHttpServlet hspHttpServlet HspTomcatV3.servletMapping.get(servletName);//3. 调用service , 通过OOP的动态绑定机制调用运行类型的 doGet/doPostif (hspHttpServlet ! null) {//得到hspHttpServlet.service(hspRequest, hspResponse);} else {//没有这个servlet , 返回404的提示信息String resp HspResponse.respHeader h1404 Not Found/h1;OutputStream outputStream hspResponse.getOutputStream();outputStream.write(resp.getBytes());outputStream.flush();outputStream.close();}socket.close();} catch (IOException e) {e.printStackTrace();} finally {//最后一定确保socket要关闭if (socket ! null) {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}} }/*** author 韩顺平* version 1.0* 第3版的Tomcat, 实现通过xml反射来初始化容器*/ public class HspTomcatV3 {//1. 存放容器 servletMapping// -ConcurrentHashMap// -HashMap// key - value// ServletName 对应的实例public static final ConcurrentHashMapString, HspHttpServletservletMapping new ConcurrentHashMap();//2容器 servletUrlMapping// -ConcurrentHashMap// -HashMap// key - value// url-pattern ServletNamepublic static final ConcurrentHashMapString, StringservletUrlMapping new ConcurrentHashMap();//你可以这里理解session, tomcat还维护一个容器public static final ConcurrentHashMapString, HttpSessionsessionMapping new ConcurrentHashMap();//你可以这里理解filter, tomcat还维护了filter的容器public static final ConcurrentHashMapString, StringfilterUrlMapping new ConcurrentHashMap();public static final ConcurrentHashMapString, FilterfilterMapping new ConcurrentHashMap();//变强..public static void main(String[] args) {HspTomcatV3 hspTomcatV3 new HspTomcatV3();hspTomcatV3.init();//启动hsptomcat容器hspTomcatV3.run();}//启动HspTomcatV3容器public void run() {try {ServerSocket serverSocket new ServerSocket(8080);System.out.println(hsptomcatv3在8080监听);while (!serverSocket.isClosed()) {Socket socket serverSocket.accept();HspRequestHandler hspRequestHandler new HspRequestHandler(socket);new Thread(hspRequestHandler).start();}} catch (IOException e) {e.printStackTrace();}}//直接对两个容器进行初始化public void init() {//读取web.xml dom4j //得到web.xml文件的路径 拷贝一份.String path HspTomcatV3.class.getResource(/).getPath();//System.out.println(path path);//使用dom4j技术完成读取SAXReader saxReader new SAXReader();//困难-真的掌握try {Document document saxReader.read(new File(path web.xml));System.out.println(document document);//得到根元素Element rootElement document.getRootElement();//得到根元素下面的所有元素ListElement elements rootElement.elements();//遍历并过滤到 servlet servlet-mappingfor (Element element : elements) {if (servlet.equalsIgnoreCase(element.getName())) {//这是一个servlet配置//System.out.println(发现 servlet);//使用反射将该servlet实例放入到servletMappingElement servletName element.element(servlet-name);Element servletClass element.element(servlet-class);servletMapping.put(servletName.getText(),(HspHttpServlet) Class.forName(servletClass.getText().trim()).newInstance());} else if (servlet-mapping.equalsIgnoreCase(element.getName())) {//这是一个servlet-mapping//System.out.println(发现 servlet-mapping);Element servletName element.element(servlet-name);Element urlPatter element.element(url-pattern);servletUrlMapping.put(urlPatter.getText(), servletName.getText());}}} catch (Exception e) {e.printStackTrace();}//验证这两个容器是否初始化成功System.out.println(servletMapping servletMapping);System.out.println(servletUrlMapping servletUrlMapping);} }
http://www.dnsts.com.cn/news/239175.html

相关文章:

  • 效果好的手机网站建设蓝天采集 wordpress
  • app网站建设教程视频教程旅游手机网站模板
  • 网站开发设计培训太原网站建设电话
  • 建设网站多少钱 2017网站建设网络推广公司有哪些
  • 有没有做面粉美食的网站无锡做网站设计
  • 好康的网站代码外贸站seo
  • 网站被攻击怎么让百度重新蜘蛛自动抓品牌宝网站认证
  • 公司网站模板制作ui设计师需要考什么证书
  • 宣城市政建设集团有限公司网站网站建设如何做账
  • 网站开发的基本条件企业网站源码怎么用
  • 网站怎么做认证吗网站开发技术案例
  • python做网站快么自助建站比较好的
  • 旅游网站设计方案怎么做公司宣传册设计与制作模板
  • 深圳市建工建设集团有限公司官网怎么提高网站seo优化关键字排名
  • 广东省网上注册公司流程网站seo关键字优化
  • 湘潭网站建设搭建如何自己做网站赚钱
  • 上海网站建设服务分录天津建设厅网站
  • 标签云wordpress网站排名优化公司哪家好
  • 国内网页设计网站建设自助创建网站
  • 厦门哪家网站建设最好个人对网络营销的看法
  • 曼斯特(北京)网站建设公司游戏网站的导航条怎么做的
  • 网上网站开发前端开发遇到的问题及解决方法
  • 什么网站做新产品代理seo优化方向
  • 易语言做返利网站石家庄智能网站建设
  • 网站网页直播怎么做的购物便宜的网站有哪些
  • 网站建设十佳关于进行网站建设费用的请示
  • 国内做的比较简洁的网站权威的合肥网站建设
  • 网站建设与制作价格企业邮箱电话人工服务24小时
  • 网站运营如何做桂林临桂区建设局网站
  • 网站关键词搜索排名怎么做安居客官网网站