1)提供服务,接收请求(Socket通信)
2)请求信息封装成Request对象(Response对象)
3)客户端请求资源,资源分为静态资源(html)和动态资源(Servlet)
4)资源返回给客户端浏览器
2.流程图 3.pom文件配置
4.0.0
org.example
SimpleTomCat
1.0-SNAPSHOT
8
8
org.projectlombok
lombok
1.18.22
dom4j
dom4j
1.6.1
jaxen
jaxen
1.1.6
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
utf-8
4.资源配置
4.1 h1.html
h1页面测试
手写TomCat静态页面1
4.2 web.xml
myServlet
com.tomcat.servlet.MyServlet
myServlet
/my
5. Response 与 Request 对象
package com.tomcat.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Properties;
/**
* @author sz
* @DATE 2022/5/1 15:32
*/
@Data
public class Request {
/**
* 请求方法
*/
private String method;
/**
* 请求路径
*/
private String url;
private InputStream inputStream;
public Request(InputStream inputStream) throws IOException {
this.inputStream=inputStream;
byte[] bytes = new byte[1024];
int start;
String str = "";
while (-1 != (start = inputStream.read(bytes))) {
str += new String(bytes,0,start);
if (start<1024){
break;
}
}
String[] split = str.split("\n");
//请求头第一行
try {
method = split[0].split(" ")[0];
} catch (Exception e) {
method="GET";
}
try {
url=split[0].split(" ")[1];
} catch (Exception e) {
url="/";
}
};
}
package com.tomcat.pojo;
import com.tomcat.util.HttpUtils;
import com.tomcat.util.ResponseUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.*;
import java.nio.charset.StandardCharsets;
/**
* @author sz
* @DATE 2022/5/1 15:32
*/
@Data
public class Response {
private OutputStream outputStream;
public Response(OutputStream outputStream){
this.outputStream=outputStream;
}
/**
* 根据url 返回静态资源
* @param str 静态资源url
*/
public void outputHtml(String str) throws IOException {
//获取资源的绝对路径
String absPath = ResponseUtils.getAbsPath(str);
File file = new File(absPath);
if (file.exists() && file.isFile()){
//输出资源
ResponseUtils.writeStaticHtml(new FileInputStream(file),outputStream);
}else {
//返回404
outputStream.write(HttpUtils.writeNotFound().getBytes(StandardCharsets.UTF_8));
outputStream.close();
}
}
public void output(String str) throws IOException {
outputStream.write(str.getBytes(StandardCharsets.UTF_8));
outputStream.close();
}
}
6. HttpUtils 与 ResponseUtils 工具类
package com.tomcat.util;
/**
* @author sz
* @DATE 2022/5/1 15:32
*/
public class HttpUtils {
private HttpUtils(){};
//输出成功的内容信息
public static String writeSuccess(){
String str = "HTTP/1.1 200 OK"+"\n"
+"Content-Type: text/html;charset=utf-8"+"\n"
+"\r\n";
return str;
}
//输出404的内容信息
public static String writeNotFound(){
String str = "HTTP/1.1 404 NotFound"+"\n"
+"Content-Type: text/html;charset=utf-8"+"\n"
+"\r\n"
+" HTTP/1.1 404 NotFound ";
return str;
}
}
package com.tomcat.util;
import lombok.Data;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
/**
* @author sz
* @DATE 2022/5/1 16:11
*/
@Data
public class ResponseUtils {
private ResponseUtils() {
}
;
/**
* 获取静态资源的绝对路径
*
* @param path
* @return
*/
public static String getAbsPath(String path) {
return (ResponseUtils.class.getResource("/") + path.substring(1)).split("file:/")[1];
}
/**
* 输出静态资源
*
* @param inputStream
* @param outputStream
*/
public static void writeStaticHtml(InputStream inputStream, OutputStream outputStream) throws IOException {
//首先输出请求头
outputStream.write(HttpUtils.writeSuccess().getBytes(StandardCharsets.UTF_8));
//再输出请求体
byte[] bytes = new byte[1024];
int len;
if (-1 != (len = inputStream.read(bytes))) {
outputStream.write(bytes,0,len);
}
outputStream.close();
}
}
7. Serlvet 处理动态资源
package com.tomcat.inter;
import com.tomcat.pojo.Request;
import com.tomcat.pojo.Response;
public interface Servlet {
void init();
void destory();
void service(Request request, Response response);
}
package com.tomcat.abs;
import com.tomcat.inter.Servlet;
import com.tomcat.pojo.Request;
import com.tomcat.pojo.Response;
/**
* @author sz
* @DATE 2022/5/1 20:16
*/
public abstract class HttpServlet implements Servlet {
public abstract void doGet(Request request, Response response);
public abstract void doPost(Request request, Response response);
@Override
public void service(Request request, Response response) {
if ("GET".equals(request.getMethod())) {
doGet(request, response);
} else {
doPost(request, response);
}
}
}
package com.tomcat.servlet;
import com.tomcat.abs.HttpServlet;
import com.tomcat.pojo.Request;
import com.tomcat.pojo.Response;
import com.tomcat.util.HttpUtils;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
* @author sz
* @DATE 2022/5/1 20:20
*/
public class MyServlet extends HttpServlet {
@Override
public void doGet(Request request, Response response) {
// try {
// TimeUnit.DAYS.sleep(1);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
String context = " MyServlet GET " + "\r\n"+Thread.currentThread().getName();
try {
response.output(HttpUtils.writeSuccess()+context);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void doPost(Request request, Response response) {
String context = " MyServlet POST "+ "\r\n"+Thread.currentThread().getName();
try {
response.output(HttpUtils.writeSuccess()+context);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void init() {
}
@Override
public void destory() {
}
}
8. RequestProcess 请求处理器
package com.tomcat.process;
import com.tomcat.abs.HttpServlet;
import com.tomcat.pojo.Request;
import com.tomcat.pojo.Response;
import lombok.AllArgsConstructor;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
/**
* @author sz
* @DATE 2022/5/1 21:02
*/
@AllArgsConstructor
public class RequestProcess extends Thread{
private Socket accept;
private Map servletMap;
@Override
public void run() {
try {
//获取Request对象
Request request = new Request(accept.getInputStream());
//获取Response对象
Response response = new Response(accept.getOutputStream());
//写回资源
HttpServlet httpServlet = servletMap.get(request.getUrl());
if (null==httpServlet){
//为nulll,静态资源
response.outputHtml(request.getUrl());
}else {
//不为null 动态资源
httpServlet.service(request,response);
}
}catch (Exception e){
}
}
}
9. Main 方法 服务器启动入口
package com.tomcat.main;
import com.tomcat.abs.HttpServlet;
import com.tomcat.process.RequestProcess;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* @author sz
* @DATE 2022/5/1 10:30
*/
public class Main {
/*设置端口号*/
private static Integer port = 8080;
public static void main(String[] args) throws IOException {
Main main = new Main();
main.start();
}
public void start() throws IOException {
loadServlet();
//创建线程池
ThreadPoolExecutor tomcatThreadPool = new ThreadPoolExecutor(
10,
100,
30,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100)
, new ThreadFactory() {
int i = 0;
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "TomCat线程" + "---" + (++i));
}
},
new ThreadPoolExecutor.CallerRunsPolicy()
);
//创建连接
ServerSocket serverSocket = new ServerSocket(port);
while (true) {
//获取套接字
Socket accept = serverSocket.accept();
RequestProcess requestProcess = new RequestProcess(accept, servletMap);
tomcatThreadPool.execute(requestProcess);
}
}
private Map servletMap = new HashMap();
/**
* 加载解析web.xml,初始化Servlet
*/
private void loadServlet() {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream("web.xml");
SAXReader saxReader = new SAXReader();
try {
Document document = saxReader.read(resourceAsStream);
Element rootElement = document.getRootElement();
List selectNodes = rootElement.selectNodes("//servlet");
for (int i = 0; i < selectNodes.size(); i++) {
Element element = selectNodes.get(i);
// myServlet
Element servletnameElement = (Element) element.selectSingleNode("servlet-name");
String servletName = servletnameElement.getStringValue();
// com.tomcat.servlet.MyServlet
Element servletclassElement = (Element) element.selectSingleNode("servlet-class");
String servletClass = servletclassElement.getStringValue();
// 根据servlet-name的值找到url-pattern
Element servletMapping = (Element) rootElement.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
// /my
String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
servletMap.put(urlPattern, (HttpServlet) Class.forName(servletClass).newInstance());
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
port = port;
}
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)