最近項目用到了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應該拒絕你訪問了(鑒權失敗)。