未保护的Web服务
第一个Web服务根本没有防范不利条件的机制。如以下代码所示,这个基本方法读入几个双精度输入,然后除数除被除数,返回作为结果的双精度值。
import javax.jws.*;
@WebService
public class DivideWS {
@WebMethod
public double nakedDivide(double dividend, double divisor)
{
return dividend/divisor;
}
}
测试显示了nakedDivide(…) Web方法的行为:正面测试显示,Web服务对输入数字进行了正常除法; 如果输入了零除数,应用服务器就会进行恰当处理,并返回INF值; 如果被除数或者除数什么也没有输入,就会显示详细的堆栈跟踪,还有关于XML处理内部的列表信息,譬如串行化器、SOA服务器协议处理程序和实现平台。
一般而言,堆栈跟踪信息对Web服务使用者毫无用处,使用者也没有多少办法可以从这样的通用、冗长的异常中恢复过来。这不像一组简单的文档返回代码发送到客户程序、从除以零或者空值异常中轻松恢复过来。发送到客户程序的堆栈跟踪信息不但毫无用处、代码上不可执行,它还可能会把实现细节传送给外部使用者,有可能被人进一步利用。
防御性Web服务
下面的代码片显示,防御性Web服务defensiveDivide(…)建立在前一个方法nakedDivide(…)上的基础上,添加了简单的检查机制查看除数是不是零。这可以确保除以零错误不会出现。如果除数是零,该方法就会返回0,那样调用程序就可以从不合适的零除数输入中恢复过来。在这种方法中,编程人员预料到了边界条件,编写防御性代码来处理它。
public double defensiveDivide(double dividend, double divisor)
{
if (divisor != 0)
return dividend/divisor;
else
return 0;
}
几个正面和负面测试很快显示了defensiveDivide(…) Web方法的行为:正面测试显示,Web服务对输入数值进行了正常的除法; 如果输入了零除数,不像nakedDivide(…)会在试图进行除法运算后,返回表示无限大的INF值,defensiveDivide(…)返回的是编程人员定义的显式0.0错误值,连除法运算试都不试一下;如果被除数或者除数什么也没有输入,就像nakedDivide()那样,就会显示详细的堆栈跟踪,还有关于XML处理内部的列表信息,譬如串行化器、SOA服务器协议处理程序和实现平台。
测试结果显示,虽然已经恰当地预料到并处理了除以零场景,但除此之外,防御性错误处理并没有多大作为。不过,编程人员只要避免用坏数据进行计算,就可以让defensiveDivide()比nakedDivide()更有效率。预料意味着可以提高程序效率。