上一篇博客《自己动手编写tomcat服务器(一)》并不完美,它只能支持请求静态文件,如hello.html,不能请求servlet文件,这篇将完善,同时支持这两种请求
应用包含以下文件:
HttpServer1
Request
Response
StaticResourceProcessor
ServletProcessor1
Constants
UML类图如下:
应用的入口是HttpServer1的main方法,它创建了一个HttpServer1的实例并调用它的await方法,这个方法等待HTTP请求,为每一个请求创建Request
对象和Response对象,然后根据请求的是静态文件还是一个servlet,把它们传给StaticResourceProcessor或ServletProcessor1的实例
如果请求的是静态文件,其路径为:http://machineName:port/staticResource
如果请求的是servlet,路径为:http://machineName:port/servlet/servletClass
HttpServer1的源码如下:
- package ex02.pyrmont;
- 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 {
- private static final String SHUTDOWN_COMMAND = "/SHUTDOWN";
- private boolean shutdown = false;
- public static void main(String[] args) {
- HttpServer1 server = new HttpServer1();
- server.await();
- }
- private 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);
- }
- while(!shutdown){
- Socket socket = null;
- InputStream input = null;
- OutputStream output = null;
- try{
- socket = serverSocket.accept();
- input = socket.getInputStream();
- output = socket.getOutputStream();
- Request request = new Request(input);
- request.parse();
- Response response = new Response(output);
- response.setRequest(request);
- if(request.getUri().startsWith("/servlet/")){
- ServletProcessor1 processor = new ServletProcessor1();
- processor.process(request,response);
- }else{
- StaticResourceProcessor processor = new StaticResourceProcessor();
- processor.process(request,response);
- }
- socket.close();
- shutdown = request.getUri().equals(SHUTDOWN_COMMAND);
- }catch(IOException e){
- e.printStackTrace();
- System.exit(1);
- }
- }
- }
- }
Request类的源代码如下:
- package ex02.pyrmont;
- 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 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.println(request.toString());
- uri = parseUri(request.toString());
- }
- 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 Object getAttribute(String arg0) {
- // TODO Auto-generated method stub
- return null;
- }
- public Enumeration getAttributeNames() {
- // TODO Auto-generated method stub
- return null;
- }
- public String getCharacterEncoding() {
- // TODO Auto-generated method stub
- return null;
- }
- public int getContentLength() {
- // TODO Auto-generated method stub
- return 0;
- }
- public String getContentType() {
- // TODO Auto-generated method stub
- return null;
- }
- public ServletInputStream getInputStream() throws IOException {
- // TODO Auto-generated method stub
- return null;
- }
- public String getLocalAddr() {
- // TODO Auto-generated method stub
- return null;
- }
- public String getLocalName() {
- // TODO Auto-generated method stub
- return null;
- }
- public int getLocalPort() {
- // TODO Auto-generated method stub
- return 0;
- }
- public Locale getLocale() {
- // TODO Auto-generated method stub
- return null;
- }
- public Enumeration getLocales() {
- // TODO Auto-generated method stub
- return null;
- }
- public String getParameter(String arg0) {
- // TODO Auto-generated method stub
- return null;
- }
- public Map getParameterMap() {
- // TODO Auto-generated method stub
- return null;
- }
- public Enumeration getParameterNames() {
- // TODO Auto-generated method stub
- return null;
- }
- public String[] getParameterValues(String arg0) {
- // TODO Auto-generated method stub
- return null;
- }
- public String getProtocol() {
- // TODO Auto-generated method stub
- return null;
- }
- public BufferedReader getReader() throws IOException {
- // TODO Auto-generated method stub
- return null;
- }
- public String getRealPath(String arg0) {
- // TODO Auto-generated method stub
- return null;
- }
- public String getRemoteAddr() {
- // TODO Auto-generated method stub
- return null;
- }
- public String getRemoteHost() {
- // TODO Auto-generated method stub
- return null;
- }
- public int getRemotePort() {
- // TODO Auto-generated method stub
- return 0;
- }
- public RequestDispatcher getRequestDispatcher(String arg0) {
- // TODO Auto-generated method stub
- return null;
- }
- public String getScheme() {
- // TODO Auto-generated method stub
- return null;
- }
- public String getServerName() {
- // TODO Auto-generated method stub
- return null;
- }
- public int getServerPort() {
- // TODO Auto-generated method stub
- return 0;
- }
- public boolean isSecure() {
- // TODO Auto-generated method stub
- return false;
- }
- public void removeAttribute(String arg0) {
- // TODO Auto-generated method stub
- }
- public void setAttribute(String arg0, Object arg1) {
- // TODO Auto-generated method stub
- }
- public void setCharacterEncoding(String arg0)
- throws UnsupportedEncodingException {
- // TODO Auto-generated method stub
- }
- }
Request类代表传递给Servlet的service方法的request对象,它实现了javax.servlet.ServletRequest接口
Response类的源代码如下:
- package ex02.pyrmont;
- 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;
- private OutputStream output;
- private Request request;
- private 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 {
- /* request.getUri has been replaced by request.getRequestURI */
- File file = new File(Constants.WEB_ROOT, request.getUri());
- 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);
- }
- } catch (FileNotFoundException e) {
- 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>";
- output.write(errorMessage.getBytes());
- } finally {
- if (fis != null)
- fis.close();
- }
- }
- public void flushBuffer() throws IOException {
- // TODO Auto-generated method stub
- }
- public int getBufferSize() {
- // TODO Auto-generated method stub
- return 0;
- }
- public String getCharacterEncoding() {
- // TODO Auto-generated method stub
- return null;
- }
- public String getContentType() {
- // TODO Auto-generated method stub
- return null;
- }
- public Locale getLocale() {
- // TODO Auto-generated method stub
- return null;
- }
- public ServletOutputStream getOutputStream() throws IOException {
- // TODO Auto-generated method stub
- return null;
- }
- public PrintWriter getWriter() throws IOException {
- writer = new PrintWriter(output,true);
- return writer;
- }
- public boolean isCommitted() {
- // TODO Auto-generated method stub
- return false;
- }
- public void reset() {
- // TODO Auto-generated method stub
- }
- public void resetBuffer() {
- // TODO Auto-generated method stub
- }
- public void setBufferSize(int arg0) {
- // TODO Auto-generated method stub
- }
- public void setCharacterEncoding(String arg0) {
- // TODO Auto-generated method stub
- }
- public void setContentLength(int arg0) {
- // TODO Auto-generated method stub
- }
- public void setContentType(String arg0) {
- // TODO Auto-generated method stub
- }
- public void setLocale(Locale arg0) {
- // TODO Auto-generated method stub
- }
- }
它实现了javax.servlet.ServletResponse接口,代表传递给servlet的service方法的response对象
StaticResourceProcessor的源代码如下:
- 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();
- }
- }
- }
它用来处理对静态资源的请求
ServletProcessor1的源码如下:
- package ex02.pyrmont;
- 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{
- URL[] urls = new URL[1];
- URLStreamHandler streamHandler = null;
- File classPath = new File(Constants.WEB_ROOT);
- String repository = new URL("file",null,classPath.getCanonicalPath()+ File.separator).toString();
- 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(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());
- }
- }
- }
它用来处理对servlet的请求
Constants的源代码如下:
- package ex02.pyrmont;
- import java.io.File;
- public class Constants {
- public static final String WEB_ROOT =
- System.getProperty("user.dir") + File.separator + "webroot";
- }
再写一个简单的servlet测试一下
PrimitiveServlet
- 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 destroy() {
- System.out.println("destroy");
- }
- public ServletConfig getServletConfig() {
- // TODO Auto-generated method stub
- return null;
- }
- public String getServletInfo() {
- // TODO Auto-generated method stub
- return null;
- }
- public void init(ServletConfig arg0) throws ServletException {
- System.out.println("init");
- }
- public void service(ServletRequest arg0, ServletResponse arg1)
- throws ServletException, IOException {
- System.out.println("form service");
- PrintWriter out = arg1.getWriter();
- out.println("Hello,roses are red");
- out.println("violets are blues");
- }
- }
将index.html和PrimitiveServlet编译后的class文件放入到webroot目录中,运行HttpServer1程序,在浏览器中输入:http://localhost:8080/index.html
或http://localhost:8080/servlet/PrimitiveServlet,将会看到结果
转自:http://blog.youkuaiyun.com/wenjingyu/article/details/10484091