【问题标题】:Access running instances of Servlets访问正在运行的 Servlet 实例
【发布时间】:2015-09-20 05:50:42
【问题描述】:

Java 新手,这个问题与典型的 java 工作流程不同,需要来自 node.js 背景的非常有经验的架构师的帮助,尝试基于我已经实现的一些设计模式来实现架构node.js 和 PHP 以及一些前端语言(包括 Java Swing),我期待为 Java Servlet 实现相同的功能。

我了解在 Servlet 中 doGet、doPost 等是请求的入口点,并且通过多线程对所有传入请求同时实例化和重用 servlet 的单个实例。

为了使这些设计模式(另一个主题,需要它自己的线程)工作,我需要拥有超级级别的访问权限来获取这些 servlet 实例并将我的参与者设置为代理/侦听器。

我了解到 servlet 要么在第一次请求后实例化,要么直接与容器一起加载,因此为了实现这一点,我需要在启动时加载它们,以便对它们执行操作。

再次,这个问题是不同的,可能需要一些讨论才能深入理解,以帮助我们交流彼此世界的事物。

简而言之,我需要以下两件事才能使其工作。

  1. 一种定义我自己的类(比如 Uber)的方法,以便在加载容器时加载它。
  2. 然后 Uber 类能够获取对加载的 servlet 的引用,或者 servlet 可以联系到 Uber

【问题讨论】:

    标签: java servlets


    【解决方案1】:

    解决第 1 点很容易。创建一个实现ServletContextListener 的类,并在contextInitialized 方法中创建Uber 的实例。

    第 2 点不可能。服务器不允许向您提供有关它创建的 Servlet 实例的信息。获取这些的方法ServletContext#getServlet 已弃用。此外,应用服务器可以使用Servlet 的单个实例或多个实例,服务器将在运行时决定行为。

    由于我们不完全了解您了解Servlets 实例的目的以及如何处理它们,因此我们无法提供更多帮助。

    不过,在第 1 点中,由于您创建了 Uber 的实例,您可以将其作为属性存储在 ServletContext 中,然后使用 HttpServletRequest#getServletContext 在每个 servlet 中检索它。


    根据您的评论,您似乎想要/需要实现Front Controller。为此,最好使用一个单独的 servlet 来完成这项工作,并创建真正处理请求的类。与其重新发明轮子,我建议您使用已经实现此功能的框架,如 JSF 或 Spring MVC。如果您仍想/需要自己实现该模式,请查看here

    这就是你的(奇怪和不推荐)设计的样子(基于Jozef's comment

    @WebListener
    public class AppListener implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent e) {
            Uber uber = new Uber();
            /* configure uber */
            //store it in ServletContext
            e.getServletContext().setAttribute("uber", uber);
        }
        @Override
        public void contextDestroyed(ServletContextEvent e) {
            //...
        }
    }
    

    然后在一个 servlet 中,将其注册到 Uber 的实例中:

    @WebServlet(value="/myServlet", name="myServlet")
    public class MyServlet extends HttpServlet {
        @Override
        public void init(ServletConfig config) {
            Uber uber = (Uber)config.getServletContext().getAttribute("uber");
            uber.registerServlet("myServlet", this);
        }
        //more code...
    }
    

    不过,我不喜欢其他类需要了解您的 Servlet 的想法。

    【讨论】:

    • 感谢您解决 #1,对于 #2,关键是使用 servlet 作为路由器,它们拦截请求,然后将 requestresponse 委托给 Uber(一组实际上是设计模式类),简单地说 servlet 需要知道 UberUber 需要知道 servlet 才能相互通信,我知道应用程序服务器可能使用单个实例或多个实例,这实际上阻碍了我.
    • 如果您可以控制这些 servlet 的源代码,我会考虑使用观察者模式 - 即将 Uber 类存储到 servlet 上下文中(如 Luiggi 所述),然后每个 servlet将自己注册到您的Uber 班级。不管怎样,你的设计在我看来有点过于复杂了。
    • @JozefChocholacek 你的想法很有趣,是的,我可以控制这些 servlet 的源代码,所以现在我的问题是如何从 servlet 的构造函数中联系到我的 Uber (根据 Luiggi Mendoza 的建议是一个 ServletContextListener),这将解决问题......(除了我必须考虑 servlet 的多个实例)。
    • @user3610227 你不能在 serlvet 的构造函数中这样做。请改用init 方法。不过,我同意 Jozef 的观点,这种设计很奇怪,应该避免,最好为所有非资源(js、css、图像或任何其他)请求使用单个控制器,而不是使用 Uber班级。这就像将相关代码从 Uber 移动到这个 servlet。
    • 我在研究FrontController模式,想法很有前瞻性。您能否在答案中添加代码行,通过init 方法联系Uber,以防万一权衡另一种方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 2016-09-12
    • 1970-01-01
    • 2017-10-04
    相关资源
    最近更新 更多