我的收获:
平时基于Web开发动态网页时浏览器帮我们做了关于Session的很多工作,使得我们可能不是很理解客户端和服务器端对于Session究竟是如何管理的,在不基于浏览器的Web开发中,对于Session的管理需要在客户端自己处理,主要为获取Http请求返回的SessionID(如果在服务器端创建了Session),并在下次请求的时候带上这个SessionID,服务器端才能知道是同一个会话,从而可以取得服务器上该Session的信息。
以下内容是在学习过程中摘自网上一位大神的博客(http://lanyerzz.blog.163.com/blog/static/927350720117893254375/),思路清晰,讲解到位,最后为本人修改其代码后跑通的样例。
--------------------------------------------------------------------------------------------------------------------
服务端的session管理依赖 客户端 cookie
cookie中保存有sessionid信息 例如:JSESSIONID=BEE4AE5877D573CE774701566E93477B
原理:
当客户端第一次通过http访问服务端的时候,cookie 中的 sessionid 是空的,服务器就会创建新的session,service并把session信息(JSESSIONID)通过header 返回给客户端。
当客户端再次访问service的时候,http请求的header中存有 上次service创建的sessionid信息,service在session管理器中查找对应sessionid的session,如果找到(说明session未过期),服务端不会创建新的session。
如果未找到(说明session过期),服务端会创建新的session。
cxf:
因为cxf客户端每次访问service后,虽然服务端会把sessionid返回给客户端,但是cxf再次访问的时候,并不会把这个sessionid信息通过cookie传给服务端。因此服务端会对客户端的每次访问都会创建新的session。
如果客户端的访问过多,频率很高,会导致服务端的session未及时释放,内存溢出。
通常的做法是 把服务端的session 的timeout 设置的更短,保证session 及时释放。
让cxf客户端记住sessionid:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.handler.MessageContext;
import org.apache.cxf.jaxws.handler.logical.LogicalMessageContextImpl;
public class SessionLogicalHandler implements
LogicalHandler<LogicalMessageContext> {
public SessionLogicalHandler() {
super();
}
// 静态 所有的 SessionLogicalHandler 共享 一个 cookie
public static List<String> http_headers_cookie = null;
@Override
public boolean handleMessage(LogicalMessageContext context) {
// TODO Auto-generated method stub
// javax.xml.ws.handler.MessageContext.Scope s=
// context.getScope(MessageContext.HTTP_REQUEST_HEADERS);
// Set-Cookie=[JSESSIONID=48B10A68BB05F69F8ED82A33F566C5D8; Path=/myapp;
// HttpOnly]
LogicalMessageContextImpl c = (LogicalMessageContextImpl) context;
// response 时记录服务端返回的session信息
if (c.get(MessageContext.HTTP_RESPONSE_HEADERS) != null) {
Map<String, List> header = (Map<String, List>) c
.get(MessageContext.HTTP_RESPONSE_HEADERS);
List<String> ls = header.get("Set-Cookie");// 获取header 中cookie的信息
if (ls != null) {
System.out.println(ls.get(0).split(";")[0]);
this.http_headers_cookie = ls;// 保存cookie信息
}
} else if (c.get(MessageContext.HTTP_REQUEST_HEADERS) != null
&& http_headers_cookie != null) {// request 请求的时候 把cookie信息设置进去
Map<String, List> header = (Map<String, List>) c
.get(MessageContext.HTTP_REQUEST_HEADERS);
header.put("cookie", http_headers_cookie);
} else if (c.get(MessageContext.HTTP_REQUEST_HEADERS) == null
&& http_headers_cookie != null) {// request 请求的时候 把cookie信息设置进去
Map<String, List> header = new HashMap<String, List>();
header.put("cookie", http_headers_cookie);
c.put(MessageContext.HTTP_REQUEST_HEADERS, header);
}
return true;
}
@Override
public boolean handleFault(LogicalMessageContext context) {
// TODO Auto-generated method stub
return false;
}
@Override
public void close(MessageContext context) {
// TODO Auto-generated method stub
}
}
设置handler:
import java.util.HashMap;
import java.util.Map;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.apache.cxf.transport.http.HTTPConduit;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import com.cfets.fxo.u.wsp.ws.IWsServerInfo;
public class WsClassLoader {
// 本地
private static String WS_HOST = "http://localhost:8080/fxoption/ws";
private JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
private WsClassLoader() {
}
private static WsClassLoader instance;
public static synchronized WsClassLoader getInstance() {
if (instance == null) {
instance = new WsClassLoader();
// 设置 handler
instance.factory.getHandlers().add(new SessionLogicalHandler());
}
return instance;
}
private Map<String, Object> wsCache = new HashMap<String, Object>();
@SuppressWarnings("unchecked")
public <T> T getWs(String address, Class<T> t) {
if (wsCache.get(t.getName()) == null) {
factory.setServiceClass(t);
String addressFull = WS_HOST + address;
factory.setAddress(addressFull);
Object client = factory.create();
// /开始超时设置
Client proxy = ClientProxy.getClient(client);
// proxy.get().add(new LogicalLoggingHandler());
HTTPConduit conduit = (HTTPConduit) proxy.getConduit();
HTTPClientPolicy policy = new HTTPClientPolicy();
policy.setConnectionTimeout(3000);
policy.setReceiveTimeout(0);
conduit.setClient(policy);
// /结束超时设置
wsCache.put(t.getName(), client);
}
return (T) wsCache.get(t.getName());
}
public static void main(String[] args) {
IWsServerInfo client = (IWsServerInfo) WsClassLoader.getInstance()
.getWs("/serverinfo", IWsServerInfo.class);
client.setSessionInfo();
String sessionInfo = client.getSessionInfo();
System.out.println(sessionInfo);
}
}