【问题标题】:How to parse a JDBC url to get hostname,port etc?如何解析 JDBC url 以获取主机名、端口等?
【发布时间】:2012-03-06 10:06:13
【问题描述】:

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

【问题讨论】:

  • 你想解析一个jdbc url是什么意思。您可以使用正则表达式。可以举个例子吗
  • jdbc:jtds:sqlserver://hostname:port/dbname 或 jdbc:jtds:sqlserver://hostname:port;databaseName=dbname 或 jdbc:oracle:thin:@hostname:port:dbname

标签: java parsing url jdbc


【解决方案1】:

请注意,对于某些有效的 jdbc url,@brettw 的回答可能会失败。如果主机名包含下划线 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);

【讨论】:

    【解决方案2】:

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

    /**
     * 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;
        }
      }
    }
    

    【讨论】:

      【解决方案3】:

      这对我不起作用。我想出了这些方法,基于主机名和端口总是用冒号连接在一起的假设。这个假设适用于我在工作中必须处理的所有数据库(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 + "'");
      }
      

      【讨论】:

        【解决方案4】:

        从这样的开始:

        字符串 url = "jdbc:derby://localhost:1527/netld;collat​​ion=TERRITORY_BASED:PRIMARY"; 字符串 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());

        上面的输出:

        德比 本地主机 1527 /netld;collat​​ion=TERRITORY_BASED:PRIMARY

        【讨论】:

        • 非常感谢!我可以通过这种方式轻松获取主机,端口,但我必须解析路径才能获取数据库名称
        • 你将无法从 jdbc:oracle:thin:@some.server:1521:XXX 中解析出 some server
        • 嗯,一般来说,JDBC URL 的格式是特定于 DB 的。所以没有通用的方法来解析它。
        猜你喜欢
        • 1970-01-01
        • 2012-06-06
        • 2012-03-20
        • 2015-08-18
        • 1970-01-01
        • 1970-01-01
        • 2016-05-24
        • 2021-02-20
        • 1970-01-01
        相关资源
        最近更新 更多