自学内容网 自学内容网

手写一个民用Tomcat (02)

01 我们已经完成了 基本玩具一样的Tomcat,可以实现这个功能,下面我们在规范一下

先从我们的JxdResponse ,JxdRequest  分别实现ServletRequest ,和ServletResponse

注意下 没有用的到 重写方法我就 直接去掉了,你自己可以在代码中实现以下


public class JxdResponse implements ServletResponse{
    private static final int BUFFER_SIZE = 1024;
    JxdRequest request;

    OutputStream output;
    PrintWriter writer;
    String contentType = null;
    long contentLength = -1;
    String charset = null;
    String characterEncoding = null;

    public OutputStream getOutput() {
        return output;
    }

    public void setOutput(OutputStream output) {
        this.output = output;
    }

    public JxdResponse(OutputStream output) {
        this.output = output;
    }

    public void setRequest(JxdRequest request) {
        this.request = request;
    }

    /**
     * 这个方法是静态方法演示
     * @throws IOException
     */
    public void sendStaticResource() throws IOException {
        byte[] bytes = new byte[BUFFER_SIZE];
        FileInputStream fis = null;
        try {
            File file = new File(JxdHttpServer.FILE_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, ch);
                    ch = fis.read(bytes, 0, BUFFER_SIZE);
                }
                output.flush();
            } 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>error未知</h1>";
                output.write(errorMessage.getBytes());
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        } finally {
            if(fis != null) {
                fis.close();
            }
        }
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        writer = new PrintWriter(new OutputStreamWriter(output,getCharacterEncoding()), true);
        return writer;
    }

    @Override
    public String getCharacterEncoding() {
        return characterEncoding;
    }

    @Override
    public void setCharacterEncoding(String characterEncoding) {
        this.characterEncoding = characterEncoding;
    }

    @O
}

import javax.servlet.*;
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;

public class JxdRequest implements ServletRequest {
    private InputStream input;
    private String uri;

    public JxdRequest(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]);
        }
        uri = parseUri(request.toString());
    }

    private static 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 uri;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return null;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return null;
    }
}

JxdHttpConnector  实现Runnable  接口 


import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

public class JxdHttpConnector implements Runnable {

    @Override
    public void run() {
        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 (true) {
            Socket socket = null;
            try {
                socket = serverSocket.accept();

                //交给HttpProcessor 处理
                JxdHttpProcessor processor = new JxdHttpProcessor();
                processor.process(socket);
                //交给HttpProcessor 完成 关闭
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void start() {
        Thread thread = new Thread(this);
        thread.start();
    }
}

JxdHttpProcessor  处理方法 没太大变化


import org.apache.commons.lang.text.StrSubstitutor;

import javax.servlet.Servlet;
import java.io.*;
import java.net.*;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

public class JxdHttpProcessor {

    public void process(Socket socket) { //服务器循环等待请求并处理
        while (true) {
            InputStream input = null;
            OutputStream output = null;
            try {
                input = socket.getInputStream();
                output = socket.getOutputStream();
                // create Request object and parse
                JxdRequest request = new JxdRequest(input);
                request.parse();
                // create Response object
                JxdResponse response = new JxdResponse(output);

                if (request.getUri().startsWith("/servlet/")) {
                    //加载动态资源
                    JxdServletProcessor jxdServletProcessor = new JxdServletProcessor();
                    jxdServletProcessor.process(request, response);
                } else {
                    //加载静态资源
                    StaticResourceProcessor staticResourceProcessor = new StaticResourceProcessor();
                    staticResourceProcessor.process(request, response);
                }
            } catch (Exception ea) {
                ea.printStackTrace();
            }
        }
    }
}


import org.apache.commons.lang.text.StrSubstitutor;

import javax.servlet.Servlet;
import java.io.*;
import java.net.*;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

public class JxdServletProcessor {
    //根据HTTP协议响应头定义,里面包含变量
    private static String OKMessage = "HTTP/1.1 ${StatusCode} ${StatusName}\r\n" +
            "Content-Type: ${ContentType}\r\n" +
            "Server: minit\r\n" +
            "Date: ${ZonedDateTime}\r\n" +
            "\r\n";

    public void process(JxdRequest request, JxdResponse response) {
//首先根据uri最后一个/号来定位,后面的字符串认为是servlet名字
        String uri = request.getUri();
        String servletName = uri.substring(uri.lastIndexOf("/") + 1);
        URLClassLoader loader = null;

        PrintWriter printWriter =null;
        try {
// create a URLClassLoader
            URL[] urls = new URL[1];
            URLStreamHandler streamHandler = null;
            File classPath = new File(JxdHttpServer.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());
        }


        //由上面的URLClassLoader加载这个servlet
        Class<?> servletClass = null;
        try {
            //获取PrintWriter
            response.setCharacterEncoding("UTF-8");
            printWriter = response.getWriter();
            servletClass = loader.loadClass(servletName);
        } catch (ClassNotFoundException | IOException e) {
            System.out.println(e.toString());
        }

//创建servlet新实例,然后调用
// service(),由它来写动态内容到响应体
        Servlet servlet = null;
        try {
            //写响应头
            String head = composeResponseHead();
            printWriter.println(head);
            servlet = (Servlet) servletClass.newInstance();
            servlet.service(request, response);
        } catch (Exception e) {
            System.out.println(e.toString());
        } catch (Throwable e) {
            System.out.println(e.toString());
        }

    }

    //生成响应头,填充变量值
    private String composeResponseHead() {
        Map<String, Object> valuesMap = new HashMap<>();
        valuesMap.put("StatusCode", "200");
        valuesMap.put("StatusName", "OK");
        valuesMap.put("ContentType", "text/html;charset=UTF-8");
        valuesMap.put("ZonedDateTime",  DateTimeFormatter.ISO_ZONED_DATE_TIME.format(ZonedDateTime.now()));
        StrSubstitutor sub = new StrSubstitutor(valuesMap);
        String responseHead = sub.replace(OKMessage);
        return responseHead;
    }
}

最后看一下实现类 helloWorld 实现规范的Servlet ,没必要的方法不展示,


import javax.servlet.*;
import java.io.IOException;

public class HelloWorldServlet implements Servlet {
    //http://localhost:8080/servlet/com.yixin.HelloWorldServlet
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        servletResponse.setCharacterEncoding("UTF-8");
        System.out.println("进入>>>>>>HelloWorldServlet.service方法");

        String doc = "Hello World !!!";
        String doc1 = "Happy Day!!!";
        servletResponse.getWriter().println(doc);
        servletResponse.getWriter().println(doc1);
    }
}
 

运行一下就可以了

public class JxdHttpServer {
    public static final String WEB_ROOT = System.getProperty("user.dir");

    public static final String FILE_ROOT = "D:\\";

    public static void main(String[] args) {
        JxdHttpConnector connector = new JxdHttpConnector();
        connector.start();
    }
}


原文地址:https://blog.csdn.net/weixin_39831786/article/details/137455420

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!