跟微软保持适当距离--Hessian + .net 实现RPC体系的企业应用
同在一个产业链园区的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体系的企业应用的更多相关文章
- Hessian 源码简单分析
Hessian 是一个rpc框架, 我们需要先写一个服务端, 然后在客户端远程的调用它即可. 服务端: 服务端通常和spring 做集成. 首先写一个接口: public interface Hell ...
- 我看微软收购GitHub
今天是微软收购GitHub的第三天,之前很多人担心被微软收购的GitHub会步Skype,诺基亚等企业的后尘,凡此种种我觉得更多人的担心是:GitHub不再开源免费罢了. GitHub今年4月刚成立十 ...
- 纳德拉再造微软:市值如何重回第一阵营(思维确实变了,不再是以windows为中心,拥抱其它各种平台,敢在主战场之外找到适合自己的新战场)
有人说,现在的美国硅谷充满了“咖喱味”.也有人说,硅谷已经变成“印度谷”.原因就在于,以微软CEO萨提亚·纳德拉.谷歌CEO桑达尔·皮查伊为代表的印度人,近年以来掌控了全世界最令人望而生畏的科技巨头. ...
- WPF路线图白皮书: 2015及未来
介绍 当2006年微软首次推出Windows Presentation Foundation(WPF)时,它代表了应用程序的设计和开发又向前跨出了巨大的一步.它简化了GUI应用程序的开发,有助于UI和 ...
- 华人曾与IBM抗衡! 盘点已远去的IT巨头(转)
[PConline资讯 ]从算盘到计算器,从大型机到个人PC,再到当今火热的移动终端和云计算,人类计算史已经走过了千年之久,现代IT计算领域也经过了百年浮沉.在世界工业领域,IT技术应该是诞生时间最短 ...
- Facebook人工智能实验室的前世今生
Facebook人工智能实验室的前世今生 是时候停止把Facebook当作纯粹的社交媒体公司来看了.它用无人机提供互联网服务,为了发展虚拟现实而收购Oculus,不懈追求人工智能,Facebook已经 ...
- 公司管理系列--Facebook是如何营造企业文化的[转]
本文讲下硅谷创业公司的文化,去过硅谷公司或者是看过硅谷公司报道的人,都会惊讶硅谷创业公司里面有如此奇特且活力十足的文化.在中国,企业文化是一个被滥用但是却又缺乏解读的概念,很多国内企业对保持公司的 ...
- 微软和Google的盈利模式对比分析
一: 微软和Google是世界上最成功科技巨头之一,但他们之间却有着不同的产品和业务,二者的盈利方式也各有不同,本文将分析和探讨的二者盈利模式的异同. 微软的盈利模式 在1975年由大学肄业的Bill ...
- Java 技术栈
JAVA是一个面向对象的编程语言,由SUN公司的程序员所开发.它不仅吸收了C++的各种优点,而且还撇弃了C++中难以理解的概念,如多继承.指针等:因此JAVA语言具有功能强大且简单易用两个特征, JA ...
随机推荐
- maven打jar到私服
<dependency> <groupId>fakepath</groupId> <artifactId>wcs-java-sdk</artifa ...
- oracle数据库死锁的查看及解决
Oracle常见死锁发生的原因以及解决方法 www.MyException.Cn 网友分享于:2014-09-02 浏览:0次 Oracle常见死锁发生的原因以及解决办法 一,删除和更 ...
- iis 在站点中新建虚拟目录站点之后,虚拟目录中的 web.config 与 主站点中的 web.config冲突解决方案
在虚拟目录站点中增加如下配置即可:<clear/>
- Javamail使用代码整理
package com.hengrun.mail; import java.io.*; import java.security.Security; import java.text.SimpleDa ...
- SSH: sshd dead but subsys locked
问题: 查看SSH的状态时,提示错误如下: /etc/init.d/sshd status error: sshd dead but subsys locked 解决方法: sshd -d rm -r ...
- py基础4--迭代器、装饰器、软件开发规范
本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1. 列表生成式,迭代器&生成器 列表生成式 我现在有个需求, ...
- 【POJ】1185 炮兵阵地(状压dp)
题目 传送门:QWQ 分析 看到$ M<=10 $考虑状压. 然后把每行都压一下,那么每个状态相关的就是上一行和上上行的状态. 然后枚举. 然后复杂度最坏是$ O(100 \times 1024 ...
- 给iOS开发新手送点福利,简述UIView的属性和用法
UIView 1.alpha 设置视图的透明度.默认为1. // 完全透明 view.alpha = 0; // 不透明 view.alpha = 1; 2.clipsToBounds // 默认是N ...
- samba性能调优
不知道有多少公司的内部打印及文件服务器是用的Linux,我想肯定不会太多,因为Windows实现起来更方便,更快速,当然,Windows也 是更Danger. 因为Windows有太多不确定性的东西, ...
- MySQL转Oracle,MyBatis Mapper XML 文件修改项总结
1.对于批量插入 需要更改成 <insert id="saveAll"> insert into(a,b,c) <foreach collection=" ...