手寫tomcat+servlet
阿新 • • 發佈:2018-11-30
寫程式一定要有思路,思路很重要!
一、我們分兩步第一步先實現手寫tomcat,第二部寫servlet
所用技術:
1、soket通訊 IO流
2、http請求與相應
3、解析xml
4、java反射技術
匯入所需要的jar:
<dependencies> <!-- https://mvnrepository.com/artifact/dom4j/dom4j --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency> </dependencies>
專案目錄結構:
現在開始我們的第一步,手寫tomcat
新建 Request 類:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; 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 類:
import java.io.IOException; import java.io.OutputStream; public class Response { public OutputStream outputStream; public String wirte; public static final String responseHeader="HTTP/1.1 200 \r\n" + "Content-Type: text/html\r\n" + "\r\n"; public Response(OutputStream outputStream) throws IOException { this.outputStream= outputStream; } public String getWirte() { return wirte; } public void setWirte(String wirte) { this.wirte = wirte; } }
SocketProcess 類:
import java.io.OutputStream;
import java.net.Socket;
import java.util.Map;
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());
// Map<String, Object> map = Mytomcat.servletMapping;
//
// System.out.println("map大小為:"+map.size());
// for (Map.Entry<String, Object> entry : map.entrySet()) {
// System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
// }
//從對映中找
System.out.println(request.getUrl());
String servelName = (String) Mytomcat.servletMapping.get(request.getUrl());
System.out.println(servelName);
if(servelName!=null && !servelName.isEmpty()) {
//對映有的話找到對應的物件
Servelt servlet = (Servelt) Mytomcat.servlet.get(servelName);
if(servlet!=null) {
servlet.doGet(request, response);
}else {
System.out.println("找不到對應的servlet");
}
}else {
System.out.println("找不到對應的servletMapping");
}
String res = Response.responseHeader+response.getWirte();
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();
}
}
}
}
}
Mytomcat
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 org.dom4j.Element;
public class Mytomcat {
private static final int port = 8099;
public static final HashMap<String, Object> servletMapping = new HashMap<String, Object>();
public static final HashMap<String, Object> servlet = new HashMap<String, Object>();
private void init() {
InputStream io = null;
String basePath;
try {
System.out.println("載入配置檔案開始");
//讀取web.xml
UtilsXml xml = new UtilsXml(UtilsXml.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) {
servletMapping.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();
}
}
}
}
private void start() {
try {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("Tomcat 服務已啟動,地址:localhost ,埠:" + port);
this.init();
//持續監聽
do {
Socket socket = serverSocket.accept();
System.out.println(socket);
//處理任務
Thread thread = new SocketProcess(socket);
thread.start();
} while (true);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
Mytomcat tomcat = new Mytomcat();
tomcat.start();
}
}
UtilsXml:
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
public class UtilsXml {
//定義解析器和文件物件
public SAXReader saxReader;
public Document document;
public UtilsXml(String path){
//獲取解析器
saxReader = new SAXReader();
try {
//獲取文件物件
document = saxReader.read(path);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 根據節點名稱獲取內容
* @param name 節點名稱
* @return 節點內容
*/
public String getElementText(String name){
//定位根節點
Element root = document.getRootElement();
List<Element> mapp = root.elements("servlet-mapping");
List<Element> servlet = root.elements("servlet");
String serveltName = "";
String classpath = "";
for (Element e : mapp) {
// System.out.println(e.element("url-pattern").getText());
if(e.element("url-pattern").getText().equals(name)){
serveltName = e.element("servlet-name").getText();
break;
}
}
for (Element e : servlet) {
// System.out.println(e.element("servlet-name").getText());
if(e.element("servlet-name").getText().equals(serveltName)){
classpath = e.element("servlet-class").getText();
break;
}
}
return classpath;
// //根據名稱定位節點
// Element element = root.element(name);
// //返回節點內容
// return element.getText();
}
/**
* 獲取節點下的所有節點
* @param root
* @param name
* @return
*/
public List<Element> getNodes(String name){
Element root = document.getRootElement();
return root.elements(name);
}
public static void main(String[] args) {
UtilsXml xml = new UtilsXml(UtilsXml.class.getResource("/")+"web.xml");
//System.out.println(xml.getElementText("/myhtml.html"));
List<Element> list = xml.getNodes("servlet");
for (Element element : list) {
System.out.println(element.element("servlet-name").getText() );
System.out.println(element.element("servlet-class").getText() );
}
}
Servelt 抽象類:
import com.siyuan.http.Request;
import com.siyuan.http.Response;
public abstract class Servelt {
public void service(Request request, Response response) {
//判斷是呼叫doget 還是 dopost
if ("get".equalsIgnoreCase(request.getMethod())) {
this.doGet(request, response);
} else {
this.doPost(request, response);
}
}
public abstract void doGet(Request request, Response response);
public abstract void doPost(Request request, Response response);
}
第一個servlet :
import com.siyuan.http.Request;
import com.siyuan.http.Response;
public class MyfisrtServlet extends Servelt {
@Override
public void doGet(Request request, Response response) {
System.out.println("進入了我的第一個servlet");
response.setWirte("進入了第一個servlet");
}
@Override
public void doPost(Request request, Response response) {
}
}
第二個servlet:
import com.siyuan.http.Request;
import com.siyuan.http.Response;
public class ScoendServlet extends Servelt{
@Override
public void doGet(Request request, Response response) {
System.out.println("進入了我的第二個servlet");
response.setWirte("進入了第二個servlet");
}
@Override
public void doPost(Request request, Response response) {
// TODO Auto-generated method stub
}
}
新建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>myhtml.html</servlet-name>
<servlet-class>com.siyuan.servlet.MyfisrtServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myhtml.html</servlet-name>
<url-pattern>/myhtml.html</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>myhtml2.html</servlet-name>
<servlet-class>com.siyuan.servlet.ScoendServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myhtml2.html</servlet-name>
<url-pattern>/myhtml2.html</url-pattern>
</servlet-mapping>
</web-app>
執行效果:
有問題討論可以加群一起討論:
600922504