设为首页 收藏本站
查看: 847|回复: 0

[经验分享] 跟微软保持适当距离--Hessian + .net 实现RPC体系的企业应用

[复制链接]

尚未签到

发表于 2017-2-19 10:23:31 | 显示全部楼层 |阅读模式
  同在一个产业链园区的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


DSC0000.gif DSC0001.gif


<?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>1</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>
View Code   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>
View Code   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>
View Code   用户登陆状态问题
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
    }
}
View Code   服务实现类:





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("未登录或登录超时!");
}
}
}
View Code   .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 = 1888, Sex = false };
q.Data = new byte[] { 5, 4, 3, 2, 1 };
q.CreateDate = DateTime.Now;
q.RecId = 99999;
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", "123");
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);
}
}
}
View Code

完成服务端代码下载

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-344131-1-1.html 上篇帖子: JavaEE程序员必读图书大推 下篇帖子: Spring配置数据源的四种方式(小结)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表