最近项目用到了Hessian,初次接触于是花时间研究了下。现记录Spring & Hessian的整合过程,至于Hessian是什么就不在此解释了(一款轻量级RMI框架)。
1.新建Dynamic Web Project(HessianDemo)
2.加入SpringFramework-3.x和hessian-4.0.38.jar,以及其他需要的jar包(根据实际情况在此不赘述,aopalliance、common-logging之类的)。
3.建立接口文件(主要是红框里的三个):
LichService.java:
package com.lichmama.demo.hessian.service; public interface LichService { public String sayHello(String name); }
HessianServiceImpl.java:
package com.lichmama.demo.hessian.impl; import org.springframework.stereotype.Service; import com.lichmama.demo.hessian.service.LichService; @Service public class HessianServiceImpl implements LichService { @Override public String sayHello(String name) { if (name == null || name.isEmpty()) { name = "anonymous"; } return "hello, " + name; } }
AuthHessianServiceExporter.java:
package com.lichmama.demo.hessian.exporter; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.remoting.caucho.HessianServiceExporter; import com.lichmama.common.utils.SecurityTool; //继承HessianServiceExporter可完成一些自定义的工作,如鉴权、预处理、日志、事务管理什么的 public class AuthHessianServiceExporter extends HessianServiceExporter { //密匙,用来验证访问者是否具有访问权限 private final static String authorization = "e807f1fcf82d132f9bb018ca6738a19f"; //加密后的密码:1234567890 @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //从Header里直接取出验证密匙 String requestAuth = request.getHeader("Authorization"); //如果存在且符合我们的期望则允许其访问,否则可自行编辑响应报文 //当然,密码可以稍微加密啥的(DES、AES、SHA1、MD5) if (requestAuth == null || requestAuth.isEmpty()) { System.out.println("[Authorization] header not existing"); throw new ServletException("[Authorization] header not existing"); } else { //对比加密后的密码 if (!authorization.equals(SecurityTool.getMD5Hash(requestAuth))) { System.out.println("unexpected authorization key"); throw new ServletException("unexpected authorization key"); } } //鉴权成功,则继续流转下去。控制权交回HessianServiceExporter super.handleRequest(request, response); } public static String getAuthorization() { return authorization; } }
*SecurityTool.java:
package com.lichmama.common.utils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SecurityTool { public static final char[] table = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; public static String getMD5Hash(String plain) { byte[] bytes = plain.getBytes(); MessageDigest md5; try { md5 = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); return null; } byte[] md5bytes = md5.digest(bytes); char[] hashcode = new char[md5bytes.length * 2]; for (int i=0, j=0; i<md5bytes.length; i++) { byte bt = md5bytes[i]; hashcode[j++] = table[bt >>>4 & 0xf]; hashcode[j++] = table[bt & 0xf]; } return new String(hashcode); } }
4.新建/WEB-INF/spring/spring-service.xml(用来导出hessian服务):
<?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:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:task="http://www.springframework.org/schema/task" xmlns:cache="http://www.springframework.org/schema/cache" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache-3.2.xsd"> <context:annotation-config /> <context:component-scan base-package="com.lichmama.demo.hessian" /> <bean name="/lichService" class="com.lichmama.demo.hessian.exporter.AuthHessianServiceExporter"> <property name="service" ref="hessianServiceImpl" /> <property name="serviceInterface" value="com.lichmama.demo.hessian.service.LichService" /> </bean> </beans>
5.发布HessianDemo工程即可。
6.测试Hessian服务是否可用:1.身份验证是否可用 2.接口服务是否可用(正确返回我们期望的值)
*同样还是用spring测试,至于用DynamicWeb工程还是JavaApplication随意。
6.1新建AuthHessianProxyFactory类,用于完成客户端向服务端投递authorization完成鉴权:
AuthHessianProxyFactory:
package com.lichmama.demo.hessian.proxy; import com.caucho.hessian.client.HessianProxyFactory; public class AuthHessianProxyFactory extends HessianProxyFactory { private final static String authorization = "1234567890"; @Override public String getBasicAuth() { return authorization; } }
测试客户端的spring-client-service.xml:
<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 id="proxyFactory" class="com.lichmama.demo.hessian.proxy.AuthHessianProxyFactory" /> <bean id="lichService" class="org.springframework.remoting.caucho.HessianProxyFactoryBean"> <property name="serviceUrl" value="http://192.168.0.152:8080/HessianDemo/lichService" /> <property name="serviceInterface" value="com.lichmama.demo.hessian.service.LichService" /> <property name="proxyFactory" ref="proxyFactory" /> </bean> </beans>
主要测试代码:
public class TestCase { public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-service.xml"); LichService service = (LichService) ctx.getBean("lichService"); System.out.println(service.sayHello("jaychou")); } }
正常返回:hello, jaychou
PS:修改AuthHessianProxyFactory的authorization应该拒绝你访问了(鉴权失败)。