Simple implementation of a servlet container based on a Java Web server _java

Source: Internet
Author: User
Tags first string int size locale throwable java web

The previous article wrote a simple Java Web server implementation, can only handle some static resource requests, this article implementation of the Servlet container based on the previous server made a small transformation, increased the processing of servlet requests.

Program execution steps
1. Create a ServerSocket object;
2. Call the Accept method of the ServerSocket object, wait for the connection, the connection succeeds will return a socket object, otherwise blocking waits all the time;
3. From the socket object to obtain InputStream and OutputStream byte stream, the two streams correspond to request requests and response responses respectively;
4. Processing request: Read InputStream Word throttling information, turn into a string form, and parse, here the resolution is relatively simple, just get the URI (Uniform Resource Identifier) information;
5. Processing response (two types, static resource request response, or servlet request response): If a static resource request, the requested resource file is searched from the Web_root directory based on the parsed URI information, and the resource file is read. and writes it to the outputstream byte stream; if it is a servlet request, it first generates a URLClassLoader class loader, loads the requested Servlet class, creates a Servlet object, Execute service method (data written to outputstream);
6. Close socket object;
7. Go to step 2 and continue to wait for the connection request;

Code implementation:
Add dependencies:

 <!--https://mvnrepository.com/artifact/javax.servlet/servlet-api-->
 <dependency>
 < groupid>javax.servlet</groupid>
 <artifactId>servlet-api</artifactId>
 <version >2.3</version>
 </dependency>

Server code:

Package Ex02.pyrmont.first;
Import Java.net.Socket;
Import Java.net.ServerSocket;
Import java.net.InetAddress;
Import Java.io.InputStream;
Import Java.io.OutputStream;

Import java.io.IOException;
Import Ex02.pyrmont.Request;
Import Ex02.pyrmont.Response;

Import Ex02.pyrmont.StaticResourceProcessor;

 public class HttpServer1 {//Close service command private static final String Shutdown_command = "/shutdown";
 public static void Main (string[] args) {HttpServer1 server = new HttpServer1 ();
 Wait for connection request server.await ();
 public void await () {ServerSocket serversocket = null;
 int port = 8080;
 try {//server socket Object ServerSocket = new ServerSocket (port, 1, Inetaddress.getbyname ("127.0.0.1"));
 catch (IOException e) {e.printstacktrace ();
 System.exit (1);
 //Loop wait request while (TRUE) {socket socket = NULL;
 InputStream input = null;
 OutputStream output = null;
 try {//wait for connection, after successful connection, return a socket object socket = serversocket.accept ();
 input = Socket.getinputstream (); Output = Socket.getoutputstreAM ();
 Create the Request object and parse the request request = new request (input);
 Request.parse ();
 Check if the service command is turned off if (Request.geturi (). Equals (Shutdown_command)) {break;
 ///Create Response object Response Response = new Response (output);

 Response.setrequest (Request); if (Request.geturi (). StartsWith ("/servlet/")) {//request URI begins with/servlet/, indicates servlet request ServletProcessor1 processor = new Serv
  LetProcessor1 ();
 Processor.process (request, response);
  else {//static resource request Staticresourceprocessor processor = new Staticresourceprocessor ();
 Processor.process (request, response);

 ///Close socket socket.close ();
 catch (Exception e) {e.printstacktrace ();
 System.exit (1);

 }
 }
 }
}

Constant class:

Package Ex02.pyrmont;

Import Java.io.File;

public class Constants {public
 static final String web_root = System.getproperty ("User.dir")
 + File.separator + " Webroot ";
 public static final String web_servlet_root = System.getproperty ("User.dir")
 + file.separator + "target" + file.separ Ator + "classes";
 
}

Request:

Package Ex02.pyrmont;
Import Java.io.InputStream;
Import java.io.IOException;
Import Java.io.BufferedReader;
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; The/** * * requeststring form is as follows: * get/index.html http/1.1 * host:localhost:8080 * connection:keep-alive * Ntrol:max-age=0 * ... * This function is intended to get the/index.html string/private String Parseuri (string requeststring) {int INDEX1, IND
 EX2;
 Index1 = Requeststring.indexof (");
 if (index1!=-1) {index2 = Requeststring.indexof (', index1 + 1);
 if (Index2 > Index1) return requeststring.substring (index1 + 1, index2); } return Null ///Read request information from InputStream, and get URI value public void Parse () {//Read a set of characters from this socket String from request
 Buffer 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 the 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;
 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) {} void setcharacterencoding (String encoding) throws UnsupportedencodingexcEption {}}

 

Response:

Package Ex02.pyrmont;
Import Java.io.OutputStream;
Import java.io.IOException;
Import Java.io.FileInputStream;
Import java.io.FileNotFoundException;
Import Java.io.File;
Import Java.io.PrintWriter;
Import Java.util.Locale;
Import Javax.servlet.ServletResponse;

Import Javax.servlet.ServletOutputStream;
 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 Setrequest (Request request) {this.request = Request; //Writes Web files to outputstream bytes public void Sendstaticresource () throws IOException {byte[] bytes = new Byte[buffer_siz
 E];
 FileInputStream FIS = null; try {/* Request.geturi has been replaced by Request.getrequesturi/file File = new file (Constants.web_root, REQUEST.G
 Eturi ());
 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); The catch (FileNotFoundException e) {String errormessage = "http/1.1 404 File Not found\r\n" + "content-type:text/ht
 ml\r\n "+" content-length:23\r\n "+" \ r \ n "+"  

Static resource Request Processing:

Package Ex02.pyrmont;

Import java.io.IOException;

public class Staticresourceprocessor {public

 void process (Request request, Response Response) {
 try {
 Response.sendstaticresource ();
 } catch (IOException e) {
 e.printstacktrace ();}}}


Servlet Request Processing:

Package Ex02.pyrmont.first;
Import Java.net.URL;
Import Java.net.URLClassLoader;
Import Java.net.URLStreamHandler;

Import java.io.IOException;
Import Javax.servlet.Servlet;
Import Javax.servlet.ServletRequest;

Import Javax.servlet.ServletResponse;
Import ex02.pyrmont.Constants;
Import Ex02.pyrmont.Request;

Import Ex02.pyrmont.Response; public class ServletProcessor1 {public void process (Request request, Response Response) {String URI = Request.geturi
 ();
 
 String servletname = uri.substring (Uri.lastindexof ("/") + 1);
 Class loader, which is used to load class URLClassLoader loader = null from the specified jar file or directory;
 try {URLStreamHandler streamhandler = null;
 Create class Loader loader = new URLClassLoader (new url[]{new URL (null, "file: + Constants.web_servlet_root, Streamhandler)}";
 catch (IOException e) {System.out.println (e.tostring ());
 } class<?> myClass = null;
 try {//load the corresponding servlet class MyClass = Loader.loadclass (servletname);
 catch (ClassNotFoundException e) {System.out.println (e.tostring ()); } SErvlet servlet = null;
 try {//production servlet instance servlet = (servlet) myclass.newinstance ();
 Perform Ervlet service method Servlet.service (ServletRequest) request, (Servletresponse) response);
 catch (Exception e) {System.out.println (e.tostring ());
 catch (Throwable e) {System.out.println (e.tostring ());

 }

 }
}

Servlet class:

Import javax.servlet.*;
Import java.io.IOException;
Import Java.io.PrintWriter;

public class Primitiveservlet implements Servlet {public

 void init (servletconfig config) throws servletexception {
   system.out.println ("Init");
 }

 public void Service (ServletRequest request, servletresponse response)
 throws Servletexception, IOException {
 System.out.println ("from service");
 PrintWriter out = Response.getwriter ();
 Out.println ("Hello.") Roses are red. ");
 Out.print ("Violets are blue.");
 }

 public void Destroy () {
 System.out.println ("destroy");
 }

 Public String Getservletinfo () {return
 null;
 }

 Public ServletConfig Getservletconfig () {return
 null;
 }

}

Results test:
Static resource request:

Servlet request (because only the first string is flushed to the browser, so you can't see the second string violets are blue.) We will refine the container in the following):

Improved

The previously implemented Servlet container has a serious problem where users can directly convert ServletRequest, servletresponse down to request and response types in the servlet and call their internal public methods directly , this is a bad design, and the improved method is to add the appearance class to request, Response, so that users can only access the public method defined in the Appearance class.
Request appearance Class

Package Ex02.pyrmont.second;
Import java.io.IOException;
Import Java.io.BufferedReader;
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;

Import Ex02.pyrmont.Request;

 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.getattribut
 E (attribute);
 Public enumeration<?> Getattributenames () {return request.getattributenames ();
 @SuppressWarnings ("deprecation") public string Getrealpath (string path) {return Request.getrealpath (path);
 Public RequestDispatcher Getrequestdispatcher (String path) {return request.getrequestdispatcher (path); } public Boolean ISsecure () {return request.issecure ();
 Public String getcharacterencoding () {return request.getcharacterencoding ();
 public int getcontentlength () {return request.getcontentlength ();
 Public String getContentType () {return request.getcontenttype ();
 Public ServletInputStream getInputStream () throws IOException {return Request.getinputstream ();
 Public Locale GetLocale () {return Request.getlocale ();
 Public enumeration<?> Getlocales () {return request.getlocales ();
 public string GetParameter (string name) {return request.getparameter (name);
 Public map<?,? > Getparametermap () {return request.getparametermap ();
 Public enumeration<?> Getparameternames () {return request.getparameternames ();
 String[] Getparametervalues (String parameter) {return request.getparametervalues (parameter);
 Public String Getprotocol () {return request.getprotocol (); Public BufferedReader Getreader () throws IOException {return Request.getreader ();
 Public String getremoteaddr () {return request.getremoteaddr ();
 Public String Getremotehost () {return request.getremotehost ();
 Public String Getscheme () {return request.getscheme ();
 Public String getServerName () {return request.getservername ();
 public int Getserverport () {return request.getserverport ();
 public void RemoveAttribute (String attribute) {Request.removeattribute;
 public void setattribute (String key, Object value) {Request.setattribute (key, value); } public void Setcharacterencoding (String encoding) throws Unsupportedencodingexception {Request.setcharacterencodin
 g (encoding);

 }

}

Response appearance class

Package Ex02.pyrmont.second;
Import java.io.IOException;
Import Java.io.PrintWriter;

Import Java.util.Locale;
Import Javax.servlet.ServletResponse;

Import Javax.servlet.ServletOutputStream;

Import Ex02.pyrmont.Response;

 public class Responsefacade implements Servletresponse {private servletresponse response;
 Public Responsefacade (Response Response) {this.response = Response;
 public void Flushbuffer () throws IOException {Response.flushbuffer ();
 public int getbuffersize () {return response.getbuffersize ();
 Public String getcharacterencoding () {return response.getcharacterencoding ();
 Public Locale GetLocale () {return Response.getlocale ();
 Public Servletoutputstream Getoutputstream () throws IOException {return Response.getoutputstream ();
 Public PrintWriter getwriter () throws IOException {return response.getwriter ();
 public Boolean iscommitted () {return response.iscommitted ();
 public void Reset () {response.reset (); } PublIC void Resetbuffer () {response.resetbuffer ();
 public void setbuffersize (int size) {response.setbuffersize (size);
 public void setcontentlength (int length) {response.setcontentlength (length);
 public void setContentType (String type) {Response.setcontenttype (type);
 public void SetLocale (Locale Locale) {Response.setlocale (Locale);

 }

}

Process servlet request class:  

Package Ex02.pyrmont.second;
Import Java.net.URL;
Import Java.net.URLClassLoader;
Import Java.net.URLStreamHandler;

Import java.io.IOException;
Import Javax.servlet.Servlet;
Import Javax.servlet.ServletRequest;

Import Javax.servlet.ServletResponse;
Import ex02.pyrmont.Constants;
Import Ex02.pyrmont.Request;

Import Ex02.pyrmont.Response; public class ServletProcessor2 {public void process (Request request, Response Response) {String URI = Request.geturi
 ();
 String servletname = uri.substring (Uri.lastindexof ("/") + 1);
 Class loader, which is used to load class URLClassLoader loader = null from the specified jar file or directory;
  try {URLStreamHandler streamhandler = null; Create class Loader loader = new URLClassLoader (new url[] {new URL (null, "file:" + constants.web_servlet_root, Streamhandler)
 });
 catch (IOException e) {System.out.println (e.tostring ());
 } class<?> myClass = null;
 try {//load the corresponding servlet class MyClass = Loader.loadclass (servletname); The catch (ClassNotFoundException e) {System.out.println (e.tostring ());
 The servlet servlet = null; To request, response Add appearance class, security considerations, to prevent users in the servlet directly to the ServletRequest, servletresponse down to the request and response type,/ and directly call its internal public method, because Requestfacade, Responsefacade will not have parse, sendstaticresource and other methods; Requestfacade Requestfacade = new
 Requestfacade (Request);
 Responsefacade Responsefacade = new Responsefacade (response);
  try {servlet = (servlet) myclass.newinstance ();
 Servlet.service ((ServletRequest) Requestfacade, (servletresponse) responsefacade);
 catch (Exception e) {System.out.println (e.tostring ());
 catch (Throwable e) {System.out.println (e.tostring ());

 }

 }
}

Other code is basically consistent with the servlet container that was implemented earlier.
The validator, requesting the static resources and the servlet separately, found the result to be consistent with the previously implemented container;

Reference: "In-depth analysis of Tomcat"

@author the wind of the farmer

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.