同在一个产业链园区的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 graphql 数据操作指南

    opencrud 是社区团队提出,同时prisma框架就是按照这个标准设计的,里面包含了对于graphql 数据 操作的最佳实践,目前还在完善中,但是设计以及指南覆盖的功能还是比较全的,如果用过 pr ...

  2. fusionjs 学习一 基本试用

    参考demo 项目 https://github.com/rongfengliang/fusionjs-docker-demo 安装 create startkit yarn global add c ...

  3. Django 中间件使用

     前戏 我们在前面的课程中已经学会了给视图函数加装饰器来判断是用户是否登录,把没有登录的用户请求跳转到登录页面.我们通过给几个特定视图函数加装饰器实现了这个需求.但是以后添加的视图函数可能也需要加上装 ...

  4. 后端渲染html、前端模板渲染html,jquery的html

    作者:赵魏璇链接:https://www.zhihu.com/question/28725977/answer/116177149来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  5. 使用C++生成1-33中的6个随机数,无重复

    生成1-33中的6个随机数,无重复 ------------------------------------------------------------------------   方法1.每生成 ...

  6. A Newbie’s Install of Keras & Tensorflow on Windows 10 with R

    This weekend, I decided it was time: I was going to update my Python environment and get Keras and T ...

  7. Bootstrap-CL:警告

    ylbtech-Bootstrap-CL:警告 1.返回顶部 1. Bootstrap 警告(Alerts) 本章将讲解警告(Alerts)以及 Bootstrap 所提供的用于警告的 class.警 ...

  8. ThreadCachedInt

    folly/ThreadCachedInt.h High-performance atomic increment using thread caching. folly/ThreadCachedIn ...

  9. ZOJ - 3657-The Little Girl who Picks Mushrooms

    /*ZOJ Problem Set - 3657 The Little Girl who Picks Mushrooms Time Limit: 2 Seconds Memory Limit: 327 ...

  10. hadoop学习day3 mapreduce笔记

    1.对于要处理的文件集合会根据设定大小将文件分块,每个文件分成多块,不是把所有文件合并再根据大小分块,每个文件的最后一块都可能比设定的大小要小 块大小128m a.txt 120m 1个块 b.txt ...