如何在Web应用程序启动时调用Servlet(doGet)?

3

我需要在应用程序启动时调用一个Servlet,因为它包含一些应用程序初始化逻辑。

我知道可以设置load-on-startup配置,但这只会调用Servlet的init方法。我需要调用一个doGet方法并向其中传递一些Url参数。Servlet的doGet方法需要ServletRequest和ServletResponse对象。

另外,由于这是一个集群应用程序,我需要确切地知道我正在访问哪个节点(因为一个选项就是打开一个套接字并调用Servlet)。

执行此操作的最佳选项是什么?

编辑:澄清一下,Servlet已经存在且不能修改。到目前为止,有人会手动从浏览器中调用Servlet。我需要自动化这个过程。


既然这不是你自己的代码(“我无法修复它”),我强烈建议向相关servlet的开发者/维护者报告这个严重的缺陷。 - BalusC
4个回答

3

通常,使用ServletContextListener实现引导初始化/关闭清理 - 你考虑过这个选项吗?

或者,作为一个丑陋的hack,您可以实现一个Servlet超类来处理初始化逻辑,它将被调用一次。


“你所说的‘你可以用具有初始化逻辑的Servlet超类来实现,这将只被调用一次’是什么意思?” - Dan
1
这种方法在许多Web框架(例如Jersey)中被使用。所有的servlet都继承自超级servlet,其中包含通用逻辑和引导功能(只有在调用任何子servlet时才以延迟加载的方式调用一次)。 - Vasil Remeniuk

2
最佳选择是将您在doGet方法中拥有的任何逻辑重构为一个单独的方法,该方法可以从initdoGet中调用。
如果您真的无法重构逻辑(这确实是唯一的好选择),则可以使用一些模拟库。谷歌说Spring的模拟对象很受欢迎。
使用可用的HttpServletRequestHttpServletResponse的实现,创建一个带有load-on-startup的servlet,并从其init方法中,定位当前ServletContext中的相关servlet,并使用适当的请求和响应对象调用doGet。(是的,这是一个相当糟糕的hack,但你必须做类似的事情。) 编辑:如果您不想修改WAR文件,也许应该检查您的servlet容器是否有在重新部署Web应用程序后运行某种钩子的可能性。

1
+1:永远不要将应用逻辑与启动逻辑混在一起。A)你的应用程序的第一次调用可能需要很长时间(如果你正在使用Google App Engine,则有些无关紧要)。B)这是一个可怕的修补方法。将初始化操作放在Servlet :: init()中。 - Chris K
我不确定模拟对象在这里如何发挥作用? - Dan
谢谢gustafc,我会尝试使用mocks选项。只要代码没有对这些对象做任何奇怪的事情,它应该可以工作。 - Dan
为什么不直接使用ServletContextListener,而要用模拟和部署钩子这些hack呢?! - Vasil Remeniuk
@gustafc。ServletContextListener可以与虚拟的HttpServletRequest/Response(我假设,只需要实现请求参数映射)一起使用,就像load-on-startup一样--从上下文中获取初始化的servlet并显式调用doGet。 - Vasil Remeniuk
显示剩余3条评论

0

最好的方法是使用java.lang.Runtime。这对我来说完美地运作了。您可以覆盖init方法,在其中调用servlet(这里我的servlet名称是BackEndServlet)中的doGet或doPost方法。

@Override
    public void init(ServletConfig config) throws ServletException {

        super.init(config);
        String url = "http://localhost:8080"+config.getServletContext().getContextPath()+"/BackEndServlet"; 
        System.out.println(url);
        String os = System.getProperty("os.name").toLowerCase();
        Runtime rt = Runtime.getRuntime();

        try{

            if (os.indexOf( "win" ) >= 0) {

                // this doesn't support showing urls in the form of "page.html#nameLink" 
                rt.exec( "rundll32 url.dll,FileProtocolHandler " + url);

            } else if (os.indexOf( "mac" ) >= 0) {

                rt.exec( "open " + url);

            } else if (os.indexOf( "nix") >=0 || os.indexOf( "nux") >=0) {

                // Do a best guess on unix until we get a platform independent way
                // Build a list of browsers to try, in this order.
                String[] browsers = {"epiphany", "firefox", "mozilla", "konqueror",
                                     "netscape","opera","links","lynx"};

                // Build a command string which looks like "browser1 "url" || browser2 "url" ||..."
                StringBuffer cmd = new StringBuffer();
                for (int i=0; i<browsers.length; i++)
                    cmd.append( (i==0  ? "" : " || " ) + browsers[i] +" \"" + url + "\" ");

                rt.exec(new String[] { "sh", "-c", cmd.toString() });

            } else {
                    return;
            }
           }catch (Exception e){
            return;
           }
          return;
    }

0

这只能用一个词来形容糟糕,但你可以使用 java.net.URL/java.net.URLConnection 来解决此问题。

new URL("http://localhost/yourservlet").openStream();

如何在不进行配置的情况下获取Servlet URL? - Dan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接