您的位置:首页 > 运维架构 > Tomcat

深入剖析tomcat之一个简单的servlet容器

2016-04-11 22:47 716 查看
上一篇,我们讲解了如果开发一个简单的Http服务器,这一篇,我们扩展一下,让我们的服务器具备servlet的解析功能。

简单介绍下Servlet接口

如果我们想要自定义一个Servlet,那么我们必须继承Servlet,并且实现下面几个重要的方法

public void init(ServletConfig config) throws ServletException
public void service(ServletRequest request,ServletResponse response) throws ServletException,java.io.IOException
public void destroy()
public ServletConfig getServletConfig()
public String getServletInfo()

五个方法中,init,destroy,service都是和servlet的生命周期相关的方法。当实例化某个servlet类之后,servlet会调用init进行初始化,当servlet的请求到达之后,就会调用service方法,并将servletRequest和servletResponse对象作为参数传入,前者包含客户端的Http请求的信息,后者包含服务器的响应信息。

这个简单的Servlet容器的流程如下

等待http请求

对应的servletRequest对象和servletResponse对象,

判断请求的类型,如果是请求静态资源,则找到静态资源的文件,返回给客户端

如果是Servlet请求,载入servlet类,调用service()方法,传入servletRequest对象和servletResponse对象

涉及到的主要的类

SimpleServletContainerServer

Request

Response

Servlet

PrimitiveServlet

StaticProcessor

ServletProcessor

关于Request和Response的定义在上一篇幅有定义,这里我们稍微扩展了一下,碍于篇幅,不在这里展示。

PrimitiveServlet类,继承自Servlet,Servlet请求的处理类

类定义:

package servletContainer;

import java.io.IOException;

import base.Request;
import base.Response;
import base.ServletConfig;
import interf.Servlet;

public class PrimitiveServlet implements Servlet {

@Override
public void init(ServletConfig config) {
System.out.println("PrimitiveServlet init");
}

@Override
public void service(Request request, Response response) throws IOException {
response.getOutput().write("Primitive Servlet".getBytes());
}

@Override
public void destroy() {

}

@Override
public ServletConfig getServletConfig() {
return null;
}

@Override
public String getServletInfo() {
return null;
}

}

SimpleServletContainerServer 类

功能:程序入口,监听Http请求,并且负责创建Request和Response

类定义

package servletContainer;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

import base.Request;
import base.Response;
import servletContainer.processor.ServletProcessor;
import servletContainer.processor.StaticProcessor;

public class SimpleServletContainerServer {
private static final String SHUT_DOWN = "/SHUTDOWN";

private boolean shutdown = false;

private ServletProcessor servletProcessor = new ServletProcessor();

private StaticProcessor staticProcessor = new StaticProcessor();

public static void main(String args[]){
SimpleServletContainerServer server = new SimpleServletContainerServer();
server.init();
server.await();
}

public void init(){
servletProcessor.init();
staticProcessor.init();
}

public void await(){

ServerSocket serverSocket = null;
int port = 8080;

try{
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
}
catch (IOException e){
e.printStackTrace();
System.exit(-1);
}

while(!shutdown){
Socket socket = null;
InputStream input = null;
OutputStream output = null;

try{

socket = serverSocket.accept();
input = socket.getInputStream();
output = socket.getOutputStream();

Request request = new Request(input);
request.parse();

Response response = new Response(output);
response.setRequest(request);

if(request.getUri().startsWith("/servlet/")){
servletProcessor.process(request, response);
}
else{
staticProcessor.process(request, response);
}

socket.close();
shutdown = request.getUri().equals(SHUT_DOWN);

}
catch (Exception e){
e.printStackTrace();
System.exit(1);
}
}

}

}

我们引入了StaticProcessor和ServletProcessor进行逻辑的处理,我们看下这两个类的定义

首先这两个类都继承自IProcessor接口

package servletContainer.processor;

import base.Request;
import base.Response;

public interface IProcessor {

public void init();

public void process(Request request,
Response response);
}

StaticProcessor类主要是处理静态资源请求

类定义

package servletContainer.processor;

import base.Request;
import base.Response;

public class StaticProcessor implements IProcessor {

@Override
public void process(Request request, Response response) {
try{
response.sendStaticResource();
}
catch (Exception e){
e.printStackTrace();
}
}

@Override
public void init() {

}

}

ServeletProcessor主要负责处理Servlet请求,初始化的时候,初始化所有的Servlet子类,接收到servlet的http请求之后,根据请求名称,调用对应的service函数。

类定义

package servletContainer.processor;

import java.util.HashMap;
import java.util.Map;

import base.Request;
import base.Response;
import interf.Servlet;
import servletContainer.PrimitiveServlet;

public class ServletProcessor implements IProcessor {

private Map<String,Servlet> map = new HashMap<String,Servlet>();

public ServletProcessor() {

}

public void init(){
PrimitiveServlet servlet = new PrimitiveServlet();
servlet.init(null);
map.put("PrimitiveServlet", servlet);
}

@Override
public void process(Request request, Response response) {
String uri = request.getUri();
String servletName = uri.substring(uri.lastIndexOf("/") + 1);

Servlet servlet = map.get(servletName);
try{
if(servlet != null){
servlet.service(request, response);
}
else{
String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +
"Content-Type: text/html\r\n" +
"Content-Length:23\r\n" +
"\r\n" +
"<h1>File Not Found</h1>";
response.getWriter().print(errorMessage.getBytes());
}
}
catch (Exception e){
e.printStackTrace();
}
catch (Throwable e){
e.printStackTrace();
}

}

}

结果

我们在eclipse里运行结果



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: