※內鍵攔截器
以logging為例,如下:※伺服器端
import java.util.List;
import javax.xml.ws.Endpoint;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.EndpointImpl;
import org.apache.cxf.message.Message;
String url = "http://localhost:8888/aaa/bbb/ccc";
EndpointImpl publish = (EndpointImpl) Endpoint.publish(url, new HelloWS());
System.out.println("增加server in log");
List<Interceptor<? extends Message>> in = publish.getInInterceptors();
in.add(new LoggingInInterceptor());
System.out.println("增加server out log");
List<Interceptor<? extends Message>> out = publish.getOutInterceptors();
out.add(new LoggingOutInterceptor());
System.out.println("server is start!");
※注意import的包,CXF有很多同名的class,但package不同
※在網址打上xxx.wsdl就會執行伺服器端in的部分,在console會顯示
※out的部分可用第一篇的JavaClientCallWebService.java
※用戶端
import java.util.List;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.message.Message;
HelloWSService hws = new HelloWSService();
IHelloWS hw = hws.getHelloWSPort();
Client client = ClientProxy.getClient(hw);
System.out.println("增加client out log");
List<Interceptor<? extends Message>> out = client.getOutInterceptors();
out.add(new LoggingOutInterceptor());
System.out.println("增加client in log");
List<Interceptor<? extends Message>> in = client.getInInterceptors();
in.add(new LoggingInInterceptor());
System.out.println(hw.add(1, 2));
※使用wsimport或wsdl2java產生程式碼後,使用如上的程式碼,這前幾篇也有做過,只是多個中間攔截器的部分
※首先先向server端丟出訊息,因為現在寫的是用戶端,所以對用戶端來說是out,然後伺服器端的in會接收,在來是伺服器端的out,最後再丟回給用戶端的out,攔截器完成後,再印出程式碼
※自定攔截器
※用戶端
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <ns2:add xmlns:ns2="http://test.hello/"> <arg0>1</arg0> <arg1>2</arg1> </ns2:add> </soap:Body> </soap:Envelope>
※內鍵攔截器的伺服器端的console有Inbound Message,裡面的Payload就是長這個樣子
※AddLoginInfo.java
import java.util.List;
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class AddLoginInfo extends AbstractPhaseInterceptor<SoapMessage> {
private String account;
private String password;
public AddLoginInfo(String account, String password) {
super(Phase.PRE_PROTOCOL); // 表示在轉換成SOAP之前
this.account = account;
this.password = password;
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
/**
* <login> <acc></acc> <pass></pass> </login>
*/
Document doc = DOMUtils.createDocument();
Element loginEle = doc.createElement("login");
Element accEle = doc.createElement("acc");
accEle.setTextContent(account);
Element passEle = doc.createElement("pass");
passEle.setTextContent(password);
loginEle.appendChild(accEle);
loginEle.appendChild(passEle);
List<Header> headers = msg.getHeaders();
headers.add(new Header(new QName("login"), loginEle));
System.out.println("客戶端的 handleMessage執行成功!");
}
}
※繼承 AbstractPhaseInterceptor 並增加 SOAP 的 head
※QName裡的字串必需與createElement裡的字串一樣,表示要攔截login標籤,否則攔截不到
※測試
HelloWSService hws = new HelloWSService();
IHelloWS hw = hws.getHelloWSPort();
Client client = ClientProxy.getClient(hw);
System.out.println("增加client out log");
List<Interceptor<? extends Message>> out = client.getOutInterceptors();
out.add(new AddLoginInfo("bruce", "12345"));
System.out.println(hw.add(1, 2));
※將out的攔截器指向新增的AddLoginInfo
※伺服器端的console
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <login> <acc>bruce</acc> <pass>12345</pass> </login> </soap:Header> <soap:Body> <ns2:add xmlns:ns2="http://test.hello/"> <arg0>1</arg0> <arg1>2</arg1> </ns2:add> </soap:Body> </soap:Envelope>
※一樣是 Inbound Message 的 Payload,此時會印出新增的login
※伺服器端
import javax.xml.namespace.QName;
import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
public class CheckLoginInfo extends AbstractPhaseInterceptor<SoapMessage> {
public CheckLoginInfo() {
super(Phase.PRE_PROTOCOL);
}
@Override
public void handleMessage(SoapMessage msg) throws Fault {
Header header = msg.getHeader(new QName("login"));
if (header != null) {
Element ele = (Element) header.getObject();
NodeList acc = ele.getElementsByTagName("acc");
String account = acc.item(0).getTextContent();
NodeList pass = ele.getElementsByTagName("pass");
String password = pass.item(0).getTextContent();
if ("bruce".equals(account) && "12345".equals(password)) {
System.out.println("驗證通過!");
return;
}
}
System.out.println("驗證未通過!");
throw new Fault(new RuntimeException("帳號和密碼不正確"));
}
}
※同樣繼承 AbstractPhaseInterceptor 並從head取出帳號和密碼
※server.java
String url = "http://localhost:8888/aaa/bbb/ccc";
EndpointImpl publish = (EndpointImpl) Endpoint.publish(url, new HelloWS());
List<Interceptor<? extends Message>> in = publish.getInInterceptors();
in.add(new CheckLoginInfo());
System.out.println("server is start!");
※因為客戶端丟過來,所以當然是用in去接
※此時輸入正確的帳密才會印出「call add method!」,否則就會被攔截器攔截並拋出例外
沒有留言:
張貼留言