How Tomcat Works Reading Notes 3 ------- Connector
Several Concepts: HttpServlet and Servlet
Servlet is an interface that defines a network service. All our servlets need to implement it (or its subclass)
HttpServlet is an abstract class that targets http network services.
Of course, if you have other network services in the future, you can define another class to implement Servlet.
HttpServletRequest, ServletRequest
Let's talk about the ServletRequest interface, which is used to transmit network service requests and is used in Servlet-class service methods.
Therefore, the HttpServletRequest interface mainly targets http requests.
HttpServletRequest has more methods for Http than ServletRequest. Such as getHeader, getMethod, and getSession.
For a large system, StringManager must handle error messages with caution. If you save all the error messages in a properties file, it will be extremely complicated, therefore, tomcat creates a set of properties files for each package in the system (a group rather than a group to support multi-language LocalStrings. properties, LocalStrings_es.properties, LocalStrings_ja.properties are English, Spanish, and Japanese)
For example, in the HttpProcessor class under the ex03.pyrmont. connector. http package, we reference StringManager as follows:
Protected StringManager sm =
StringManager. getManager ("ex03.pyrmont. connector. http ");
Used where an exception is to be thrown
Throw new ServletException
(Sm. getString ("httpProcessor. parseHeaders. colon "));
Now let's take a look at the properties file (partial) under the httpProcessor. parseHeaders. colon package)
HttpProcessor. parseHeaders. colon = Invalid HTTP header format
HttpProcessor. starting = Starting background thread
HttpProcessor. stopping = Stopping background thread
RequestStream. close. closed = Request stream has already been closed
Now we know the StringManager function.
In addition, the generation of StringManager is a singleton mode. You can refer to the source code.
In this chapter, the http request object is represented by httprequst (this class does not exist in jdk). It implements the HttpServletRequest interface.
When used, httprequst is transformed into HttpServletRequest and called as a parameter of the servlet service method.
Therefore, we need to set the member variables of each httprequest instance for the servlet instance. The values to be set include uri, query string, parameter, Cookie, etc.
Therefore, there is a problem here. parsing the http Request body (note that the get/post Request Method and the request header will all be parsed) involves many string operations, if we only parse the values that will be used, we can save a lot of cpu cycles.
So only when we call javax. servlet. http. getParameter (), getParameterMap (), getParameter-Names (), and getParameterValues () of HttpServletRequest will only parse the Request body (and only parse the four methods that are called multiple times )!
The specific method is to call a parseParameters () method in the first line of code in the above four methods in the HttpRequest class (the one we wrote implementing the HttpServletRequest interface. Parsed ensures that parseParameters runs only once.
(In addition, I think the request string should be part of the Request body)
Chapter 2 helps us build a simple servlet container that can load static resources and process some simple servlets. In this chapter, we need to further improve our container so that it can obtain some parameters of the request.
Therefore, the servlet in this section will inherit HttpServlet, And the passed parameter will also be HttpServletRequest.
Application code
The servlet code in this chapter is as follows:
Import javax. servlet. *; import javax. servlet. http. *; import java. io. *; import java. util. *; public class ModernServlet extends HttpServlet {public void init (ServletConfig config) {System. out. println ("ModernServlet -- init");} public void doGet (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response. setContentType ("text/html"); PrintWriter out = response. getWriter (); out. println (""); Out. println (""); Out. println ("Modern Servlet"); Out. println (""); Out. println (""); Out. println (" Headers "+ header +": "+ request. getHeader (header);} // some request information out. println (""); Out. println ("");}}
First look at the UML diagram
The system extracts a Bootstrap class, loads the HttpConnector class, and calls its start () method.
<喎?http: www.bkjia.com kf ware vc " target="_blank" class="keylink"> VcD4KPHByZSBjbGFzcz0 = "brush: java;"> package ex03.pyrmont. connector. http; import java. io. IOException; import java.net. inetAddress; import java.net. serverSocket; import java.net. socket; public class HttpConnector implements Runnable {boolean stopped; private String scheme = "http"; public String getScheme () {return scheme;} public void run () {ServerSocket serverSocket = null; int port = 8080; try {ser VerSocket = new ServerSocket (port, 1, InetAddress. getByName ("127.0.0.1");} catch (IOException e) {e. printStackTrace (); System. exit (1);} while (! Stopped) {// Accept the next incoming connection from the server socket Socket socket = null; try {socket = serverSocket. accept ();} catch (Exception e) {continue;} // Hand this socket off to an HttpProcessor processor = new HttpProcessor (this); processor. process (socket) ;}} public void start () {Thread thread = new Thread (this); thread. start ();}}
The run method of HttpConnector is similar to HttpServer1 in Chapter 1 of the book, but after obtaining inputstream in chapter 1, let him generate a request. Here, we create httpprocessor, and call its process method to convert serverSocket. accept () socket input.
The process method of HttpProcessor is as follows:
public void process(Socket socket) {SocketInputStream input = null; OutputStream output = null; try { input = new SocketInputStream(socket.getInputStream(), 2048); output = socket.getOutputStream(); // create HttpRequest object and parse request = new HttpRequest(input); // create HttpResponse object response = new HttpResponse(output); response.setRequest(request); response.setHeader("Server", "Pyrmont Servlet Container ***"); parseRequest(input, output); parseHeaders(input); //check if this is a request for a servlet or a static resource //a request for a servlet begins with "/servlet/" if (request.getRequestURI().startsWith("/servlet/")) { ServletProcessor processor = new ServletProcessor(); processor.process(request, response); } else { StaticResourceProcessor processor = new StaticResourceProcessor(); processor.process(request, response); } // Close the socket socket.close(); // no shutdown for this application } catch (Exception e) { e.printStackTrace(); } }
Check this line of code
Input = new SocketInputStream (socket. Fig (), 2048 );
SocketInputStream is a packaging class that implements the InputStream interface. We use SocketInputStream to use its readRequestLine () method readHeader method. The former can read the request method, uri and request protocol, and the latter can read the request header.
Build HttpRequest
ParseRequest (input, output );
ParseHeaders (input );
These two methods are the core of the process method, or the core of Chapter 3. To put it simply, the two methods are used to parse http requests and fill in the HttpRequst object. Of course, there are many details here.
This section is simple and easy to explain. It is also difficult to explain. It is generally five parts.
1. Read the input stream of the socket.
Is the following line of code
Input = new SocketInputStream (socket. Fig (), 2048 );
If you are interested, you can check the source code of readRequestLine.
2. parse the request line (that is, the first line of the http request includes the Request Method uri Protocol version)
3. parse the Request Header
4. parse cookies
5. Obtain parameters (the lazy load mentioned above)
Build HttpResponse
In the ServletResponse In chapter 2, we only implement some functions, and the print method cannot be automatically refreshed.
public PrintWriter getWriter() throws IOException { // autoflush is true, println() will flush, // but print() will not. writer = new PrintWriter(output, true); return writer; }
Through the code in the second chapter above, we know that writer is an instance of the PrintWriter class.
1. In this chapter, we use ResponseWriter to construct a writer instance (ResponseWriter inherits from PrintWriter)
2. The output in Chapter 2 is an instance of the OutputStream interface. In chapter 3, we replace it with ResponseStream (ResponseStream inherits ServletOutputStream, while the latter implements the OutputStream interface)
3 At the same time, an OutputStreamWriter is also required as a bridge between ResponseWriter and ResponseStream.
The Code is as follows:
Public PrintWriter getWriter () throws IOException {ResponseStream newStream = new ResponseStream (this); // this indicates HttpResopnse newStream. setCommit (false); OutputStreamWriter osr = new OutputStreamWriter (newStream, getCharacterEncoding (); writer = new ResponseWriter (osr); return writer ;}
The static resource processor and servlet processor are basically the same as those in the previous chapter.
References
Http://zhidao.baidu.com/link? Url = BGdS8iiz12FmAlVLsoGj6n3LwclvQ7rD-8GOJ6U8uguM8IGZrDUooTkjnySAInrMkqA6a7XofgNu4J3ynbOPC _