Всем привет, в этой главе мы реализуем упрощенную версию tomcat. Если у вас есть какие-либо вопросы, пожалуйста, свяжитесь со мной по адресу mr_beany@163.com. Также попросите руководства великих богов, спасибо
Работа программы необходима для поддержки сервера, и tomcat глубоко любим энтузиастами Java и признан некоторыми разработчиками программного обеспечения из-за его стабильной работы и бесплатной производительности.В настоящее время это популярный сервер веб-приложений.
Итак, как именно это работает? Сегодня мы реализуем упрощенную версию tomcat, чтобы это почувствовать.
Один: импортируйте пакет jar, который анализирует xml
<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);
}
}
Третий: реализовать запрос и ответ
Запрос — это инкапсуляция запроса браузера, а Ответ — это ответ на запрос браузера. Другими словами, Запрос используется для получения информации о запросе, а Ответ используется для добавления информации, которая должна быть возвращена в браузер. .
Создать Запрос.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;
}
}
Создать ответ.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;
}
}
Четвертое: реализовать сервлет
сделать интерфейс
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);
}
Затем реализуйте свой собственный сервлет
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
Здесь настраивается соответствующее отношение сервлета пути запроса, а файл помещается в папку ресурсов
<?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();
}
Девять: Тест
Начните запускать основной метод void в tomcat.java.
Следующие слова появляются, чтобы указать, что запуск прошел успешно, а затем введите в адресной строке
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();
перезагрузиться, посетить
конец
Желаю всем счастливого Нового года. Спасибо за поддержку!
Другие статьи:
Создайте свой собственный фоновый фреймворк SpringBoot с нуля
Адрес облака кода:git ee.com/bean также/no SPR…
Адрес гитхаба:GitHub.com/my bean also/no s…