资源描述
Hessian源码分析和Hack --让Hessian携带远程调用端的信息
项目选定Hessian作为web service的实现方式,确实很轻量级,速度就跟直接用socket差不多,全是二进制传送节约了不少开销。但是在使用过程中有业务需要是必须获得远程端的ip地址,主机名等信息的。翻便Hessian的文档和google了n次未果,迫不得已到caucho和spring论坛去问,都没有得到答复。今天心一横把hessian的源代码加入到项目中单步跟踪,总算有点小收获。献丑分享出来,一方面给需要的朋友,主要还是希望各位找找是否存在bug,以及是否有更好的改良。
一:先撇开Spring不谈,来看看纯Hessian的调用
按照hessian文档里边介绍的demo,在web.xml里边如下配置
Java代码
1. <servlet>
2. <servlet-name>hello</servlet-name>
3. <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
4. <init-param>
5. <param-name>home-class</param-name>
6. <param-value>example.BasicService</param-value>
7. </init-param>
8. <init-param>
9. <param-name>home-api</param-name>
10. <param-value>example.Basic</param-value>
11. </init-param>
12. </servlet>
13.
14. <servlet-mapping>
15. <url-pattern>/hello</url-pattern>
16. <servlet-name>hello</servlet-name>
17. </servlet-mapping>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>
<init-param>
<param-name>home-class</param-name>
<param-value>example.BasicService</param-value>
</init-param>
<init-param>
<param-name>home-api</param-name>
<param-value>example.Basic</param-value>
</init-param>
</servlet>
<servlet-mapping>
<url-pattern>/hello</url-pattern>
<servlet-name>hello</servlet-name>
</servlet-mapping>
由此可知Hessian调用的入口是HessianServlet这个Servlet,进去看看
Java代码
1. /**
2. * Servlet for serving Hessian services.
3. */
4. public class HessianServlet extends GenericServlet {
5. private Class _homeAPI;
6. private Object _homeImpl;
7.
8. private Class _objectAPI;
9. private Object _objectImpl;
10.
11. private HessianSkeleton _homeSkeleton;
12. private HessianSkeleton _objectSkeleton;
13.
14. private SerializerFactory _serializerFactory;
15.
16. public String getServletInfo()
17. {
18. return "Hessian Servlet";
19. }
20.
21. /**
22. * Sets the home api.
23. */
24. public void setHomeAPI(Class api)
25. {
26. _homeAPI = api;
27. }
28.
29. /**
30. * Sets the home implementation
31. */
32. public void setHome(Object home)
33. {
34. _homeImpl = home;
35. }
36.
37. /**
38. * Sets the object api.
39. */
40. public void setObjectAPI(Class api)
41. {
42. _objectAPI = api;
43. }
44.
45. /**
46. * Sets the object implementation
47. */
48. public void setObject(Object object)
49. {
50. _objectImpl = object;
51. }
52.
53. /**
54. * Sets the service class.
55. */
56. public void setService(Object service)
57. {
58. setHome(service);
59. }
60.
61. /**
62. * Sets the api-class.
63. */
64. public void setAPIClass(Class api)
65. {
66. setHomeAPI(api);
67. }
68.
69. /**
70. * Gets the api-class.
71. */
72. public Class getAPIClass()
73. {
74. return _homeAPI;
75. }
76.
77. /**
78. * Sets the serializer factory.
79. */
80. public void setSerializerFactory(SerializerFactory factory)
81. {
82. _serializerFactory = factory;
83. }
84.
85. /**
86. * Gets the serializer factory.
87. */
88. public SerializerFactory getSerializerFactory()
89. {
90. if (_serializerFactory == null)
91. _serializerFactory = new SerializerFactory();
92.
93. return _serializerFactory;
94. }
95.
96. /**
97. * Sets the serializer send collection java type.
98. */
99. public void setSendCollectionType(boolean sendType)
100. {
101. getSerializerFactory().setSendCollectionType(sendType);
102. }
103.
104. /**
105. * Initialize the service, including the service object.
106. */
107. public void init(ServletConfig config)
108. throws ServletException
109. {
110. super.init(config);
111.
112. try {
113. if (_homeImpl != null) {
114. }
115. else if (getInitParameter("home-class") != null) {
116. String className = getInitParameter("home-class");
117.
118. Class homeClass = loadClass(className);
119.
120. _homeImpl = homeClass.newInstance();
121.
122. init(_homeImpl);
123. }
124. else if (getInitParameter("service-class") != null) {
125. String className = getInitParameter("service-class");
126.
127. Class homeClass = loadClass(className);
128.
129. _homeImpl = homeClass.newInstance();
130.
131. init(_homeImpl);
132. }
133. else {
134. if (getClass().equals(HessianServlet.class))
135. throw new ServletException("server must extend HessianServlet");
136.
137. _homeImpl = this;
138. }
139.
140. if (_homeAPI != null) {
141. }
142. else if (getInitParameter("home-api") != null) {
143. String className = getInitParameter("home-api");
144.
145. _homeAPI = loadClass(className);
146. }
147. else if (getInitParameter("api-class") != null) {
148. String className = getInitParameter("api-class");
149.
150. _homeAPI = loadClass(className);
151. }
152. else if (_homeImpl != null) {
153. _homeAPI = findRemoteAPI(_homeImpl.getClass());
154.
155. if (_homeAPI == null)
156. _homeAPI = _homeImpl.getClass();
157. }
158.
159. if (_objectImpl != null) {
160. }
161. else if (getInitParameter("object-class") != null) {
162. String className = getInitParameter("object-class");
163.
164. Class objectClass = loadClass(className);
165.
166. _objectImpl = objectClass.newInstance();
167.
168. init(_objectImpl);
169. }
170.
171. if (_objectAPI != null) {
172. }
173. else if (getInitParameter("object-api") != null) {
174. String className = getInitParameter("object-api");
175.
176. _objectAPI = loadClass(className);
177. }
178. else if (_objectImpl != null)
179. _objectAPI = _objectImpl.getClass();
180.
181. _homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);
182. if (_objectAPI != null)
183. _homeSkeleton.setObjectClass(_objectAPI);
184.
185. if (_objectImpl != null) {
186. _objectSkeleton = new HessianSkeleton(_objectImpl, _objectAPI);
187. _objectSkeleton.setHomeClass(_homeAPI);
188. }
189. else
190. _objectSkeleton = _homeSkeleton;
191. } catch (ServletException e) {
192. throw e;
193. } catch (Exception e) {
194. throw new ServletException(e);
195. }
196. }
197.
198. private Class findRemoteAPI(Class implClass)
199. {
200. if (implClass == null || implClass.equals(GenericService.class))
201. return null;
202.
203. Class []interfaces = implClass.getInterfaces();
204.
205. if (interfaces.length == 1)
206. return interfaces[0];
207.
208. return findRemoteAPI(implClass.getSuperclass());
209. }
210.
211. private Class loadClass(String className)
212. throws ClassNotFoundException
213. {
214. ClassLoader loader = Thread.currentThread().getContextClassLoader();
215.
216. if (loader != null)
217. return Class.forName(className, false, loader);
218. else
219. return Class.forName(className);
220. }
221.
222. private void init(Object service)
223. throws ServletException
224. {
225. if (service instanceof Service)
226. ((Service) service).init(getServletConfig());
227. else if (service instanceof Servlet)
228. ((Servlet) service).init(getServletConfig());
229. }
230.
231. /**
232. * Execute a request. The path-info of the request selects the bean.
233. * Once the bean's selected, it will be applied.
234. */
235. public void service(ServletRequest request, ServletResponse response)
236. throws IOException, ServletException
237. {
238. HttpServletRequest req = (HttpServletRequest) request;
239. HttpServletResponse res = (HttpServletResponse) response;
240.
241. if (! req.getMethod().equals("POST")) {
242. res.setStatus(500, "Hessian Requires POST");
243. PrintWriter out = res.getWriter();
244.
245. res.setContentType("text/html");
246. out.println("<h1>Hessian Requires POST</h1>");
247.
248. return;
249. }
250.
251. String serviceId = req.getPathInfo();
252. String objectId = req.getParameter("id");
253. if (objectId == null)
254. objectId = req.getParameter("ejbid");
255.
256. ServiceContext.begin(req, serviceId, objectId);
257.
258. try {
259. InputStream is = request.getInputStream();
260. OutputStream os = response.getOutputStream();
261.
262. Hessian2Input in = new Hessian2Input(is);
263. AbstractHessianOutput out;
264.
265. SerializerFactory serializerFactory = getSerializerFactory();
266.
267. in.setSerializerFactory(serializerFactory);
268.
269. int code = in.read();
270.
271. if (code != 'c') {
272. // XXX: deflate
273. throw new IOException("expected 'c' in hessian input at " + code);
274. }
275.
276. int major = in.read();
277. int minor = in.read();
278.
279. if (major >= 2)
280. out = new Hessian2Output(os);
281. else
282. out = new HessianOutput(os);
283.
284. out.setSerializerFactory(serializerFactory);
285.
286. if (objectId != null)
287. _objectSkeleton.invoke(in, out);
288. else
289. _homeSkeleton.invoke(in, out);
290.
291. out.close();
292. } catch (RuntimeException e) {
293. throw e;
294. } catch (ServletException e) {
295. throw e;
296. } catch (Throwable e) {
297. throw new ServletException(e);
298. } finally {
299. ServiceContext.end();
300. }
301. }
302. }
/**
* Servlet for serving Hessian services.
*/
public class HessianServlet extends GenericServlet {
private Class _homeAPI;
private Object _homeImpl;
private Class _objectAPI;
private Object _objectImpl;
private HessianSkeleton _homeSkeleton;
private HessianSkeleton _objectSkeleton;
private SerializerFactory _serializerFactory;
public String getServletInfo()
{
return "Hessian Servlet";
}
/**
* Sets the home api.
*/
public void setHomeAPI(Class api)
{
_homeAPI = api;
}
/**
* Sets the home implementation
*/
public void setHome(Object home)
{
_homeImpl = home;
}
/**
* Sets the object api.
*/
public void setObjectAPI(Class api)
{
_objectAPI = api;
}
/**
* Sets the object implementation
*/
public void setObject(Object object)
{
_objectImpl = object;
}
/**
* Sets the service class.
*/
public void setService(Object service)
{
setHome(service);
}
/**
* Sets the api-class.
*/
public void setAPIClass(Class api)
{
setHomeAPI(api);
}
/**
* Gets the api-class.
*/
public Class getAPIClass()
{
return _homeAPI;
}
/**
* Sets the serializer factory.
*/
public void setSerializerFactory(SerializerFactory factory)
{
_serializerFactory = factory;
}
/**
* Gets the serializer factory.
*/
public SerializerFactory getSerializerFactory()
{
if (_serializerFactory == null)
_serializerFactory = new SerializerFactory();
return _serializerFactory;
}
/**
* Sets the serializer send collection java type.
*/
public void setSendCollectionType(boolean sendType)
{
getSerializerFactory().setSendCollectionType(sendType);
}
/**
* Initialize the service, including the service object.
*/
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
try {
if (_homeImpl != null) {
}
else if (getInitParameter("home-class") != null) {
String className = getInitParameter("home-class");
Class homeClass = loadClass(className);
_homeImpl = homeClass.newInstance();
init(_homeImpl);
}
else if (getInitParameter("service-class") != null) {
String className = getInitParameter("service-class");
Class homeClass = loadClass(className);
_homeImpl = homeClass.newInstance();
init(_homeImpl);
}
else {
if (getClass().equals(HessianServlet.class))
throw new ServletException("server must extend HessianServlet");
_homeImpl = this;
}
if (_homeAPI != null) {
}
else if (getInitParameter("home-api") != null) {
String className = getInitParameter("home-api");
_homeAPI = loadClass(className);
}
else if (getInitParameter("api-class") != null) {
String className = getInitParameter("api-class");
_homeAPI = loadClass(className);
}
else if (_homeImpl != null) {
_homeAPI = findRemoteAPI(_homeImpl.getClass());
if (_homeAPI == null)
_homeAPI = _homeImpl.getClass();
}
if (_objectImpl != null) {
}
else if (getInitParameter("object-class") != null) {
String className = getInitParameter("object-class");
Class objectClass = loadClass(className);
_objectImpl = objectClass.newInstance();
init(_objectImpl);
}
if (_objectAPI != null) {
}
else if (getInitParameter("object-api") != null) {
String className = getInitParameter("object-api");
_objectAPI = loadClass(className);
}
else if (_objectImpl != null)
_objectAPI = _objectImpl.getClass();
_homeSkeleton = new HessianSkeleton(_homeImpl, _homeAPI);
if (_objectAPI != null)
_homeSkeleton.setObjectClass(_objectAPI);
if (_objectImpl != null) {
_objectSkeleton = new HessianSkeleton(_objectImp
展开阅读全文