同在一个产业链园区的XX厂因为5台Window2003服务器收到了律师函并且被迫下了12万$的采购单,虽然100万对XXX厂来数不是大数目,但是总有种被打劫的感觉。

在企业ERP应用中服务层一般都是做成远程调用的,具体Windows平台的技术有WebService,WCF,Remoting等,这里展示的是服务端采用linux 平台下采用Hessian组件实现RPC.

服务端:
Web服务器:JBoss,tomcat (weblogic挺美但是不免费啊)
数据库:mysql(一般erp都用oracle做数据库,当然那个啥费用也是不含糊地)
客户端:
逆天的XP(sp3) 加.net4.0 (NND,这个组合量你也收不了多少钱把!)
VS2010? 我们用180试用版或者那啥notepad

Hessian+spring配置
1.web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<display-name>HessianTest</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:conf/ht-core.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>hessionRpc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:conf/ht-rpc.xml</param-value>
</init-param>
<load-on-startup></load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>hessionRpc</servlet-name>
<url-pattern>/rpc/*</url-pattern>
</servlet-mapping> <servlet>
<description></description>
<display-name>TestSpring</display-name>
<servlet-name>TestSpring</servlet-name>
<servlet-class>f.studio.web.servlet.TestSpring</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TestSpring</servlet-name>
<url-pattern>/TestSpring</url-pattern>
</servlet-mapping>
<filter>
<display-name>HessianCtxFilter</display-name>
<filter-name>HessianCtxFilter</filter-name>
<filter-class>f.studio.web.filter.HessianCtxFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HessianCtxFilter</filter-name>
<url-pattern>/rpc/*</url-pattern>
</filter-mapping> <welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

2.Service,DAO等spring配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean name="studentServiceImpl"
class="f.studio.service.impl.StudentServiceImpl" scope="prototype" />
</beans>

3.Hessian导出层spring配置,因为一个项目里可能使用strut2,Servlet,cxf等服务提供层,但是他们需要共用Service,DAO等
参考:http://jinnianshilongnian.iteye.com/blog/1602617

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd"> <bean name="/studentServiceRpc"
class="org.springframework.remoting.caucho.HessianServiceExporter">
<property name="service" ref="studentServiceImpl" />
<property name="serviceInterface" value="f.studio.service.StudentService" />
</bean> </beans>

用户登陆状态问题
Hessian的C#实现可以自己保存cookie,并且是全局的(应用程序范围)
服务端尝试使用Hessian提供的ServiceContext获取对Session的引用但是结果总为null,所以写个filter 来自己维护用户登陆Session供Service实现类使用

package f.studio.web.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import f.studio.util.HessianCtxContainer; /**
* Servlet Filter implementation class HessianCtxFilter
*/
public class HessianCtxFilter implements Filter { public static final String LOGIN_SESSION_KEY="LOGIN_USER_KEY";
/**
* Default constructor.
*/
public HessianCtxFilter() {
// TODO Auto-generated constructor stub
} /**
* @see Filter#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
} /**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpSession session = ((HttpServletRequest) request).getSession(true);
System.out.println("sessionId:" + session.getId());
try { Object user = session.getAttribute(LOGIN_SESSION_KEY);
HessianCtxContainer.setAttribute(LOGIN_SESSION_KEY, user);
System.out.println("sessionUser:" + user);
chain.doFilter(request, response); } finally {
//移除掉ThreadLocal中Map中的对象防止益出
//session具备自动移动除功能
//不要在环境下(cxf,strut2等)使用HessionCtxContainer,避免线程重用时造成混乱
Object user = HessianCtxContainer.remove(LOGIN_SESSION_KEY);
session.setAttribute(LOGIN_SESSION_KEY, user);
} } /**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException {
// TODO Auto-generated method stub
} }

服务实现类:

package f.studio.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List; import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession; import org.omg.PortableInterceptor.USER_EXCEPTION; import com.caucho.hessian.io.Hessian2Output;
import com.caucho.services.server.ServiceContext; import f.studio.domain.Klass;
import f.studio.domain.QueryStudentInfo;
import f.studio.domain.StudentInfo;
import f.studio.service.StudentService;
import f.studio.util.HessianCtxContainer;
import f.studio.web.filter.HessianCtxFilter; public class StudentServiceImpl implements StudentService { public List<StudentInfo> query(QueryStudentInfo q) { CheckLogin(); ServletRequest request= ServiceContext.getContextRequest();
System.out.println(ServiceContext.getServiceName());
//HttpSession session= request.getSession(true);
//session.setAttribute("User", new Date()); System.out.println("ServiceImpHashCode:" + this.hashCode());
System.out.println(q);
//if(1==1)throw new RuntimeException("运行错误信息啊");
List<StudentInfo> list=new ArrayList<StudentInfo>();
Klass klass=new Klass();
klass.setId(9999);
klass.setName("张老师");
klass.setAddTime(new Date()); for(int i=0;i<10;i++){
StudentInfo s=new StudentInfo(); //===父类
s.setRecId(88888);
s.setCreateDate(new Date());
//==
s.setId(i);
s.setName("张思念" + i);
s.setSex(i % 5 ==0);
//===添加两个元素==
s.getKs().add(klass);
s.getKs().add(klass); list.add(s);
}
return list;
} public String hello(String name) {
return "Hi " +name;
} public void Login(String username, String password) {
if("Admin".equals(username) && "123".equals(password)){
HessianCtxContainer.setAttribute(HessianCtxFilter.LOGIN_SESSION_KEY , username);
return;
}
throw new RuntimeException("错误的用户名或密码!");
} public static void CheckLogin(){ if(HessianCtxContainer.getAttribute(HessianCtxFilter.LOGIN_SESSION_KEY)==null){
throw new RuntimeException("未登录或登录超时!");
}
}
}

.net客户端,需要添加对hessianCsharp.dll的引用
调用一次Login后,再执行其他调用

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using hessiancsharp.client; namespace HessianTest
{
using f.studio.domain;
using System.Threading;
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
} private void button1_Click(object sender, EventArgs e)
{
try
{
CHessianProxyFactory factory = new CHessianProxyFactory("userName", "password");
string url = "http://localhost/HessianTest/rpc/studentServiceRpc";//修改为你的server端地址
StudentService test = (StudentService)factory.Create(typeof(StudentService), url);
string result = test.hello("大白鲨");
var q = new QueryStudentInfo() { BTime = DateTime.Now, Name = "哈哈", Id = , Sex = false };
q.Data = new byte[] { , , , , };
q.CreateDate = DateTime.Now;
q.RecId = ; var list = test.query(q);
foreach (var it in list)
{
Console.WriteLine(it);
}
Console.WriteLine(result);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
} } private void button5_Click(object sender, EventArgs e)
{
try
{
CHessianProxyFactory factory = new CHessianProxyFactory("userName", "password");
string url = "http://localhost/HessianTest/rpc/studentServiceRpc";//修改为你的server端地址
StudentService test = (StudentService)factory.Create(typeof(StudentService), url);
test.Login("Admin", ""); Console.WriteLine("登陆成功");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
} public interface StudentService
{
string hello(string name);
List<StudentInfo> query(QueryStudentInfo q);
void Login(String usename, String password);
} } namespace f.studio.domain
{
public class BaseInfo
{
private DateTime? createDate; public DateTime? CreateDate
{
get { return createDate; }
set { createDate = value; }
}
private long? recId; public long? RecId
{
get { return recId; }
set { recId = value; }
}
}
/// <summary>
/// 上传时用需要保持命名空间与服务器一致
/// </summary>
public class QueryStudentInfo :BaseInfo
{
private int id;
private String name;
private DateTime? btime;
private Byte[] data;
private bool sex; public int Id
{
get { return id; }
set { id = value; } }
public DateTime? BTime
{
get { return btime; }
set { btime = value; }
}
public string Name
{
get { return name; }
set { name = value; }
}
public Byte[] Data
{
get { return data; }
set { data = value; }
}
public bool Sex
{
get { return sex; }
set { sex = value; }
}
} /// <summary>
/// 不能使用public int Id{get;set;}
/// private 字段名称,大小写需要跟服务端定义一致
/// [Serializable]标记貌似不是必须的
/// </summary>
public class Klass :BaseInfo
{
private int id;
private String name;
private DateTime? addTime; public DateTime? AddTime
{
get { return addTime; }
set { addTime = value; }
}
public string Name
{
get { return name; }
set { name = value; }
} public int Id
{
get { return id; }
set { id = value; }
} } public class StudentInfo :BaseInfo
{
private string name;
private bool? sex;
private long id;
private byte[] fileData; public byte[] FileData
{
get { return fileData; }
set { fileData = value; }
}
private List<Klass> ks; public List<Klass> Ks
{
get { return ks; }
set { ks = value; }
} public string Name
{
get { return name; }
set { name = value; }
} public long Id
{
get { return id; }
set { id = value; }
} public bool? Sex
{
get { return sex; }
set { sex = value; }
}
public override string ToString()
{
return string.Format("Id:{0},Name:{1},Sex:{2},RecId:{3},CreateDate:{4}", Id, Name, Sex,RecId,CreateDate);
} }
}

完成服务端代码下载

跟微软保持适当距离--Hessian + .net 实现RPC体系的企业应用的更多相关文章

  1. Hessian 源码简单分析

    Hessian 是一个rpc框架, 我们需要先写一个服务端, 然后在客户端远程的调用它即可. 服务端: 服务端通常和spring 做集成. 首先写一个接口: public interface Hell ...

  2. 我看微软收购GitHub

    今天是微软收购GitHub的第三天,之前很多人担心被微软收购的GitHub会步Skype,诺基亚等企业的后尘,凡此种种我觉得更多人的担心是:GitHub不再开源免费罢了. GitHub今年4月刚成立十 ...

  3. 纳德拉再造微软:市值如何重回第一阵营(思维确实变了,不再是以windows为中心,拥抱其它各种平台,敢在主战场之外找到适合自己的新战场)

    有人说,现在的美国硅谷充满了“咖喱味”.也有人说,硅谷已经变成“印度谷”.原因就在于,以微软CEO萨提亚·纳德拉.谷歌CEO桑达尔·皮查伊为代表的印度人,近年以来掌控了全世界最令人望而生畏的科技巨头. ...

  4. WPF路线图白皮书: 2015及未来

    介绍 当2006年微软首次推出Windows Presentation Foundation(WPF)时,它代表了应用程序的设计和开发又向前跨出了巨大的一步.它简化了GUI应用程序的开发,有助于UI和 ...

  5. 华人曾与IBM抗衡! 盘点已远去的IT巨头(转)

    [PConline资讯 ]从算盘到计算器,从大型机到个人PC,再到当今火热的移动终端和云计算,人类计算史已经走过了千年之久,现代IT计算领域也经过了百年浮沉.在世界工业领域,IT技术应该是诞生时间最短 ...

  6. Facebook人工智能实验室的前世今生

    Facebook人工智能实验室的前世今生 是时候停止把Facebook当作纯粹的社交媒体公司来看了.它用无人机提供互联网服务,为了发展虚拟现实而收购Oculus,不懈追求人工智能,Facebook已经 ...

  7. 公司管理系列--Facebook是如何营造企业文化的[转]

      本文讲下硅谷创业公司的文化,去过硅谷公司或者是看过硅谷公司报道的人,都会惊讶硅谷创业公司里面有如此奇特且活力十足的文化.在中国,企业文化是一个被滥用但是却又缺乏解读的概念,很多国内企业对保持公司的 ...

  8. 微软和Google的盈利模式对比分析

    一: 微软和Google是世界上最成功科技巨头之一,但他们之间却有着不同的产品和业务,二者的盈利方式也各有不同,本文将分析和探讨的二者盈利模式的异同. 微软的盈利模式 在1975年由大学肄业的Bill ...

  9. Java 技术栈

    JAVA是一个面向对象的编程语言,由SUN公司的程序员所开发.它不仅吸收了C++的各种优点,而且还撇弃了C++中难以理解的概念,如多继承.指针等:因此JAVA语言具有功能强大且简单易用两个特征, JA ...

随机推荐

  1. git推送报错: No path specified. See 'man git-pull' for valid url syntax或does not appear to be a git repository以及remote: error: insufficient permission for adding an object to repository databa

    本地(windows)代码想推送到linux自己搭建的git服务端,第一步是建立本地与服务端的关联,第二步是本地推送到服务端. 第一步需要看你的本地工程是否从git上clone来的,如果是clone来 ...

  2. Mysql的“Table 'mysql.servers' doesn't exist”的解决方法

    安装MYSQL后,又一次系统出现问题了,于是我查看mysql的错误日志,竟发现Table 'mysql.servers' doesn't exist问题的错误, 虽然与我的问题无关,但这个问题还是引起 ...

  3. [C++ Primer] 第6章: 函数

    参数传递 const形参和实参: 顶层const作用于对象本身, 和其他初始化过程一样, 当用实参初始化形参时会忽略掉顶层const, 换句话说, 形参顶层const被忽略掉了, 当形参有顶层cons ...

  4. JpGraph使用详解

    微信平台开发的推广支持应用里,为了满足用户渠道推广分析的需要,公众平台提供了生成带参数二维码的接口.使用该接口可以获得多个带不同场景值的二维码,用户扫描后,公众号可以接收到事件推送,借此可以通过统计不 ...

  5. SQL2008如何清空压缩数据库日志

    SQL2008如何清空压缩数据库日志 编写人:左丘文 2015-4-10 近期在给一系统初始化资料时,不断的导入导出,因此一不小心,就将数据的SQL(sql2008R2)的是日志档弄得比数据库还大,给 ...

  6. Makefile编写 三 伪目标的作用

    本节我们讨论一个Makefile中的一个重要的特殊目标:伪目标. 伪目标是这样一个目标:它不代表一个真正的文件名,在执行make时可以指定这个目标来执行其所在规则定义的命令,有时我们也可以将一个伪目标 ...

  7. ASI接口

    Asynchronous Serial Interface ,异步串行接口,用于传送码流的一个标准DVB接口. 在目前的DVB-C系统设备的传输接口有两种MPEG2视频码流传输接口标准:异步串行接口A ...

  8. memcached内存管理机制分析

    memached是高性能分布式内存对象系统,通过在内存中存储数据对象来减少对磁盘的数据读取次数,提高服务速度. 从业务需求出发.我们通过一条命令(如set)将一条键值对(key,value)插入mem ...

  9. 黄聪:360、chrome开发插件扩展如何跨域调用其他网站的信息并且显示在扩展、tab中的api

    chrome插件提供了查找tab的api chrome.tabs.get(integer tabId, function callback) 但是出于安全的考虑,tab的属性中没有document 因 ...

  10. 微博短链接的生成算法(Java版本)

    最近看到微博的短链接真是很火啊,新浪.腾讯.搜狐等微博网站都加入了短链接的功能.之所以要是使用短链接,主要是因为微博只允许发140 字,如果链接地址太长的话,那么发送的字数将大大减少.短链接的主要职责 ...