4.4Webservice

点击打开链接:个人笔记
包括的内容有:
wb的发布和客户端的调用
免费web服务常用连接:http://www.webxml.com.cn/zh_cn/web_services.aspx
客户端调用网上服务的例子
分析rpc/document_ware/document_bare的不同的参数交互方式。
webserivce的其他数据格式的传递与交互(date map Bean list String)。
wb的异常处理
1.: webservice中的名词介绍:
  1.1:与WebServices 相关的 J2EE 技术称为 JWS(Java WebServices),
      其中含有 JAX-WS、JAX-RS、JAXB、JAXR、SAAJ、 StAX等技术。
  1.2:xml:   可扩展性标记语言。
  1.3:XSD:是指XML结构定义 ( XML Schemas Definition ), XML Schema 是DTD的替代品。XML Schema语言也就是XSD。
                 XML Schema描述了XML文档的结构。一个XML Schema会定义:文档中出现的元素、文档中出现的属性、
                 子元素、子元素的数量、子元素的顺序、元素是否为空、元素和属性的数据类型、元素或属性的默认和固定值。
  1.4:SOAP  即 Simple Object AccessProtocol 也就是简单对象访问协议。因为 SOAP基于XML和HTTP ,
        其通过XML 来实现消息描述,然后再通过 HTTP 实现消息传输。所以SOAP 是用于在应用程序之间进行通信的一种通信协议。
  1.5:WSDL 即Web Services Description Language也就是 Web 服务描述语言。
         是基于 XML的用于描述 Web 服务以及如何访问 Web 服务的语言。它里面定义了web服务所使用的方法、变量名、返回值、url
         等。看WSDL这个文件时从下往上看。
   1.6:JAXB(Java API for XML Binding)即XML元素跟Java对象之间的绑定。JAXP(Java API for XML Processing)包括了对
         XML的解析、校验、查询、变换。JAXM(Java API for XML Messaging简称JAXM)是为Java平台上的应用程序定义的API,
         用以通过XML(以及SOAP)发送和接收消息,支持同步消息和异步消息。SAAJ支持带附件的SOAP消息。SAAJ是JAXM下的一个
         分支。
   1.7:jax-rpc/jax-ws/jax-rs
        支持 SOAP 的是JAX-RPC/JAX-WS方式,支持REST的是JAX-RS
2: webservice的实现方式: jax-ws/xfire/cxf/axis2等
3:  发布一个最简单的webservie以及客户端的调用方式:
    3.1 首先得创建发布一个webservice,先创建一个Java工程,在com.webservice这个包下创建一个接口FirstService并且在接口类名
       前加上@WebService这个注解(表明这是一个Web服务接口)和在接口中定义一些方法。再在这个包里创建一个First实现类,实现的接
       口为前面创建的接口。并且要在First类的前面加上@WebService(endpointInterface = "com.webservice.FirstService")来说
       明它实现的服务接口类是哪个。结构是:
         
     
      
      Endpoint.publish(address, implementor);其中的address是webservice的访问地址,可以随意填写,第二个参数是new一个实
      现对象。访问的时候address加上?WSDL。
  3.2: 客户端调用服务端: 有三种方式(1.代理模式2.sope消息的方式3.客户端桩的模式)
         都得先创建一个Java工程名叫WebServiceClient01.
         3.2.1:代理模式
         先将服务端的接口类拷到客户端中。
      
         再写调用类:
     
      3.2.2: 客户端桩的模式:通过WSDL地址,或者WSDL文件,生成客户端的调用类
       一:使用MyEclipse工具来生成{内部调用jdk的命令}
       二:通过jdk自带的命令来生成。
       二:通过jdk自带的命令来生成
        -d <directory>            指定放置生成的输出文件的位置
        -keep                     保留生成的文件
        -p <pkg>                  指定目标程序包
        -verbose                  有关编译器在执行什么操作的输出消息
         先在e盘建一个名叫test_service的文件夹,
         再在jdk的目录下用命令行来运行总的执行命令是:
         D:\jdk\bin>wsimport -d E:\test_service -p com.client -keep -verbose http://localhost:5050/first?wsdl
         然后在到E:\test_service\com\client里把.class的都删了。再把com包整个拷到一个Java工程名叫WebServiceClient01里。
         最后写调用类:               
       
       一:使用MyEclipse工具来生成
              先在工程中建一个包名叫com.myeclipse,再在这个包上右键点击-->other-->Web Service Client点击后进行下一步下一
      步。       
       
             注意:生成客户端的时候,服务端一定要处于发布状态,不然可能会生成失败。
          最后写调用类:      
        
        3.3:发送原始的Soap消息:Http协议中,通过Soap协议来发送XML数据的消息格式。这种消息格式称为Soap消息。
        3.4:还有其它两种
              1:利用开源的工具(CXF,AXis2)也提供相应的调用方法。
              2:Http协议中,通过Soap协议来发送XML数据的消息格式
                   利用开源Commont-httpClient来模拟HTTP请求,发送XML的消息格式。
4:注解:
     @WebResult(name="returnWord") 接口的返回值
     @WebParam(name="cityName")接口的参数
    
5:免费web服务常用连接: http://www.webxml.com.cn/zh_cn/web_services.aspx
6:例子:客户端调用网上的服务
         因为是调用网上的,所以用wsdl地址生成客户端时会有错,所以一般情况下都是用wsdl文件。
         步骤:
                 先建一个名叫wsdl的文件夹,再在这个文件夹里建一个带有.wsdl后缀的文件(chinese_to_english.wsdl)。
                  再把网上的那个wsdl地址里的内容复制到chinese_to_english.wsdl。
                  删除里面的中文描述和过时的标签。
                   最后像利用wsdl地址生成那样生成客户端文件。生成完后,wsdl文件夹就可以删了。
                   最后的最后就是写调用类啦!
 7: 分析rpc/document_ware/document_bare的不同的参数交互方式。
         rpc:@SOAPBinding(style = SOAPBinding.Style.RPC)即远程调用模式,rpc没有bare模式。
        
        RPC模式下,方法中的参数与返回值,直接定义在message元素中。
        <message name="add">
            <part name="x" type="xsd:int"/>
            <part name="y" type="xsd:int"/>
        </message>
        <message name="addResponse">
            <part name="addResult" type="xsd:int"/>
        </message>
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc"/>
    
       document_bare:@SOAPBinding(style = SOAPBinding.Style.DOCUMENT,
                 parameterStyle = SOAPBinding.ParameterStyle.BARE)

        注意点:bare模式下,webservice的方法只能有一个参数。

        Bare模式下,方法中的参数与返回值,直接在xsd文件中使用type来做声明。
        
        <message name="divide">
            //name为方法参数的名称   element为直接引用xsd中定义的元素。
            <part name="x" element="tns:x"/>
        </message>
        <message name="divideResponse">
            <part name="divideResult" element="tns:divideResult"/>
        </message>

        <xs:element name="divideResult" type="xs:int"/>
        <xs:element name="x" type="xs:int"/>

    document_warpper:封装格式。message方法中可以传递多个参数。
        每一个参数都使用了封装类型。
        <xs:element name="add" type="tns:add" /> //tns:add又引用下面定义的complexType类型。
          <xs:element name="addResponse" type="tns:addResponse" />
          <xs:element name="divide" type="tns:divide" />
          <xs:element name="divideResponse" type="tns:divideResponse" />

         <xs:complexType name="add">
            <xs:sequence>
                <xs:element name="x" type="xs:int" />
                <xs:element name="y" type="xs:int" />
            </xs:sequence>
         </xs:complexType>
8.webserivce的其他数据格式的传递与交互。
     日期类型/Bean/List/Map接口如何处理:
     日期类型:服务端是java中的日期类型。java.util.Date
     Soap消息中传递是XML中的日期类型。XMLGregorianCalendar
     XMLGregorianCalendar---->GregorianCalendar----->Date---->格式化成字符串。
     Map:服务端是Map类型,但是WSDL定义的是List类型。
     将Map做为WebSevice的数据传递时,不能再放入其他的复杂数据类型,如自定义的一些类型。
     注意:一般情况下我们不会使用这些复杂的类型,而是使用String这种基本的类型。
     8.1:日期类型:客户端测试代码: 

 package com.date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.xml.datatype.XMLGregorianCalendar;

import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;

public class TestMain {
public static void main(String[] args) {
TestMain testMain = new TestMain();

// testMain.get();

testMain.set();
}

private void get() {
IDateService dateService = new DateImplService().getDateImplPort();
/**
* XML元素中的日历对象
*/
XMLGregorianCalendar xmlCalendar = dateService.getSysDate();
int year = xmlCalendar.getYear();
int month = xmlCalendar.getMonth();
System.out.println(year + "-" + month);
/**
* 转成java中的日历对象
*/
GregorianCalendar calendar = xmlCalendar.toGregorianCalendar();
Date date = calendar.getTime();
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("接收服务端返回的日期 = " + dateFormat.format(date));

}

private void set() {
/**
* java中的日历对象
*/
Date date = new Date(2015-1900, 6, 7, 11, 12, 14);
GregorianCalendar calendar = new GregorianCalendar();
calendar.setTime(date);
/**
* 转为XML中的日历对象
*/
XMLGregorianCalendar xmlCalendar = new XMLGregorianCalendarImpl(
calendar);
IDateService dateService = new DateImplService().getDateImplPort();
dateService.setClient(xmlCalendar);

}
}
服务端实现类的代码:

package com.webservice;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.jws.WebService;

@WebService(endpointInterface = "com.webservice.IDateService")
public class DateImpl implements IDateService {

public Date getSysDate() {
Date date = new Date();
return date;
}

public void setClient(Date date) {

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

String strTime = dateFormat.format(date);

System.out.println("接收到客户端传递的Date数据 = " + strTime);

}

}



8.2: 将Map做为WebSevice的数据传递时
     服务器端实现类的代码:
     
package sss.webservice;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.jws.WebService;
@WebService(endpointInterface = "sss.webservice.IMapService")
public class MapImpl implements IMapService {

@Override
public Map<String, Object> getMap() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("key1", "hahah");
map.put("key2", new Date());
return map;
}
@Override
public void setMap(Map<String, Object> map) {
if(map!=null){
Set<Entry<String, Object>> entries = map.entrySet();
for (Entry<String, Object> entry : entries) {
String keyString = entry.getKey();
Object object = entry.getValue();
System.out.println("从客户端发送过来的数据:"+keyString+" "+object);
}
}
}

}

   客户端测试类的代码:

package sss.Map;

import java.util.Date;
import java.util.List;
import java.util.Map;
import sss.Map.*;
import sss.Map.GetMapResponse.GetMapResult;
import sss.Map.GetMapResponse.GetMapResult.Entry;

public class TestMain {
public static void main(String[] args) {
TestMain testMain = new TestMain();
//testMain.get();
testMain.set();
}

private void get() {
IMapService iMapService = new MapImplService().getMapImplPort();
GetMapResult gMapResult = iMapService.getMap();
List<sss.Map.GetMapResponse.GetMapResult.Entry> list = gMapResult.getEntry();
for (Entry entry : list) {
String keyString = entry.getKey();
Object object = entry.getValue();
System.out.println("服务器端发来的数据:"+keyString + " "+object);
}
}

private void set() {
IMapService iMapService = new MapImplService().getMapImplPort();
SetMap.Map map = new SetMap.Map();
List<sss.Map.SetMap.Map.Entry> list = map.getEntry();
//注意每一个entry都得另外新创建,不然list里就只有一个entry
sss.Map.SetMap.Map.Entry entry = new sss.Map.SetMap.Map.Entry();
entry.setKey("key1");
entry.setValue("hahah");
list.add(entry);
sss.Map.SetMap.Map.Entry entry1 = new sss.Map.SetMap.Map.Entry();
entry1.setKey("time");
entry1.setValue(new Date());
list.add(entry1);
iMapService.setMap(map);
}
}


8.3: 将String做为WebSevice的数据传递时,可以把String封装成xml或json格式。
服务端代码:
package com.webservice;

import javax.jws.WebService;

@WebService(endpointInterface = "com.webservice.IStrService")
public class StrImpl implements IStrService {
//服务端的接口实现类
public String getXMLStr() {
StringBuffer xmlStr = new StringBuffer();
xmlStr.append("<root>");
xmlStr.append("<head>");
xmlStr.append("");
xmlStr.append("</head>");
xmlStr.append("<body>");
xmlStr.append("<userbean>");
xmlStr.append("<userid>1</userid><username>用户名</username>");
xmlStr.append("</userbean>");
xmlStr.append("</body>");
xmlStr.append("</root>");
return xmlStr.toString();
}

public void setStrList(String xmlStr) {
}

}

客户端代码:

package com.str;

import java.io.StringReader;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
//客户端测试类
public class TestMain {
public static void main(String[] args) {
TestMain.get();
}
private static void get() {
IStrService strService = new StrImplService().getStrImplPort();
String xmlStr = strService.getXMLStr();
System.out.println("xmlStr = " + xmlStr);
// 解析XML的字符串 Dom4j
try {
SAXReader reader = new SAXReader();
Document document = reader.read(new StringReader(xmlStr));
Element userBean = (Element) document
.selectSingleNode("/root/body/userbean");
String userid = userBean.elementText("userid");
String username = userBean.elementText("username");
System.out.println(userid + "\t" +username);
} catch (Exception e) {
e.printStackTrace();
}
}
}

注意: 解析XML的字符串时可以用dom4j,要记得拷相应的jar包。
9.异常处理:
 wsdl中会把编译异常当作消息来处理,而运行时异常则不当作消息来处理。
正规情况下我们是抛编译异常,但我们一般都是抛运行时异常,也就是让我们交互不成功,双方都报错。
WebService中的自定义异常时,一般继承Exception,不继承RunTimeException
原因:继承Exception,WebService会将异常在wsdl中定义为一个message.
出现异常时,会将异常封装成为一个Soap消息传递给客户端。客户端就会获取到异常消息。
继承RunTimeException:服务端会抛异常,客户端接到的不是具体的异常。
是Soap中默认的异常。SoapFaultException
服务端代码:
服务端接口
package sss.webservice;
import java.util.Date;

import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
//服务端接口
@WebService
public interface IExceptionService {
@WebResult(name = "addResult")
public int add(@WebParam(name = "x")int x,@WebParam(name = "y")int y)throws Exception;
@WebResult(name = "subResult")
public int sub(@WebParam(name = "x")int x,@WebParam(name = "y")int y)throws RuntimeException;
@WebResult(name = "divideResult")
public int divide(@WebParam(name = "x")int x,@WebParam(name = "y")int y)throws DivideException;
}

接口实现类

package sss.webservice;

import javax.jws.WebService;
//服务端接口实现类
@WebService(endpointInterface = "sss.webservice.IExceptionService")
public class ExceptionImpl implements IExceptionService {

@Override
public int add(int x, int y) throws Exception {
if(x == 0 || y == 0){
throw new Exception("Exception:add中的X或Y不能为0。。。");
}
else return x+y;
}

@Override
public int sub(int x, int y) throws RuntimeException {
if(x == 0 || y == 0){
throw new RuntimeException("RuntimeException:sub中的X或Y不能为0。。。");
}
else return x+y;

}

@Override
public int divide(int x, int y) throws DivideException {
if(x == 0 || y == 0){
throw new DivideException("DivideException:divide中的X或Y不能为0。。。");
}
else return x+y;
}

}

客户端测试类:

package sss.Exception;
//客户端测试类
public class TestMain {
public static void main(String[] args) {
TestMain testMain = new TestMain();
//testMain.add();
  //testMain.sub();
testMain.didv();
}

private void add() {
// 服务端没有异常
// 客户端:com.exception.Exception_Exception
//这种抛编译异常的方式结果是客户端和服务端交互成功,
//当服务端发生错误的时候,会把错误抛给客户端,所以导致最后服务端没有报错,而只有客户端报错。
//这种异常的使用只有常规的时候会使用,不然一般情况下是不会使用的。
IExceptionService iExceptionService = new ExceptionImplService().getExceptionImplPort();
try {
iExceptionService.add(0, 10);
} catch (Exception_Exception e) {
System.out.println(e.getFaultInfo().getMessage());
e.printStackTrace();
}

}

private void sub() {
// 服务端的异常:java.lang.RuntimeException
// 客户端的异常:javax.xml.ws.soap.SOAPFaultException 交互不成功异常
//这种抛出运行异常的方式是使客户端和服务端交互不成功,
//并且告诉双方你们出错的原因
//我们普遍都是使用这种方式。
IExceptionService iExceptionService = new ExceptionImplService().getExceptionImplPort();
iExceptionService.sub(0, 10);
}

private void didv() {
//和抛出编译异常的效果是一样的。
IExceptionService exceptionService = new ExceptionImplService()
.getExceptionImplPort();

try {
exceptionService.divide(1, 0);
} catch (DivideException_Exception e) {
System.out.println(e.getFaultInfo().getMessage());
e.printStackTrace();
}

}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值