强制重定向至HTTPS

有时候需要把网页强制切换成HTTPS,即使用户已经访问了HTTP的版本。原因可能是你不想让用户使用HTTP来访问,因为它不安全。要做到这个很简单,如果不想用PHP或者Apache的mod_rewrite来做这件事,用Javascript也可以。代码如下:

用了这段代码,如果用户访问了如http://leonax.net/...,会被重定向到https://leonax.net/.....。如果想反过来,即把HTTPS强制重定向到HTTP,把targetProtocol的值改成http就行。是不是很方便?

JUnit中获取测试类和方法的名称

在JUnit的测试中,有时候需要获得所属的类(Class)或者方法(Method)的名称,以方便记录日志什么的。

在JUnit中提供了TestName类来做到这一点,在org.junit.rules中:

虽然TestName只提供了方法的名称,要加上类的名称很容易,只需对TestName稍作修改如下:

在测试用例中的用法是:

大功告成!

使用WebDriver对特定的WebElement截图

用过 WebDriver 的同学都知道,WebDriver 可以对浏览器中的页面进行截图。例如:

这样产生的图片是整个网页。但有时候我们并不需要整个网页,只需要某些特定的 WebElement,以避免一些干扰。

虽然 WebDriver 本身没有提供这样的 API,不过我们可以自己来,就是在全屏的截图中再进行裁剪,如下:

其中 ImageIO 和 BufferedImage 分别来自 javax.imageio 和 java.awt.image。

这种方法可以很好的削减截图的大小,也避免了一些不确定因素(比如日期时间等),是测试中保存截图的很好的方式。

注:如果测试的网页中含有 iframe,则需要使用更复杂的方式计算 WebElement 的位置,详见:计算网页中某个元素的位置

使用 Preconditions 来检查传入参数

Preconditions 是 Guava 中的一个类库,用于检查传入参数,一个常见用法如下:

用法简单明了,就是检查参数 elements 是不是 null,如果是 null 则扔出 NullPointerException。当然 Preconditions 类里还有其它方法,可能满足几乎所有的传入参数的检查。Preconditions 的好处在于,它在 call stack 中更容易理解,并且每个方法还提供了格式化字符串的变体,形如:

和 Java 自带的 assert 关键字不同的是,Preconditions 的方法在 release 版本中依然有效,这么做的原因,大概是因为 Java 已经很慢了,不太乎多做些检查吧-_-

StringBuffer vs StringBuilder

早先用Java的时候,知道有个类叫StringBuffer,用来拼接较长的字符串。转到C#之后,也有一个似类功能的类叫作StringBuilder,简写都是sb,非常好记。

再后来转移回Java的时候,发现Java也有了StringBuilder,于是就好奇了一下为什么在StringBuffer之后又推出了StringBuilder。

原来Java的StringBuilder(和C#一样)是非线程安全的,而早先的StringBuffer具有一定的线程安全属性。当然,推出StringBuilder,主要也是因为它没有必要在多线程的情况下使用。

常见的StringBuilder(或者StringBuffer)的用例是:

在这种情况下,StringBuilder都不是一个类成员,它只是一个局部变量,根本谈不上多线程的问题。

于是,StringBuilder的引入带来了非常大的性能提升,而且一点安全问题也没有……

Java里的static import

换了工作要把Java重新捡起来了,这个在大学里用过的语言,虽然不复杂,还是有一些奇怪的地方的。比如static import。

Static import是JDK 1.5中引进的特性,不过读大学那会还真没注意到。它的作用是把静态(static)的方法或者常量import进来。比如:

使用了static import之后,就可以写成:

注意"Math."和"System."可以省略掉了。

Static import和import的规则类似,引用的内容不可以有歧义。

使用了static import,代码会变短,增加了可读性,但一定程度上会对代码整体的理解造成困难,因为常量和静态方法看上去像全局变得和全局方法了,有点C++的味道,失去了一些OO的美感。

在C#中判断某个类是否实现了某个接口

有时我们需要判断某个类是否实现了某个接口(Interface),比如在使用反射机制(Reflection)来查找特定类型的时候。

简单来说,可以使用Type.IsAssignableFrom方法:

从字面意思可以看出,IsAssignableFrom表示BarClass类型能否赋值给IFoo接口,所以它返回true的条件就是BarClass直接或间接实现了IFoo接口。Type类型中还有一个方法是IsSubclassOf,它只能用于判断类的继承关系,比如

表示FooClass是继承自BarClass。

当然IsAssignableFrom也可以用来判断继承关系。

于是,对于以下的代码:

IsSubclassOf和IsAssignableFrom的返回值为: