同在一个产业链园区的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. opencrud 中文参考翻译(完成部分)

    opencrud 是一个就比较好的关于graphql 实现的指南(当前只有部分文档,完整的还没有,实际上apollo 有相关的文档都挺不错的) 同时在github 有一个中文的简单翻译(后期应该会和官 ...

  2. FastAdmin 的前端环境怎么安装?

    FastAdmin 的前端环境怎么安装? 安装 Git 安装 Node.js 安装 cnpm 安装 bower 开始安装 FastAdmin 的前端组件 bower install bower upd ...

  3. 什么是HBase(六)性能调优

    硬件层面 内存要大,最好是ECC(Error Checking and Correcting),实现内存的动态纠错:CPU要多路(每个路彼此隔离)每个路一个CPU,每个cpu上面一般都是2~12核. ...

  4. System.IO.Path类

    System.IO.Path为路径的操作封装了很多很有的东西,利用该类提供的方法能够快速处理路径操作的问题.下面详细了解一下. 1.属性 属性太复杂了,反映什么系统平台的信息,看不懂,等以后看得懂了再 ...

  5. php常量的实现

    1.php的常量 就是一个简单的标识符,脚本执行期间不会改变,大小写敏感,默认大写. 常量的存储结构 typedef struct _zend_constant { zval value; //常量值 ...

  6. JVM体系结构之七:持久代、元空间(Metaspace) 常量池==了解String类的intern()方法、常量池介绍、常量池从Perm-->Heap

    一.intern()定义及使用 相信绝大多数的人不会去用String类的intern方法,打开String类的源码发现这是一个本地方法,定义如下: public native String inter ...

  7. VS2017如何配置openGL环境

    转自:http://blog.csdn.net/qq_26982531/article/details/62056913 这里着重介绍vs2017配置openGL环境与以前版本的不同之处:       ...

  8. JavaScript(二)-精简

    十三 DOM(文档对象模型) 1 作用 : 可访问javascript HTML文档的所有元素. 2 功能: (1) 改变html输出流 eg: <script>              ...

  9. var和let示例

    声明后未赋值,表现相同 (function() { var varTest; let letTest; console.log(varTest); //输出undefined console.log( ...

  10. C#实现图片文件到数据流再到图片文件的转换

    //----引入必要的命名空间using System.IO;using System.Drawing.Imaging; //----代码部分----// private byte[] photo;/ ...