宁波网站设计推广服务公司,建筑业务网站建设,wordpress首页美化,wordpress引用文件文章目录 1.Tomcat整体架构分析自己理解 2.第一阶段1.实现功能2.代码1.TomcatV1.java 3.调试阶段1.阻塞在readLine导致无法返回结果 4.结果演示 3.第二阶段1.实现功能2.代码1.RequestHander.java2.TomcatV2.java 3.调试阶段1.发现每次按回车会接受到两次请求 4.结果演示 4.第三… 文章目录 1.Tomcat整体架构分析自己理解 2.第一阶段1.实现功能2.代码1.TomcatV1.java 3.调试阶段1.阻塞在readLine导致无法返回结果 4.结果演示 3.第二阶段1.实现功能2.代码1.RequestHander.java2.TomcatV2.java 3.调试阶段1.发现每次按回车会接受到两次请求 4.结果演示 4.第三阶段1.实现功能2.总体框架3.代码实现1.封装Request1.Request.java2.RequestHander.java单元测试报错Sock is closed原因修改之后 2.封装Response3.Response.java4.RequestHander.java单元测试无误 3.设计servlet规范5.Servlet.java6.HttpServlet.java7.CalServlet.java8.WebUtils.java9.RequestHander.java单元测试无误 4.xml 反射初始化容器10.web.xml11.TomcatV3.java12.RequestHander.java 4.总体调试阶段1.空指针异常 5.结果演示 5.课后作业1.更新WebUtils.java添加方法 2.修改RequestHander.java3.cal.html4.调试阶段5.结果展示 1.Tomcat整体架构分析 自己理解
pdf下载 2.第一阶段
1.实现功能
编写自己的Tomcat能接受浏览器的请求并返回结果
2.代码
1.TomcatV1.java
package Tomcat;import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;/*** author 孙显圣* version 1.0* 第一个版本的可以接收浏览器的请求并返回信息*/
public class TomcatV1 {public static void main(String[] args) throws Exception {//在8080端口监听ServerSocket serverSocket new ServerSocket(8081);System.out.println(Tomcat在8080端口监听);//只要不是手动关闭服务则循环获取连接while (!serverSocket.isClosed()) {//获取连接Socket accept serverSocket.accept();//获取输入流InputStream inputStream accept.getInputStream();//使用转换流转为bufferedreader可以读取一行BufferedReader bufferedReader new BufferedReader(new InputStreamReader(inputStream, utf-8));//字符串缓冲区String buff null;while ((buff bufferedReader.readLine()) ! null) {//readline()在网络编程中只有客户端的连接关闭了才会返回null,所以如果不设置别的判定条件退出则会阻塞//由于请求信息最后有一个\r\n读到这个\r\n会返回一个就可以退出了if (buff.equals()) {break;}System.out.println(buff);}//tomcat向浏览器发送http响应\r\n是换行String respHead HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n; //响应头下面要空一行才能写响应体所以两个换行String resp respHead h1hello world!/h1;//获取输出流OutputStream outputStream accept.getOutputStream();//输出outputStream.write(resp.getBytes());//关闭outputStream.flush();outputStream.close();inputStream.close();accept.close();}}
}
3.调试阶段
1.阻塞在readLine导致无法返回结果
最开始我并没有添加如果readLine()读到就退出循环的逻辑后来发现readLine()在网络编程中只有浏览器端关闭连接才会返回null当读到了请求的\r\n的时候就会返回一个字符串然后阻塞在这里等待输入所以在循环中添加当读到\r\n即返回的时候退出即可
4.结果演示 3.第二阶段
1.实现功能
BIO线程模型支持多线程 2.代码
1.RequestHander.java
package Tomcat.handler;import java.io.*;
import java.net.Socket;/*** author 孙显圣* version 1.0* 处理http请求的线程类*/
public class RequestHander implements Runnable{//定义一个socket属性private Socket socket null;public RequestHander(Socket socket) {this.socket socket;}public void run() {//可以对客户端或浏览器进行交互try {//获取输入流InputStream inputStream socket.getInputStream();//转换成BufferedReader,方便按行读取BufferedReader bufferedReader new BufferedReader(new InputStreamReader(inputStream, utf-8));System.out.println(tomcatV2接受到浏览器的数据如下);//接受数据//设置缓冲String buff null;//循环读取while ((buff bufferedReader.readLine()) ! null) {//判断是否读取到了\r\nif (buff.equals()) {break; //读取完毕则退出循环避免readLine阻塞}System.out.println(buff);}//获取输出流返回信息到浏览器OutputStream outputStream socket.getOutputStream();String respHead HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n; //响应头下面要空一行才能写响应体所以两个换行String resp respHead h1hello 孙显圣!/h1;outputStream.write(resp.getBytes());//关闭outputStream.flush();outputStream.close();inputStream.close();socket.close();} catch (IOException e) {throw new RuntimeException(e);} finally {//确保关闭if (socket ! null) {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}}
}
2.TomcatV2.java
package Tomcat;import Tomcat.handler.RequestHander;import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;/*** author 孙显圣* version 1.0*/
public class TomcatV2 {public static void main(String[] args) throws IOException {//在8080端口监听ServerSocket serverSocket new ServerSocket(8080);System.out.println(TomcatV2在8080端口监听);//只要没有手动关闭则服务一直开启循环监听while (!serverSocket.isClosed()) {Socket socket serverSocket.accept();//将获取的socket交给线程类来处理RequestHander requestHander new RequestHander(socket);Thread thread new Thread(requestHander);thread.start(); //启动线程}}
}
3.调试阶段
1.发现每次按回车会接受到两次请求 原因就是每次请求还要请求一下页面的小图标 4.结果演示 4.第三阶段
1.实现功能 2.总体框架 3.代码实现
1.封装Request
1.Request.java
package Tomcat.http;/*** author 孙显圣* version 1.0*/import java.io.*;
import java.util.HashMap;/*** 1.Request的作用就是封装http请求的数据 GET /tomcatv2?a9b3 HTTP/1.1* 2.比如methodget uri/tomcat/cal还有参数列表num1num2* 3.相当于原生的HttpServletRequest*/
public class Request {private String method;private String uri;//存放参数列表private HashMapString, String parametersMapping new HashMapString, String();//构造方法获取inputStream来封装信息public Request(InputStream inputStream) throws IOException {//转换成BufferedReaderBufferedReader bufferedReader new BufferedReader(new InputStreamReader(inputStream, utf-8));//读取第一行String s bufferedReader.readLine();//将内容封装到属性String[] split s.split( );method split[0];//判断是否有参数列表int index split[1].indexOf(?);if (index -1) { //没有参数列表uri split[1];}else { //有参数列表uri split[1].substring(0,index);String parameters split[1].substring(index 1, split[1].length());String[] split1 parameters.split(); //分割参数//判断后面是否有东西if (split1 ! null !.equals(split1)) {//遍历参数for (String parameterPair : split1) {String[] split2 parameterPair.split();parametersMapping.put(split2[0],split2[1]);}}}//不能关闭否则socket也就关闭了
// inputStream.close();}public String getMethod() {return method;}public String getUri() {return uri;}public String getParameter(String name) {if (parametersMapping.containsKey(name)) {return parametersMapping.get(name);}else {return null;}}}
2.RequestHander.java
package Tomcat.handler;import Tomcat.http.Request;import java.io.*;
import java.net.Socket;/*** author 孙显圣* version 1.0* 处理http请求的线程类*/
public class RequestHander implements Runnable {//定义一个socket属性private Socket socket null;public RequestHander(Socket socket) {this.socket socket;}public void run() {//可以对客户端或浏览器进行交互try {//获取输入流InputStream inputStream socket.getInputStream();//封装到Request里Request request new Request(inputStream);//获取数据System.out.println(request.getUri() request.getMethod());System.out.println(request.getParameter(num1) request.getParameter(num2) request.getParameter(num3));//获取输出流返回信息到浏览器OutputStream outputStream socket.getOutputStream();String respHead HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n; //响应头下面要空一行才能写响应体所以两个换行String resp respHead h1hello 孙显圣!/h1;outputStream.write(resp.getBytes());//关闭outputStream.flush();outputStream.close();inputStream.close();socket.close();} catch (IOException e) {throw new RuntimeException(e);} finally {//确保关闭if (socket ! null) {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}}
}
单元测试报错Sock is closed 原因
在Request.java中获取完参数顺便把inputStream关闭了导致了Socket也一起关闭了使得主线程在使用socket的时候出现了已经关闭的错误 修改之后 2.封装Response
3.Response.java
package Tomcat.http;/*** author 孙显圣* version 1.0*/import java.io.OutputStream;/*** 1.这个response对象可以封装OutputSream* 2.即可以通过这个对象返回http响应给浏览器* 3.相当于原生的HttpServletResponse*/
public class Response {private OutputStream outputStream null;//封装一个响应头public static final String respHeader HTTP/1.1 200 OK\r\n Content-Type: text/html;charsetutf-8\r\n\r\n; //响应头下面要空一行才能写响应体所以两个换行public Response(OutputStream outputStream) {this.outputStream outputStream;}//以后再Servlet里面获取输出流public OutputStream getOutputStream() {return outputStream;}
}
4.RequestHander.java
package Tomcat.handler;import Tomcat.http.Request;
import Tomcat.http.Response;import java.io.*;
import java.net.Socket;/*** author 孙显圣* version 1.0* 处理http请求的线程类*/
public class RequestHander implements Runnable {//定义一个socket属性private Socket socket null;public RequestHander(Socket socket) {this.socket socket;}public void run() {//可以对客户端或浏览器进行交互try {//获取输入流InputStream inputStream socket.getInputStream();//封装到Request里Request request new Request(inputStream);//获取数据System.out.println(request.getUri() request.getMethod());System.out.println(request.getParameter(num1) request.getParameter(num2) request.getParameter(num3));//获取输出流返回信息到浏览器OutputStream outputStream socket.getOutputStream();//封装到Response对象中Response response new Response(outputStream);//获取输出流输出信息OutputStream outputStream1 response.getOutputStream();outputStream1.write((response.respHeader h1response响应你好孙显圣/h1).getBytes());//关闭outputStream.flush();outputStream.close();inputStream.close();socket.close();} catch (IOException e) {throw new RuntimeException(e);} finally {//确保关闭if (socket ! null) {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}}
}
单元测试无误 3.设计servlet规范
5.Servlet.java
package Tomcat.servlet;import Tomcat.http.Request;
import Tomcat.http.Response;import java.io.IOException;/*** author 孙显圣* version 1.0* 保留三个核心方法*/
public interface Servlet {void init() throws Exception;void service(Request request, Response response) throws IOException;void destroy();
}
6.HttpServlet.java
package Tomcat.servlet;import Tomcat.http.Request;
import Tomcat.http.Response;import java.io.IOException;/*** author 孙显圣* version 1.0*/
public abstract class HttpServlet implements Servlet {public void service(Request request, Response response) throws IOException {//抽象模板设计模式判断类型来决定调用什么方法if (GET.equalsIgnoreCase(request.getMethod())) {//以后会反射创建子类实例调用子类的service方法子类没有就从父类找然后再使用动态绑定到子类的doGet方法this.doGet(request, response);} else if (POST.equalsIgnoreCase(request.getMethod())) {this.doPost(request, response);}}public abstract void doGet(Request request, Response response);public abstract void doPost(Request request, Response response);}
7.CalServlet.java
package Tomcat.servlet;import Tomcat.http.Request;
import Tomcat.http.Response;
import Tomcat.utils.WebUtils;import java.io.IOException;
import java.io.OutputStream;/*** author 孙显圣* version 1.0*/
public class CalServlet extends HttpServlet {public void doGet(Request request, Response response) {//完成计算任务int num1 WebUtils.parseInt(request.getParameter(num1), 0);int num2 WebUtils.parseInt(request.getParameter(num2), 0);int sum num1 num2;//返回计算结果给浏览器OutputStream outputStream response.getOutputStream();String resp Response.respHeader h1 num1 num2 sum /h1;try {outputStream.write(resp.getBytes());//关闭outputStream.flush();outputStream.close();} catch (IOException e) {throw new RuntimeException(e);}}public void doPost(Request request, Response response) {this.doGet(request, response);}public void init() throws Exception {}public void destroy() {}
}
8.WebUtils.java
package Tomcat.utils;/*** author 孙显圣* version 1.0*/
public class WebUtils {//把String类型转换成int类型如果是非整数则返回默认值public static int parseInt(String str, int defaultVal) {try {return Integer.parseInt(str);} catch (NumberFormatException e) {System.out.println(转换失败);}return defaultVal;}}
9.RequestHander.java
package Tomcat.handler;import Tomcat.http.Request;
import Tomcat.http.Response;
import Tomcat.servlet.CalServlet;import java.io.*;
import java.net.Socket;/*** author 孙显圣* version 1.0* 处理http请求的线程类*/
public class RequestHander implements Runnable {//定义一个socket属性private Socket socket null;public RequestHander(Socket socket) {this.socket socket;}public void run() {//可以对客户端或浏览器进行交互try {//获取输入流InputStream inputStream socket.getInputStream();//封装到Request里Request request new Request(inputStream);//获取输出流返回信息到浏览器OutputStream outputStream socket.getOutputStream();//封装到Response对象中Response response new Response(outputStream);CalServlet calServlet new CalServlet();calServlet.service(request,response); //这个会调用他抽象父类的service方法inputStream.close();socket.close();} catch (IOException e) {throw new RuntimeException(e);} finally {//确保关闭if (socket ! null) {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}}
}
单元测试无误 4.xml 反射初始化容器 10.web.xml 11.TomcatV3.java
package Tomcat;import Tomcat.handler.RequestHander;
import Tomcat.servlet.HttpServlet;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;/*** author 孙显圣* version 1.0*/
public class TomcatV3 {//设置两个hashmap容器在启动的Tomcat的时候就初始化//存放名字和实例public static final ConcurrentHashMapString, HttpServletservletMapping new ConcurrentHashMapString, HttpServlet();//存放路径和名字public static final ConcurrentHashMapString, StringservletUrlMapping new ConcurrentHashMapString, String();public static void main(String[] args) throws MalformedURLException, DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException {TomcatV3 tomcatV3 new TomcatV3();tomcatV3.init();tomcatV3.run();}//启动TomcatV3容器public void run() {try {ServerSocket serverSocket new ServerSocket(8080);System.out.println(TomcatV3在8080端口监听);while (!serverSocket.isClosed()) { //只要没有手动关闭服务就循环获取连接Socket socket serverSocket.accept();//将socket交给线程处理RequestHander requestHander new RequestHander(socket);new Thread(requestHander).start(); //启动线程}} catch (IOException e) {throw new RuntimeException(e);}}private void init() throws MalformedURLException, DocumentException, ClassNotFoundException, InstantiationException, IllegalAccessException {//获取该类的路径String path TomcatV3.class.getResource(/).getPath();//使用dom4j读取web.xml文件//获取解析器SAXReader saxReader new SAXReader();//读取文件Document read saxReader.read(new File(path web.xml));//获取根元素Element rootElement read.getRootElement();//获取所有二级元素ListElement servlet rootElement.elements();//遍历所有二级元素根据不同类型做处理for (Element element : servlet) {if (servlet.equalsIgnoreCase(element.getName())) {//获取名字和全类名Element servletName element.element(servlet-name);Element servletClass element.element(servlet-class);//通过反射创建实例Class? aClass Class.forName(servletClass.getText().trim()); //trim是清除空格HttpServlet httpServlet (HttpServlet) aClass.newInstance();//将其放到容器中去servletMapping.put(servletName.getText(), httpServlet);} else if (servlet-mapping.equalsIgnoreCase(element.getName())) {//获取名字和urlElement servletName element.element(servlet-name);Element servletUrl element.element(url-pattern);//将其放到容器中去servletUrlMapping.put(/tomcat servletUrl.getText(), servletName.getText());}}}}
12.RequestHander.java
package Tomcat.handler;import Tomcat.TomcatV3;
import Tomcat.http.Request;
import Tomcat.http.Response;
import Tomcat.servlet.CalServlet;
import Tomcat.servlet.HttpServlet;import java.io.*;
import java.net.Socket;/*** author 孙显圣* version 1.0* 处理http请求的线程类*/
public class RequestHander implements Runnable {//定义一个socket属性private Socket socket null;public RequestHander(Socket socket) {this.socket socket;}public void run() {//可以对客户端或浏览器进行交互try {//获取输入流InputStream inputStream socket.getInputStream();//封装到Request里Request request new Request(inputStream);//获取输出流返回信息到浏览器OutputStream outputStream socket.getOutputStream();//封装到Response对象中Response response new Response(outputStream);String uri request.getUri();String servletName TomcatV3.servletUrlMapping.get(uri);if (servletName null) {servletName ;}HttpServlet httpServlet TomcatV3.servletMapping.get(servletName);//判断是否得到了这个对象if (httpServlet ! null) {httpServlet.service(request, response);} else {//没有得到则返回404String resp Response.respHeader h1404 not found/h1;response.getOutputStream().write(resp.getBytes());}inputStream.close();socket.close();} catch (IOException e) {throw new RuntimeException(e);} finally {//确保关闭if (socket ! null) {try {socket.close();} catch (IOException e) {throw new RuntimeException(e);}}}}
}
4.总体调试阶段
1.空指针异常 5.结果演示 5.课后作业 1.更新WebUtils.java
添加方法 //判断是不是html格式的文件如果是就直接读取文件内容并且返回truepublic static boolean isHtml(String uri, Response response) {//使用正则表达式匹配html文件String regStr (/.*)*/(.*\\.html);Pattern compile Pattern.compile(regStr);Matcher matcher compile.matcher(uri);if (!matcher.find()) { //没匹配到就直接返回falsereturn false;}//得到html文件的路径String path D:\\Intelij IDEA Project\\java_web\\tomcat\\target\\classes\\ matcher.group(2);System.out.println(path);//根据路径读取文件并存放到StringBuilder中StringBuilder stringBuilder new StringBuilder();try {BufferedReader bufferedReader new BufferedReader(new FileReader(path));String buf null;while ((buf bufferedReader.readLine()) ! null) {stringBuilder.append(buf); //存放到stringBuilder中}//将stringBuilder的内容响应给浏览器String resp Response.respHeader stringBuilder.toString();response.getOutputStream().write(resp.getBytes());}catch (Exception e) {System.out.println(文件找不到);return false; //返回false之后就会继续进行原来的逻辑弹出404}//如果不出异常则说明响应成功return true;}2.修改RequestHander.java 3.cal.html
!DOCTYPE html
html langen
headmeta charsetUTF-8titleTitle/title
/head
body
form action/tomcat/CalServlet methodgetnum1:input typetext namenum1num2:input typetext namenum2input typesubmit value提交
/form
/body
/html4.调试阶段
一直显示我的cal.html文件找不到调了半个小时原因是String path TomcatV3.class.getResource(/).getPath();使用这个来获取的路径没有空格而我的资源路径是这个D:\\Intelij IDEA Project\\java_web\\tomcat\\target\\classes\\中间带了空格真的是醉了深刻体会到文件夹起名不要带空格的重要性了
5.结果展示