Self simulation of a simple tomcat

Source: Internet
Author: User

    • The role of the servlet container
Overall, a full-featured servlet container does some of the following for each HTTP request of the servlet:
1, when the servlet is first invoked, the Servlet class is loaded and the servlet's Init method is called, only once,
2, for each request, we need to new a request and response the corresponding instance,
3, invoking the Servlet's service method, passing both the ServletRequest and Servletresponse objects,
4, when the Servlet class is closed, the destroy method of calling the servlet is written in the Servlet class.


Now I have my own simulation implementation of the simplest Tomcat, in addition to the 1th and 4th above, the basic function is implemented, the code is as follows:

Package Linkin;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{/** * WEB_ROOT is The directory where our HTML and other files reside. Web_root is the "Webroot" directory under the working directory. * The working directory is the location of the file system from where the * Java command was invoked. *///shutdown commandprivate static final String Shutdown_command = "/shutdown";//The Shutdown COMMAND receivedprivate bo Olean shutdown = false;public static void Main (string[] args) {HttpServer1 server = new HttpServer1 (); server.await ();} public void await () {ServerSocket ServerSocket = null;int Port = 8080;try{serversocket = new ServerSocket (port, 1, InetAddr Ess.getbyname ("127.0.0.1"));} catch (IOException e) {e.printstacktrace (); System.exit (1);} Loop waiting for a requestwhile (!shutdown) {Socket socket = Null;inputstream input = null; OutputStream output = Null;try{socket = Serversocket.accept (); input = Socket.getinputstream (); output = Socket.getoutputstream ();//Create Request object and Parserequest request = new request (input); Request.parse ();// Create Response objectresponse Response = new Response (output); Response.setrequest (request);//Check if this is a request For a servlet or//a static resource//a request for a servlet begins with "/servlet/" if (Request.geturi (). StartsWith ("/se rvlet/")) {ServletProcessor1 processor = new ServletProcessor1 ();p rocessor.process (request, response);} Else{staticresourceprocessor processor = new Staticresourceprocessor ();p rocessor.process (request, response);} Close the Socketsocket.close ();//Check if the previous URI is a shutdown Commandshutdown = Request.geturi (). Equals (SHU Tdown_command);} catch (Exception e) {e.printstacktrace (); System.exit (1);}}}

Package Linkin;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 String GetURI () {return URI;} private string Parseuri (string requeststring) {int index1, index2;index1 = Requeststring.indexof ("); if (index1! =-1) {in Dex2 = Requeststring.indexof (", index1 + 1), if (Index2 > Index1) return requeststring.substring (index1 + 1, index2);} return null;} public void Parse () {//Read a set of characters from the socketstringbuffer 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.print (Request.tostring ()); URI = Parseuri (request.tostring ());} /* Implementation of ServletRequest */public Object getattribute (String attribute) {return null;} Public enumeration Getattributenames () {return null;} public string Getrealpath (string path) {return null;} Public RequestDispatcher Getrequestdispatcher (String path) {return null;} public Boolean issecure () {return false;} Public String getcharacterencoding () {return null;} public int getcontentlength () {return 0;} Public String getContentType () {return null;} Public ServletInputStream getInputStream () throws Ioexception{return null;} Public Locale GetLocale () {return null;} Public enumeration Getlocales () {return null;} public string GetParameter (string name) {return null;} Public Map Getparametermap () {return null;} Public enumeration Getparameternames () {return null;} Public string[] Getparametervalues (String parameter) {return null;} Public String Getprotocol () {return null;} Public BuffEredreader Getreader () throws Ioexception{return null;} Public String getremoteaddr () {return null;} Public String Getremotehost () {return null;} Public String Getscheme () {return null;} Public String getServerName () {return null;} public int Getserverport () {return 0;} public void RemoveAttribute (string attribute) {}public void SetAttribute (string key, Object value) {}public void Setcharacterencoding (String encoding) throws unsupportedencodingexception{} @Overridepublic string getlocaladdr () { return null;} @Overridepublic String Getlocalname () {return null;} @Overridepublic int Getlocalport () {return 0;} @Overridepublic int Getremoteport () {return 0;}}

Package Linkin;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;public static final String web_root = System.getproperty ("User . Dir ") + File.separator +" Webroot "; Request Request;outputstream output; PrintWriter writer;public Response (outputstream output) {this.output = output;} public void Setrequest (Request request) {this.request = Request;} /* This method was used to serve static pages */public void Sendstaticresource () throws ioexception{byte[] bytes = new byte [Buffer_size]; FileInputStream FIS = null;try{/* Request.geturi have been replaced by Request.getrequesturi */file file = new file (WEB_ROO T, Request.geturi ()); FIS = new FileInputStream (file);/* * HTTP Response = Status-line ((General-header | response-header | * entity-header) CRLF) CRLF [message-body] status-line = * Http-version sp status-code sp reason-phrase CRLF */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" + "
Package Linkin;import Java.io.ioexception;public class staticresourceprocessor{public void process (Request request, Response Response) {Try{response.sendstaticresource ();} catch (IOException e) {e.printstacktrace ();}}}

Package Linkin;import Java.io.file;import java.io.ioexception;import java.net.url;import java.net.URLClassLoader; Import Java.net.urlstreamhandler;import Javax.servlet.servlet;import Javax.servlet.servletrequest;import Javax.servlet.servletresponse;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{//Create a urlclassloaderurl[] urls = new url[1]; URLStreamHandler streamhandler = null; File ClassPath = new file (response.web_root);//The forming of repository is taken from the//Createclassloader method in/ /org.apache.catalina.startup.ClassLoaderFactoryString repository = (new URL ("file", NULL, Classpath.getcanonicalpath () + file.separator). toString ();//The code for forming the URL is taken from//the Addrepository method in//Org.apache. Catalina.loader.standardclassloader.urls[0] = new URL (null, Repository, streamhandler); LoadeR = new URLClassLoader (URLs);} catch (IOException e) {System.out.println (e.tostring ());} Class MyClass = null;try{system.out.println (servletname); myClass = Loader.loadclass (servletname);} catch (ClassNotFoundException e) {System.out.println (e.tostring ());} servlet servlet = null;try{//Run the reflection, initialize an instance, and call the Servlet's service method. 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 ());}}}

Package Linkin;import Java.io.ioexception;import Java.io.printwriter;import javax.servlet.servlet;import Javax.servlet.servletconfig;import Javax.servlet.servletexception;import Javax.servlet.servletrequest;import Javax.servlet.servletresponse;public class Primitiveservlet implements servlet{@Overridepublic void Init ( ServletConfig config) throws servletexception{system.out.println ("Init");} @Overridepublic void Service (ServletRequest request, servletresponse response) throws Servletexception, ioexception{ System.out.println ("from service"); PrintWriter out = Response.getwriter (); Out.println ("



Additional notes:

First look at the 2 lines of code that calls the Servlet's service method inside the servlet's processor above:

try {servlet = (servlet) myclass.newinstance (); Servlet.service ((ServletRequest) request, (Servletresponse) response);}

Here's the problem: the processor we're writing is not saying that we can only accept requests from the servlet, so the parameters we pass in here are request and response type, but we're now calling the servlet. It is also dangerous to pass in ServletRequest and servletresponse type parameters, where the request and the corresponding is not the servlet type, right? So we have to achieve an effect is to say: I posted this request and response this 2 pieces of code can only be used in our own class, under my own package used, in other places can not be accessed, this way I would like to go down to ensure that there is no mistake, It is also possible to ensure that the methods in these 2 classes are safe, such as the external class must not invoke the Parseuri method of the request, how to do? There are 2 ways to achieve this:

1, let the above request class and the response class have the default access rights, that is, only in their own package is accessed, then this is safe.

2, using the façade design mode, the specific explanation please see my design pattern inside the article. The general meaning is in the above request and response outside to encapsulate a façade, the request and response privatization, all of the methods are actually used this request and response class to invoke, In this case, there is no direct access to the 2 classes of request and response outside of the package. The code is as follows:


Package Linkin;import Java.io.bufferedreader;import Java.io.ioexception;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 Requestfacade implements servletrequest{private servletrequest request = Null;public Requestfacade (Request request) {this.request = Request;} /* Implementation of the ServletRequest */public Object getattribute (String attribute) {return Request.getattribute ( attribute);} Public enumeration Getattributenames () {return request.getattributenames ();} ......................}




Self simulation of a simple tomcat

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.