WebService技术总结(三):项目实战——使用XML,dom4j,Xpath实现远程调用

来源:互联网 发布:山地别墅案例 知乎 编辑:程序博客网 时间:2024/04/27 21:56

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>

服务端代码:

  1. 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.csdn.net/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);    }}

返回结果:
这里写图片描述

0 0
原创粉丝点击