Hessian 与 Session

Hessian 与 Session

 

作者:终南   <li.zhongnan@hotmail.com>

 

 

1. ServiceContext

ServiceContext 代表为 Hessian 客户端提供服务的上下文环境,用来处理与客户端请求有关的信息。在最简单和常用的应用中,在服务器端可以通过 ServiceContext 来获取代表客户端的 ServletRequest (在 HTTP 环境中为 HttpServletRequest),因此就可以知道客户端的相关信息,如客户端的 IP 地址、端口、Header和用户名等,重要的是可以获取到代表会话的 Session 对象。

代码举例:
package example;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.caucho.services.server.ServiceContext;

public class BasicService implements Basic {
public String hello(String name) {
   System.out.println("======== hello ========/n");
   HttpServletRequest req = (HttpServletRequest) ServiceContext
     .getContextRequest();
   req.getSession().setAttribute("port", 1000);

   System.out.println("getRemoteAddr() = " + req.getRemoteAddr());
   System.out.println("getRemotePort() = " + req.getRemotePort());
   System.out.println("getRemoteUser() = " + req.getRemoteUser());
   System.out
     .println("getSession().getId() = " + req.getSession().getId());
   for (Enumeration<String> e = req.getHeaderNames(); e.hasMoreElements();) {
    String headerName = e.nextElement();
    System.out.println(headerName + " = " + req.getHeader(headerName));

   }

   return "Hello, " + name;
}
}

在上面的示例中,通过 ServiceContext 的静态方法 getContextRequest() 获取代表客户端请求的 HttpServletRequest 对象,然后就可以像普通 Web 编程那样使用 Request 和 Session 对象了。

2. Hessian 中 Sessian 的问题

一般来说,RPC 或 Web Service 这类的应用都是无状态的,但是有些应用则需要有状态的远程调用,比如先登录认证,然后再执行其他操作。
Hessian 本身也没有对有状态的应用提供直接支持。查看 HessianProxy 的代码可以发现,每次发送请求的时候,Hessain 都会调用 HessianProxyFactory 类的 openConnection 重新打开连接,并且在远程调用完成后关闭连接。

重新打开连接
protected URLConnection sendRequest(String methodName, Object []args)
    throws IOException
{
    URLConnection conn = null;
   
    conn = _factory.openConnection(_url);
    boolean isValid = false;

    try {
      // Used chunked mode when available, i.e. JDK 1.5.
      if (_factory.isChunkedPost() && conn instanceof HttpURLConnection) {
try {
   HttpURLConnection httpConn = (HttpURLConnection) conn;

   httpConn.setChunkedStreamingMode(8 * 1024);
} catch (Throwable e) {
}
      }
   
      addRequestHeaders(conn);

      OutputStream os = null;

      try {
os = conn.getOutputStream();
      } catch (Exception e) {
throw new HessianRuntimeException(e);
      }

      if (log.isLoggable(Level.FINEST)) {
PrintWriter dbg = new PrintWriter(new LogWriter(log));
os = new HessianDebugOutputStream(os, dbg);
      }
     
      AbstractHessianOutput out = _factory.getHessianOutput(os);

      out.call(methodName, args);
      out.flush();

      isValid = true;

      return conn;
    } finally {
      if (! isValid && conn instanceof HttpURLConnection)
((HttpURLConnection) conn).disconnect();
    }
}

关闭连接
public Object invoke(Object proxy, Method method, Object []args)
    throws Throwable
{
...
     
      conn = sendRequest(mangleName, args);

      if (conn instanceof HttpURLConnection) {
httpConn = (HttpURLConnection) conn;
        int code = 500;

        try {
          code = httpConn.getResponseCode();
        } catch (Exception e) {
        }

        parseResponseHeaders(conn);
    ...
       
      try {
if (httpConn != null)
   httpConn.disconnect();
      } catch (Exception e) {
log.log(Level.FINE, e.toString(), e);
      }
    }
}

在登录认证的应用中,在调用登录认证的方法后执行其他业务操作时,需要对用户是否登录进行验证,由于 Hessian 每次调用都会重新打开和关闭连接,因此每次调用都是一个新的 Session,前面是否登录的信息就不能获取到。

3. 扩展 Hessian 的客户端程序实现对 Sessian 的支持

HTTP 是一个无状态的协议,其状态的实现是通过 Cookie 来实现的,根据 HTTP 的这个特点,我们可以在 Hessian 客户端首次调用后的每次调用中,将首次调用得到的 Cookie 添加到 HTTP Header 中,从而模拟出有状态的 HTTP 连接。
通过查看 HessianProxy 类的代码发现,其中有两个没有实现内容方法,可以获取服务器端返回的头信息 和设置发送给服务器端的 HTTP 请求头信息:

/**
   * Method that allows subclasses to parse response headers such as cookies.
   * Default implementation is empty.
   * @param conn
   */
protected void parseResponseHeaders(URLConnection conn) {
  
}

/**
   * Method that allows subclasses to add request headers such as cookies.
   * Default implementation is empty.
   */
protected void addRequestHeaders(URLConnection conn) {
  
}

在使用 Hessian 进行远程调用时,addRequestHeaders 方法在 sendRequest 时调用,parseResponseHeaders 在成功发送请求后调用。因此我们可以扩展 HessianProxy 类,重新实现这两个方法,在首次调用时获取 Cookie 新,在随后的调用中 将 Cookie 添加到请求头信息中。
除了重新实现 HessianProxy 类外,还需要重新实现 HessianProxyFactory 类的 public Object create(Class api, String urlName, ClassLoader loader) 方法,以便让 HessianProxyFactory 使用重新实现的 HessianProxy 类。

重新实现的代码:
package example;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;

import com.caucho.hessian.client.HessianProxy;
import com.caucho.hessian.client.HessianProxyFactory;
import com.caucho.hessian.io.HessianRemoteObject;

public class MyHessianProxyFactory extends HessianProxyFactory {

@Override
public Object create(Class api, String urlName, ClassLoader loader)
    throws MalformedURLException {
   if (api == null)
    throw new NullPointerException(
      "api must not be null for HessianProxyFactory.create()");
   InvocationHandler handler = null;

   URL url = new URL(urlName);
   handler = new MyHessianProxy(url, this);

   return Proxy.newProxyInstance(loader, new Class[] { api,
     HessianRemoteObject.class }, handler);
}
}

class MyHessianProxy extends HessianProxy {
/** Variable for saving cookie list */
private List<String> cookies = null;

public MyHessianProxy(URL url, HessianProxyFactory factory) {
   super(url, factory);
}

/** Get cookie list from the headers of response */
@Override
protected void parseResponseHeaders(URLConnection conn) {
   List<String> _cookies = conn.getHeaderFields().get("Set-Cookie");
   if (_cookies != null)
    cookies = _cookies;
}

/** Add cookie list to request headers*/
@Override
protected void addRequestHeaders(URLConnection conn) {
   if (cookies != null) {
    for (String cookieString : cookies) {
     conn.setRequestProperty("Cookie", cookieString);
    }
   }
}

}

4. 应用举例
接口:
package example;

import java.util.List;

public interface Basic {

public boolean login(String user, String password);
public int giveMeMoney();
public void increaseMyMoney() throws Exception;
}

实现接口的服务:
package example;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import com.caucho.services.server.ServiceContext;

public class BasicService implements Basic {

public boolean login(String user, String password) {
   HttpServletRequest req = (HttpServletRequest) ServiceContext
   .getContextRequest();
   if (user.equals("user") && password.equals("password"))
   {
    req.getSession().setAttribute("user", user);
    return true;   
   }
   return false;
}
public int giveMeMoney()
{
   HttpServletRequest req = (HttpServletRequest) ServiceContext
   .getContextRequest();
   if(req.getSession().getAttribute("user") != null)
    return 1000;
   return 0;  
}
public void increaseMyMoney() throws Exception
{
   HttpServletRequest req = (HttpServletRequest) ServiceContext
   .getContextRequest();
   if(req.getSession().getAttribute("user") != null)
   {
    System.out.println(req.getSession().getAttribute("user") + "'s money increased!!!");
   }
   else
    throw new Exception("Invalid User");
   
}
}

客户端程序:
package example;
import java.net.MalformedURLException;

import com.caucho.hessian.client.HessianProxyFactory;

public class BasicClient {
public static void main(String []args) throws MalformedURLException
{
    String url = "
http://127.0.0.1:8080/hproj/hello";

    HessianProxyFactory factory = new MyHessianProxyFactory();
    factory.setUser("tomcat");
    factory.setPassword("tomcat");
    Basic basic = (Basic) factory.create(Basic.class, url);

    try {
   basic.increaseMyMoney();
} catch (Exception e) {
     System.out.println("ERROR: " + e.getMessage());
}
    basic.login("user", "password");
    System.out.println(basic.giveMeMoney());
    try {
   basic.increaseMyMoney();
} catch (Exception e) {
     System.out.println("ERROR: " + e.getMessage());
}   
}
}

在客户端程序中,不在使用原来的 HessianProxyFactory, 而是使用重新实现的 MyHessianProxyFactory 类。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Hessian矩阵是多元函数极值判定的重要工具。对于一个具有n个变量的多元函数f(x1, x2, ... , xn),Hessian矩阵是一个n×n的矩阵,其元素为二阶偏导数。Hessian矩阵的定义如下: Hessian矩阵的第i行第j列元素,即Hessian矩阵的第(i, j)元素,表示函数f对第i个变量x_i和第j个变量x_j的混合偏导数。 多元函数的极值可能出现在驻点 (critical point)或者临界点 (boundary point)上,通过Hessian矩阵可以判断一个驻点的极值类型。具体的判断方法如下: 1. 首先,计算函数f的一阶偏导数,求出所有的驻点。 2. 对于每个驻点,计算Hessian矩阵。 3. 判断Hessian矩阵的正定性(positive definite)、负定性(negative definite)、不定性(indefinite)或者半定性(positive semi-definite和negative semi-definite)。 - 如果Hessian矩阵在驻点处是正定的,则该点为函数的极小值点; - 如果Hessian矩阵在驻点处是负定的,则该点为函数的极大值点; - 如果Hessian矩阵在驻点处是不定的,则该点既不是极小值点也不是极大值点; - 如果Hessian矩阵在驻点处是半定的,则需要进一步分析。 4. 进一步分析半定性的情况。 - 如果Hessian矩阵在驻点处是半正定的,则该点可能是函数的极小值点,也可能是鞍点; - 如果Hessian矩阵在驻点处是半负定的,则该点可能是函数的极大值点,也可能是鞍点; - 如果Hessian矩阵在驻点处即半正定又半负定,则该点既可能是函数的极小值点又可能是极大值点。 通过以上步骤,我们可以利用Hessian矩阵来判断多元函数的驻点的极值类型,从而找到函数的极值点。需要注意的是,Hessian矩阵为对称矩阵,而且其元素的值与函数的表达式有关,要根据具体问题进行计算,以得到准确的极值判定结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值