Upgrade the http server to a servlet container and the server to a servlet

Source: Internet
Author: User

Upgrade the http server to a servlet container and the server to a servlet

The previous blog post explains how to write a simple http server, but only requests static resources. Therefore, in this blog post, you can upgrade a simple http server to a servlet container,

It can process static resources and request simple servlets.

Now, let's look at servlet program development from the perspective of servlet containers. Simply put, for each http request of a servlet, a fully functional servlet container has the following things to do:

* When you call a servlet for the first time, you need to load the servlet class and call its init () method.

* Create a javax. servlet. ServletRequest instance and a javax. servlet. ServletResponse instance for each request.

* Call the service method of the servlet and pass in the ServletRequest object and ServletResponse object as parameters.

* When the servlet class is closed, call its destroy () method and uninstall the servlet.

Of course, the servlet container written in this blog does not have such a complete set of functions, and only some of these functions can be completed.

This servlet container is completed on the basis of the http server. Therefore, it only adds several classes and enhances the functions. The servlet container includes the following classes.

* HttpServer

* Request

* Response

* StaticResourceProcessor

* ServletProcessor

The source code of the above five classes is:

HttpServer:

package cn.com.servletServer;import java.io.File;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;public class HttpServer {/** * WEB_ROOT is the directory where our html and other files reside. * For this package,WEB_ROOT is the "webroot" directory under the * working directory. * the working directory is the location in the file system * from where the java command was invoke. */public static final String WEB_ROOT=System.getProperty("user.dir")+File.separator+"webroot";private static final String SHUTDOWN_COMMAND="/SHUTDOWN";private boolean shutdown=false;public static void main(String[] args) {HttpServer server=new HttpServer();server.await();}public void await(){ServerSocket serverSocket=null;int port=8080;try {serverSocket=new ServerSocket(port,1,InetAddress.getByName("127.0.0.1"));} catch (Exception e) {e.printStackTrace();System.exit(0);}while(!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("/servlet/")){ServletProcessor processor=new ServletProcessor();processor.process(request, response);}else{StaticResourceProcessor processor=new StaticResourceProcessor();processor.process(request, response);}//close the socket socket.close();//check if the previous URI is a shutdown commandshutdown=request.getUri().equals(SHUTDOWN_COMMAND);} catch (Exception e) {e.printStackTrace();System.exit(1);}}}}
This HttpServer class is similar to the previous HttpServer class, but the HttpServer class in this application can request both static resources and servlet resources.

The await () method in this class will wait for the HTTP request until it receives a close command, and this method can distribute the http request to the StaticResourceProcessor object.

Or ServletProcesor object. When the url contains the string "/servlet/", the request is forwarded to the ServletProcessor object. Otherwise, the http request is sent

StaticResourceProcessor object processing.

Request:

package cn.com.servletServer;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.AsyncContext;import javax.servlet.DispatcherType;import javax.servlet.RequestDispatcher;import javax.servlet.ServletContext;import javax.servlet.ServletInputStream;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;public class Request implements ServletRequest {private InputStream input;private String uri;public Request(InputStream input){this.input=input;}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 (Exception 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());}public 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 String getUri(){return this.uri;}@Overridepublic AsyncContext getAsyncContext() {// TODO Auto-generated method stubreturn null;}@Overridepublic Object getAttribute(String arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic Enumeration<String> getAttributeNames() {// TODO Auto-generated method stubreturn null;}@Overridepublic String getCharacterEncoding() {// TODO Auto-generated method stubreturn null;}@Overridepublic int getContentLength() {// TODO Auto-generated method stubreturn 0;}@Overridepublic long getContentLengthLong() {// TODO Auto-generated method stubreturn 0;}@Overridepublic String getContentType() {// TODO Auto-generated method stubreturn null;}@Overridepublic DispatcherType getDispatcherType() {// TODO Auto-generated method stubreturn null;}@Overridepublic ServletInputStream getInputStream() throws IOException {// TODO Auto-generated method stubreturn null;}@Overridepublic String getLocalAddr() {// TODO Auto-generated method stubreturn null;}@Overridepublic String getLocalName() {// TODO Auto-generated method stubreturn null;}@Overridepublic int getLocalPort() {// TODO Auto-generated method stubreturn 0;}@Overridepublic Locale getLocale() {// TODO Auto-generated method stubreturn null;}@Overridepublic Enumeration<Locale> getLocales() {// TODO Auto-generated method stubreturn null;}@Overridepublic String getParameter(String arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic Map<String, String[]> getParameterMap() {// TODO Auto-generated method stubreturn null;}@Overridepublic Enumeration<String> getParameterNames() {// TODO Auto-generated method stubreturn null;}@Overridepublic String[] getParameterValues(String arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic String getProtocol() {// TODO Auto-generated method stubreturn null;}@Overridepublic BufferedReader getReader() throws IOException {// TODO Auto-generated method stubreturn null;}@Overridepublic String getRealPath(String arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic String getRemoteAddr() {// TODO Auto-generated method stubreturn null;}@Overridepublic String getRemoteHost() {// TODO Auto-generated method stubreturn null;}@Overridepublic int getRemotePort() {// TODO Auto-generated method stubreturn 0;}@Overridepublic RequestDispatcher getRequestDispatcher(String arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic String getScheme() {// TODO Auto-generated method stubreturn null;}@Overridepublic String getServerName() {// TODO Auto-generated method stubreturn null;}@Overridepublic int getServerPort() {// TODO Auto-generated method stubreturn 0;}@Overridepublic ServletContext getServletContext() {// TODO Auto-generated method stubreturn null;}@Overridepublic boolean isAsyncStarted() {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean isAsyncSupported() {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean isSecure() {// TODO Auto-generated method stubreturn false;}@Overridepublic void removeAttribute(String arg0) {// TODO Auto-generated method stub}@Overridepublic void setAttribute(String arg0, Object arg1) {// TODO Auto-generated method stub}@Overridepublic void setCharacterEncoding(String arg0)throws UnsupportedEncodingException {// TODO Auto-generated method stub}@Overridepublic AsyncContext startAsync() throws IllegalStateException {// TODO Auto-generated method stubreturn null;}@Overridepublic AsyncContext startAsync(ServletRequest arg0, ServletResponse arg1)throws IllegalStateException {// TODO Auto-generated method stubreturn null;}}
The Request class needs to process servlet, so it implements all the methods declared in the javax. Servlet. ServletRequest interface, but only a simple servlet needs to be processed here. Therefore, only

A small number of methods, most of which are left blank and will be implemented later.

Response:

package cn.com.servletServer;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.OutputStream;import java.io.PrintWriter;import java.util.Locale;import javax.servlet.ServletOutputStream;import javax.servlet.ServletResponse;/** * 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 * */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;}public void sendStaticResource()throws IOException{byte[] bytes=new byte[BUFFER_SIZE];FileInputStream fis=null;try {File file=new File(HttpServer.WEB_ROOT,request.getUri());if(file.exists()){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);}}else{//file not foundString errorMessage="HTTP/1.1 404 File Not Found\r\n"+"Content-Type:text/html\r\n"+"Content-Length:23\r\n"+"\r\n"+"The Response class implements the javax. servlet. ServletRequest interface, which provides the implementation of all the methods declared in the ServletResponse interface, similar to the Request class,

Except the getWriter () method, most methods are left empty.

In the getWriter () method, the second parameter of the PrintWriter class constructor is a Boolean value, indicating whether autoFlush is enabled. True passed in the second parameter indicates any call to the println () method.

The output will be refreshed, but the output will not be refreshed when the print () method is called. Therefore, a small bug is left here and will be solved later.

StaticResourceProcessor:

package cn.com.servletServer;public class StaticResourceProcessor {public void process(Request request,Response response){try {response.sendStaticResource();} catch (Exception e) {e.printStackTrace();}}}
This class has only one method, that is, the process () method, and only one purpose, that is, it is used to process static resources.

ServletProcessor:

Package cn.com. servletServer; import java. io. file; import java.net. URL; import java.net. URLClassLoader; import java.net. URLStreamHandler; import javax. servlet. servlet; import javax. servlet. servletRequest; import javax. servlet. servletResponse;/*** this class is used to process requests to servlet Resources * @ author Administrator **/public class ServletProcessor {public void process (Request request, Response response) {String uri = request. getUri (); String servletName = uri. substring (uri. lastIndexOf ("/") + 1); URLClassLoader loader = null; try {URL [] urls = new URL [1]; URLStreamHandler streamHandle = null; file classPath = new File (HttpServer. 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. standardClassLoaderurls [0] = new URL (null, repository, streamHandle); loader = new URLClassLoader (urls);} catch (Exception e) {System. out. println (e. toString ();} Class myClass = null; try {myClass = loader. loadClass ("cn.com. client. "+ servletName);} catch (ClassNotFoundException e) {System. out. println (e. toString ();} Servlet servlet = null; try {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 ());}}}
This class is also relatively simple. There is only one method: the process () method, which is used to process requests to servlet resources,

However, this class has some problems. The original servlet resources only need to be put into webroot, but here it cannot request servlet resources in webroot, and it can only put the servlet

Resources can be requested in a src package. If you have any idea, please give me some advice.

The servlet used for testing is relatively simple. The source code is as follows:

package cn.com.client;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 destroy() {}@Overridepublic ServletConfig getServletConfig() {return null;}@Overridepublic String getServletInfo() {return null;}@Overridepublic void init(ServletConfig arg0) throws ServletException {}@Overridepublic void service(ServletRequest request, ServletResponse response)throws ServletException, IOException {System.out.print("from service");PrintWriter out=response.getWriter();out.println("Hello. Roses are red.");out.print("Violets are blue.");}}
Now let's test.

Page:

In this way, a simple servlet container is complete, but there are many problems that will be solved one by one later.

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.