hessianでSessionを使用する問題について
このスレッドはhessianのsessionやcookieの問題を議論することを目的としており、hessianの使用ネットや公式には多くの例があるため、ここでは議論しない.
最近1つのプロジェクトをして、clientは多種のプラットフォームの携帯電話のクライアントとpcブラウザのflashに直面して、rpcの方案を探す過程の中で、最初はphprpcを使うことを選んで、phprpcはObjective-cのclientバージョン(Hproseはこの版があるが、有料のようだ)がなくて、後でhessianに乗り換えて、hessianの使用の過程の中で発見して、hessianのclientはcookieのメカニズムをサポートしないで、さらに、そのserver側は共有セッションをサポートしていない.すなわち、hessianはhttpプロトコルを使用しており、clientの実装はcookieをサポートしていないため、clientはserverの呼び出しのたびに新しいセッションを確立するが、呼び出すたびにjsessionidやuseridのようなパラメータが固定されていると、不快に見えるようになる.ネット上で1篇の招待状があることを見ますhttp://qieqie.iteye.com/blog/82492httpプロトコル層でaopを使用して使用者に対して透明な増加と剥離というパラメータを使用する人を見て、私はやはり不快に思っています.私のサービスエンドアーキテクチャでは、クラスタスキームが決定されているので、クラスタのsessionに対してmemcached-session-managerを使用する準備ができています.これにより、標準的なhttpセッションを使用してアーキテクチャを変更する必要があります.
仕方なく、hessianを拡張することにしました(私は4.0.7を使っています)、その間にネット上の達人が以前のバージョンを修正したhessianを見たことがあります(貼るのを参照).http://hi.baidu.com/li_zhongnan/blog/item/37fe8ffaefe9ad17a9d31153.html)という方法で試してみるとまだクッキーが使えないことに気づき、その後、元のHessianProxyのparseResponseHeadersメソッドが廃棄されていることに気づき、ソースコードをめくってみると、HessianURLConnection(このクラスは古いhessianにはないかもしれません)に新しいparseResponseHeadersメソッドがあることに気づき、拡張が始まり、ソースコードを変更しないために自分で新しいプロジェクトを作りました.そして基礎工事として私のclientに引用されて、ここで私は核心部分のclassコードだけを貼って、興味のある友达はこの基礎の上で更に改善することができます:
コードのcookiesがstaticを使用しているのは、早起きしたIEブラウザがプロセスごとに新しいsessionを開くメカニズムではなく、clientが共通のsessionを使用することを主に考慮しているからです.
クライアント呼び出しの例:
変更後、サーバ側でrequestおよびsessionを取得するには、次のコードを使用します.
しかし問題はまた来て、私はテストの時に発見して、このようなrequestとsessionを取得する方法はhessianが持っているHessianServiceを使ってサービスの発表を行うだけで、spring mvcとspringのHessianServiceExporterを使ってhessianのサービスの発表を行うならば、このようなrequestとsessionを取得する方法は依然として利用できません.Spring 3のソースコードを見て驚いたことに、HessianServiceExporterおよびHessianExporterの実装では、hessianのservletのようにServiceContext.beginやServiceContext.end()メソッドを呼び出すことはありません.springはhessianのソースコードやapiをよく見ています.また、springは開発者にservletコンテナ関連のrequestやsessionなどのインスタンスを手に入れたくないということです.しかし、いずれにしても、私はこのようなニーズを持っていて、springのHessianServiceExporterを拡張しました(3以前のバージョンの実装は少し違いがあるかもしれません):
spring mvcのservletプロファイルは次のとおりです.
これでspringを使用してhessianサービスをパブリッシュしても、ServiceContextでコンテキストのrequestなどの情報を取得できます.
以上はhessian clientに対してもspringのhessianパッケージに対しても増分拡張のみを行う.
最近1つのプロジェクトをして、clientは多種のプラットフォームの携帯電話のクライアントとpcブラウザのflashに直面して、rpcの方案を探す過程の中で、最初はphprpcを使うことを選んで、phprpcはObjective-cのclientバージョン(Hproseはこの版があるが、有料のようだ)がなくて、後でhessianに乗り換えて、hessianの使用の過程の中で発見して、hessianのclientはcookieのメカニズムをサポートしないで、さらに、そのserver側は共有セッションをサポートしていない.すなわち、hessianはhttpプロトコルを使用しており、clientの実装はcookieをサポートしていないため、clientはserverの呼び出しのたびに新しいセッションを確立するが、呼び出すたびにjsessionidやuseridのようなパラメータが固定されていると、不快に見えるようになる.ネット上で1篇の招待状があることを見ますhttp://qieqie.iteye.com/blog/82492httpプロトコル層でaopを使用して使用者に対して透明な増加と剥離というパラメータを使用する人を見て、私はやはり不快に思っています.私のサービスエンドアーキテクチャでは、クラスタスキームが決定されているので、クラスタのsessionに対してmemcached-session-managerを使用する準備ができています.これにより、標準的なhttpセッションを使用してアーキテクチャを変更する必要があります.
仕方なく、hessianを拡張することにしました(私は4.0.7を使っています)、その間にネット上の達人が以前のバージョンを修正したhessianを見たことがあります(貼るのを参照).http://hi.baidu.com/li_zhongnan/blog/item/37fe8ffaefe9ad17a9d31153.html)という方法で試してみるとまだクッキーが使えないことに気づき、その後、元のHessianProxyのparseResponseHeadersメソッドが廃棄されていることに気づき、ソースコードをめくってみると、HessianURLConnection(このクラスは古いhessianにはないかもしれません)に新しいparseResponseHeadersメソッドがあることに気づき、拡張が始まり、ソースコードを変更しないために自分で新しいプロジェクトを作りました.そして基礎工事として私のclientに引用されて、ここで私は核心部分のclassコードだけを貼って、興味のある友达はこの基礎の上で更に改善することができます:
package com.caucho.hessian.client;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
/**
*
*
* @author liliang
* @descirption session cookie
*/
public class CookieHessianURLConnection extends HessianURLConnection {
/**
* @description cookie
*/
private static List<String> cookies = null;
CookieHessianURLConnection(URL url, URLConnection conn) {
super(url, conn);
}
@Override
protected void parseResponseHeaders(HttpURLConnection conn)
throws IOException {
super.parseResponseHeaders(conn);
List<String> _cookies = conn.getHeaderFields().get("Set-Cookie");
if (_cookies != null)
cookies = _cookies;
}
public void addRequestHeaders() {
if (cookies != null) {
for (String cookieString : cookies) {
addHeader("Cookie", cookieString);
}
}
}
}
package com.caucho.hessian.client;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
*
*
* @author liliang
* @descirption CookieHessianURLConnection
* open HessianURLConnectionFactory
*/
public class CookieHessianURLConnectionFactory extends
AbstractHessianConnectionFactory {
private static final Logger log = Logger
.getLogger(CookieHessianURLConnectionFactory.class.getName());
@Override
public HessianConnection open(URL url) throws IOException {
if (log.isLoggable(Level.FINER))
log.finer(this + " open(" + url + ")");
URLConnection conn = url.openConnection();
// HttpURLConnection httpConn = (HttpURLConnection) conn;
// httpConn.setRequestMethod("POST");
// conn.setDoInput(true);
long connectTimeout = getHessianProxyFactory().getConnectTimeout();
if (connectTimeout >= 0)
conn.setConnectTimeout((int) connectTimeout);
conn.setDoOutput(true);
long readTimeout = getHessianProxyFactory().getReadTimeout();
if (readTimeout > 0) {
try {
conn.setReadTimeout((int) readTimeout);
} catch (Throwable e) {
}
}
/*
* // Used chunked mode when available, i.e. JDK 1.5. if
* (_proxyFactory.isChunkedPost() && conn instanceof HttpURLConnection)
* { try { HttpURLConnection httpConn = (HttpURLConnection) conn;
*
* httpConn.setChunkedStreamingMode(8 * 1024); } catch (Throwable e) { }
* }
*/
return new CookieHessianURLConnection(url, conn);
}
}
public class MyHessianProxy extends HessianProxy {
public MyHessianProxy(URL url, HessianProxyFactory factory, Class<?> api) {
super(url, factory, api);
}
/** Add cookie list to request headers */
@Override
protected void addRequestHeaders(HessianConnection conn) {
super.addRequestHeaders(conn);
if(conn instanceof CookieHessianURLConnection) {
CookieHessianURLConnection connection = (CookieHessianURLConnection)conn;
connection.addRequestHeaders();
}
}
}
package com.mostar.common.hessian;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.URL;
import com.caucho.hessian.client.HessianProxyFactory;
import com.caucho.hessian.io.HessianRemoteObject;
public class MyHessianProxyFactory extends HessianProxyFactory {
@Override
public Object create(Class<?> api, URL url, ClassLoader loader) {
if (api == null)
throw new NullPointerException(
"api must not be null for HessianProxyFactory.create()");
InvocationHandler handler = null;
handler = new MyHessianProxy(url, this, api);
return Proxy.newProxyInstance(loader, new Class[] { api,
HessianRemoteObject.class }, handler);
}
}
コードのcookiesがstaticを使用しているのは、早起きしたIEブラウザがプロセスごとに新しいsessionを開くメカニズムではなく、clientが共通のsessionを使用することを主に考慮しているからです.
クライアント呼び出しの例:
//
System.setProperty(HessianConnectionFactory.class.getName(),
CookieHessianURLConnectionFactory.class.getName());
String url = "http://10.0.8.1:8080/test/hello.service";
MyHessianProxyFactory factory = new MyHessianProxyFactory();
IHellowordService hellowordService = (IHellowordService) factory
.create(IHellowordService.class, url);
System.out.println(hellowordService.sayHello("myname"));
変更後、サーバ側でrequestおよびsessionを取得するには、次のコードを使用します.
HttpServletRequest req = (HttpServletRequest) ServiceContext
.getContextRequest();
req.getSession();
しかし問題はまた来て、私はテストの時に発見して、このようなrequestとsessionを取得する方法はhessianが持っているHessianServiceを使ってサービスの発表を行うだけで、spring mvcとspringのHessianServiceExporterを使ってhessianのサービスの発表を行うならば、このようなrequestとsessionを取得する方法は依然として利用できません.Spring 3のソースコードを見て驚いたことに、HessianServiceExporterおよびHessianExporterの実装では、hessianのservletのようにServiceContext.beginやServiceContext.end()メソッドを呼び出すことはありません.springはhessianのソースコードやapiをよく見ています.また、springは開発者にservletコンテナ関連のrequestやsessionなどのインスタンスを手に入れたくないということです.しかし、いずれにしても、私はこのようなニーズを持っていて、springのHessianServiceExporterを拡張しました(3以前のバージョンの実装は少し違いがあるかもしれません):
/**
*
*
* @author liliang
* @descirption spring HessianServiceExporter , service httpRequest
*/
public class HessianServiceContextExporter extends HessianServiceExporter {
@Override
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
//
String serviceId = request.getPathInfo();
String objectId = request.getParameter("id");
if (objectId == null)
objectId = request.getParameter("ejbid");
ServiceContext.begin(request, serviceId, objectId);
// spring
super.handleRequest(request, response);
} finally {
ServiceContext.end();
}
}
}
spring mvcのservletプロファイルは次のとおりです.
<bean name="/hello.service"
class="org.springframework.remoting.caucho.HessianServiceContextExporter">
<property name="service" ref="hellowordService" />
<property name="serviceInterface"
value="com.mostar.sng.service.sample.IHellowordService" />
</bean>
これでspringを使用してhessianサービスをパブリッシュしても、ServiceContextでコンテキストのrequestなどの情報を取得できます.
以上はhessian clientに対してもspringのhessianパッケージに対しても増分拡張のみを行う.