一个简单的Web服务器-支持Servlet请求

Posted fudashi233

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个简单的Web服务器-支持Servlet请求相关的知识,希望对你有一定的参考价值。

上接 一个简单的Web服务器-支持静态资源请求,这个服务器可以处理静态资源的请求,那么如何处理Servlet请求的呢?

 

判断是否是Servlet请求

首先Web服务器需要判断当前请求是否是Servlet请求。

像Tomcat,通过解析HTTP报文拿到请求url后,就可以根据web.xml来查找是否有匹配的Servlet,如果有匹配则认定为是一个有效的Servlet请求,然后将request,response传给对应的servlet的service()方法。

这里既然要实现一个简单的Web服务器,就怎么简单怎么来。认定以“/servlet”为前缀的url为Servlet请求,比如http://localhost:8080/servlet/cn.edu.jxau.tomcat.PrimitiveServlet,则是一个请求cn.edu.jxau.tomcat.PrimitiveServlet的Servlet请求。判定逻辑如下

// HttpServer 类的service()方法,是整个服务器的入口
        while (true) 
            try (Socket socket = serverSocket.accept()) 
                System.out.println("客户端建立连接:" + socket);
                Request request = new Request(socket.getInputStream());
                if (Objects.isNull(request.getUri())) 
                    continue;
                
                if (isShutdownComment(request))  //如果是shutdown命令,则关闭服务器
                    break;
                
                Response response = new Response(request, socket.getOutputStream());
if (request.getUri().startsWith("/servlet/")) // 请求Servlet资源 new ServletProcessor().process(request, response); else // 请求静态资源 response.sendStaticResource(); // 书上使用了StaticResourceProcessor new StaticResourceProcessor().process(request,response); catch (Exception e) e.printStackTrace();

 

加载Servlet

如果确实是Servlet请求,下一步就是实例化Servlet并调用service()方法。

首先需要知道请求是哪个Servlet:根据url拿到Servlet的名称

然后需要调用Servlet的service()方法:使用ClassLoader加载对应的Servlet字节码,然后实例化Servlet,调用service()方法,传入request,response。

// ServletProcessor 类的process()方法,用于处理Servlet请求
public void process(Request request, Response response) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException 

        String uri = request.getUri();
        String servletName = uri.substring(uri.lastIndexOf("/") + 1);
        File file = new File(Constants.WEB_ROOT);
        String urlStr = new URL("file", null, file.getCanonicalPath() + File.separator).toString(); //使用File协议
        URL[] urlArr = new URL[1];
        urlArr[0] = new URL(urlStr);
        System.out.println(Arrays.toString(urlArr));
        URLClassLoader loader = new URLClassLoader(urlArr);
        Class clazz = loader.loadClass(servletName); // 根据Servlet的全路径名加载Servlet字节码
        Servlet servlet = (Servlet) clazz.newInstance(); // 实例化Servlet
        servlet.service(request, response); //调用Servlet.service()
    

 

PrimitiveServlet的实现如下,实现了Servlet接口,service()方法的实现是重点。

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 

        PrintWriter out = response.getWriter();
        out.println("HTTP/1.1 200 Status OK\\r\\n");
        out.println("Content-Type: text/html\\r\\n");
        out.println("Content-Length: 36\\r\\n");
        out.println("\\r\\n");
        out.println("<h1>Status OK</h1>");
        out.print("<h1>Status OK</h1>");
    

    public void destroy() 
        System.out.println("-------destroy");
    

    public String getServletInfo() 
        return null;
    

    public ServletConfig getServletConfig() 
        return null;
    

 

参考

1.《How Tomcat Works》 - Budi Kurniawan

以上是关于一个简单的Web服务器-支持Servlet请求的主要内容,如果未能解决你的问题,请参考以下文章

27 | 新特性:Tomcat如何支持异步Servlet?

Servlet常用技术web

学习总结------Servlet的简单理解

面试简单整理之web

Eclipse下创建简单Servlet

servlet是啥