问题
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