`

Hessian实战应用之获取客户端请求URL和重新转发客户端请求

阅读更多

在项目中,可能存对Hessian的特殊的要求改造,以下两个例子就是我在项目中遇到的

 

一、对服务器方法调用前做一些校验,获取客户端请求参数

实现方法:继承com.caucho.hessian.server.HessianServlet重写service方法,代码如下:

/**
 * 本地化的HessianServlet,用于服务务器方法调用前的校验
 * 
 * @author ZhangMingxue
 * 
 */
public class MHessianServlet extends HessianServlet {
	private static final long serialVersionUID = 1620619522783394602L;

	@SuppressWarnings("unchecked")
	@Override
	public void service(ServletRequest request, ServletResponse response)
			throws IOException, ServletException {
		System.out.println("服务器方法调用前");
		// 在service方法中可以将request强转成HttpServletRequest,就可以获取很多信息
		HttpServletRequest req = (HttpServletRequest) request;
		String path = req.getContextPath();
		String basePath = req.getScheme() + "://" + req.getServerName() + ":"
				+ req.getServerPort() + path + "/";
		// 1.获取客户端请求路径
		String requestURI = req.getRequestURI();
		System.out.println(basePath);
		System.out.println(requestURI);
		// 2.获取客户端参数信息
		Enumeration<String> parameterNames = req.getParameterNames();
		if (null != parameterNames) {
			while (parameterNames.hasMoreElements()) {
				String paramterValue = req.getParameter(parameterNames
						.nextElement());
				System.out.println(paramterValue);
			}
		}
		// 3.会话管理 ...
		super.service(request, response);
		System.out.println("服务器方法调用后");
	}
}

配置如下:配置成自己继承后的Servlet

<servlet>
		<servlet-name>HelloServlet2</servlet-name>
		<!-- 自己继承后的Servlet -->
		<servlet-class>com.mengya.hessian.MHessianServlet</servlet-class>
		<init-param>
			<param-name>home-class</param-name>
			<param-value>com.mengya.imple.HelloImple</param-value>
		</init-param>
		<init-param>
			<param-name>home-api</param-name>
			<param-value>com.mengya.inter.IHello</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>HelloServlet2</servlet-name>
		<url-pattern>/HelloServlet2</url-pattern>
	</servlet-mapping>

 客户端测试:

public class Hello2Test {
	public static void main(String[] args) {
		// 服务器访问路径
		String url = "http://127.0.0.1:8080/HessianDemos/HelloServlet2?method=add&param=p1";
		HessianProxyFactory hessianProxyFactory = new HessianProxyFactory();
		try {
			// IHello是客户端的接口,与服务器接口一致(客户端的语言包括:Java,Objective C,Flex 等)
			IHello iHello = (IHello) hessianProxyFactory.create(IHello.class,
					url);
			// 客户端调服务器的接口实现
			System.out.println("Result == " + iHello.sayHello());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
}

 

二、获取客户端的请求URL,对于特殊的URL重新转发,继承Hessian的Servlet,改造service和invoke方法

实现代码如下:

/**
 * 本地化的HessianServlet,用于请求转发
 * 
 * @author ZhangMingxue
 * 
 */
public class ForwardHessianServlet extends HessianServlet {
	private static final long serialVersionUID = 4497196628911041481L;

	@Override
	public void service(ServletRequest request, ServletResponse response)
			throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		// 客户端的请求路径
		String requestURI = req.getRequestURI();
		this.realizeService(request, response, requestURI);
	}

	// 在原service()方法添加了一个参数
	@SuppressWarnings("deprecation")
	public void realizeService(ServletRequest request,
			ServletResponse response, String requestURI) throws IOException,
			ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;

		if (!req.getMethod().equals("POST")) {
			res.setStatus(500, "Hessian Requires POST");
			PrintWriter out = res.getWriter();
			res.setContentType("text/html");
			out.println("<h1>Hessian Requires POST</h1>");
			return;
		}

		String serviceId = req.getPathInfo();
		String objectId = req.getParameter("id");
		if (objectId == null)
			objectId = req.getParameter("ejbid");

		ServiceContext.begin(req, serviceId, objectId);
		try {
			InputStream is = request.getInputStream();
			OutputStream os = response.getOutputStream();
			response.setContentType("application/x-hessian");
			SerializerFactory serializerFactory = getSerializerFactory();
			// 修改为调用自己的invoke方法
			this.invoke(is, os, objectId, serializerFactory, requestURI);
		} catch (RuntimeException e) {
			throw e;
		} catch (ServletException e) {
			throw e;
		} catch (Throwable e) {
			throw new ServletException(e);
		} finally {
			ServiceContext.end();
		}
	}

	protected void invoke(InputStream is, OutputStream os, String objectId,
			SerializerFactory serializerFactory, String requestURI)
			throws Exception {
		URL url = null;
		HttpURLConnection conn = null;
		try {
			// 客户端请求原始URL
			System.out.println(requestURI);
			// 根据实际情况,转向到别一个服务器中
			url = new URL("http://127.0.0.1:8080/HessianDemos/HelloServlet");
			System.out.println("转向到:" + url);
			conn = (HttpURLConnection) url.openConnection();
			conn.setRequestProperty("Content-Type", "x-application/hessian");
			conn.setDoOutput(true);
			conn.setRequestMethod("POST");

			OutputStream ros = conn.getOutputStream();
			byte[] buff = new byte[1024 * 64];
			int length;
			while ((length = is.read(buff)) > 0) {
				ros.write(buff, 0, length);
			}
			ros.flush();
			ros.close();

			InputStream ris = conn.getInputStream();
			while ((length = ris.read(buff)) > 0) {
				os.write(buff, 0, length);
			}
			ris.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (conn != null)
				conn.disconnect();
		}
	}
}

 配置如下:

<servlet>
		<servlet-name>ForwardHelloServlet</servlet-name>
		<servlet-class>com.mengya.hessian.ForwardHessianServlet</servlet-class>
		<init-param>
			<param-name>home-class</param-name>
			<param-value>com.mengya.imple.HelloImple</param-value>
		</init-param>
		<init-param>
			<param-name>home-api</param-name>
			<param-value>com.mengya.inter.IHello</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>ForwardHelloServlet</servlet-name>
		<url-pattern>/ForwardHelloServlet</url-pattern>
	</servlet-mapping>

 客户端测试代码:

public class ForwardHelloTest {
	public static void main(String[] args) {
		// 服务器访问路径
		String url = "http://127.0.0.1:8080/HessianDemos/ForwardHelloServlet";
		HessianProxyFactory hessianProxyFactory = new HessianProxyFactory();
		try {
			// IHello是客户端的接口,与服务器接口一致(客户端的语言包括:Java,Objective C,Flex 等)
			IHello iHello = (IHello) hessianProxyFactory.create(IHello.class,
					url);
			// 客户端调服务器的接口实现
			System.out.println("Result == " + iHello.sayHello());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
	}
}

 

7
3
分享到:
评论
3 楼 kandy_dou 2014-08-20  
                          
2 楼 xiaobojava 2013-04-16  
spring的方法拦截器也能做到,servlet的拦截器能不到
1 楼 rkikbs 2013-04-16  
相当于在调用hessian服务之前,走下拦截器。只不过spring或者servlet的拦截器拦截不到hessian的服务。是把?

相关推荐

    全国计算机等级考试二级openGauss数据库程序设计样题解析

    主要内容涵盖单选题和操作题两大部分。单选题涉及openGauss数据库的基本概念、数据模型、SQL语法、事务管理和用户权限等方面的知识点。操作题则围绕一个名为bookdb的图书购买信息数据库展开,具体任务包括插入图书信息、更新顾客信息、删除购买记录、查询特定图书信息以及创建视图、存储过程和触发器等实际操作。每道题目均附带详细的解题步骤和最终答案。

    新建 Microsoft Word 文档 (9).docx

    新建 Microsoft Word 文档 (9).docx

    Delphi 12.3控件之nrCommLib Pro v9.54 Full Source for D10.3-D12.7z

    Delphi 12.3控件之nrCommLib Pro v9.54 Full Source for D10.3-D12.7z

    三菱PLC FX5U控制四轴伺服系统:硬件配置、参数设置及运动控制详解

    内容概要:本文详细介绍了使用三菱PLC FX5U控制四轴伺服系统的全过程,涵盖硬件配置、电气接线、参数设置以及运动控制逻辑。硬件方面,选用三菱FX5U-64MT作为主控制器,搭配四个MR-JE-20A伺服驱动器和其他必要组件。软件部分则深入探讨了轴参数初始化、原点回归、多轴联动、HMI界面设计及报警处理等关键技术环节。特别针对旋转轴的特殊处理进行了详细说明,如双速原点回归、绝对定位指令的应用等。此外,还提供了调试经验和优化技巧,确保系统的高精度和平稳运行。 适合人群:从事自动化控制系统设计、调试的技术人员,尤其是对三菱PLC和伺服系统有一定了解的研发人员。 使用场景及目标:适用于工业自动化领域的四轴伺服控制系统开发,旨在帮助工程师掌握从硬件选型到软件编程的一整套解决方案,提高项目的成功率和技术水平。 其他说明:文中附有多份参考资料,包括完整的程序文件、界面工程、CAD接线图和伺服参数清单,便于读者进行实际操作和验证。

    分阶段学习:先掌握基础,再深入细分领域 理论与实践结合:学完算法后立刻用代码实现 保持持续学习:AI技术迭代快,需跟踪最新进展

    分阶段学习:先掌握基础,再深入细分领域。 理论与实践结合:学完算法后立刻用代码实现。 保持持续学习:AI技术迭代快,需跟踪最新进展。

    电子硬件课程设计-Word文档

    电子硬件课程设计

    智慧农贸信息化管理平台.zip

    Java项目基于ssm框架的课程设计,包含LW+ppt

    脚本-压测相关-zyx编写

    脚本-压测相关-zyx编写

    jspm机房预约系统lw+ppt.zip

    Java项目基于ssm框架的课程设计,包含LW+ppt

    app.mobileconfig

    app.mobileconfig

    基于MotorCAD的2极12槽永磁直流有刷电机设计与优化教程

    内容概要:本文详细介绍了使用MotorCAD进行2极12槽永磁直流有刷电机的设计与优化方法。首先,通过Python脚本设置电机的基本参数,如外径、轴向长度、额定转速等。接着,深入探讨了磁钢选型、绕组设置、电磁仿真、热分析等多个关键技术环节。针对常见的设计难题,如齿槽转矩、磁钢充磁方向、绕组跨距等提供了具体的解决方案。同时,还分享了一些提高仿真精度和优化性能的实用技巧,如参数扫描、FEA计算、热管理等。最后,通过实测数据分析验证了设计方案的有效性。 适合人群:电机设计工程师、高校相关专业师生、对电机设计感兴趣的开发者。 使用场景及目标:适用于需要精确设计和优化小型永磁直流有刷电机的场合,帮助用户掌握MotorCAD的具体应用,提高设计效率和产品质量。 其他说明:文中提供的Python和VB脚本示例有助于自动化参数设置和批量处理任务,减少重复劳动。此外,还强调了在设计过程中需要注意的关键技术和常见陷阱,确保设计方案的可行性和可靠性。

    三相逆变器基于PI闭环与解耦控制的MATLAB仿真实现

    内容概要:本文详细介绍了三相逆变器在MATLAB/Simulink环境下的PI闭环控制及解耦控制的实现方法。首先,通过坐标变换将三相电流从静止坐标系转换到旋转坐标系,确保功率守恒并实时更新转子位置角。接着,实现了带有抗饱和处理的PI控制器,防止积分风-up现象。然后,针对d轴和q轴之间的耦合问题,引入了解耦控制,通过低通滤波和交叉耦合项来稳定系统。此外,还讨论了PWM生成模块的死区时间和仿真结果的验证方法,强调了参数调试的重要性和具体策略。 适合人群:电力电子工程师、自动化控制领域的研究人员以及对三相逆变器控制感兴趣的高校师生。 使用场景及目标:适用于需要深入了解三相逆变器控制原理和技术实现的研究项目或工程应用。主要目标是掌握PI控制器的设计、解耦控制的应用及其在MATLAB/Simulink中的仿真实现。 其他说明:文中提供了详细的代码示例和调试技巧,帮助读者更好地理解和实践相关理论。同时提醒读者,仿真成功并不代表实际硬件运行无误,建议在实验过程中准备必要的保护措施。

    58面经面试过程和题目.txt

    58面经面试过程和题目.txt

    OceanBase OBCP 实验指导手册V1.3

    OceanBase OBCP 实验指导手册V1.3

    ABB喷涂机器人IRC5P与PLC Profinet通讯配置及程序号启动详解

    内容概要:本文详细介绍了ABB喷涂机器人IRC5P与PLC通过Profinet通讯进行程序号启动的具体步骤和注意事项。主要内容涵盖Profinet通讯的基本配置,包括设备名称、IP地址设置,RAPID代码编写,任务声明,信号映射,以及调试技巧。文中还分享了许多实际调试中的经验和常见错误,如大小写敏感、IP地址分配、程序号有效性和信号防抖处理等。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是负责机器人与PLC通讯配置的技术人员。 使用场景及目标:帮助技术人员正确配置ABB喷涂机器人IRC5P与PLC之间的Profinet通讯,确保程序号能够顺利启动,避免常见的配置错误和调试难题。 其他说明:文章强调了硬件和软件配置相结合的重要性,并提供了详细的代码示例和调试建议,有助于提高系统的稳定性和可靠性。

    电子硬件课后习题题目及要求.docx

    电子硬件课后习题题目及要求.docx

    亲测开源好用的红盟云发卡源码对接支付宝等支持一件搭建

    亲测开源好用的红盟云发卡源码对接支付宝等支持一件搭建,方便建立自己的发卡平台,源码全部开源无加密,可方便而开使用。 测试环境:php7.2+mysql+宝塔面板 安装教程: ①设置public运行目录 ②设置thinkphp伪静态 ③访问域名填写数据库信息根据提示安装

    Delphi 12.3控件之MiTeC-System-Information-Component-Suite-15.1.0-Full-Source.7z

    Delphi 12.3控件之MiTeC_System_Information_Component_Suite_15.1.0_Full_Source.7z

    Delphi 12.3控件之StyleControls 5.80.7z

    Delphi 12.3控件之StyleControls 5.80.7z

Global site tag (gtag.js) - Google Analytics