如何解析JDBC URL以获取主机名、端口等?

45

如何解析JDBC URL(oracle或sqlserver),以获取主机名、端口和数据库名称,URL的格式是不同的。


你说要解析JDBC URL是什么意思?你可以使用正则表达式。你能给一个例子吗? - Ank
3
jdbc:jtds:sqlserver://hostname:port/dbname 或 jdbc:jtds:sqlserver://hostname:port;databaseName=dbname 或 jdbc:oracle:thin:@hostname:port:dbname - Mickel Lee
4个回答

69

从这个开始:

String url = "jdbc:derby://localhost:1527/netld;collation=TERRITORY_BASED:PRIMARY";
String cleanURI = url.substring(5);
URI uri = URI.create(cleanURI); System.out.println(uri.getScheme()); System.out.println(uri.getHost()); System.out.println(uri.getPort()); System.out.println(uri.getPath());

以上的输出结果为:

derby
localhost
1527
/netld;collation=TERRITORY_BASED:PRIMARY

非常感谢!我可以通过这种方式轻松获取主机和端口,但我必须解析路径以获取数据库名称。 - Mickel Lee
12
你无法从jdbc:oracle:thin:@some.server:1521:XXX中解析出“some server”。请只返回翻译后的文本。 - Oleg Mikheev
6
一般来说,JDBC URL 的格式是特定于数据库的。因此,没有通用的方法来解析它。 - Alexei Osipov
注意带有下划线的主机名。它们通常在Docker Compose或Kubernetes环境中使用,并且该代码无法正确处理(我稍后将发布基于PostgreSQL驱动程序代码的解决方案)。 - Lubo

6

这对我没有起作用。我基于一个假设提出了以下方法,即主机名和端口号总是由冒号连接在一起。这个假设适用于我工作中处理的所有数据库(Oracle、Vertica、MySQL等),但它可能无法适用于某些不使用网络端口的东西。

String url = null; // set elsewhere in the class
final public String regexForHostAndPort = "[.\\w]+:\\d+";
final public Pattern hostAndPortPattern = Pattern.compile(regexForHostAndPort);
public String getHostFromUrl() {
    Matcher matcher = hostAndPortPattern.matcher(url); 
    matcher.find();
    int start = matcher.start();
    int end = matcher.end();
    if(start >= 0 && end >= 0) {
        String hostAndPort = url.substring(start, end);
        String [] array = hostAndPort.split(":");
        if(array.length >= 2)
            return array[0];
    }
    throw new IllegalArgumentException("couldn't find pattern '" + regexForHostAndPort + "' in '" + url + "'");
}

public int getPortFromUrl() {
    Matcher matcher = hostAndPortPattern.matcher(url); 
    matcher.find();
    int start = matcher.start();
    int end = matcher.end();
    if(start >= 0 && end >= 0) {
        String hostAndPort = url.substring(start, end);
        String [] array = hostAndPort.split(":");
        if(array.length >= 2)
            return Integer.parseInt(array[1]);
    }
    throw new IllegalArgumentException("couldn't find pattern '" + regexForHostAndPort + "' in '" + url + "'");
}

1
请注意,@brettw的答案可能无法处理某些有效的jdbc url。如果主机名包含下划线,则uri getHost()返回null(参见here),而getPost()返回-1。
为了解决这个问题,我添加了一个检查空主机的步骤:
  String jdbcUrl = "jdbc:jtds:sqlserver://ABC_XYZ:1433/Database";
  String cleanURI = jdbcUrl.substring("jdbc:jtds:".length());

  URI uri = URI.create(cleanURI);
  String host = uri.getHost();
  int port = uri.getPort();

  if(host == null){
    String regex = ".*://(\\w*):(\\d++)/.*";
    Pattern p = Pattern.compile(regex);

    Matcher matcher = p.matcher(jdbcUrl);
    if(matcher.find()){
      host =  matcher.group(1);
      port =  Integer.valueOf(matcher.group(2));
    } else {
      // handle fail
    }
  }

  System.out.println("host = " + host);
  System.out.println("port = " + port);

1

我在我的项目中使用这个类。 使用起来非常简单。

/**
 * Split di una url JDBC nei componenti.
 * Estrae i componenti di una uri JDBC del tipo: <br>
 * String url = "jdbc:derby://localhost:1527/netld;collation=TERRITORY_BASED:PRIMARY"; <br>
 * nelle rispettive variabili pubbliche.
 * @author Nicola De Nisco
 */
public class JdbcUrlSplitter
{
  public String driverName, host, port, database, params;

  public JdbcUrlSplitter(String jdbcUrl)
  {
    int pos, pos1, pos2;
    String connUri;

    if(jdbcUrl == null || !jdbcUrl.startsWith("jdbc:")
       || (pos1 = jdbcUrl.indexOf(':', 5)) == -1)
      throw new IllegalArgumentException("Invalid JDBC url.");

    driverName = jdbcUrl.substring(5, pos1);
    if((pos2 = jdbcUrl.indexOf(';', pos1)) == -1)
    {
      connUri = jdbcUrl.substring(pos1 + 1);
    }
    else
    {
      connUri = jdbcUrl.substring(pos1 + 1, pos2);
      params = jdbcUrl.substring(pos2 + 1);
    }

    if(connUri.startsWith("//"))
    {
      if((pos = connUri.indexOf('/', 2)) != -1)
      {
        host = connUri.substring(2, pos);
        database = connUri.substring(pos + 1);

        if((pos = host.indexOf(':')) != -1)
        {
          port = host.substring(pos + 1);
          host = host.substring(0, pos);
        }
      }
    }
    else
    {
      database = connUri;
    }
  }
}

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