The previous section (how Tomcat Works 1 writes a simple static Web server) has written a simple Web server that can handle only static resources, and this section will continue to take a small step forward, creating two different servlet containers that can use the servlet to simply handle dynamic content. Note that the code for each section is based on the continuation of the previous section, so it is necessary to start with the first section.
Before you write your code, you need to get a general idea of what a servlet is, which is handy for later comprehension, and here's a simple servlet that doesn't do anything:
Package Prymont;import Java.io.ioexception;import Javax.servlet.servlet;import javax.servlet.servletconfig;import Javax.servlet.servletexception;import Javax.servlet.servletrequest;import javax.servlet.servletresponse;/** * Each servlet implements a servlet interface * This interface has 5 methods that need to be implemented, and the servlet is only intended to give you an overall impression of the servlet, so none of the methods are implemented. */public class Primitiveservlet implements servlet{//when the servlet container is shutting down or the servlet container is not running out of memory, the method is called by the servlet container and only once// This method is typically used to clean up resources. @Overridepublic void Destroy () {} @Overridepublic servletconfig Getservletconfig () {return null;} @Overridepublic String Getservletinfo () {return null;} When the servlet is initialized, the method is called by the servlet container and is called once//this method is suitable for some one-time loading actions, such as database driver. @Overridepublic void init (ServletConfig arg0) throws Servletexception {}//servlet container is responsible for invoking the service method for each request. and pass a ServletRequest (encapsulate client request)//and Servletresponse (encapsulated response) object. @Overridepublic void Service (ServletRequest arg0, Servletresponse arg1) throws Servletexception, IOException {}}
First of all, the function of our first version of the servlet container is to wait for an HTTP request, if it is to request a static resource to the static resource processor, and if it is to request a dynamic resource then load the appropriate servlet and invoke its service method. Both ServletRequest and Servletresponse objects are passed. (The first version is loaded each time a servlet class is requested)
This release deals with both static and dynamic resources for the last major new Staticresourceprocessor and ServletProcessor1 two classes, while the request and response objects are also individually integrated
Http://machineName:port/staticResource request is a static resource, Http://localhost:8080/servlet/PrimitiveServlet request is a dynamic resource, Therefore, the HttpServer1 only needs a slight change to meet the requirements.
Staticresourceprocessor simply call the response Sendstaticresource () method, there is nothing to say, the following focus on the implementation of ServletProcessor1:
Package Server1;import Java.io.file;import Java.io.ioexception;import java.net.malformedurlexception;import Java.net.url;import Java.net.urlclassloader;import Java.net.urlstreamhandler;import Javax.servlet.Servlet;import Javax.servlet.servletexception;import Javax.servlet.servletrequest;import javax.servlet.servletresponse;/** * To complete the dynamic loading of the servlet class * and invoke the Servlet's service method * */public class ServletProcessor1 {/** * load servlet * * @param request * @pa RAM Response */public void process (Request request, response response) {///servlet/servetclass String URI = Request. GetURI (); Intercept the servlet name String servletname = uri.substring (Uri.lastindexof ("/") + 1); The JDK provides a URL class loader that loads class URLClassLoader loader = null according to the URL; url[] urls = new url[1]; Specifies that all class files under load WebApp file ClassPath = new file (Constant.web_app); URLStreamHandler streamhandler = null; try {//Use the file protocol to load class//Getcanonicalpath from native Classpath to return absolute path (without.) String repository = new URL ("file", NULL, C Lasspath.getcAnonicalpath () + file.separator). toString (); Urls[0] = new URL (null, Repository, streamhandler); } catch (Malformedurlexception e) {e.printstacktrace (); } catch (IOException e) {e.printstacktrace (); } loader = new URLClassLoader (URLs); Class clazz = null; try {//According to the servlet name loading class, where the processing of the name is not perfect, the actual need to do the stitching according to the package name//For the simple servlet class all without the package name Clazz = Loader.loadclass (servletname); } catch (ClassNotFoundException e) {e.printstacktrace (); } servlet servlet = null; try {//reflection Create instance servlet = (servlet) clazz.newinstance (); Down transformation calls the service method Servlet.service ((servletrequest) request, (Servletresponse) response); } catch (Instantiationexception e) {e.printstacktrace (); } catch (Illegalaccessexception e) {e.printstacktrace (); } catch (Servletexception e) {e.printstacktrace (); } catch (IOException e) {e.printstacktrace (); } }}
This is the whole process of working with Servlets, and you can access our servlet through Http://localhost:8080/servlet/PrimitiveServlet.
One serious problem with our first program is that when the service method passed to the servlet transforms both the request and the response object, so that if the person who knows the internal implementation, You can write your servlet down to request and response objects, and call their methods, in fact, the two objects are container private should not be exposed to the developer (specifically some methods can not be used by developers), One way is to let these two classes use the default package access permissions, in fact, there is a more elegant way to implement is the façade mode.
In the second edition of this section, add two classes, Requestfacade and Responsefacade, to control the visibility of some methods. The specific way is to provide Requestfacade with a parametric constructor, the parameter type is the request object, the façade class encapsulation ServletRequest method, actually just passed to the request object implementation, This allows the facade object to be passed when the service method is invoked, so that the encapsulated facade object is obtained even through a downward transformation. The Requestfacade object fragment is as follows:
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); }
Responsefacade objects are similar, do not put out the code.
A little different is the ServletProcessor1 part of the processing, the specific changes are as follows:
Servlet servlet = null; Requestfacade Requestfacade = new Requestfacade (request); Responsefacade Responsefacade = new Responsefacade (response); try { //Reflection Create instance servlet = (servlet) clazz.newinstance (); Down transformation calls the service method Servlet.service ((servletrequest) Requestfacade, (servletresponse) responsefacade); } catch (Instantiationexception e) { e.printstacktrace (); } catch (Illegalaccessexception e) { E.printstacktrace (); } catch (Servletexception e) { e.printstacktrace (); } catch (IOException e) { e.printstacktrace (); }
Constructs a Requestfacade object from the request object and transitions it to the service method.
The above is a simple servlet container implemented in this section. The next section will come into contact with a very important concept in Tomcat-the connector
How Tomcat Works 2