6,一个简单的servlet容器
总的来说,一个全功能的servlet容器会为servlet的每个HTTP请求做下面一些工作:
当第一次调用servlet的时候,加载该servlet类并调用servlet的init方法(仅仅一次)。
对每次请求,构造一个javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例。
调用servlet的service方法,同时传递ServletRequest和ServletResponse对象。
当servlet类被关闭的时候,调用servlet的destroy方法并卸载servlet类。下面这个简单的servlet容器不能做上面的工作,相反,做了下面的几件事
1,等待HTTP请求。
2,构造一个ServletRequest对象和一个ServletResponse对象。
3,假如该请求需要一个静态资源的话,调用StaticResourceProcessor实例的process方法,同时传递ServletRequest和ServletResponse对象。
4,假如该请求需要一个servlet的话,加载servlet类并调用servlet的service方法,同时传递ServletRequest和ServletResponse对象。
------------------------------------------------------------------------------------------------
Servlet由Servlet容器来管理,当客户请求到来时,容器创建一个ServletRequest对象,封装请求数据,同时创建一个ServletResponse对象,封装响应数据。这两个对象将被容器作为service()方法的参数传递给Servlet,Serlvet利用ServletRequest对象获取客户端发来的请求数据,利用ServletRequest对象发送响应数据。
所以,我们的容器应构造一个ServletRequest和ServletResponse,即实现这俩个接口即可。
核心代码如下:
package org.tomcat; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; public class HttpServer1 { private static final String SHUTDOWN_COMMAND= "/SHUTDOWN"; private boolean shutdown =false; public static void main(String[] args){ HttpServer1 server = new HttpServer1(); server.await(); } private 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.proess(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); } } } }
package org.tomcat; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.Enumeration; import java.util.Locale; import java.util.Map; import javax.servlet.RequestDispatcher; import javax.servlet.ServletInputStream; import javax.servlet.ServletRequest; public class Request implements ServletRequest{ private InputStream input; private String uri; public Request(InputStream input){ this.input = input; } public void parse(){ StringBuffer request= new StringBuffer(2048); int i; byte[] buffer =new byte[2048]; try{ i = input.read(buffer); }catch(IOException e){ e.printStackTrace(); i=-1; } for(int j=0;j<i;j++){ request.append((char)buffer[j]); } System.out.println(request.toString()); uri = parseUri(request.toString()); } 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 Object getAttribute(String arg0) { return null; } public Enumeration getAttributeNames() { return null; } public String getCharacterEncoding() { return null; } public int getContentLength() { return 0; } public String getContentType() { return null; } public ServletInputStream getInputStream() throws IOException { return null; } public String getLocalAddr() { return null; } public Locale getLocale() { return null; } public Enumeration getLocales() { return null; } public String getLocalName() { return null; } public int getLocalPort() { return 0; } public String getParameter(String arg0) { return null; } public Map getParameterMap() { return null; } public Enumeration getParameterNames() { return null; } public String[] getParameterValues(String arg0) { return null; } public String getProtocol() { return null; } public BufferedReader getReader() throws IOException { return null; } public String getRealPath(String arg0) { return null; } public String getRemoteAddr() { return null; } public String getRemoteHost() { return null; } public int getRemotePort() { return 0; } public RequestDispatcher getRequestDispatcher(String arg0) { return null; } public String getScheme() { return null; } public String getServerName() { return null; } public int getServerPort() { return 0; } public boolean isSecure() { return false; } public void removeAttribute(String arg0) { } public void setAttribute(String arg0, Object arg1) { } public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException { } public String getUri() { return uri; } }
package org.tomcat; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Locale; import javax.servlet.ServletOutputStream; import javax.servlet.ServletResponse; public class Response implements ServletResponse { private static final int BUFFER_SIZE=1024; Request request; OutputStream output; PrintWriter writer; public Response(OutputStream output){ this.output = output; } 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,BUFFER_SIZE); 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(); } } public void flushBuffer() throws IOException { } public int getBufferSize() { return 0; } public String getCharacterEncoding() { return null; } public String getContentType() { return null; } public Locale getLocale() { return null; } public ServletOutputStream getOutputStream() throws IOException { return null; } public PrintWriter getWriter() throws IOException { writer = new PrintWriter(output,true); return writer; } public boolean isCommitted() { return false; } public void reset() { } public void resetBuffer() { } public void setBufferSize(int arg0) { } public void setCharacterEncoding(String arg0) { } public void setContentLength(int arg0) { } public void setContentType(String arg0) { } public void setLocale(Locale arg0) { } public void setRequest(Request request) { this.request = request; } }