在JAX-WS 中实现多个Service间会话保持( 1 )
笔者前言:笔者是想着用CXF来开发点东西的,没想到比AXIS2的会话管理曲折那么多。可能是笔者对基本的规范和协议不甚了解吧。以下部分转贴,代码基本是笔者改写的。即使如此,笔者认为还是标题为转贴内容吧。 一。前言
二。服务器端代码
package com.zx.cxf.service; import java.util.Date; import java.util.List; import javax.jws.WebParam; import javax.jws.WebService; //注解生命此为WEBSERVICE @WebService public interface HelloWorld { //接受HTTP传过来的参数TEXT为这个方法的参数值 String sayHi(@WebParam(name = "text") String text); Date curDate(); List<Long> addNumber(@WebParam(name = "addToNum") Long num); }
package com.zx.cxf.service; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.annotation.Resource; import javax.jws.WebMethod; import javax.jws.WebParam; import javax.jws.WebService; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.xml.ws.WebServiceContext; import javax.xml.ws.handler.MessageContext; import org.apache.cxf.transport.http.AbstractHTTPDestination; import org.springframework.beans.factory.annotation.Autowired; @WebService(endpointInterface = "com.zx.cxf.service.HelloWorld",serviceName = "HelloWorld") public class HelloWorldImpl implements HelloWorld { private List<Long> localNumbers; //通过注解,自动注入如下需要用到的变量(没用到setter方法哦.不过没错误) @Resource private WebServiceContext context; private HttpServletRequest request; //通过注解,声明定义一些列WEBSERVICE的东西.笔者忘记怎么说了,详细调查后补上 @WebMethod(operationName="sayHello",action="hello") public String sayHi(@WebParam(name = "text") String text) { //获得MessageContext上下文,在WEBSERVICE中,是用这个上下文的. MessageContext ctx = context.getMessageContext(); /*HttpServletRequest request = (HttpServletRequest) ctx.get(AbstractHTTPDestination.HTTP_REQUEST);*/ //获得HTTP的SESSION HttpSession session =((javax.servlet.http.HttpServletRequest)ctx.get(MessageContext.SERVLET_REQUEST)).getSession(); //这只是一个统计变量 Integer count = (Integer)session.getAttribute("count"); String change = null; /** * 判断客户端是第几次访问,用以测试SESSIONID究竟有没改变. * 这是配合客户端中,对多个SERVICE中保持会话状态的测试. * 这2种测试,在客户端代码中会注解说明. */ if(count == null){ session.setAttribute("count",1); }else{ count++; if(count >= 2) change = "你是第二次访问了"; } //HttpSession session = request.getSession(); return "Hello " + text + "sessionID: "+session.getId()+" "+change; } @WebMethod(exclude=true) public Date curDate() { return new Date(); } public List<Long> addNumber(@WebParam(name = "addToNum") Long num) { if (localNumbers == null) { localNumbers = new ArrayList<Long>(); } localNumbers.add(num); return localNumbers; } public void setRequest(HttpServletRequest request){ this.request = request; } } 2.3补发SPRING的配置代码 <?xml version="1.0" encoding="UTF-8"?> <!-- START SNIPPET: beans --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jaxws="http://cxf.apache.org/jaxws" 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"> <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 class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/> <bean id="serverPasswordCallback" class="cxf.server.ServerPasswordCallback" /> <!--<jaxws:endpoint id="helloWorld" implementor="com.zx.cxf.service.HelloWorldImpl" address="/HelloWorld" > --> <jaxws:endpoint id="helloWorld" address="/HelloWorld" > <jaxws:implementor> <bean class="com.zx.cxf.service.HelloWorldImpl"></bean> </jaxws:implementor> <!--<jaxws:inInterceptors> <bean class="org.apache.cxf.interceptor.LoggingInInterceptor" /> SAAJInInterceptor只在CXF是2.0.X版本时或之前版本时才是必须的 <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor"/> <bean class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor"> <constructor-arg> <map> <entry key="action" value="UsernameToken" /> <entry key="passwordType" value="PasswordText" /> <entry key="user" value="FHDServer" /> <entry key="passwordCallbackRef"> <ref bean="serverPasswordCallback" /> </entry> </map> </constructor-arg> </bean> </jaxws:inInterceptors> --></jaxws:endpoint> </beans> <!-- END SNIPPET: beans --> 三。客户端代码
package clients; import java.net.URL; import java.util.List; import javax.xml.namespace.QName; import javax.xml.ws.Binding; import javax.xml.ws.BindingProvider; import javax.xml.ws.handler.Handler; import com.zx.cxf.handle.Myhandle; import com.zx.cxf.service.HelloWorld; import com.zx.cxf.service.HelloWorld_Service; public class TestHello { private static final QName SERVICE_NAME = new QName("http://service.cxf.zx.com/","HelloWorld"); public static final Myhandle handler = new Myhandle(); /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { URL wsdlURL = HelloWorld_Service.WSDL_LOCATION; HelloWorld_Service ss = new HelloWorld_Service(wsdlURL,SERVICE_NAME); HelloWorld port = ss.getHelloWorldImplPort(); //这是使用BindingProvider设置在此次访问中,对于SESSION进行保留 ((BindingProvider)port).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,true); //((BindingProvider)port).getRequestContext().put("thread.local.request.context",true); //测试会发现2此的打印的SESSIONID都是一样的,如果不是用以上BindingProvider的话,SESSIONID是不一样的。 //因为客户端对于WEB SERVICE访问,没特殊设置每次的访问都是新访问,服务器都会建立新的会话。 ?System.out.println(port.sayHi("sonx")); Thread.currentThread().sleep(3000); System.out.println(port.sayHi("sonx")); } }
package com.zx.cxf.handle; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.xml.namespace.QName; import javax.xml.ws.handler.MessageContext; import javax.xml.ws.handler.soap.SOAPHandler; import javax.xml.ws.handler.soap.SOAPMessageContext; public class Myhandle implements SOAPHandler<SOAPMessageContext> { private List cookie = null; public Set<QName> getHeaders() { // TODO Auto-generated method stub return null; } public void close(MessageContext context) { // TODO Auto-generated method stub } public boolean handleFault(SOAPMessageContext context) { // TODO Auto-generated method stub return false; } public boolean handleMessage(SOAPMessageContext context) { try { //获得当前调用方向 Boolean out = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); if(!out){//响应 Map<String,List<String>> responseHeaders = (Map<String,List<String>>) context.get(MessageContext.HTTP_RESPONSE_HEADERS); List<String> c = responseHeaders.get("Set-cookie"); //sessionid在该域中 if(cookie==null && c!=null){ //这是第一次HTTP调用,cookie刚刚得到 cookie = c; //保存该cookie }else{ System.out.println("DEBUG: 现在不是第一个调用HTTP了.因此COOKIE早已存在."); } }else{ //请求 //获取请求上下文 java.util.Map<String,List<String>> requestHeaders = (Map<String,List<String>>) context.get(MessageContext.HTTP_REQUEST_HEADERS); if(requestHeaders==null){ //请求上下文可能为空,构造一个新的即可 requestHeaders = new HashMap<String,List<String>>(); //将一个空的请求上下文设置到SOAPMessageContext中 context.put(MessageContext.HTTP_REQUEST_HEADERS,requestHeaders); //设置该请求上下文全局有效 context.setScope(MessageContext.HTTP_REQUEST_HEADERS,MessageContext.Scope.APPLICATION); } //如果已经获得了sessionid,将该sessionid设置到请求上下文中即可 if(cookie!=null){ requestHeaders.put("cookie",cookie); } } } catch (Exception e) { e.printStackTrace(); } return true;//返回true,意味着其它Handler也可以被调用 } }
package clients; import java.net.URL; import java.util.List; import javax.xml.namespace.QName; import javax.xml.ws.Binding; import javax.xml.ws.BindingProvider; import javax.xml.ws.handler.Handler; import com.zx.cxf.handle.Myhandle; import com.zx.cxf.service.HelloWorld; import com.zx.cxf.service.HelloWorld_Service; public class TestHello { private static final QName SERVICE_NAME = new QName("http://service.cxf.zx.com/",SERVICE_NAME); HelloWorld port = ss.getHelloWorldImplPort(); //((BindingProvider)port).getRequestContext().put(BindingProvider.SESSION_MAINTAIN_PROPERTY,true); //调用到了我们之前声明的HANDLER了哦。实现多个SERVICE间的会话保持。 Binding binding = ((BindingProvider) port).getBinding(); List<Handler> handlerList = binding.getHandlerChain();//获得Handler链 if (!handlerList.contains(handler)) {//防止重复插入Handler handlerList.add(handler); binding.setHandlerChain(handlerList); } System.out.println(port.sayHi("sonx")); Thread.currentThread().sleep(3000); System.out.println(port.sayHi("sonx")); } } 四。笔者后言
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |