WebServices中使用cxf开发日志拦截器以及自定义拦截器

首先下载一个cxf实例,里面包含cxf的jar包。我下的是apache-cxf-2.5.9


1、为什么要设置拦截器?

为了在webservice请求过程中,能动态操作请求和响应数据, CXF设计了拦截器.


2、拦截器分类

1. 按所处的位置分:服务器端拦截器,客户端拦截器

2. 按消息的方向分:入拦截器,出拦截器

3. 按定义者分:系统拦截器,自定义拦截器

技术分享


3、拦截器API

Interceptor(拦截器接口)

AbstractPhaseInterceptor(自定义拦截器从此继承)

LoggingInInterceptor(系统日志入拦截器类)

LoggingOutInterceptor(系统日志出拦截器类)


技术分享


4、编写实现拦截器

? 使用日志拦截器,实现日志记录

– LoggingInInterceptor

– LoggingOutInterceptor

? 使用自定义拦截器,实现用户名与密码的检验

– 服务器端的in拦截器

– 客户端的out拦截器

– benjamin/123456



系统日志拦截器代码实现:

Server:

SEI:

package com.wiseweb.ws;

import javax.jws.WebMethod;
import javax.jws.WebService;

/**
 * SEI
 * @author piqiu
 *
 */
@WebService
public interface HelloWS {

	@WebMethod
	public String sayHello(String name) ;
}

SEI的实现:

package com.wiseweb.ws;

import javax.jws.WebService;

/**
 * SEI的实现
 * @author piqiu
 *
 */
@WebService
public class HelloWSImpl implements HelloWS {

	@Override
	public String sayHello(String name) {
		System.out.println("server sayHello():" + name);
		return "Hello: " + name;
	}

}

ServerTest:

package com.wiseweb.ws.server;

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.jaxws22.EndpointImpl;
import org.apache.cxf.message.Message;

import com.wiseweb.ws.HelloWSImpl;

/**
 * 发布webservice
 * @author piqiu
 *
 */
public class ServerTest {

	public static void main(String[] args) {
		String address = "http://10.211.55.3:8888/day01_ws/hellows" ;
		Endpoint endpoint = Endpoint.publish(address, new HelloWSImpl()) ;
		EndpointImpl endpointImpl = (EndpointImpl) endpoint ;
		
		List<Interceptor<? extends Message>> inInterceptors = endpointImpl.getInInterceptors() ;
		inInterceptors.add(new LoggingInInterceptor()) ;
		
		List<Interceptor<? extends Message>> outInterceptors = endpointImpl.getOutInterceptors() ;
		outInterceptors.add(new LoggingOutInterceptor()) ;
		
		System.out.println("发布webservice成功!");
	}
}

Client:

把下载下来的apache-cxf-2.5.9的bin目录配置到系统环境变量的path中去,以便可以在cmd中执行bin中的bat文件

技术分享


在cmd中输入wsdl2java SEI地址就可以生成客户端代码了,同样也可以使用wsimport命令。

项目截图:

技术分享


ClientTest:

package com.wiseweb.client;

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;

import com.wiseweb.ws.HelloWS;
import com.wiseweb.ws.HelloWSImplService;

public class ClientTest {

	public static void main(String[] args) {
		HelloWSImplService helloWSImplService = new HelloWSImplService() ;
		HelloWS helloWS = helloWSImplService.getHelloWSImplPort() ;
		
		Client client = ClientProxy.getClient(helloWS) ;
		List<Interceptor<? extends Message>> outInterceptors = client.getOutInterceptors() ;
		outInterceptors.add(new LoggingOutInterceptor()) ;
		
		List<Interceptor<? extends Message>> inInterceptors = client.getInInterceptors() ;
		inInterceptors.add(new LoggingInInterceptor()) ;
		
		String result = helloWS.sayHello("benjaminwhx") ;
		System.out.println(result);
		
	}
}

运行结果Server端和Client端比较:

Client:

信息: Outbound Message
---------------------------
ID: 1
Address: http://10.211.55.3:8888/day01_ws/hellows
Encoding: UTF-8
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://ws.wiseweb.com/"><arg0>benjaminwhx</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
三月 03, 2015 11:03:17 上午 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[224], content-type=[text/xml;charset=UTF-8], Server=[Jetty(7.5.4.v20111024)]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://ws.wiseweb.com/"><return>Hello: benjaminwhx</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------
Hello: benjaminwhx

Server:

发布webservice成功!
三月 03, 2015 11:03:15 上午 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Inbound Message
----------------------------
ID: 1
Address: http://10.211.55.3:8888/day01_ws/hellows?wsdl
Encoding: UTF-8
Http-Method: GET
Content-Type: text/xml
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], content-type=[text/xml], Host=[10.211.55.3:8888], Pragma=[no-cache], User-Agent=[Apache CXF 2.5.9]}
--------------------------------------
三月 03, 2015 11:03:16 上午 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Inbound Message
----------------------------
ID: 2
Address: http://10.211.55.3:8888/day01_ws/hellows
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml; charset=UTF-8
Headers: {Accept=[*/*], Cache-Control=[no-cache], connection=[keep-alive], Content-Length=[197], content-type=[text/xml; charset=UTF-8], Host=[10.211.55.3:8888], Pragma=[no-cache], SOAPAction=[""], User-Agent=[Apache CXF 2.5.9]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHello xmlns:ns2="http://ws.wiseweb.com/"><arg0>benjaminwhx</arg0></ns2:sayHello></soap:Body></soap:Envelope>
--------------------------------------
server sayHello():benjaminwhx
三月 03, 2015 11:03:17 上午 org.apache.cxf.services.HelloWSImplService.HelloWSImplPort.HelloWS
信息: Outbound Message
---------------------------
ID: 2
Encoding: UTF-8
Content-Type: text/xml
Headers: {}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:sayHelloResponse xmlns:ns2="http://ws.wiseweb.com/"><return>Hello: benjaminwhx</return></ns2:sayHelloResponse></soap:Body></soap:Envelope>
--------------------------------------


自定义拦截器代码实现:

Server:

SEI和SEI实现都不做变动,增加一个interceptor:

package com.wiseweb.ws.interceptor;

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;

public class CheckUserInterceptor extends AbstractPhaseInterceptor<SoapMessage>{

	public CheckUserInterceptor() {
		super(Phase.PRE_PROTOCOL);
	}

	@Override
	public void handleMessage(SoapMessage message) throws Fault {
		Header header = message.getHeader(new QName("wiseweb")) ;
		if(header != null) {
			Element element = (Element)header.getObject() ;
			String username = element.getElementsByTagName("username").item(0).getTextContent() ;
			String password = element.getElementsByTagName("password").item(0).getTextContent() ;
			if(username.equals("benjamin") && password.equals("123456")) {
				System.out.println("用户名与密码正确,通过验证!");
				return ;
			}else {
				throw new Fault(new RuntimeException("请输入正确的用户名和密码!")) ;
			}
		}else {
			throw new Fault(new RuntimeException("请输入用户名和密码!")) ;
		}
	}

}

ServerTest:

package com.wiseweb.ws.server;

import java.util.List;

import javax.xml.ws.Endpoint;

import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.jaxws22.EndpointImpl;
import org.apache.cxf.message.Message;

import com.wiseweb.ws.HelloWSImpl;
import com.wiseweb.ws.interceptor.CheckUserInterceptor;

public class ServetTest2 {

	public static void main(String[] args) {
		String address = "http://10.211.55.3:8888/day01_ws/hellows" ;
		Endpoint endpoint = Endpoint.publish(address, new HelloWSImpl()) ;
		EndpointImpl endpointImpl = (EndpointImpl) endpoint ;
		
		List<Interceptor<? extends Message>> inInterceptors = endpointImpl.getInInterceptors() ;
		inInterceptors.add(new CheckUserInterceptor()) ;
		
		System.out.println("发布webservice成功!");
	}
}


Client:

通过构造方法传入要比较的用户名和密码:

package com.wiseweb.client.interceptor;

import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

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.Document;
import org.w3c.dom.Element;

public class AddUserInterceptor extends AbstractPhaseInterceptor<SoapMessage>{

	private String username ;
	private String password ;
	
	public AddUserInterceptor(String username, String password) {
		super(Phase.PRE_PROTOCOL);
		this.username = username ;
		this.password = password ;
	}

	@Override
	public void handleMessage(SoapMessage message) throws Fault {
		List<Header> headers = message.getHeaders() ;
		
		DocumentBuilder builder = null ;
		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		Document document = builder.newDocument() ;
		Element root = document.createElement("wiseweb") ;
		Element username = document.createElement("username") ;
		username.setTextContent(this.username);
		Element password = document.createElement("password") ;
		password.setTextContent(this.password);
		root.appendChild(username) ;
		root.appendChild(password) ;
		headers.add(new Header(new QName("wiseweb"), root)) ;
	}

}

ClientTest:

package com.wiseweb.client;

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;

import com.wiseweb.client.interceptor.AddUserInterceptor;
import com.wiseweb.ws.HelloWS;
import com.wiseweb.ws.HelloWSImplService;

public class ClientTest2 {

	public static void main(String[] args) {
		HelloWSImplService helloWSImplService = new HelloWSImplService() ;
		HelloWS helloWS = helloWSImplService.getHelloWSImplPort() ;
		
		Client client = ClientProxy.getClient(helloWS) ;
		List<Interceptor<? extends Message>> outInterceptors = client.getOutInterceptors() ;
		outInterceptors.add(new AddUserInterceptor("benjamin", "123456")) ;
		
		String result = helloWS.sayHello("benjaminwhx") ;
		System.out.println(result);
		
	}
}

运行结果Server和Client比较:

Server:

发布webservice成功!
用户名与密码正确,通过验证!
server sayHello():benjaminwhx


Client:

Hello: benjaminwhx


如果输入的用户名和密码不正确,运行结果为:

Server:

org.apache.cxf.interceptor.Fault: 请输入正确的用户名和密码!
	at com.wiseweb.ws.interceptor.CheckUserInterceptor.handleMessage(CheckUserInterceptor.java:29)
	at com.wiseweb.ws.interceptor.CheckUserInterceptor.handleMessage(CheckUserInterceptor.java:1)
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
	at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:122)
	at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.serviceRequest(JettyHTTPDestination.java:348)
	at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:312)
	at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:72)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:943)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:879)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:117)
	at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:250)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:110)
	at org.eclipse.jetty.server.Server.handle(Server.java:349)
	at org.eclipse.jetty.server.HttpConnection.handleRequest(HttpConnection.java:441)
	at org.eclipse.jetty.server.HttpConnection$RequestHandler.content(HttpConnection.java:936)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:801)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:224)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:51)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:586)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:44)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:598)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:533)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.RuntimeException: 请输入正确的用户名和密码!
	... 23 more


Client:

Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: 请输入正确的用户名和密码!
	at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
	at com.sun.proxy.$Proxy25.sayHello(Unknown Source)
	at com.wiseweb.client.ClientTest2.main(ClientTest2.java:26)
Caused by: org.apache.cxf.binding.soap.SoapFault: 请输入正确的用户名和密码!
	at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.unmarshalFault(Soap11FaultInInterceptor.java:75)
	at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:46)
	at org.apache.cxf.binding.soap.interceptor.Soap11FaultInInterceptor.handleMessage(Soap11FaultInInterceptor.java:35)
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
	at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:114)
	at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:69)
	at org.apache.cxf.binding.soap.interceptor.CheckFaultInterceptor.handleMessage(CheckFaultInterceptor.java:34)
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
	at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:801)
	at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1679)
	at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1517)
	at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1425)
	at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
	at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:650)
	at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
	at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
	at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:462)
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:365)
	at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:318)
	at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:95)
	at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
	... 2 more

这样就可以有效的验证访客的身份。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。