【问题标题】:How to implement Template Method in Servlet如何在 Servlet 中实现模板方法
【发布时间】:2025-12-21 15:20:22
【问题描述】:

我想创建两个带有模板方法 (GOF) 变体的 HttpServlet。所以我创建了从 HttpServlet 扩展的抽象类:

abstract public class AbstractServlet extends HttpServlet {

    abstract void doSomeAction();

    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs){

        try {
            //here some logging, getting headers etc.
            System.out.println("Nothing really matters");

            //invoke concrete class
            doSomeAction();

            //write response
            rs.getOutputStream().write(new String("Simple response from class " + this.getClass().getCanonicalName()).getBytes());

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

还有两个具体的类:

public class A extends AbstractServlet {

    @Override
    void doSomeAction() {
        System.out.println("I'm doing something in A");
    }
}


public class B extends AbstractServlet {
    @Override
    void doSomeAction() {
        System.out.println("I'm doing something in B");
    }
}

在调用(成功)其中一项服务后,我无法得到任何响应。经过一些调试,Tomcat的NIO通道和闩锁似乎有问题:

2016-01-31 19:13:52 Http11NioProtocol [DEBUG] 套接字: [org.apache.tomcat.util.net.NioEndpoint$KeyAttachment@6bc6f271:org.apache.tomcat.util.net.NioChannel@2072289:java.nio.channels.SocketChannel[已连接 本地=/0:0:0:0:0:0:0:1:8080 远程=/0:0:0:0:0:0:0:1:57585]],状态 输入:[OPEN_READ],声明输出:[CLOSED]

2016-01-31 19:13:52 LimitLatch [DEBUG] 计数 向下[http-nio-8080-exec-2] latch=1

但老实说,我不知道发生了什么。有趣的是,当 servlet 通过例如 IOUtils.toByteArray(InputStream is) 消耗所有 servletrequest 输入流时,一切正常!

abstract public class AbstractServlet extends HttpServlet {

    abstract void doSomeAction();

    @Override
    protected void service(HttpServletRequest rq, HttpServletResponse rs){

        try {
            //here some logging, getting headers etc.


        //Consume all inputStream
        org.apache.commons.io.IOUtils.toByteArray(rq.getInputStream());

        //invoke concrete class
        doSomeAction();

        //write response
        rs.getOutputStream().write(new String("Simple response from class " + this.getClass().getCanonicalName()).getBytes());

    } catch (IOException e) {
        e.printStackTrace();
    }
}

}

问题出在哪里?

最好的问候。

【问题讨论】:

    标签: java tomcat servlets design-patterns nio


    【解决方案1】:

    好的,我发现了问题。我发送了大约 100 MB 内容的大型 http 帖子,但由于业务需求,我只阅读了前 1024 B 的消息(连同规范,我能够在消息的开头找到有趣的信息)。正如我所看到的,Tomcat 不允许我在 1024B 之后中断输入流并立即发送响应。

    所以,我的最后一个问题是:

    是否可以做类似的事情(只读部分消息)?还是违反 TCP 标准?

    【讨论】:

    • 你尝试了什么?您应该能够关闭输入流。另一种方法是在标头中发送 1024b 元信息
    • 是的,我可以关闭输入流,但这并不能解决我的问题。似乎只有当我阅读整个请求消息时,我才能回复客户端。此外,无法在标头中发送元数据。