SOA(面向服务的架构) Service1,Service2,Service3--所有组件都是“即插即用”的
IBM提倡的SOA架构,希望以“组装电脑”的方式来开发软件。 1,各种提供服务的组件。 2,企业服务总线(EnterpriseServiceBus,ESB)
CXF号称是SOA框架
CXF(Apache)
cxf框架的使用 1,下载cxf 2,配置cxf下bin的path环境变量 3,测试环境变量是否配置正确
cxf框架目录介绍 /bin常用命令 /doc开发文档 /libjar包
cxf内置了一个JettyWeb服务器 (tomcat的开发者就是javaee规范的制定者) 使用cxf开发webservice服务端 1,开发一个webservice接口 加上@WebService注释 2,开发实现类 加上@WebService()注释 加上属性endpointInterface="com.kenan.cxf.HelloWorld"指定实现的接口 serviceName=“HelloworldService” 3,加入jar包 cxf servlet3.0 jetty-*(JettyWeb服务器) asm common-logging neethi xmlschema-core wsdl4j 4,创建测试类,发布ws(需要在main方法中) HelloWorldhw=newHImpl(); Endpoint.publish("http://localhost:9999/hello",hw); 5,访问http://localhost/hello?wsdl
使用cxf开发webservice客户端 1,使用wsdl2java将服务端暴露的wsdl文档转换为java代码 2,找到实现了service接口的类,该类可以当成工厂来使用 HelloWorldImplfac=new(); 3,生产HelloWorldhello=fac.getHelloWorldWsPort(); 调用远程方法 hello.say("sdf");
1,当形参,返回值为String的时候,cxf可以轻松的处理 2,当形参返回值类型为javabean的复合类,List集合,数组,cxf也可以很好的处理
wsdl介绍 wsdl:webservicedefinationlanguage
wsdl是一个xml文档 xml中的两个属性 targetNamespace(规定自己这个文档的命名空间)相当于java中的包名 xmlns(命名空间:xmlnamespace)相当于java中要引入的
WSDL文档 1,WebService接口
一次webservice的调用,其实不是方法调用,而是发送SOAP消息(xml文档片段) 要调用的方法,和传入的参数都写在xml文档中,也就是一个SOAP消息
SOAPsimpleobjectaccessproto简单对象协议 调用一次webservice的本质 1,客户端把要调用方法参数,转换成xml文档片段(SOAP消息),该文档必须符合wsdl文档规范 2,通过网络,把xml文档传给服务器 3,服务器接受到xml文档 4,服务器解析xml文档片段,提取其中的数据。 并把数据转换调用webservice所需要的参数类型 5,服务器执行方法 6,把执行方法得到的返回值,再次转换成xml文档片段 7,通过网络,把xml文档片段传给客户端 8,客户端接受到XML文档 9,客户端解析到XML文档,提取其中的数据 并把数据转换成调用webservice的返回值
从上面调用的本质来看,要一个语言支持webservice 唯一的要求是,该语言支持xml文档解析,声称,支持网络传输
如果遇到cxf无法转换的类型,就需要我们自定义转换 如对于map对象 1,使用@XmlJavaTypeAdapter注释无法处理的类型 通过(value=)XmlAdapter指定一个转换器 转换器在这里就可以把cxf搞不定的类型搞定 2,实现自己的转换器,开发一个cxf搞得定的类型需要实现XmlAdapter抽象类 这里有两个参数,第一个是搞得定的类型 第二个是搞不定的类型 extendsXmlAdapter<StringCat,Map<string,Cat>>
SOAP协议:简单对象传输协议 传入消息: header:默认情况下,header元素不是强制出现的,header元素 有程序员控制添加,主要用于携带一些额外的信息 2013-1-2822:13:26org.apache.cxf.services.HelloWorldImpl.HelloWorldImplPort.HelloWorld 信息:InboundMessage ---------------------------- ID:3 Address:http://localhost:9999/hello Encoding:UTF-8 Http-Method:POST Content-Type:text/xml;charset=UTF-8 Headers: {Accept=[text/xml,multipart/related,text/html,image/gif,image/jpeg,*;q=.2,*/*;q=.2], connection=[keep-alive], Content-Length=[195], content-type=[text/xml; charset=UTF-8], Host=[localhost:9999], SOAPAction=[""], User-Agent=[Java/1.6.0_13]} Payload: <?xmlversion="1.0"?> <S:Envelopexmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:helloxmlns:ns2="http://ws.cxf.kenan.com/"> <arg0>你好</arg0> </ns2:hello> </S:Body> </S:Envelope> --------------------------------------
传出消息: 2013-1-2822:13:26org.apache.cxf.services.HelloWorldImpl.HelloWorldImplPort.HelloWorld 信息:OutboundMessage --------------------------- ID:3 Encoding:UTF-8 Content-Type:text/xml Headers:{} Payload: <soap:Envelopexmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:helloResponsexmlns:ns2="http://ws.cxf.kenan.com/"> <return>你好</return> </ns2:helloResponse> </soap:Body> </soap:Envelope> --------------------------------------
webservice急需解决的问题:如何收钱? --如何进行权限控制? 为了进行权限控制,需要: 客户端发送soap消息的时候,必须携带用户名和密码信息 如果没有,或者不正确,拒绝调用
拦截器 为了让程序员放访问,并修改cxf声称的xml文档,cxf提供的拦截器 分为In拦截器 Out拦截器 服务器端添加拦截器: 1,在发布的时候 EndPointImplep=En...publish(); 添加in拦截器 ep.getInInterceptors().add(e); 添加out拦截器 ep.getOutInterceptors().add(e); 2,系统的拦截器 这个是日志的拦截器 newLoggingInInterceptor();(默认输出到控制台) newLoggingOutInterceprot(); 3,创建自定义拦截器需要实现Interceptor 一般我们会继承AbstractPhaseInterceptor
客户端添加拦截器
1,倒入jar包(zxf。。。) 2,Clientclient=ClientProxy.getClient(hi); hi为webserice接口类对象 client.getInInterceptors().add();
自定义拦截器 1,继承AbstractPhaseInterceptor extendsAbstractPhaseInterceptor<SoapMessage> 2,实现handlMessage方法 这个方法中的形参就是被拦截到的soap消息 解析soap消息,或者修改soap消息 3,写构造函数,显式调用父类构造函数,程序将不会隐式调用父类无参数的构造函数 super(Phase.PRE_INVOKE)在调用之前拦截soap消息 4,消息处理 参数SoapMessagemsg System.our.println(msg); List<Header>headers=msg.getHeaders(); if(headers!=null&&headers.size()>0){ //加入要求第一个header存放用户名和密码 Headerh=headers.get(0); Elementele=(Element)h.getObject(); NodeListuserIds=ele.getElementsByTagName("userId"); NodeListuserPasses=ele.getElementsByTagName("userPass");
if(userIds.getLength==1&&userPasses.getLength()==1){ StringuserId=userIds.item)0).getTextContent(); StringuserPass=userPasses.item(0).getTextContent(); if(){ //验证通过 return; } } } 自定义客户端的OutInterceptor 1,同上 2,构造器 publicConstructor(StringuserId,StringuserPass){ super(Phase.PREPARE_SEND);//在发送soap消息之前调用该拦截器 this.userId= this.userPass.. } 3,HandleMessage List<Header>headers=msg.getHeaders(); Documentdoc=DOMUtils.createDocument(); Elementele=doc.createElement("authHeader"); ElementidEle=doc.createElement("userId"); idEle.setTextContent(userId); ElementpassEle=doc.createElement("userPass"); passEle.setTextContent(userPass);
ele.appenChild(idEle); ele.appenChild(passEle); 生成如下文档 <authHeader> <userId></userId> <userPass></userPass> </authHeader> //把ele元素包装成header,并添加到soap消息中 Headerheader=newHeader(newQName("qname"),ele); headers.add(header);
客户端利用拦截器在发功的soap消息中写入数据后的消息 <soap:Envelopexmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <authHeader> <userId>23</userId> <userPass>sdr</userPass> </authHeader> </soap:Header> <soap:Body> <ns2:helloxmlns:ns2="http://ws.cxf.kenan.com/"> <arg0>你好</arg0></ns2:hello ></soap:Body> </soap:Envelope>
服务器端代码:
转换器:用于转换Map数据类型
packagecom.kenan.cxf.adapter;
importjava.util.HashMap;
importjava.util.Map;
importjavax.xml.bind.annotation.adapters.XmlAdapter;
importcom.kenan.cxf.adapter.domain.StringCat;
importcom.kenan.cxf.adapter.domain.StringCat.Entry;
importcom.kenan.cxf.domain.Cat;
publicclassMapXmlAdapterextendsXmlAdapter<StringCat,Map<String,Cat>>{
@Override
publicMap<String,Cat>unmarshal(StringCatv)throwsException{
Map<String,Cat>m=newHashMap<String,Cat>();
for(Entryentry:v.getEntries()){
m.put(entry.getKey(),entry.getValue());
}
returnm;
}
@Override
publicStringCatmarshal(Map<String,Cat>v)throwsException{
StringCats=newStringCat();
for(Stringkey:v.keySet()){
Entrye=newEntry(key,v.get(key));
s.getEntries().add(e);
}
returns;
}
}
用户map转换器的实体
packagecom.kenan.cxf.adapter.domain;
importjava.util.ArrayList;
importjava.util.List;
importcom.kenan.cxf.domain.Cat;
publicclassStringCat{
publicstaticclassEntry{
privateStringkey;
privateCatvalue;
publicEntry(){
}
publicEntry(Stringkey,Catvalue){
super();
this.key=key;
this.value=value;
}
publicStringgetKey(){
returnkey;
}
publicvoidsetKey(Stringkey){
this.key=key;
}
publicCatgetValue(){
returnvalue;
}
publicvoidsetValue(Catvalue){
this.value=value;
}
}
privateList<Entry>entries=newArrayList<Entry>();
publicList<Entry>getEntries(){
returnentries;
}
publicvoidsetEntries(List<Entry>entries){
this.entries=entries;
}
}
进行权限验证的过滤器:AuthInterceptor
packagecom.kenan.cxf.auth;
importjava.util.List;
importorg.apache.cxf.binding.soap.SoapMessage;
importorg.apache.cxf.headers.Header;
importorg.apache.cxf.interceptor.Fault;
importorg.apache.cxf.phase.AbstractPhaseInterceptor;
importorg.apache.cxf.phase.Phase;
importorg.w3c.dom.Element;
importorg.w3c.dom.NodeList;
publicclassAuthInterceptorextendsAbstractPhaseInterceptor<SoapMessage>{
publicAuthInterceptor(){
super(Phase.PRE_INVOKE);
}
@Override
publicvoidhandleMessage(SoapMessagemsg)throwsFault{
List<Header>headers=msg.getHeaders();
if(headers!=null&&headers.size()>0){
Headerheader=headers.get(0);
Elementele=(Element)header.getObject();
NodeListuserIdList=ele.getElementsByTagName("userId");
NodeListuserPassList=ele.getElementsByTagName("userPass");
if(userIdList!=null&&userIdList.getLength()==1&&userPassList!=null&&userPassList.getLength()==1){
StringuserId=userIdList.item(0).getTextContent();
StringuserPass=userPassList.item(0).getTextContent();
if(userId.equals("admin")&&userPass.equals("admin")){
return;
}
}
}
thrownewFault(newException("验证不通过"));
}
}
model层也就是数据库实体层,这里仅用于测试,并没有链接数据库
类cat
packagecom.kenan.cxf.domain;
publicclassCat{
privateIntegerid;
privateStringname;
privateStringcolor;
publicCat(){
super();
}
publicCat(Integerid,Stringname,Stringcolor){
super();
this.id=id;
this.name=name;
this.color=color;
}
publicIntegergetId(){
returnid;
}
publicvoidsetId(Integerid){
this.id=id;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicStringgetColor(){
returncolor;
}
publicvoidsetColor(Stringcolor){
this.color=color;
}
@Override
publicStringtoString(){
return"Cat[id="+id+",name="+name+",color="+color+"]";
}
}
类User
packagecom.kenan.cxf.domain;
publicclassUser{
privateIntegerid;
privateStringname;
privateStringpass;
privateStringaddress;
publicUser(){
super();
}
publicUser(Integerid,Stringpass,Stringaddress){
super();
this.id=id;
this.name=name;
this.pass=pass;
this.address=address;
}
publicIntegergetId(){
returnid;
}
publicvoidsetId(Integerid){
this.id=id;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicStringgetPass(){
returnpass;
}
publicvoidsetPass(Stringpass){
this.pass=pass;
}
publicStringgetAddress(){
returnaddress;
}
publicvoidsetAddress(Stringaddress){
this.address=address;
}
@Override
publicinthashCode(){
finalintprime=31;
intresult=1;
result=prime*result+((name==null)?0:name.hashCode());
result=prime*result+((pass==null)?0:pass.hashCode());
returnresult;
}
@Override
publicbooleanequals(Objectobj){
if(this==obj)
returntrue;
if(obj==null)
returnfalse;
if(getClass()!=obj.getClass())
returnfalse;
Userother=(User)obj;
if(name==null){
if(other.name!=null)
returnfalse;
}elseif(!name.equals(other.name))
returnfalse;
if(pass==null){
if(other.pass!=null)
returnfalse;
}elseif(!pass.equals(other.pass))
returnfalse;
returntrue;
}
}
websercie接口
packagecom.kenan.cxf.ws;
importjava.util.List;
importjava.util.Map;
importjavax.jws.WebService;
importjavax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
importcom.kenan.cxf.adapter.MapXmlAdapter;
importcom.kenan.cxf.domain.Cat;
importcom.kenan.cxf.domain.User;
@WebService
publicinterfaceHelloWorld{
Stringhello(Stringname);
List<Cat>getCatsByUser(Useruser);
@XmlJavaTypeAdapter(value=MapXmlAdapter.class)Map<String,Cat>getAllCats();
}
webservice接口实现类
packagecom.kenan.cxf.ws.impl;
importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.List;
importjava.util.Map;
importjavax.jws.WebService;
importcom.kenan.cxf.domain.Cat;
importcom.kenan.cxf.domain.User;
importcom.kenan.cxf.ws.HelloWorld;
@WebService(endpointInterface="com.kenan.cxf.ws.HelloWorld",
serviceName="HelloWorldImpl")
publicclassHelloWorldImplimplementsHelloWorld{
@Override
publicStringhello(Stringname){
System.out.println("hello:"+name);
returnname;
}
@Override
publicList<Cat>getCatsByUser(Useruser){
System.out.println(user.getName());
Listlist=newArrayList();
list.add(newCat(12,"sdf","sdf"));
list.add(newCat(12,"2df","sdf"));
list.add(newCat(12,"3df","4df","sdf"));
returnlist;
}
@Override
publicMap<String,Cat>getAllCats(){
Map<String,Cat>();
m.put("1",newCat(12,"2","34"));
m.put("2","34"));
m.put("3","34"));
m.put("4","34"));
returnm;
}
}
发布webservice
packagecom.kenan.cxf.ws.impl;
importstaticorg.junit.Assert.*;
importjavax.xml.ws.Endpoint;
importorg.apache.cxf.interceptor.LoggingInInterceptor;
importorg.apache.cxf.interceptor.LoggingOutInterceptor;
importorg.apache.cxf.jaxws.EndpointImpl;
importcom.kenan.cxf.auth.AuthInterceptor;
importcom.kenan.cxf.ws.HelloWorld;
publicclassWSTest{
publicstaticvoidmain(String[]args){
HelloWorldhello=newHelloWorldImpl();
EndpointImplep=(EndpointImpl)(Endpoint.publish("http://localhost:9999/hello",hello));
//ep.getInInterceptors().add(newLoggingInInterceptor());
//ep.getOutInterceptors().add(newLoggingOutInterceptor());
ep.getInInterceptors().add(newAuthInterceptor());
}
}
客户端
1,首先用sadl2java命令倒入需要的java代码,然后开发自己的拦截器
2,拦截器,用户实现权限认证
packagecom.kenan.cxf.auth;
importjava.util.List;
importjavax.xml.namespace.QName;
importorg.apache.cxf.binding.soap.SoapMessage;
importorg.apache.cxf.headers.Header;
importorg.apache.cxf.helpers.DOMUtils;
importorg.apache.cxf.interceptor.Fault;
importorg.apache.cxf.phase.AbstractPhaseInterceptor;
importorg.apache.cxf.phase.Phase;
importorg.w3c.dom.Document;
importorg.w3c.dom.Element;
publicclassAuthOutInterceptorextendsAbstractPhaseInterceptor<SoapMessage>{
privateStringuserId;
privateStringuserPass;
publicAuthOutInterceptor(StringuserId,StringuserPass){
super(Phase.PREPARE_SEND);
this.userId=userId;
this.userPass=userPass;
}
@Override
publicvoidhandleMessage(SoapMessagemsg)throwsFault{
List<Header>headers=msg.getHeaders();
Documentdoc=DOMUtils.createDocument();
Elementele=doc.createElement("authHeader");
ElementidEle=doc.createElement("userId");
idEle.setTextContent(userId);
ElementpassEle=doc.createElement("userPass");
passEle.setTextContent(userPass);
ele.appendChild(idEle);
ele.appendChild(passEle);
headers.add(newHeader(newQName("kenan"),ele));
}
}
客户端webservcie调用
packagetest;
importjava.util.List;
importorg.apache.cxf.endpoint.Client;
importorg.apache.cxf.frontend.ClientProxy;
importorg.apache.cxf.interceptor.LoggingOutInterceptor;
importcom.kenan.cxf.auth.AuthOutInterceptor;
importcom.kenan.cxf.ws.Cat;
importcom.kenan.cxf.ws.Entry;
importcom.kenan.cxf.ws.StringCat;
importcom.kenan.cxf.ws.User;
importcom.kenan.cxf.ws.impl.HelloWorldImpl;
publicclassTest{
/**
*@paramargs
*/
publicstaticvoidmain(String[]args){
HelloWorldImplhelloWorld=newHelloWorldImpl();
com.kenan.cxf.ws.HelloWorldhello=helloWorld.getHelloWorldImplPort();
//拦截器
Clientclient=ClientProxy.getClient(hello);
client.getOutInterceptors().add(newAuthOutInterceptor("admin","admin"));
client.getOutInterceptors().add(newLoggingOutInterceptor());
hello.hello("你好");
//Useruser=newUser();
//user.setName("柯南");
//List<Cat>l=hello.getCatsByUser(user);
//for(Catcat:l){
//System.out.println(cat.getName());
//}
//StringCats=hello.getAllCats();
//for(Entryentry:s.getEntries()){
//System.out.println(entry.getKey()+":"+entry.getValue());
//}
}
}
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|