内容简介:Hello大家好,本章我们自己实现一个简易版的tomcat 。有问题可以联系我mr_beany@163.com。另求各路大神指点,感谢程序的运行少不了服务器的支持,而tomcat因其性能稳定,免费等优点,深受 Java 爱好者的喜爱并得到了部分软件开发商的认可,为目前比较流行的 Web 应用服务器。那么到底它是怎么运行的呢?今天我们来实现一个简化版tomcat来感受一下。
Hello大家好,本章我们自己实现一个简易版的tomcat 。有问题可以联系我mr_beany@163.com。另求各路大神指点,感谢
程序的运行少不了服务器的支持,而tomcat因其性能稳定,免费等优点,深受 Java 爱好者的喜爱并得到了部分软件开发商的认可,为目前比较流行的 Web 应用服务器。
那么到底它是怎么运行的呢?今天我们来实现一个简化版tomcat来感受一下。
一:导入解析xml的jar包
<dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency>复制代码
二:编写XML解析类
package com.example.demo.utils; import java.util.List; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.io.SAXReader; /** * @author zy */ public class XmlUtils { /** * 定义解析器和文档对象 */ public SAXReader saxReader; public Document document; public XmlUtils(String path) { //获取解析器 saxReader = new SAXReader(); try { //获取文档对象 document = saxReader.read(path); } catch (DocumentException e) { e.printStackTrace(); } } /** * 获取节点下的所有节点 * * @param name * @return */ public List<Element> getNodes(String name) { Element root = document.getRootElement(); return root.elements(name); } } 复制代码
三:实现Request和Response
其中Request是对浏览器的请求的封装,而Response是对浏览器请求的响应,换而言之就是Request 用来取出请求信息,而 Response 则用来添加要返回给浏览器的信息。
创建Request.java
package com.example.demo.http; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; /** * @author zy */ public class Request { private String method; private String url; public Request(InputStream inputStream) throws IOException { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); String[] methodAndUrl = bufferedReader.readLine().split(" "); this.method = methodAndUrl[0]; this.url = methodAndUrl[1]; System.out.println("请求类型:"+ method); System.out.println("请求路径:"+ url); } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } }复制代码
创建Response.java
package com.example.demo.http; import java.io.OutputStream; /** * @author zy */ public class Response { private OutputStream outputStream; private String write; public Response(OutputStream outputStream){ this.outputStream = outputStream; } public String getWrite() { return write; } public void setWrite(String write) { this.write = write; } }复制代码
四:实现Servlet
先做个接口
package com.example.demo.servlet; import com.example.demo.http.Request; import com.example.demo.http.Response; /** * @author zy */ public abstract class AbstractServlet { public abstract void doGet(Request request, Response response); public abstract void doPost(Request request, Response response); }复制代码
再来实现自己的Servlet
package com.example.demo.servlet; import com.example.demo.http.Request; import com.example.demo.http.Response; /** * @author zy */ public class FirstServlet extends AbstractServlet { @Override public void doGet(Request request, Response response) { response.setWrite("我的第一个Servlet"); } @Override public void doPost(Request request, Response response) { this.doGet(request, response); } }复制代码
五:创建web.xml
这里配置了请求路径的servlet的对应关系,文件放在resources文件夹下
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>first.html</servlet-name> <servlet-class>com.example.demo.servlet.FirstServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>first.html</servlet-name> <url-pattern>/first.html</url-pattern> </servlet-mapping> </web-app>复制代码
六,创建tomcat,初始化配置文件
package com.example.demo.tomcat; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.HashMap; import java.util.List; import com.example.demo.utils.XmlUtils; import org.dom4j.Element; /** * @author zy */ public class Tomcat { /** * 设置端口号 */ private static final int PORT = 8080; public static final HashMap<String, Object> SERVLET_MAPPING = new HashMap<>(); public static final HashMap<String, Object> SERVLET = new HashMap<>(); /** * 控制服务器启动关闭 */ public boolean tomcatStarBool = true; private void init() { InputStream io = null; try { System.out.println("加载配置文件开始"); //读取配置文件 XmlUtils xml = new XmlUtils(XmlUtils.class.getResource("/")+"web.xml"); //将所有的类都存储到容器中 List<Element> list = xml.getNodes("servlet"); for (Element element : list) { SERVLET.put(element.element("servlet-name").getText(), Class.forName(element.element("servlet-class").getText()).newInstance()); } //映射关系创建 List<Element> list2 = xml.getNodes("servlet-mapping"); for (Element element : list2) { SERVLET_MAPPING.put(element.element("url-pattern").getText(), element.element("servlet-name").getText()); } System.out.println("加载配置文件结束"); } catch (Exception ex) { ex.printStackTrace(); } finally { if (io != null) { try { io.close(); } catch (Exception e) { e.printStackTrace(); } } } } }复制代码
七:创建处理请求任务的SocketProcess
package com.example.demo.tomcat; import com.example.demo.http.Request; import com.example.demo.http.Response; import com.example.demo.servlet.AbstractServlet; import java.io.OutputStream; import java.net.Socket; /** * @author zy */ public class SocketProcess extends Thread{ protected Socket socket; public SocketProcess(Socket socket){ this.socket = socket; } @Override public void run() { try { Request request = new Request(socket.getInputStream()); Response response = new Response(socket.getOutputStream()); String servletName = (String) Tomcat.SERVLET_MAPPING.get(request.getUrl()); if(servletName!=null && !servletName.isEmpty()) { //映射有的话找到对应的对象 AbstractServlet servlet = (AbstractServlet) Tomcat.SERVLET.get(servletName); if(servlet!=null) { servlet.doGet(request, response); }else { System.out.println("找不到对应的servlet"); } }else { System.out.println("找不到对应的servletMapping"); } String res = response.getWrite(); OutputStream outputStream = socket.getOutputStream(); outputStream.write(res.getBytes("GBK")); outputStream.flush(); outputStream.close(); }catch (Exception ex){ ex.printStackTrace(); }finally { if (socket != null) { try { socket.close(); } catch (Exception e) { e.printStackTrace(); } } } } }复制代码
八:在tomcat.java中添加启动方法
private void start() { try { ServerSocket serverSocket = new ServerSocket(PORT); System.out.println("Tomcat 服务已启动,地址:localhost ,端口:" + PORT); this.init(); //持续监听 do { Socket socket = serverSocket.accept(); //处理任务 Thread thread = new SocketProcess(socket); thread.start(); } while (tomcatStarBool); } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { Tomcat tomcat = new Tomcat(); tomcat.start(); }复制代码
九:测试
启动在tomcat.java中运行void main方法
出现如下字样代表启动成功,然后地址栏中输入
http://localhost:8080/first.html
?????为什么是这样。。。。。。
啊!原来没有添加响应头信息
Response.java中加入
/** * 响应头信息 */ public static final String RESPONSE_HEADER ="HTTP/1.1 200 \r\n" + "Content-Type: text/html\r\n" + "\r\n";复制代码
SocketProcess.java中
String res = response.getWrite();复制代码
改成
String res = Response.RESPONSE_HEADER + response.getWrite();复制代码
重新启动,访问
结尾
祝大家新年快乐。感谢支持!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
ANSI Common Lisp
Paul Graham / Prentice Hall / 1995-11-12 / USD 116.40
For use as a core text supplement in any course covering common LISP such as Artificial Intelligence or Concepts of Programming Languages. Teaching students new and more powerful ways of thinking abo......一起来看看 《ANSI Common Lisp》 这本书的介绍吧!