学了两天的web service,感觉这项技术确实不错,今天就要在项目中使用一下他了。听王老师讲之前,确实对银联的系统不太了解,不明白它是怎么实现跨行取款的。王老师讲了它的实现原理,并使用web service进行了实现。
银联项目就是模拟我们现在使用的银联卡,在任何银行的atm取款机上都可以取款。各银行的软件系统是不一样的,要让它在别的银行atm取款机上也提供存储,查询,取款等服务,就要通过银联服务器向外提供web service。项目中创建3个web project 分别是bankunion(银联),icbc(中国工商银行),cbc(中国建设银行)。
三个项目上都要建立web service ,提供服务,icbc和cbc上建立web client,作为客户端。
项目的web service用xfire来实现,创建 web service时要导入jar包
xfire 1.2 core libraries
xfire 1.2 http client libraries
xfire 1.2 jaxb2 libraries
dbcp的jar包 和 mysql驱动jar包
bankunion的数据库存储银行卡号的前缀和银行系统对外提供服务的wsdl url地址。然后根据用户输入的银行前缀选择对应的wsdl对其提供服务。
主要方法:
public boolean login(String id, String pwd) {
String prefix = id.substring(0,4);
IAccountDao accountDao = new AccountDaoJdbcImpl();
String wsdlURL = accountDao.getBankWSDLByPrefix(prefix);
return true;
}
cbc中设置银行卡号为“4367”,当用户登录时,先读取其前缀,如果为“4367”,则验证其卡号和密码,正确让其登录,进行用户想要的操作。不正确报错,让其重新输入。如果不为“4367”,则作为bankunion提供的web service的客户端去访问服务器,有服务器根据银行前缀选择对应的银行wsdl,对它提供服务,远程调用该银行的方法来验证用户的卡号和密码。此项目中用到的web service实现的功能就是这样,相关代码如下:
public boolean login(String id, String pwd) {
boolean flag = false;
String prefix = id.substring(0, 4);
if (prefix.equals(bankPrefix)) {
IAccountDao accountDao = new AccountDaoJdbcImpl();
flag = accountDao.findAccountByIdAndPwd(new Integer(id), pwd);
} else {
AccountClient client = new AccountClient();
AccountPortType service = client.getAccountHttpPort();
flag = service.login(id, pwd);
}
// TODO Auto-generated method stub
return flag;
}
public AccountPortType getAccountHttpPort() {
return ((AccountPortType)(this).getEndpoint(new QName("http://domain.bankunion.itcast.cn", "AccountHttpPort")));
}
@WebMethod(operationName = "login", action = "")
@WebResult(name = "out", targetNamespace = "http://domain.bankunion.itcast.cn")
public boolean login(
@WebParam(name = "in0", targetNamespace = "http://domain.bankunion.itcast.cn")
String in0,
@WebParam(name = "in1", targetNamespace = "http://domain.bankunion.itcast.cn")
String in1);
在钱的存取操作中,钱的类型要用BigDecimal ,BigDecimal是不可变的、任意精度的有符号十进制数。BigDecimal 由任意精度的整数非标度值 和 32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负 scale 次幂。因此,BigDecimal 表示的数值是 (unscaledValue × 10-scale)。 他的运算要比double型的更精确。在使用BigDecimal进行比较的时候,会发现new BigDecimal(0.1)与new BigDecimal(”0.1″)不相等,这是因为BigDecimal(double var)构造方法的结果有一定的不可预知性。有人可能认为在 Java 中写入 new BigDecimal(0.1) 所创建的 BigDecimal 实际上等于 0.1000000000000000055511151231257827021181583404541015625。这是因为 0.1 无法准确地表示为 double(或者说对于该情况,不能表示为任何有限长度的二进制小数)。这样,传入 到构造方法的值不会正好等于 0.1(虽然表面上等于该值)。另一方面,String 构造方法是完全可预知的:写入 new BigDecimal(”0.1″) 将创建一个 BigDecimal,它正好 等于预期的 0.1。通常优先使用 String 构造方法。当 double 必须用作 BigDecimal 的源时,先使用 Double.toString(double) 方法,然后使用 BigDecimal(String) 构造方法,将 double 转换为 String。要获取该结果,请使用 static valueOf(double) 方法。
还有个两个人使用存款折和银联卡同时对一个账户取钱的问题,这样就有可能取出比存款额大的钱数,显然这是不允许的。解决方法是
1.把数据库的自动提交改为手动提交。
connection.setAutoCommit(false);
2。对要操作的行上锁,在sql语句中实现。
String sql = "select account from accounts where id=? for update";
这样在一个用户对数据库中一行操作时,提交之前,另一个用户无法对其操作,这个问题也就解决了。