响应流程
示意图
如图所示,Server作为一个完整的Tomcat,里面有许多Service(当然本项目就写了一个),它对应着一个Web应用。Service底下包含着Connector和Container,其中Connector用来接收请求,并根据请求的协议将请求发给Container处理,这个处理的过程是用创建的新线程进行的(BIO);而Container可以视为Servlet的容器,但不是直接的容器。Container底下Engine,Engine分发请求至对应的Host;Host只会处理与请求url的host对应的请求,接着会下发至Context;Context用来判别请求的资源路径,根据资源路径发送至Wrapper;Wrapper封装了Servlet,可以视作Servlet的直接容器。并且以上这些组件都实现了LifeCycle接口,该接口规定了各个组件生命周期的各种API。
关键类及其接口
Lifecycle接口
该接口定义了组件生命周期的各种行为,包括初始化、开始、停止、销毁。
public interface Lifecycle {
// 初始化方法
public void init();
// 启动方法
public void start();
// 停止方法,和start对应
public void stop();
// 销毁方法,和init对应
public void destroy();
// 获取生命周期状态
public LifecycleState getState();
}
Connector类
Connector类主要封装了ServerSocket,用来监听前端请求,并解析数据封装成Request、Response对象,以便传给Container类进行处理。
传递请求的本质上是创建新的线程进行处理,这是因为Tomcat处理Http请求本身就是BIO的过程,为了提升效率都是用多线程进行处理多个请求的,这里也是比较粗放的模拟了创建线程处理请求。
public class Connector implements Lifecycle, Component {
private LifecycleState lifecycleState = LifecycleState.NEW;
public static HttpServletRequest request;
public static HttpServletResponse response;
public static Component container;
public static ServerSocket serverSocket;
static {
try {
serverSocket = new ServerSocket(8080);
} catch (IOException e) {
e.printStackTrace();
}
}
public Connector() {
}
@Override
public void init() {
container = Service.container;
lifecycleState = LifecycleState.INITIALIZED;
}
@Override
public void start() {
while (true) {
try {
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String method = bufferedReader.readLine();
if (method == null) {
continue;
}
String context=method.split(" ")[1];
if (method.startsWith("GET")) {
method = method.substring(0, 3);
} else {
method = method.substring(0, 4);
}
String host="";
while (true) {
String msg = bufferedReader.readLine();
if (msg.length()==0){
break;
}
if (msg.startsWith("Host")){
host=msg.split(":")[1].substring(1);
break;
}
}
request = new HttpServletRequest(method,host,context,inputStream);
response = new HttpServletResponse(outputStream);
new Thread(new Runnable() {
@Override
public void run() {
Container container = (Container) Connector.container;
container.start();
try {
if (socket != null)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
}
}
@Override
public void stop() {
try {
if (serverSocket != null)
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void destroy() {
stop();
}
@Override
public LifecycleState getState() {
return null;
}
@Override
public Component getChild() {
return null;
}
@Override
public void setChild(Component child) {
}
}
Request和Response类
Request主要封装了请求路径、host、输入流对象以及请求方法等;而Response封装了输出流对象和响应头(简化响应数据的封装,直接预置了text/html类型的响应头)。
public class HttpServletRequest {
private String method;
private String host;
private String context;
private InputStream inputStream;
public HttpServletRequest(String method, String host, String context, InputStream inputStream) {
this.method = method;
this.host = host;
this.context = context;
this.inputStream = inputStream;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public String getContext() {
return context;
}
public void setContext(String context) {
this.context = context;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public InputStream getInputStream() {
return inputStream;
}
public void setInputStream(InputStream inputStream) {
this.inputStream = inputStream;
}
}
public class HttpServletResponse {
private OutputStream outputStream;
private String responseHeader="HTTP/1.1 200\r\nContent-Type:text/html\r\n\r\n";
public HttpServletResponse(OutputStream outputStream) {
this.outputStream = outputStream;
}
public OutputStream getOutputStream() {
return outputStream;
}
public void setOutputStream(OutputStream outputStream) {
this.outputStream = outputStream;
}
public String getResponseHeader() {
return responseHeader;
}
public void setResponseHeader(String responseHeader) {
this.responseHeader = responseHeader;
}
}
HttpServlet类
Container接收到Request、Response对象一级一级传递下去最终到了Servlet,这里才是处理请求,返回响应的业务逻辑所在之处。根据Request的请求方法类型,执行不同的方法(doGet、doPost)。并且空闲的Servlet应该及时销毁,这里也是用Timer对象进行一个周期任务,监听Servlet是否应该被销毁。
public class HttpServlet implements Lifecycle, Component {
private LifecycleState lifecycleState = LifecycleState.NEW;
private long deathTime;
private Timer timer;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws RuntimeException {
try {
response.getOutputStream().write((response.getResponseHeader() + "Hello!!").getBytes());
response.getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (response.getOutputStream() != null)
response.getOutputStream().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws RuntimeException {
doGet(request, response);
}
@Override
public void init() {
if (lifecycleState == LifecycleState.NEW) {
lifecycleState = LifecycleState.INITIALIZED;
}
System.out.println("=========HttpServlet初始化成功,超时时间为2s=========");
}
@Override
public void start() {
if (timer == null) {
timer = new Timer();
}
if (lifecycleState == LifecycleState.NEW) {
init();
} else if (lifecycleState == LifecycleState.STOPPING || lifecycleState == LifecycleState.IDELING) {
lifecycleState = LifecycleState.INITIALIZED;
} else if (lifecycleState == LifecycleState.DESTROYING) {
//如果正在销毁,返回wrapper重新执行
}
if (lifecycleState == LifecycleState.INITIALIZED) {
lifecycleState = LifecycleState.STARTING;
HttpServletRequest request = Connector.request;
HttpServletResponse response = Connector.response;
deathTime = System.currentTimeMillis();
try {
switch (request.getMethod()) {
case "GET":
doGet(request, response);
if (System.currentTimeMillis() - deathTime >= 2000) {
System.out.println("=========HttpServlet的get请求超时,超时时间为2s=========");
}
break;
case "POST":
doPost(request, response);
if (System.currentTimeMillis() - deathTime >= 2000) {
System.out.println("=========HttpServlet的post请求超时,超时时间为2s=========");
}
break;
}
//response返回消息
//。。。。。。。。。。
//闲置将被销毁
deathTime = System.currentTimeMillis();
lifecycleState = LifecycleState.IDELING;
canDestory();
} catch (Exception e) {
stop();
System.out.println("=========HttpServlet出现未知错误=========");
e.printStackTrace();
erroResponse();
}
}
}
private void erroResponse() {
OutputStream outputStream = Connector.response.getOutputStream();
try {
outputStream.write((Connector.response.getResponseHeader() + "erro!!").getBytes());
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (outputStream != null)
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void canDestory() {
timer.schedule(new TimerTask() {
@Override
public void run() {
if (System.currentTimeMillis() - deathTime >= 2000 && lifecycleState == LifecycleState.IDELING) {
System.out.println("=========HttpServlet的闲置时间超过2s,将被销毁=========");
destroy();
}
}
}, 10, 500);
}
@Override
public void stop() {
lifecycleState = LifecycleState.STOPPING;
}
@Override
public void destroy() {
lifecycleState = LifecycleState.DESTROYING;
Component component = Connector.container;
while (true) {
component = component.getChild();
if (component instanceof Wrapper) {
break;
}
}
component.setChild(null);
timer.cancel();
timer = null;
System.gc();
}
@Override
public LifecycleState getState() {
return this.lifecycleState;
}
@Override
public Component getChild() {
return null;
}
@Override
public void setChild(Component child) {
}
}
测试结果
前端请求
如图所示,前端请求对应的url,得到响应。
servlet的初始化和销毁
servlet在请求到来时会进行初始化并且处理请求,同时会启动线程监控生命周期,对于空闲两秒的servlet会进行销毁。
评论区