※內鍵攔截器
以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!」,否則就會被攔截器攔截並拋出例外
沒有留言:
張貼留言