深入剖析Tomcat-第二章:一个简单的servlet容器(1)

内容:在上一章的基础上多了对servlet的处理,重点是ServletProcessor1这个类,利用到了URL、URLClassLoader(可以参看文档)和java反射机制

webroot:

public class HttpServer1 {
	private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
	private boolean shutdown = false;

	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/")) {
					ServletProcessor1 processor = new ServletProcessor1();
					processor.process(request, response);
				} else {
					StaticResourceProcessor processor = new StaticResourceProcessor();
					processor.process(request, response);
				}

				socket.close();
				shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
			} catch (Exception e) {
				e.printStackTrace();
				System.exit(1);
			}
		}
	}

	public static void main(String[] args) {
		HttpServer1 server = new HttpServer1();
		System.out.println("start");
		server.await();
	}
}
public class Request implements ServletRequest{
	private InputStream input;
	private String uri;

	public Request(InputStream inputStream) {
		this.input = inputStream;
	}

	public String getUri() {
		return this.uri;
	}

	private String parseUri(String requestString) {
		int index1, index2;
		index1 = requestString.indexOf(' ');
		if (index1 != -1) {
			index2 = requestString.indexOf(' ', index1 + 1);
			if (index2 > index1)
				return requestString.substring(index1 + 1, index2);
		}
		return null;
	}

	public void parse() {
		StringBuffer request = new StringBuffer(2048);
		int i;
		byte bytes[] = new byte[2048];
		try {
			i = input.read(bytes);
		} catch (IOException e) {
			e.printStackTrace();
			i = -1;
		}

		for (int j = 0; j < i; j++)
			request.append((char) bytes[j]);
		System.out.print(request.toString());
		uri = parseUri(request.toString());
	}

	@Override
	public AsyncContext getAsyncContext() {
		return null;
	}

	@Override
	public Object getAttribute(String arg0) {
		return null;
	}

	@Override
	public Enumeration<String> getAttributeNames() {
		return null;
	}

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

	@Override
	public int getContentLength() {
		return 0;
	}

	@Override
	public long getContentLengthLong() {
		return 0;
	}

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

	@Override
	public DispatcherType getDispatcherType() {
		return null;
	}

	@Override
	public ServletInputStream getInputStream() throws IOException {
		return null;
	}

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

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

	@Override
	public int getLocalPort() {
		return 0;
	}

	@Override
	public Locale getLocale() {
		return null;
	}

	@Override
	public Enumeration<Locale> getLocales() {
		return null;
	}

	@Override
	public String getParameter(String arg0) {
		return null;
	}

	@Override
	public Map<String, String[]> getParameterMap() {
		return null;
	}

	@Override
	public Enumeration<String> getParameterNames() {
		return null;
	}

	@Override
	public String[] getParameterValues(String arg0) {
		return null;
	}

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

	@Override
	public BufferedReader getReader() throws IOException {
		return null;
	}

	@Override
	public String getRealPath(String arg0) {
		return null;
	}

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

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

	@Override
	public int getRemotePort() {
		return 0;
	}

	@Override
	public RequestDispatcher getRequestDispatcher(String arg0) {
		return null;
	}

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

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

	@Override
	public int getServerPort() {
		return 0;
	}

	@Override
	public ServletContext getServletContext() {
		return null;
	}

	@Override
	public boolean isAsyncStarted() {
		return false;
	}

	@Override
	public boolean isAsyncSupported() {
		return false;
	}

	@Override
	public boolean isSecure() {
		return false;
	}

	@Override
	public void removeAttribute(String arg0) {
	}

	@Override
	public void setAttribute(String arg0, Object arg1) {
	}

	@Override
	public void setCharacterEncoding(String arg0)
			throws UnsupportedEncodingException {
	}

	@Override
	public AsyncContext startAsync() throws IllegalStateException {
		return null;
	}

	@Override
	public AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1)
			throws IllegalStateException {
		return null;
	}

}
public class Response implements ServletResponse {

	private static final int BUFFER_SIZE = 1024;
	private Request request;
	private OutputStream output;
	private PrintWriter writer;

	public Response(OutputStream output) {
		this.output = output;
	}

	public void setRequest(Request request) {
		this.request = request;
	}

	public void sendStaticResource() throws IOException {
		byte bytes[] = new byte[BUFFER_SIZE];
		FileInputStream fis = null;
		try {
			File file = new File(Constants.WEB_ROOT, request.getUri());
			fis = new FileInputStream(file);
			int ch = fis.read(bytes, 0, BUFFER_SIZE);
			while (ch != -1) {
				output.write(bytes, 0, ch);
				ch = fis.read(bytes, 0, BUFFER_SIZE);
			}
		} catch (FileNotFoundException e) {
		    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>";
		    output.write(errorMessage.getBytes());
		} finally {
			if (fis != null)
				fis.close();
		}
	}

	@Override
	public void flushBuffer() throws IOException {
		// TODO Auto-generated method stub

	}

	@Override
	public int getBufferSize() {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public String getCharacterEncoding() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public String getContentType() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Locale getLocale() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public ServletOutputStream getOutputStream() throws IOException {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public PrintWriter getWriter() throws IOException {
		writer = new PrintWriter(output, true);
		return writer;
	}

	@Override
	public boolean isCommitted() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void reset() {
		// TODO Auto-generated method stub

	}

	@Override
	public void resetBuffer() {
		// TODO Auto-generated method stub

	}

	@Override
	public void setBufferSize(int arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setCharacterEncoding(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setContentLength(int arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setContentLengthLong(long arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setContentType(String arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setLocale(Locale arg0) {
		// TODO Auto-generated method stub

	}

}
public class Constants {
  public static final String WEB_ROOT =
    System.getProperty("user.dir") + File.separator  + "webroot";
}
public class StaticResourceProcessor {
	public void process(Request request, Response response) {
		try {
			response.sendStaticResource();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}
public class ServletProcessor1 {
	public void process(Request request, Response response) {
		String uri = request.getUri();
		String servletName = uri.substring(uri.lastIndexOf("/") + 1);
		URLClassLoader loader = null;

		try {
			URL urls[] = new URL[1];
			URLStreamHandler streamHandler = null;
			File classPath = new File(Constants.WEB_ROOT);
		    String repository = (new URL("file", null,
		    		classPath.getCanonicalPath() + File.separator)).toString() ;
		    urls[0] = new URL(null, repository, streamHandler);
		    loader = new URLClassLoader(urls);
		} catch(IOException e) {
			System.out.println(e.toString());
		}

		Class myClass = null;
		try {
			myClass = loader.loadClass(servletName);
		} catch(ClassNotFoundException e) {
			System.out.println(e.toString());
		}

		Servlet servlet = null;

		try {
			servlet = (Servlet) myClass.newInstance();
			servlet.service((ServletRequest) request, (ServletResponse) response);
		} catch (Exception e) {
			System.out.println(e.toString());
		} catch (Throwable e) {
			System.out.println(e.toString());
		}
	}

}
时间: 2024-08-28 23:33:17

深入剖析Tomcat-第二章:一个简单的servlet容器(1)的相关文章

编译原理 龙书 第二章 一个简单的算术式(+,-)翻译器实现

昨天晚上决定正面硬刚神课<编译原理>.硬上龙书. 下面是 一个简单的算术式中缀变后缀的翻译器. 这个也是 龙书中 一个C实现源码 .部分用c++改写. #include <iostream> #include <ctype.h> #include <stdlib.h> #include <stdio.h> using namespace std; int lookahead; void error()//错误处理 { cout<<&q

how tomcat works 读书笔记(二)----------一个简单的servlet容器

app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/article/details/39378157) 回顾我们上一章,我们开发了一个最最简单的web服务器,它可以使用户访问服务器内的静态资源.当然这是远远不够的,在这一节里,我们就试着让服务器在能相应静态资源的基础上继续支持servlet. servlet接口 javax.servlet.Servlet接口

Tomcat学习笔记(二)—— 一个简单的Servlet容器

1.简介:Servlet编程是通过javax.Servlet和javax.servlet.http这两个包的类和接口实现的,其中javax.servlet.Servlet接口至关重要,所有的Servlet必须实现该接口或者继承实现了该接口的类. 2.Servlet接口有5个方法: public void init(ServletConfig config) throws ServletException; public void service(ServletRequest request, S

一个简单的Servlet容器实现[一]

上篇写了一个简单的Java web服务器实现,只能处理一些静态资源的请求,本篇文章实现的Servlet容器基于前面的服务器做了个小改造,增加了Servlet请求的处理. 程序执行步骤 创建一个ServerSocket对象: 调用ServerSocket对象的accept方法,等待连接,连接成功会返回一个Socket对象,否则一直阻塞等待: 从Socket对象中获取InputStream和OutputStream字节流,这两个流分别对应request请求和response响应: 处理请求:读取In

2.一个简单的Servlet容器

很显然Http服务器会按照Http协议对获取的请求进行分析并返回规定的信息,通过对Http的理解,java大叔将其返回的信息封装成一个类,称为Servlet,至此,Http服务器在Java中就变成了按照Http协议对获取的请求进行分析并返Servlet,很明显,Http服务器在这里也就变为了Servlet容器...    注:服务器是什么?理解万岁...

编译原理-第二章 一个简单的语法指导编译器-2.4 语法制导翻译

语法制导翻译: 定义:语法制导翻译是通过向一个文法的产生式附加一些规则或程序片段而得到的 功能:给定词法单元流,通过向一个文法产生式附加一些语义动 作,语法制导分析产生语法分析树,并实现翻译动作 相关概念: 属性:表示与某个程序构造相关的任意的量,因为用文法符号(终结符号或非终结符号)来表示程序构造,所以可将属性的概念从程序构造扩展到表示这些构造的文法符号上 综合属性:如果某个属性在语法分析树节点N上的值由N的子节点和N本身的属性值确定,则该属性为综合属性,其性质为只需对语法分析树进行一次自底向

编译原理-第二章 一个简单的语法指导编译器-2.3 语法定义

语法定义: 文法定义: 定义:用以描述程序设计语言语法的表示方法——“上下文无关文法”,简称“文法”,文法自然地描述了大多数程序设计语言构造地层次化语法结构 实例: 如果用变量expr来表示表达式,用变量stmt表示语句,则 相关概念: 产生式:使用箭头(→)表示"可以具有如下形式",用相关变量表示表达式和语句的构造规则产生的式子.每个生产式包括一个称为生产式头或左部的非终结符号,一个箭头,和一个称为生产式体或右部的由终结符号组成的序列. 终结符号:有时也称为词法单元,终结符号是该文法

深入剖析Tomcat-第二章:一个简单的servlet容器(2)

内容:在上一篇中存在一些安全问题,因为我们需要将request和response想上转型为ServletRequest和ServletResponse,了解这个servlet容器内部工作原理的servlet程序员可以将ServletRequest和ServletResponse分别向下转型然后就能调用Request和Response的parse()和sendStaticResource()了.所以我们需要利用外观类来解决,添加两个RequestFacade和ResponseFacade,然后分别

攻城狮在路上(肆)How tomcat works(二) 一个简单的servlet容器

该节在上一节的基础上增加了所谓对静态资源和动态资源访问的不同控制流程.示例里面采用的是对路径“/servlet/”进行了特殊处理. 一. 主要还是从HttpServer1中的main方法开始,先解析出Request和Response对象,然后如果请求路径中包含/servlet/路径的话, 就进入ServletProcesser1进行处理,否则就进入StaticProcessor进行处理. 在ServletProcessor1中,对Request和Response进行了封装,通过URLClassL