XML具有跨平台性,在企业webservice开发中, 经常将请求参数封装为XML,并且返回一个XML作为结果。
需求: 客户端将发票号码,发票代码作为条件,调用服务端,查询金额,税额信息
客户端请求参数xml形式:
<?xml version="1.1" encoding="utf-8"?>
<invoice>
<code>4200161130</code>
<number>01140087</number>
</invoice>
服务端返回的XML结果:
<?xml version="1.0" encoding="UTF-8"?>
<result>
<invoice>
<amount precision="2">403.77</amount>
<tax precision="2">24.23</tax>
</invoice>
</result>
服务端代码:
- POJO:Invoice
public class Invoice {
private String code;
private String num;
private double amount;
private double tax;
//省略getter和setter
}
2.DAO实现类,省略DAO接口:使用oracle数据库做了一个简单的查询操作,结果封装为一个java bean集合
public class InvoiceDaoImp implements InvoiceDao {
@Override
public List<Invoice> query(String code, String num) throws Exception {
String url = "jdbc:oracle:thin:@10.101.238.173:1521:orcl";
String user = "gkzq";
String password = "gkzq";
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection connection = DriverManager.getConnection(url, user, password);
String sql = "SELECT account, tax FROM bd_invoice WHERE code = ? and name = ?";
PreparedStatement stat = connection.prepareStatement(sql);
stat.setString(1, code);
stat.setString(2,num);
ResultSet results = stat.executeQuery();
List<Invoice> invoices = new ArrayList<Invoice>();
while(results.next()){
Invoice invoice = new Invoice();
double amount = results.getDouble(1);
double tax = results.getDouble(2);
invoice.setAmount(amount);
invoice.setTax(tax);
invoices.add(invoice);
}
return invoices;
}
}
3.webservice部分:SEI及其实现类
注意这里抛出了Exception异常,为后面的一个bug埋下伏笔
public interface InvoiceService {
public String getInvoices(String clientXml) throws Exception;
}
实现类:涉及到了dom4j和Xpath的相关知识,十分简单,都是见名知意的API,忘了的同学可以复习一下
- 方法parseXml解析从客户端传来的请求XML,并封装成一个Invoice对象;
- 方法create将服务端查询的List结果对象转换为一个XML,返回给客户端;
@WebService(targetNamespace="http://invoice.yonyou.com",
serviceName="InvoiceService",
name="InvoicePort")
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class InvoiceServiceImp implements InvoiceService{
private InvoiceDao invoiceDao = new InvoiceDaoImp();
@Override
@WebMethod
public @WebResult(name="rspXml")String getInvoices(@WebParam(name="requestXml")String clientXml) throws Exception {
//客户端传过来的是一个xml,条件都在xml里
Invoice condition = parseXml(clientXml);
//查询结果
List<Invoice> invoices = invoiceDao.query(condition.getCode(), condition.getNum());
//把结果也要转换成一个xml,返回给客户端
return create(invoices);
}
private String create(List<Invoice> invoices) {
Document rspXml = DocumentHelper.createDocument();
Element root = DocumentHelper.createElement("result");
rspXml.setRootElement(root);
if(invoices != null && invoices.size() > 0){
for (Invoice temp : invoices) {
Element invoice = root.addElement("invoice");
Element amount = invoice.addElement("amount");
amount.addText(temp.getAmount() + "");
amount.addAttribute("precision", "2");
Element tax = invoice.addElement("tax");
tax.addText(temp.getTax() + "");
tax.addAttribute("precision", "2");
}
}
return rspXml.asXML();
}
private Invoice parseXml(String clientInfo) throws Exception{
Document doc = DocumentHelper.parseText(clientInfo);
String code = doc.selectSingleNode("/invoice/code").getText();
String num = doc.selectSingleNode("/invoice/number").getText();
Invoice temp = new Invoice();
temp.setCode(code);
temp.setNum(num);
return temp;
}
}
服务端代码的编写到此结束了,可以发布服务了,编写发布服务的代码:
public class Publish {
public static void main(String[] args) {
String address = "http://10.101.238.173:20161/invoice";
Endpoint.publish(address, new InvoiceServiceImp());
}
}
运行结果如下:
com.sun.xml.internal.ws.model.RuntimeModelerException: runtime modeler error: Wrapper class com.yonyou.service.imp.jaxws.ExceptionBean is not found. Have you run APT to generate them?
wtf?网上百度了一下这错误,无果,然后翻墙谷歌,任然无果,尝试用APT命令编译,百度出来的教程惨不忍睹,最后在csdn的一篇博客中看到解决方法:http://blog.youkuaiyun.com/rongbo_j/article/details/50967438
解决方法如下:
1.打开cmd,进入到服务端项目bin路径下
2.执行以下命令:wsgen -keep -cp . com.yonyou.service.imp.InvoiceServiceImp
3.打开生成的ExceptionBean.java,全选,复制到src目录下
4.运行发布程序即可
至此,服务端代码编写完成,可以输入http://10.101.238.173:20161/invoice?wsdl看一下生成的wsdl文件
生成客户端java文件
接下来都是很简单的操作了
1.cmd切换到客户端项目src下
2.运行wsdl2java命令:wsdl2java -d . -frontend jaxws21 http://10.101.238.173:201
61/invoice?wsdl
3.客户端生成的代码如下:
客户端调用
首先准备请求的XML文件
<?xml version="1.1" encoding="utf-8"?>
<invoice>
<code>4200161130</code>
<number>01140087</number>
</invoice>
编写调用的代码:
public class Client {
public static String requestXml = "<?xml version=\"1.1\" encoding=\"utf-8\"?>" +
"<invoice>" +
"<code>4200161130</code>" +
"<number>01140087</number>" +
"</invoice>";
public static void main(String[] args) throws Exception_Exception, MalformedURLException {
URL url = new URL("http://10.101.238.173:20161/invoice?wsdl");
String namespace = "http://invoice.yonyou.com";
String serviceName = "InvoiceService";
QName qName = new QName(namespace, serviceName);
Service service = Service.create(url,qName);
InvoicePort port = service.getPort(InvoicePort.class);
String rspXml = port.getInvoices(requestXml);
System.out.println(rspXml);
}
}
返回结果: