Get the server port number from tomcat without a request

☆樱花仙子☆ 提交于 2019-11-27 00:38:58

With this:

List<String> getEndPoints() throws MalformedObjectNameException,
        NullPointerException, UnknownHostException, AttributeNotFoundException,
        InstanceNotFoundException, MBeanException, ReflectionException {
    MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
    QueryExp subQuery1 = Query.match(Query.attr("protocol"), Query.value("HTTP/1.1"));
    QueryExp subQuery2 = Query.anySubString(Query.attr("protocol"), Query.value("Http11"));
    QueryExp query = Query.or(subQuery1, subQuery2);
    Set<ObjectName> objs = mbs.queryNames(new ObjectName("*:type=Connector,*"), query);
    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) {
            if (addr.isAnyLocalAddress() || addr.isLoopbackAddress() || 
                addr.isMulticastAddress()) {
                continue;
            }
            String host = addr.getHostAddress();
            String ep = scheme + "://" + host + ":" + port;
            endPoints.add(ep);
        }
    }
    return endPoints;
}

You will get a List like this:

[http://192.168.1.22:8080]

For anybody who is interested in how we solved this, here is the mock code

Server server = ServerFactory.getServer();
        Service[] services = server.findServices();
        for (Service service : services) {
            for (Connector connector : service.findConnectors()) {
                ProtocolHandler protocolHandler = connector.getProtocolHandler();
                if (protocolHandler instanceof Http11Protocol
                    || protocolHandler instanceof Http11AprProtocol
                    || protocolHandler instanceof Http11NioProtocol) {
                    serverPort = connector.getPort();
                    System.out.println("HTTP Port: " + connector.getPort());
                }
            }


        }
Arun Maharana
public void getIpAddressAndPort() 
throws MalformedObjectNameException, NullPointerException,
            UnknownHostException {

        MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();

        Set<ObjectName> objectNames = beanServer.queryNames(new ObjectName("*:type=Connector,*"),
                Query.match(Query.attr("protocol"), Query.value("HTTP/1.1")));

        String host = InetAddress.getLocalHost().getHostAddress();
        String port = objectNames.iterator().next().getKeyProperty("port");

        System.out.println("IP Address of System : "+host );
        System.out.println("port of tomcat server : "+port);

    }

The server port number doesn't exist. It can have any number of port numbers. So what you're asking doesn't make sense. The port number associated with a specific request does make sense.

  • Get Hold of MBean/JMX Object for Tomcat/Server Instance
  • Get Virtual Server Instance Related Data from there

Check http://svn-mirror.glassfish.org/glassfish-svn/tags/embedded-gfv3-prelude-b07/web/web-glue/src/main/java/com/sun/enterprise/web/WebContainer.java for reference

The content of the MBeanServer can then be exposed through various protocols, implemented by protocol connectors[RMI/IIOP], or protocol adapters[SNMP/HTTP]. In this case, use of SNMP adapter will be a better approach so that a SNMP trap can be placed without knowing the exact IP/port of other Application Servers

These types of servers are designed to be able to listen on (almost) arbitrary ports and to hide these details from the contained applications which normally do not need to know.

The only way is to read the configuration files yourself and have access to the command line arguments that started the server where the configuration files may have been overridden. You have to know a lot about the system you are running on for this to work. There is no way of doing it portably.

Even if there were, there are cases in which it simply does not matter like being behind a NAT, certain firewalls, etc.

mschonaker

You could use crossContext. But I don't think that's app server agnostic.

I would share a custom class, behaving as a registry of running applications in the same tomcat instance through JNDI, as I explained here.

During startup, through a ContextListener or through an Spring container event, I would obtain the registry through a JNDI lookup, add my web app instance with an url obtained from the servletcontext.contextpath, and finally register a listener to hear other applications registering themselves. That's the more server agnostic I can think of.

Obtaining the port won't be server agnostic, you should use a context parameter.

EDIT: I'm sorry, forgot to say that what I've described is to share objects among contexts, but no, you can't not know the port unless you use some server API (not agnostic at all).

I am not entirely sure if you can access the Tomcat port from code in the environment configuration you need. Did you consider actually having the full URL to the web service passed as a configuration param/setting (probably in a .properties file) to the app?

This way you wouldn't have to hardcode the port and de-couple both your apps so that you could technically have the web service on an external tomcat but still access it by just changing the property, avoiding code re-build.

Previously on a large distributed project, the design I used was to have the centralised service initialise the several services with the central service's URL(& port).

Obviously this means that the central service must maintain a list of the services (URL & port) to initialise.

If you want to access an application on the same server instance, just omit the server part of the URL. Some examples what you can achieve. The current document is at http://example.com:8080/app2/doc.html

  • xxx.html becomes http://example.com:8080/app2/xxx.html
  • ../xxx.html becomes http://example.com:8080/xxx.html
  • ../xxx.html becomes http://example.com:8080/xxx.html
  • ../foo/xxx.html becomes http://example.com:8080/foo/xxx.html
  • ../../xxx.html becomes http://example.com:8080/xxx.html (there is no way to go beyond the root)
  • /xxx.html becomes http://example.com:8080/xxx.html This is probably what you look for.
  • //other.com/xxx.html becomes http://example.com:8080/xxx.html Useful if you want to keep "https:"
public String getPort() {
    MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
    Set<ObjectName> objectNames;
    try {
        objectNames = beanServer.queryNames(new ObjectName("*:type=ProtocolHandler,*"),
                Query.match(Query.attr("name"), Query.value("\"http-*")));
    } catch (MalformedObjectNameException e) {
        LOGGER.error("Port not defined!", e);
    }

    return objectNames.iterator().next().getKeyProperty("port");
}

public String getSecurePort() {
    MBeanServer beanServer = ManagementFactory.getPlatformMBeanServer();
    Set<ObjectName> objectNames;
    try {
        objectNames = beanServer.queryNames(new ObjectName("*:type=ProtocolHandler,*"),
                Query.match(Query.attr("name"), Query.value("\"https-*")));
    } catch (MalformedObjectNameException e) {
        LOGGER.error("SecuredPort not defined!", e);
    }

    return objectNames.iterator().next().getKeyProperty("port");
}

Hmm, how would an application get started in Tomcat without a request? Maybe I'm going brain dead for a moment here, but I don't think any classes will load until a request hits. Sure, you could have classes independent of any particular request, but they'd need a request to get them fired off at some point.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!