说说cxf中的拦截器,可以分为系统拦截器(如日志拦截器)和自定义拦截器,也可以分为出拦截器和入拦截器,也可以分为服务器拦截器和客户端拦截器。
下面将实现一个可以进行登陆验证的拦截器,其中用户名作为方法参数传递,密码放在发送给服务器的xml的header中。
服务端
代码结构如下:
ValidUser:
applicationContext
CXFServices
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws"xmlns:soap="http://cxf.apache.org/bindings/soap"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ?????????????http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd ?????????????http://cxf.apache.org/bindings/soap http://cxf.apache.org/schemas/configuration/soap.xsd"><!-- 1.使用jaxws:endpoint标签的配置发布一个 webservice 2.用implementor属性配置服务提供实现类 3.address属性配置外部访问的相对路径 4.使用 jaxws:inInterceptors 标签配置2个日志拦截器,用来打印调用时的日志信息 5.注意:在此配置文件中,需加入jaxws与soap命名空间 --><!-- <import resource="classpath*:META-INF/cxf/cxf.xml" /> <import resource="classpath*:META-INF/cxf/cxf-extension-soap.xml" /> ?<import resource="classpath*:META-INF/cxf/cxf-servlet.xml" /> --><bean id="jaxWsServiceFactoryBean" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean"><property name="wrapped" value="true" /></bean><jaxws:endpoint id="loginCheckService"implementor="login.check.ws.impl.LoginCheck" address="/loginCheck"><jaxws:inInterceptors><bean id="inLoggingInterceptor" class="org.apache.cxf.interceptor.LoggingInInterceptor" /><bean id="outLoggingInterceptor" class="org.apache.cxf.interceptor.LoggingOutInterceptor" /><bean id="loginCheckInterceptor" class="login.check.ws.impl.LoginCheck" /></jaxws:inInterceptors><jaxws:serviceFactory><ref bean="jaxWsServiceFactoryBean" /></jaxws:serviceFactory></jaxws:endpoint></beans> ?
web.xml文件
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> ??<display-name>logincheckws</display-name> ??<welcome-file-list> ????<welcome-file>index.html</welcome-file> ????<welcome-file>index.htm</welcome-file> ????<welcome-file>index.jsp</welcome-file> ????<welcome-file>default.html</welcome-file> ????<welcome-file>default.htm</welcome-file> ????<welcome-file>default.jsp</welcome-file> ??</welcome-file-list> ????<!-- 加入spring --> ????<context-param> ??????<param-name>contextConfigLocation</param-name> ??????<param-value>classpath:applicationContext*.xml</param-value> ????</context-param> ????<listener> ?????<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> ????</listener> ?????<!-- 加入CXF支持 --> ????<servlet> ?????????<description>Apache CXF Endpoint</description> ?????????<display-name>cxf</display-name> ?????????<servlet-name>cxf</servlet-name> ?????????<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class> ?????????<load-on-startup>1</load-on-startup> ?????</servlet> ?????<servlet-mapping> ?????????<servlet-name>cxf</servlet-name> ?????????<url-pattern>/services/*</url-pattern> ?????</servlet-mapping> ???</web-app>
LoginCheck:继承了AbstractPhaseInterceptor,实现了handleMessage方法,用来从客户端发来soap消息头中获取密码,并会保存在ThreadLocal变量中,供校验用户时使用。
package login.check.ws.impl;import java.util.List;import javax.jws.WebService;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;import login.check.constant.ValidUser;import login.check.ws.interf.ILoginCheck;@WebService(endpointInterface="login.check.ws.interf.ILoginCheck", targetNamespace="http://login.check.ws")public class LoginCheck extends AbstractPhaseInterceptor<SoapMessage> implements ILoginCheck{private static final ThreadLocal<String> passwords = new ThreadLocal<>();public LoginCheck() {super(Phase.PRE_PROTOCOL);}@Overridepublic boolean checkUser(String username) {return ValidUser.validUser.get(username).equals(passwords.get());}@Overridepublic void handleMessage(SoapMessage message) throws Fault {List<Header> headers = message.getHeaders();if(headers == null || headers.size() == 0){throw new Fault(new RuntimeException("无密码信息"));}Element passwordEle = null;for(Header header: headers){QName qName = header.getName();String nameSpace = qName.getNamespaceURI();String tagName = qName.getLocalPart();if(nameSpace != null && nameSpace.equals("http://login.check.ws.password") && tagName != null){passwordEle = (Element)header.getObject();break;}}if(null == passwordEle){throw new Fault(new RuntimeException("无密码信息"));}NodeList passwordList = passwordEle.getElementsByTagName("password");if(passwordList == null || passwordList.getLength() != 1){throw new Fault(new RuntimeException("密码信息错误"));}passwords.set(passwordList.item(0).getTextContent());}}
客户端
首先是生成客户端代码,在此不在赘述,
然后自定义一个拦截器,向soap消息头中写入密码信息,这里密码的获取也用到的ThreadLocal变量,在测试类中将密码存入ThreadLocal变量中,然后在拦截器中就可以获取到密码了。
拦截器代码如下:
package login.check.ws.client;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;import login.check.ws.test.LoginTest;public class PasswordInterceptor extends AbstractPhaseInterceptor<SoapMessage> {public PasswordInterceptor() {super(Phase.PREPARE_SEND);}@Overridepublic void handleMessage(SoapMessage message) throws Fault {List<Header> headers = message.getHeaders();Document doc = DOMUtils.createDocument();Element passwordNS = doc.createElementNS("http://login.check.ws.password", "loginCheck");Element password = doc.createElement("password");password.setTextContent(LoginTest.password.get());passwordNS.appendChild(password);headers.add(new Header(new QName("loginCheck"), passwordNS));}}
测试代码如下:
使用了三个拦截器并将密码存入了ThreadLocal中,
测试结果如下:
代码地址:https://files.cnblogs.com/files/liunianfeiyu/logincheckwebservice.rar
webserive学习记录5-拦截器完成登陆校验
原文地址:https://www.cnblogs.com/liunianfeiyu/p/8399382.html