Java一个简单的web服务器(支持简单的Servlet)

来源:互联网 发布:python入门经典 下载 编辑:程序博客网 时间:2024/06/05 14:13

我们知道一个全功能的servlet容器会为servlet的每个HTTP请求做下面一些工作:

  1. 当第一次调用servlet的时候,加载该servlet类并调用servlet的init方法(仅仅一次)。
  2. 对每次请求,构造一个javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例。
  3. 调用servlet的service方法,同时传递ServletRequest和ServletResponse对象。
  4. 当servlet类被关闭的时候,调用servlet的destroy方法并卸载servlet类。

下面这个例子,主要实现了一下几个功能:
  1. 等待HTTP请求。
  2. 构造一个ServletRequest对象和一个ServletResponse对象。
  3. 假如该请求需要一个静态资源的话,调用StaticResourceProcessor实例的process方法,同时传递ServletRequest和ServletResponse对象。
  4. 假如该请求需要一个servlet的话,加载servlet类并调用servlet的service方法,同时传递ServletRequest和ServletResponse对象。
首页看下项目的目录结构:



HttpServer1 这个类主要是等待前端的请求,来判断调用Servlet处理类,还是静态资源处理类,代码如下:

package test;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 { // shutdown commandprivate static final String SHUTDOWN_COMMAND = "/SHUTDOWN";// the shutdown command receivedprivate boolean 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, InetAddress.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("/servlet/")) {ServletProcessor1 processor = new ServletProcessor1();processor.process(request, response);} else {StaticResourceProcessor processor = new StaticResourceProcessor();processor.process(request, response);}// Close the socketsocket.close();// check if the previous URI is a shutdown commandshutdown = request.getUri().equals(SHUTDOWN_COMMAND);} catch (Exception e) {e.printStackTrace();System.exit(1);}}}}


servlet的service方法从servlet容器中接收一个javax.servlet.ServletRequest实例和一个javax.servlet.ServletResponse实例。
这就是说对于每一个HTTP请求,servlet容器必须构造一个ServletRequest对象和一个ServletResponse对象并把它们传递给正在服务的servlet的service方法。

Request类代表一个request对象并被传递给servlet的service方法。就本身而言,它必须实现javax.servlet.ServletRequest接口。这个类必须提供这个接口所有方法的实现。不过,我们想要让它非常简单并且仅仅提供实现其中一些方法,其他方法则留空。

package test;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) {index2 = requestString.indexOf(' ', index1 + 1);if (index2 > index1)return requestString.substring(index1 + 1, index2);}return null;}public void parse() { StringBuffer 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());}@Overridepublic Object getAttribute(String arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic Enumeration 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 String getContentType() {// 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 getLocales() {// TODO Auto-generated method stubreturn null;}@Overridepublic String getParameter(String arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic Map getParameterMap() {// TODO Auto-generated method stubreturn null;}@Overridepublic Enumeration 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 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}}

同理Response类也一样:

package test;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;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;                    File file = new File(Constants.WEB_ROOT+"webroot",request.getUri());          if(file.exists()){              try {                  fis = new FileInputStream(file);                  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) {                  // TODO Auto-generated catch block                  e.printStackTrace();              }catch(IOException e){                  e.printStackTrace();              }finally{                  if(fis !=null){                      fis.close();                  }              }                        }else{              //找不到文件               String errorMessage = "HTTP/1.1 404 File Not Found\r\n" +       "Content-Type: text/html\r\n" +       "Content-Length: 23\r\n" +       "\r\n" +       "<h1>File Not Found</h1>";               try {                  output.write(errorMessage.getBytes());                  output.flush();              } catch (IOException e) {                  // TODO Auto-generated catch block                  e.printStackTrace();              }          }      }  @Overridepublic void flushBuffer() throws IOException {// TODO Auto-generated method stub}@Overridepublic int getBufferSize() {// TODO Auto-generated method stubreturn 0;}@Overridepublic String getCharacterEncoding() {// TODO Auto-generated method stubreturn null;}@Overridepublic String getContentType() {// TODO Auto-generated method stubreturn null;}@Overridepublic Locale getLocale() {// TODO Auto-generated method stubreturn null;}@Overridepublic ServletOutputStream getOutputStream() throws IOException {// TODO Auto-generated method stubreturn null;}@Overridepublic PrintWriter getWriter() throws IOException {writer = new PrintWriter(output, true);return writer;}@Overridepublic boolean isCommitted() {// TODO Auto-generated method stubreturn false;}@Overridepublic void reset() {// TODO Auto-generated method stub}@Overridepublic void resetBuffer() {// TODO Auto-generated method stub}@Overridepublic void setBufferSize(int arg0) {// TODO Auto-generated method stub}@Overridepublic void setCharacterEncoding(String arg0) {// TODO Auto-generated method stub}@Overridepublic void setContentLength(int arg0) {// TODO Auto-generated method stub}@Overridepublic void setContentType(String arg0) {// TODO Auto-generated method stub}@Overridepublic void setLocale(Locale arg0) {// TODO Auto-generated method stub}}

StaticResourceProcessor类用来提供静态资源请求。唯一的方法是process方法

package test;import java.io.IOException;public class StaticResourceProcessor {public void process(Request request, Response response) {try {response.sendStaticResource();} catch (IOException e) {e.printStackTrace();}}}

ServletProcessor1类用于处理servlet的HTTP请求

package test;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(Constants.WEB_ROOT+"bin"+File.separator+"test"+File.separator);// 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 {myClass = loader.loadClass("test.PrimitiveServlet");} 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());}}}


最后再写一个简单的Servlet类:

package test;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 {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.");}public void destroy() {System.out.println("destroy");}public String getServletInfo() {return null;}public ServletConfig getServletConfig() {return null;}}


package test;import java.io.File;public class Constants {public static final String WEB_ROOT =  System.getProperty("user.dir")+File.separator;}


最后运行HttpServer1类,在浏览器中测试:

Servlet







静态资源







参考书籍:《how tomcat works》
0 0
原创粉丝点击