【问题标题】:Retrieve the port of the server on startup of servlet container (independent of server)在 servlet 容器启动时检索服务器的端口(独立于服务器)
【发布时间】:2014-04-04 20:28:54
【问题描述】:

我想检索我的 Jersey 2.6 容器正在运行的服务器的主机和端口。该容器当前部署在 Tomcat 7 上。但是,我不得不发布可部署在每台支持 Java servlet 的服务器上的应用程序。在这种情况下,它是一个 Tomcat,但解决方案必须是独立于服务器的。

我已经注册了一个 Jersey 启动类,我想在其中获取主机和端口。但是,我还没有找到任何解决方案来获取端口。

我的类,在我的 Jersey servlet 初始化时调用:

public class ServletInitialization extends ResourceConfig {
    public ServletInitialization() {
        int port    = ???;
        String host = InetAddress.getLocalHost().getHostName();
    }
}

在我的研究中,我发现了一个3 year old question,它指的是同样的问题。接受的答案集中在 Tomcat 上,我认为只能在 Tomcat 上正确运行(import org.apache.catalina.*)。我想避免在启动时修改服务器引擎、服务器配置或向服务器注入任何东西。

我尝试使用普通的 Java servlet,但也找不到获取端口的方法:

public class ServletInitializationPlain extends HttpServlet {

    @Override
    public void init() {
       int port = ???;  
    }   
}

是否有人知道如何在启动时从 servlet 容器中检索端口(独立于运行它的服务器)?


编辑

我已经接受了 steohans 解决方案,但我认为这很棘手,为什么我的 ServletInitialization 在 web 容器启动时没有被调用。因为实际上 ResourceConfig 不是 Servlet。我现在将解释这个问题:

我扩展了 ResourceConfig.class,它是 Application.class 的子类。这个 Application 类不是扩展的 Java servlet,而是 Jersey 的一个自己的类。我虽然在 Web 容器启动时调用了一个应用程序。然而,在 Jersey 规范中可以读到,Application 类本身需要由 ServletContainer.class 处理,ServletContainer.class 是 Java Servlet 的子类。 此处理在 web.xml 中定义。 最后,这里的一切都是 servlet。

由于无法在启动时获取端口,因此在分派请求时当然可以:

@Path("example")
public class ServletMethods {
    @GET
    public Response example(@HeaderParam("Host") String host) {
         return Response.ok(host).build();
    }
}

【问题讨论】:

    标签: java jersey jax-rs jersey-2.0


    【解决方案1】:

    我找到了这个答案,它可以工作Get the server port number from tomcat with out a request

    List<String> getEndPoints() throws MalformedObjectNameException,
            NullPointerException, UnknownHostException, AttributeNotFoundException,
            InstanceNotFoundException, MBeanException, ReflectionException {
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
        Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));
        String hostname = InetAddress.getLocalHost().getHostName();
        InetAddress[] addresses = InetAddress.getAllByName(hostname);
        ArrayList<String> endPoints = new ArrayList<String>();
        for (Iterator<ObjectName> i = objs.iterator(); i.hasNext();) {
            ObjectName obj = i.next();
            String scheme = mbs.getAttribute(obj, "scheme").toString();
            String port = obj.getKeyProperty("port");
            for (InetAddress addr : addresses) {
                String host = addr.getHostAddress();
                String ep = scheme + "://" + host + ":" + port;
                endPoints.add(ep);
            }
        }
        return endPoints;
    }
    

    不幸的是,这只适用于 tomcat

    【讨论】:

      【解决方案2】:

      序言:确保区分 Web 容器(也称为 servlet 容器)p.a.雄猫。还有 Jersey ServletContainer 类,它只是一个 servlet。 (见javadoc

      简短: 不行,只有一有请求才能拿到监听端口。

      长: 一个 Servlet 没有绑定到一个特定的端口,所以不应该有一个函数来检索监听端口。 (没有特定容器)

      您的网络容器有组织监听的任务,甚至不必自己处理。例如,您还可以使用 apache 来侦听请求,将它们传递给调用您的 Servlet 的 tomcat。此外,当您的 init 函数被调用时,您的 Web 容器根本不需要监听。

      您还可以告诉 tomcat 监听两个不同的端口,将请求发送给同一个 Servlet。如果您想了解更多信息,请查看关于 tomcat 连接器的 this 教程。

      但是,一旦您有请求,您就知道使用了哪个端口,您可以使用HttpServletRequest 中的getLocalPort() 来获取端口。

      【讨论】:

      • “apache 监听请求,将它们传递给 tomcat”是什么意思?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-29
      • 1970-01-01
      • 1970-01-01
      • 2017-03-20
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多