hession简单模拟

闲来无事,自己手动写写代码,如有错误不必深究,哈哈……

hession的实现:
1、业务接口
2、业务实现,继承HessianServlet
3、服务端配置HessianServlet
4、客户端调用利用HessianProxyFactory的create方法根据接口创建代理类

我的简单实现:
1、业务接口
2、业务实现类,类中方法最好抛出个Exception,方便客户端接受异常信息
3、服务端配置实现了自己的业务逻辑的servlet,继承自AbstractServiceSrv
4、客户端调用利用ProxyFactory的create方法根据接口创建代理类
5、简单的单点登录

简单模拟hession代理类:

/*
* @(#)ProxyHandler.java
* Copyright (c) 2011 TravelSky Technology Ltd. All Right Reserved.
*/
package com.common.handler;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream;

import com.common.model.CommonReq;
import com.common.model.CommonResp;
/**
* @author yangxu
* @email yangxu_email@163.com
* @QQ 435214753
* @describe hessian简单模拟
*/
public class ProxyFactory implements InvocationHandler {
/**
*
*/
protected static Logger log = Logger.getLogger(ProxyFactory.class.getName());
/**
*
*/
private String serviceUrl;
/**
* 连接超时时间
*/
private int connectTimeout = 3000;
/**
* 读取超时时间
*/
private int readTimeout = 3000;
/**
*
*/
private String sessionId;
/**
*
*/
private boolean login = false;

/**
* 创建代理类
* @param api
* @param serviceUrl
* @return
*/
public Object create(Class> api, String serviceUrl) {
this.serviceUrl = serviceUrl;
return Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(), new Class[] { api }, this);
}

/*
* (non-Javadoc)
*
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
return process(proxy, method, args);
}

/**
* 请求处理
* @param proxy
* @param method
* @param args
* @return
* @throws Exception
*/
public Object process(Object proxy, Method method, Object[] args)
throws Exception {
String apiName = proxy.getClass().getInterfaces()[0].getName();
String methodName = method.getName();
Object result = null;
try {
HttpURLConnection conn = this.openConnection();
if (sessionId != null && sessionId!="") {
conn.setRequestProperty("Cookie", sessionId);
}
this.sendRequest(conn, apiName, methodName, args);

conn.connect();

CommonResp resp = this.getCommonResp(conn.getInputStream());

String cookie = conn.getHeaderField("Set-Cookie");
if (cookie != null && cookie != "") {
sessionId = cookie;
log.info("cookie:" + cookie);
}

result = resp.getRespobject();

conn.disconnect();

} catch (Exception e) {
log.info(e.getMessage());
throw e;
}
return result;
}

/**
* 获取HttpURLConnection连接
* @return
* @throws IOException
*/
private HttpURLConnection openConnection() throws IOException {
URL url = new URL(serviceUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setAllowUserInteraction(true);
conn.setConnectTimeout(connectTimeout);
conn.setDefaultUseCaches(false);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setReadTimeout(readTimeout);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-java-serialized-object");
conn.setUseCaches(false);
conn.setDefaultAllowUserInteraction(true);
return conn;
}

/**
* 获取返回值
*
* @param in
* @return
* @throws Exception
*/
private CommonResp getCommonResp(InputStream in) throws Exception {
GZIPInputStream gzip = new GZIPInputStream(in);
ObjectInputStream objin = new ObjectInputStream(gzip);
CommonResp resp = (CommonResp) objin.readObject();
if (resp.getException() != null) {
throw resp.getException();
}
return resp;
}

/**
* 发送请求
* @param conn
* @param apiName
* @param methodName
* @param args
* @throws IOException
*/
private void sendRequest(HttpURLConnection conn, String apiName,
String methodName, Object[] args) throws IOException {
ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream());
CommonReq req = new CommonReq();
req.setServicename(apiName);
req.setMethodname(methodName);
req.setParams(args);
if(login) req.setRequestType(CommonReq.REQ_TYPE_LOGIN);
out.writeObject(req);
out.flush();
out.close();
}

/**
* @return the login
*/
public boolean isLogin() {
return login;
}

/**
* @param login the login to set
*/
public void setLogin(boolean login) {
this.login = login;
}
/**
* @return the sessionId
*/
public String getSessionId() {
return sessionId;
}

/**
* @param sessionId
* the sessionId to set
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}

/**
* @return the connectTimeout
*/
public int getConnectTimeout() {
return connectTimeout;
}

/**
* @param connectTimeout
* the connectTimeout to set
*/
public void setConnectTimeout(int connectTimeout) {
this.connectTimeout = connectTimeout;
}

/**
* @return the readTimeout
*/
public long getReadTimeout() {
return readTimeout;
}

/**
* @param readTimeout
* the readTimeout to set
*/
public void setReadTimeout(int readTimeout) {
this.readTimeout = readTimeout;
}
}



服务端需要配置的servlet的基类:

/*
* @(#)AbstractServiceSrv.java
* Copyright (c) 2011 TravelSky Technology Ltd. All Right Reserved.
*/
package com.common;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.log4j.Logger;

import com.common.model.CommonReq;
import com.common.model.CommonResp;

/**
* @author yangxu
* @email yangxu_email@163.com
* @QQ 435214753
*/
public abstract class AbstractServiceSrv extends HttpServlet {
/**
*
*/
private static Logger logger = Logger.getLogger(AbstractServiceSrv.class);
/**
*
*/
public static final String SERVICE_SRV_USER = "ServiceSrvUser";
/**
*
*/
private static final long serialVersionUID = 5342831535532910596L;

/* (non-Javadoc)
* @see javax.servlet.GenericServlet#init()
*/
@Override
public void init() throws ServletException {
// TODO Auto-generated method stub
super.init();
}
/**
* Destruction of the servlet. <br>
*/
public void destroy() {
super.destroy();
}
/**
*
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}

/**
*
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
process(request, response);
}
/**
*
* @param request
* @param response
* @throws ServletException
* @throws IOException
*/
private void process(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

ObjectInputStream objIn = new ObjectInputStream(request.getInputStream());
CommonResp resp = new CommonResp();
try {
CommonReq reqObject = (CommonReq) objIn.readObject();

//登陆
if(reqObject.getRequestType().equals(CommonReq.REQ_TYPE_LOGIN)){
//登陆
resp = loginProcess(request, reqObject);
}else{
resp = normalProcess(request, reqObject);
}

sendResp(response,resp);

} catch (Exception e) {
logger.error("", e);
resp.setErrormsg(e.getMessage());
resp.setErrorflag(true);
resp.setException(e);
sendResp(response,resp);
}
}
/**
* 以GZIP格式发送返回的序列化对象
* @param response
* @param resp
* @throws IOException
*/
private void sendResp(HttpServletResponse response,CommonResp resp) throws IOException{
GZIPOutputStream gzip = new GZIPOutputStream(response
.getOutputStream());
ObjectOutputStream objout = new ObjectOutputStream(gzip);
objout.writeObject(resp);
objout.flush();
objout.close();
}
/**
* 用户登录
* @param request
* @param req
* @return
*/
private CommonResp loginProcess(HttpServletRequest request,CommonReq req) {
HttpSession session = request.getSession(true);
CommonResp resp = invokeResp(req.getServicename(),req.getMethodname(),req.getParams());
Object obj = resp.getRespobject();
if(obj != null){
session.setAttribute(AbstractServiceSrv.SERVICE_SRV_USER, obj);
resp.setSessionId(session.getId());
}
return resp;
}
/**
* 普通请求
* @param request
* @param req
* @return
*/
private CommonResp normalProcess(HttpServletRequest request,CommonReq req) {
HttpSession session = request.getSession(true);
CommonResp resp = new CommonResp();
if(!authUser(session,req,resp)){
return resp;
}
return invokeResp(req.getServicename(),req.getMethodname(),req.getParams());
}
/**
* 权限验证
* @param session
* @return
*/
private boolean authUser(HttpSession session,CommonReq req,CommonResp resp){
boolean flag = false;
Object sessionUser = session.getAttribute(SERVICE_SRV_USER);
if(sessionUser!=null){
flag = authUserProcess(sessionUser,req,resp);
}else{
resp.setErrorflag(true);
resp.setErrormsg("用户未登录或登录超时");
resp.setException(new Exception("用户未登录或登录超时"));
}
return flag;
}

/**
*
* @param serviceName
* @param methodName
* @param params
* @param resp
* @return
*/
private CommonResp invokeResp(String serviceName,String methodName, Object[] params){
CommonResp resp = new CommonResp();
try {
Object obj = invoke(serviceName,methodName,params);
resp.setRespobject(obj);
} catch (Exception e) {
logger.error(e.getMessage(), e);
resp.setErrorflag(true);
resp.setErrormsg(e.getCause().getMessage());
resp.setException(new Exception(e.getCause().getMessage()));
}
return resp;
}

/**
* 用户权限验证
* @param sessionUser
* @param resp
* @return
*/
protected abstract boolean authUserProcess(Object sessionUser,CommonReq req,CommonResp resp);
/**
* 执行本地方法
* @param serviceName
* @param methodName
* @param params
* @return
*/
protected abstract Object invoke(String serviceName,String methodName, Object[] params) throws Exception;

}



自己封装的请求对象:

/*
* @(#)CommonReq.java
* Copyright (c) 2011 TravelSky Technology Ltd. All Right Reserved.
*/
package com.common.model;

import java.io.Serializable;

/**
* @author yangxu
* @email yangxu_email@163.com
* @QQ 435214753
* @describe 封装的请求对象
*/
public class CommonReq implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8383278004624449271L;

public static final String REQ_TYPE_LOGIN = "req_type_login";

public static final String REQ_TYPE_NORMAL = "req_type_normal";

//uiservice中方法名
private String methodname ;

//uiservice名
private String servicename ;

//参数对象数组
private Object params[] ;

//请求类型
private String requestType = REQ_TYPE_NORMAL;

/**
* @return the methodname
*/
public String getMethodname() {
return methodname;
}

/**
* @param methodname the methodname to set
*/
public void setMethodname(String methodname) {
this.methodname = methodname;
}

/**
* @return the servicename
*/
public String getServicename() {
return servicename;
}

/**
* @param servicename the servicename to set
*/
public void setServicename(String servicename) {
this.servicename = servicename;
}

/**
* @return the params
*/
public Object[] getParams() {
return params;
}

/**
* @param params the params to set
*/
public void setParams(Object[] params) {
this.params = params;
}

/**
* @return the requestType
*/
public String getRequestType() {
return requestType;
}

/**
* REQ_TYPE_LOGIN:登陆
* REQ_TYPE_NORMAL:普通请求
* @param requestType the requestType to set
*/
public void setRequestType(String requestType) {
this.requestType = requestType;
}
}




自己封装的返回对象:

/*
* @(#)CommonResp.java
* Copyright (c) 2011 TravelSky Technology Ltd. All Right Reserved.
*/
package com.common.model;

import java.io.Serializable;

/**
* @author yangxu
* @email yangxu_email@163.com
* @QQ 435214753
* @describe 封装的返回对象
*/
public class CommonResp implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8896807549053453795L;

private boolean errorflag;

private Object respobject;

private String errormsg;

private Exception exception;

private String sessionId;
/**
* @return the sessionId
*/
public String getSessionId() {
return sessionId;
}

/**
* @param sessionId the sessionId to set
*/
public void setSessionId(String sessionId) {
this.sessionId = sessionId;
}

/**
* @return the errorflag
*/
public boolean isErrorflag() {
return errorflag;
}

/**
* @param errorflag
* the errorflag to set
*/
public void setErrorflag(boolean errorflag) {
this.errorflag = errorflag;
}

/**
* @return the respobject
*/
public Object getRespobject() {
return respobject;
}

/**
* @param respobject
* the respobject to set
*/
public void setRespobject(Object respobject) {
this.respobject = respobject;
}

/**
* @return the errormsg
*/
public String getErrormsg() {
return errormsg;
}

/**
* @param errormsg
* the errormsg to set
*/
public void setErrormsg(String errormsg) {
this.errormsg = errormsg;
}

/**
* @return the exception
*/
public Exception getException() {
return exception;
}

/**
* @param exception
* the exception to set
*/
public void setException(Exception exception) {
this.exception = exception;
}
}



继承自AbstractServiceSrv,自己的业务逻辑servlet,需要在web.xml中配置


/*
* @(#)ServiceSrv.java
* Copyright (c) 2011 TravelSky Technology Ltd. All Right Reserved.
*/
package com.serverlet;

import javax.servlet.ServletException;
import org.apache.log4j.Logger;
import com.common.AbstractServiceSrv;
import com.common.model.CommonReq;
import com.common.model.CommonResp;
import com.model.User;
import com.serverlet.context.ServiceContext;

/**
* @author yangxu
* @email yangxu_email@163.com
* @QQ 435214753
*/
public class ServiceSrv extends AbstractServiceSrv {
/**
*
*/
private static Logger logger = Logger.getLogger(ServiceSrv.class);

/**
*
*/
private static final long serialVersionUID = -8722444565736070073L;

/* (non-Javadoc)
* @see com.common.AbstractServiceSrv#authUserProcess(java.lang.Object, com.common.CommonResp)
*/
@Override
public boolean authUserProcess(Object sessionUser, CommonReq req, CommonResp resp) {
boolean flag = false;

User user = (User)sessionUser;
logger.info("ServiceSrv--------user.getName():"+user.getName()+"------user.getPassword():"+user.getPassword());

//TODO 自己的权限验证逻辑
/*
* 可以将req中的user对象与session中的对象比对,也可以验证user是否有某种权限
*/
//TODO 自己的校验逻辑
if(true){
flag = true;
}else{
/*
* 将错误信息放入CommonResp对象中
* resp.setErrorflag(errorflag);
* resp.setErrormsg(errormsg);
* resp.setException(exception);
*/
flag= false;
}

return flag;
}

/* (non-Javadoc)
* @see com.common.AbstractServiceSrv#invoke(java.lang.String, java.lang.String, java.lang.Object[])
*/
@Override
protected Object invoke(String serviceName, String methodName,
Object[] params) throws Exception {
return ServiceContext.invoke(serviceName, methodName, params);
}

/* (non-Javadoc)
* @see com.common.AbstractServiceSrv#init()
*/
@Override
public void init() throws ServletException {
ServiceContext.initService();
}

}




服务端调用接口的简单实现

/*
* @(#)ServerContext.java
* Copyright (c) 2011 TravelSky Technology Ltd. All Right Reserved.
*/
package com.serverlet.context;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.common.model.ServiceVO;

/**
* @author yangxu
* @email yangxu_email@163.com
* @QQ 435214753
*/
public class ServiceContext{

public static ConcurrentHashMap<String,Object> serviceMap= new ConcurrentHashMap<String,Object>();

private static Logger logger = Logger.getLogger(ServiceContext.class);
/**
* 初始化配置文件,测试用,实现不全
*/
public static void initService(){
SAXReader reader = new SAXReader();
logger.info("=========initService start=========");
try {
Document doc = reader.read(ServiceContext.class.getResource("/service-config.xml"));
Element services = doc.getRootElement();

for (Iterator<Element> i = services.elementIterator(); i.hasNext();) {
Element e = (Element)i.next();
String name = e.attributeValue("name");
String type = e.attributeValue("type");
Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass(type);
//组装ServiceVO
ServiceVO serviceVO = new ServiceVO();
serviceVO.setServiceObj(cls.newInstance());
Method[] methods = cls.getMethods();
Map<String,Method> methodMap = new HashMap<String,Method>();
//TODO 可以根据 获取method的name,判断是否为set方法,模拟注入
//TODO 方法重载暂时没有处理,如有相同名称不同参数的method会出问题
for(Method method:methods){
methodMap.put(method.getName(), method);
}
serviceVO.setMethodMap(methodMap);
serviceMap.put(name, serviceVO);
}
logger.info("=========initService end=========");
}catch(Exception e){
logger.error("系统初始化失败", e);
}
}
/**
* 如果结合spring的话,可以将此处修改成调用spring中配置的uiservice
* @param serviceName
* @param methodName
* @param parms
* @return
* @throws Exception
*/
public static Object invoke(String serviceName,String methodName,Object[] parms) throws Exception{
if(serviceMap.containsKey(serviceName)){
ServiceVO serviceVO = (ServiceVO)serviceMap.get(serviceName);
Object service = serviceVO.getServiceObj();
Map<String,Method> methodMap = serviceVO.getMethodMap();
if(methodMap.containsKey(methodName)){
return methodMap.get(methodName).invoke(service, parms);
}
}
return null;
}
}



模拟时用到的配置service-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<services>
<service name="com.dao.UserManager" type="com.dao.UserManagerImp"></service>
</services>



测试用例:

/*
* @(#)ProxyTest.java
* Copyright (c) 2011 TravelSky Technology Ltd. All Right Reserved.
*/
package com.test;

import java.net.SocketTimeoutException;

import junit.framework.TestCase;

import com.common.handler.ProxyFactory;
import com.dao.UserManager;
import com.model.User;


/**
* @author yangxu
* @email yangxu_email@163.com
* @QQ 435214753
*/
public class ProxyTest extends TestCase{

/**
* @param args
*/

public void TestLogin(){
String serviceURL = "http://localhost:8090/CallServerHandler/serverContext.srv";
ProxyFactory factory = new ProxyFactory();
factory.setConnectTimeout(1000);
factory.setReadTimeout(1000);
factory.setLogin(true);
UserManager mgr = (UserManager)factory.create(UserManager.class,serviceURL);
try {
User user = mgr.login("yangxu", "myPassword");
System.out.println("SessionId:"+factory.getSessionId());
}catch(SocketTimeoutException e){
System.out.println("==========="+e.getMessage()+"===========");
e.printStackTrace();
}catch (Exception e) {
System.out.println("==========="+e.getMessage()+"===========");
e.printStackTrace();
}
}

public void TestNormal(){
String serviceURL = "http://localhost:8090/CallServerHandler/serverContext.srv";
ProxyFactory factory = new ProxyFactory();
factory.setConnectTimeout(1000);
factory.setReadTimeout(1000);
//将第一个测试用例打印出的sessionId拷贝至此处
factory.setSessionId("JSESSIONID=1AA028B88FD00BED43CD95DDDB5CA451; Path=/CallServerHandler");
UserManager mgr = (UserManager)factory.create(UserManager.class,serviceURL);
User user = null;
try {
user = (User)mgr.findUserById("asdsa");
}catch(SocketTimeoutException e){
System.out.println("==========="+e.getMessage()+"===========");
e.printStackTrace();
}catch (Exception e) {
System.out.println("==========="+e.getMessage()+"===========");
e.printStackTrace();
}
System.out.println(user.getName()+" "+user.getPassword());
}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值