Java如何校验IP/Domain格式

说到校验IP地址或者Domain的格式是否正确,很多人可能是想到用正则表达式来校验。
一种比较好的做法是使用现成的库来完成此功能,尤其是比较流行的类库,经过了大量的验证,比自己实现要安全可靠。
本文推荐使用Google的Guava库里的工具类来校验。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>19.0</version>
</dependency>

校验IP地址格式的有效性

//com.google.common.net.InetAddresses#isInetAddress(String ipString)

InetAddresses.isInetAddress("1.1.1.1");//true
InetAddresses.isInetAddress("1.1.1");//false
InetAddresses.isInetAddress("127.0.0.1");//true
InetAddresses.isInetAddress("fc00::");//true
InetAddresses.isInetAddress("localhost");//false
InetAddresses.isInetAddress("256.256.1212.1");//false
InetAddresses.isInetAddress("256.256.257.1");//false
InetAddresses.isInetAddress("300.300.300.300");//false

//校验ip是ipv4地址还是ipv6地址
InetAddresses.forString("fc00::") instanceof Inet6Address;//true
InetAddresses.forString("127.0.0.1") instanceof Inet4Address;//true

校验Domain的合法性

//com.google.common.net.InternetDomainName#isValid(String name)

InternetDomainName.isValid("www.baidu.com"); //true
InternetDomainName.isValid("127.0.0.1"); //false
InternetDomainName.isValid("a.b.c.com"); //true
InternetDomainName.isValid("http://a.b.c.com"); //false
InternetDomainName.isValid("http://a.b.c.com/"); //false

Url的host部分合法性的校验

//com.google.common.net.HostSpecifier#isValid(String specifier)

//检查是否可以作为url的host部分,可能是domain或者ip
HostSpecifier.isValid("a.b.c.com");//true
HostSpecifier.isValid("a.b.c.com:90");//false
HostSpecifier.isValid("http://a.b.c.com");//false
HostSpecifier.isValid("127.0.0.1");//true
HostSpecifier.isValid("127.0.0.1:80");//false
HostSpecifier.isValid("111::");//true

Guava的设计哲学

本文是自己学习Guava类库的一些学习心得,主要来自Guava的官方文档,并夹杂了一些自己的理解。
Guava是Google内部使用的核心Java类库的开源版本,这些核心实用类都是Google内部员工平时编码中经常使用的类库,已经在Google的生产环境验证,因此,我们可以放心的使用他们。
Guava的定位是使得用Java语言工作更加愉快和更加高效。JDK自带的utilities类(比如Collections类)被广泛应用并极大的简化了Java代码,Guava的目标就是要继续这个“传说”。
Effective Java第47条,“了解并使用类库”,告诉我们,使用类库比自己写一个实用工具类更可取。(个人觉得,如果为了学习,这条可以忽略,相反,自己写一个类库并且跟现有的优秀的类库比较,反而更利于个人成长。)
【总之,不要重复造轮子。如果你需要一些看起来很通用的功能,那么可能已经存在相应的类库实现了你的功能。如果存在,那么就使用它;如果你不知道,那么可以去搜下。总之,使用类库大部分情况比自己实现要更好。这个无关你作为一个程序员的能力,因为通用的类库集聚了大部分程序员的努力,肯定比你自己实现这个功能投入的精力要多。】(摘自effective java)
所以,不得不说:
  • Guava在Google的生产环境经过了实战测试。
  • Guava经过了很多的单元测试。自动化的测试,并且覆盖率很高,尤其是collect子包。
  • Guava开发很活跃,用户参与也很积极。
  • 总之,很牛逼。
Guava在增加特性方面偏保守,在决定是否增加一个特性时,会考虑是否‘实用’并且‘普遍存在’。‘实用’表现在:可以节省你大量的代码;避免让你写出很难调试或者易于出错的代码;提高可读性;提高速度。‘普遍存在’就是在代码中竟然被使用,这一项可以通过Google内部的代码库里扫描统计出来。
相对于增加特性方面的保守,Guava在去除不需要的特性方面很果断,会把这些特性标为deprecate继而删除该特性。因此,使用@Beta注解的类或者方法要谨慎使用。
Guava的实现针对一些通用的设计原则,包括:
  • 针对特定的场景,这些api是最优的解决方案;
  • 类或者方法的语义是可以从他们的签名上很明显很直观的看出来。实现可以很smart,但是名字要很直观。
  • 鼓励Guava的用户有好的代码习惯,而Guava它自己的代码本身也是好代码习惯的典范。(比如快速失败,拒绝null)
  • 不要试图单独解决每一种场景,相反提供通用的工具以解决我们可能没遇到过的场景。
  • 强调可维护性,并留出未来重构的空间。(结果:大部分暴露出去的类应该是final的,就像effective java 17条说的;把AbstractXXX类暴露出去也应该很谨慎。)