深入剖析tomcat之一个简单的servlet容器
上一篇,我们讲解了如果开发一个简单的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里运行结果


深入剖析tomcat之一个简单的servlet容器的更多相关文章
- 一个简单的servlet容器
[0]README 0.1)本文部分文字转自 “深入剖析Tomcat”,旨在学习 一个简单的servlet容器 的基础知识: 0.2)for complete source code, pleas ...
- how tomcat works 读书笔记(二)----------一个简单的servlet容器
app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...
- Tomcat学习笔记(二)—— 一个简单的Servlet容器
1.简介:Servlet编程是通过javax.Servlet和javax.servlet.http这两个包的类和接口实现的,其中javax.servlet.Servlet接口至关重要,所有的Servl ...
- 一个简单的Servlet容器实现
上篇写了一个简单的Java web服务器实现,只能处理一些静态资源的请求,本篇文章实现的Servlet容器基于前面的服务器做了个小改造,增加了Servlet请求的处理. 程序执行步骤 创建一个Serv ...
- 深入剖析tomcat之一个简单的web服务器
这个简单的web服务器包含三个类 HttpServer Request Response 在应用程序的入口点,也就是静态main函数中,创建一个HttpServer实例,然后调用其await()方法. ...
- 攻城狮在路上(肆)How tomcat works(二) 一个简单的servlet容器
该节在上一节的基础上增加了所谓对静态资源和动态资源访问的不同控制流程.示例里面采用的是对路径“/servlet/”进行了特殊处理. 一. 主要还是从HttpServer1中的main方法开始,先解析出 ...
- Tomcat剖析(二):一个简单的Servlet服务器
Tomcat剖析(二):一个简单的Servlet服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三) ...
- How tomcat works(深入剖析tomcat)servlet容器
How tomcat works (5)servlet容器阅读笔记 第四章阅读了tomcat默认连接器的实现,当时connector中的使用的容器是自定义的容器,也是非常之简单奥,一个人就干完了所有的 ...
- 《深入剖析Tomcat》阅读(二)
Tomcat是基于Sun公司标准的开源Servlet容器. Servlet是什么? Servlet(Server Applet),全称Java Servlet,未有中文译文.是用Java编写的服务器端 ...
随机推荐
- ecma6 yield
function * generator(k){ console.log('begin'); var x = yield k; console.log('x:',x); var y = yield x ...
- C#中Finally的一个不太常见的用法
最近在看.net BCL 传送门 的源码. 在 System.Collections.Concurrent.ConcurrentQueue 中看到一段有意思的代码.注意这段代码是写在Concurren ...
- js实用篇之String对象
概述 String对象是JavaScript原生提供的三个包装对象之一,用来生成字符串的包装对象. var s1 = 'abc'; var s2 = new String('abc'); typeof ...
- Android开发学习之路-Handler消息派发机制源码分析
注:这里只是说一下sendmessage的一个过程,post就类似的 如果我们需要发送消息,会调用sendMessage方法 public final boolean sendMessage(Mess ...
- Redux
redux是Flux的一种实现方式,但还是和Flux有些不同. React控制视图层,要想做一个完整的数据流,必须要用react-redux. 官方demo,自己收集了一下: demo1http:// ...
- 移动web app开发必备 - zepto事件问题
问题描述: 项目在祖先元素上绑定了 touchstart,touchmove,touchend事件,用来处理全局性的事件,比如滑动翻页 正常状态下: 用户在子元素上有交互动作时,默认状态下都是会冒泡到 ...
- es6学习笔记一数组(中)
接着上一篇,给大家再分享一些数组的其他方法.大家也可以去点击这里学习数组更多的方法 concat方法: 概述: concat() 方法将传入的数组或非数组值与原数组合并,组成一个新的数组并返回. ...
- nodejs+easyui(抽奖活动后台)增删改查
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfAAAAJACAIAAAD97KNZAAAgAElEQVR4nO2daXxb5Z2o7w+dO1/ufL ...
- javascript面向对象系列第一篇——构造函数和原型对象
× 目录 [1]构造函数 [2]原型对象 [3]总结 前面的话 一般地,javascript使用构造函数和原型对象来进行面向对象编程,它们的表现与其他面向对象编程语言中的类相似又不同.本文将详细介绍如 ...
- JAVA--继承
项目开发遇到一个问题,稀里糊涂给实现了,现在重点讨论一下这是个什么情况,大神们如果看到希望给点指点. 问题:子类与父类具有相同的属性和方法,将子类实例化为父类,调用对应属性的get.set方法,打印出 ...