How to get the configured HTTP and HTTPS port numbers in server.xml from Java code at runtime

自古美人都是妖i 提交于 2020-01-06 18:04:03

问题


In our project, we have implemented SOAP webservices using Apache CXF framework. Clients used to request the server for some command execution. The request consists of host, port and the protocol used for connection. If the client uses a HTTPS configured port number and specify the protocol as HTTP, then we get a connection refused - socket exception as expected. But, I need to throw a proper error message like "Unable to connect to host "XYZ" with port "ABC" using http protocol". For this, I need to get the configured http and https port numbers from tomcat server.xml file at runtime and then compare it with my request parameters.

Anyone, please help me out on how to retrieve that?


回答1:


You can always parse the tomcat's server.xml file and fetch the port values:

  public static Integer getTomcatPortFromConfigXml(File serverXml) {
   Integer port;
   try {
      DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
      domFactory.setNamespaceAware(true); // never forget this!
      DocumentBuilder builder = domFactory.newDocumentBuilder();
      Document doc = builder.parse(serverXml);
      XPathFactory factory = XPathFactory.newInstance();
      XPath xpath = factory.newXPath();
      XPathExpression expr = xpath.compile
        ("/Server/Service[@name='Catalina']/Connector[count(@scheme)=0]/@port[1]");
      String result = (String) expr.evaluate(doc, XPathConstants.STRING);
      port =  result != null && result.length() > 0 ? Integer.valueOf(result) : null;
   } catch (Exception e) {
     port = null;
   }
   return port;
}

Above code should get you the HTTP port from server.xml. For HTTPS port, the XPathExpression has to be modified to

XPathExpression expr = xpath.compile
            ("/Server/Service[@name='Catalina']/Connector[@scheme='https']/@port[1]");

Please note that the above snippets are based on the assumption that the server.xml is the standard tomcat's server file where the service name is defined as "Catalina". Following is a standard server.xml file:

<Server>
    <Service name="Catalina">
        <Connector port="8080">
            #...
        </Connector>
    </Service>
</Server>

Reference: Code link




回答2:


It is possible to access Tomcat core classes on runtime this way (For Tomcat 7, I've not tested with Tomcat 8):

import java.lang.management.ManagementFactory;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import org.apache.catalina.Service;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardServer;
import org.apache.log4j.Logger;

public class TomcatConnectors {

    public static final String CATALINA_SERVICE_NAME = "Catalina";

    public static final String CONNECTOR_HTTP_PROTOCOL_NAME = "HTTP/1.1"; 

    private Logger logger = Logger.getLogger(this.getClass());

    private Collection<Connector> connectors;

    /**
     * 
     */
    public TomcatConnectors() {
        super();
        this.connectors = new HashSet<Connector>();
        this.loadConnectors();
        this.getConnectorPorts();
    }

    /**
     * 
     * @return
     */
    protected StandardServer getServerInstance(){
        org.apache.catalina.core.StandardServer server = null; 
        try{
            MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
            server = (StandardServer)mbeanServer.getAttribute(
                        new ObjectName("Catalina:type=Server"),
                        "managedResource"
                    );
            if(logger.isDebugEnabled()){
                logger.debug("Server found. Info: ");
                logger.debug(" - address          : " + server.getAddress());
                logger.debug(" - domain           : " + server.getDomain());
                logger.debug(" - info             : " + server.getInfo());
                logger.debug(" - shutdown port    : " + server.getPort());
                logger.debug(" - shutdown command : " + server.getShutdown());
                logger.debug(" - serverInfo       : " + server.getServerInfo());
                logger.debug(" - status           : " + server.getStateName());

            }               

        }catch(Throwable t){
            logger.fatal("Fatal Error Recovering StandardServer from MBeanServer : " + t.getClass().getName() + ": " + t.getMessage(), t);
        }
        return server;
    }

    /*
     * 
     */
    protected Service getCatalinaService(){
        org.apache.catalina.core.StandardServer server = this.getServerInstance();
        Service[] services = server.findServices();
        for(Service aService : services){
            if(logger.isDebugEnabled()){
                logger.debug("Service: " + aService.getName() + 
                        ", info: " + aService.getInfo() + 
                        ", state: " + aService.getStateName());
            }

            if(aService.getName().equalsIgnoreCase(CATALINA_SERVICE_NAME)){
                return aService;                
            }
        }
        return null;
    }

    protected void loadConnectors() {
        Service catalinaService = this.getCatalinaService();
        if(catalinaService == null){
            throw new IllegalStateException("Service Catalina cannot be null");
        }
        if(catalinaService.findConnectors() != null && catalinaService.findConnectors().length > 0){
            logger.debug("List of connectors: ");
            for(Connector aConnector : catalinaService.findConnectors()){
                if(logger.isDebugEnabled()){
                    logger.debug("Connector.getProtocol: " + aConnector.getProtocol());
                    logger.debug("Connector.getPort: " + aConnector.getPort());
                    logger.debug("Connector.getInfo: " + aConnector.getInfo());
                    logger.debug("Connector.getStateName: " + aConnector.getStateName());
                    logger.debug("Connector.property.bindOnInit: " + aConnector.getProperty("bindOnInit"));
                    logger.debug("Connector.attribute.bindOnInit: " + aConnector.getAttribute("bindOnInit"));
                    logger.debug("Connector.getState: " + aConnector.getState());
                }
                this.connectors.add(aConnector);
            }
        }
    }

    /**
     * @return the connectors
     */
    public Collection<Connector> getConnectors() {
        if(this.connectors.isEmpty()){
            this.loadConnectors();
        }
        return connectors;
    }

    public Map<String, Set<Integer>> getConnectorPorts(){
        if(this.connectors.isEmpty()){
            this.loadConnectors();
        }
        Map<String, Set<Integer>> connectorPorts = new HashMap<String, Set<Integer>>();
        for(Connector c: this.connectors){
            Set<Integer> set;
            if(!connectorPorts.containsKey(c.getProtocol())){
                set = new HashSet<Integer>();
                set.add(c.getLocalPort());
            }else{
                set = connectorPorts.get(c.getProtocol());
                set.add(c.getLocalPort());
            }           

            connectorPorts.put(c.getProtocol(), set);
        }
        logger.debug("connectorPorts : " + connectorPorts);     
        return connectorPorts;
    }

}

This is the config which I've tested with:

<Service name="Catalina">

    <Connector port="8787" protocol="HTTP/1.1" />

    <Connector port="8009" protocol="AJP/1.3" />

    ...

And this is the output:

TomcatConnectors:137 - connectorPorts : {HTTP/1.1=[8787], AJP/1.3=[8009]}


来源:https://stackoverflow.com/questions/25376841/how-to-get-the-configured-http-and-https-port-numbers-in-server-xml-from-java-co

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