<< 每个jQuery开发者应该知道的重要技巧 | 首页 | java Jackson 库操作 json 的基本演示 - joyous的专栏 - 博客频道 - CSDN.NET >>

如何用Mule创建动态的HTTP代理服务

 

目的

引入动态http代理的主要目的是在加入新的http代理而不需要重启Mule代理服务。注意,要真正的动态代理,需要注入实现了路径与服务器地址映射的检索服务的Spring的Bean,在enricher位置通过groovy获得Bean的实例进行调用。

 

实例程序的限制:

这个例子程序缺乏生产环境中使用处理:

  • 错误处理
  • 从数据库检索路径的映射配置信息

            这个例子将HTTP相对路径和目标服务器之间的映射写在XML配置文件里。这当然不能允许动态修改代理配置。

  • 支持更多的HTTP方法

             只支持HTTP get和post方法

  • 处理的HTTP参数。

             实例程序没考虑HTTP参数但这些都被认为是在HTTP相对路径的一部分。

  • 支持HTTPS。

 

为了能够有一个服务代理,一个简单的SOAP问候服务使用一个Mule配置文件和一个Java类实现。

Mule配置包含以下配置:

01.<?xml version="1.0" encoding="UTF-8"?>
02.<mule
09.xsi:schemaLocation="
14. 
15.<spring:beans>
16.<spring:bean id="helloService" class="com.ivan.mule.dynamichttpproxy.HelloService"/>
17.</spring:beans>
18. 
19.<flow name="GreetingFlow">
20.<inbound-endpoint address="http://localhost:8182/services/GreetingService"
21.exchange-pattern="request-response"/>
22. 
23.<cxf:jaxws-service serviceClass="com.ivan.mule.dynamichttpproxy.HelloService"/>
24.<component>
25.<spring-object bean="helloService"/>
26.</component>
27.</flow>
28.</mule>

 

服务类:

01.package com.ivan.mule.dynamichttpproxy;
02. 
03.import java.util.Date;
04.import javax.jws.WebParam;
05.import javax.jws.WebResult;
06.import javax.jws.WebService;
07. 
08./**
09.* SOAP web service endpoint implementation class that implements
10.* a service that extends greetings.
11.*
12.* @author Ivan Krizsan
13.*/
14.@WebService
15.public class HelloService {
16./**
17.* Greets the person with the supplied name.
18.*
19.* @param inName Name of person to greet.
20.* @return Greeting.
21.*/
22.@WebResult(name = "greeting")
23.public String greet(@WebParam(name = "inName") final String inName) {
24.return "Hello " + inName + ", the time is now " + new Date();
25.}
26.}

 

 

服务器信息Bean,用于存储原始HTTP请求路径与对应目标服务器ip端口的映射信息:

01.package com.ivan.mule.dynamichttpproxy;
02. 
03./**
04.* Holds information about a server which to forward requests to.
05.*
06.* @author Ivan Krizsan
07.*/
08.public class ServerInformationBean {
09.private String serverAddress;
10.private String serverPort;
11.private String serverName;
12. 
13./**
14.* Creates an instance holding information about a server with supplied
15.* address, port and name.
16.*
17.* @param inServerAddress
18.* @param inServerPort
19.* @param inServerName
20.*/
21.public ServerInformationBean(final String inServerAddress,
22.final String inServerPort, final String inServerName) {
23.serverAddress = inServerAddress;
24.serverPort = inServerPort;
25.serverName = inServerName;
26.}
27. 
28.public String getServerAddress() {
29.return serverAddress;
30.}
31. 
32.public String getServerPort() {
33.return serverPort;
34.}
35. 
36.public String getServerName() {
37.return serverName;
38.}
39.}

 

动态HTTP 代理Mule配置:

001.<?xml version="1.0" encoding="UTF-8"?>
002.<!--
003.The dynamic HTTP proxy Mule configuration file.
004. 
005.Author: Ivan Krizsan
006.-->
015.version="CE-3.4.0"
016.xsi:schemaLocation="
 
022. 
023.<spring:beans>
024.<!--
025.Mappings from path to server represented by a hash map.
026.A map has been choosen to limit the scope of this example.
027.Storing data about mappings between path to server in a database
028.will enable runtime modifications to the mapping data without
029.having to stop and restart the general proxy Mule application.
030.-->
031.<util:map id="pathToServerAndPortMapping" map-class="java.util.HashMap">
032.<!-- Entry for MyServer. -->
033.<spring:entry key="services/GreetingService">
034.<spring:bean class="com.ivan.mule.dynamichttpproxy.ServerInformationBean">
035.<spring:constructor-arg value="localhost"/>
036.<spring:constructor-arg value="8182"/>
037.<spring:constructor-arg value="MyServer"/>
038.</spring:bean>
039.</spring:entry>
040.<!-- Entry for SomeOtherServer. -->
041.<spring:entry key="services/GreetingService?wsdl">
042.<spring:bean class="com.ivan.mule.dynamichttpproxy.ServerInformationBean">
043.<spring:constructor-arg value="127.0.0.1"/>
044.<spring:constructor-arg value="8182"/>
045.<spring:constructor-arg value="SomeOtherServer"/>
046.</spring:bean>
047.</spring:entry>
048.</util:map>
049.</spring:beans>
050. 
051.<flow name="HTTPGeneralProxyFlow">
052.<!--
053.Note that if you increase the length of the path to, for instance
054.generalProxy/additionalPath, then the expression determining
055.the outgoing path need to be modified accordingly.
056.Changing the path, without changing its length, require no
057.modification to outgoing path.
058.-->
059.<http:inbound-endpoint
060.exchange-pattern="request-response"
061.host="localhost"
062.port="8981"
063.path="dynamicHttpProxy" doc:name="HTTP Receiver"/>
064. 
065.<!-- Extract outgoing path from received HTTP request. -->
066.<set-property
067.value="#[org.mule.util.StringUtils.substringAfter(org.mule.util.StringUtils.substringAfter(message.inboundProperties['http.request'], '/'), '/')]"
068.propertyName="outboundPath"
069.doc:name="Extract Outbound Path From Request" />
070. 
071.<logger message="#[string:Outbound path = #[message.outboundProperties['outboundPath']]]"level="DEBUG"/>
072. 
073.<!--
074.Using the HTTP request path, select which server to forward the request to.
075.Note that there should be some kind of error handling in case there is no server for the current path.
076.Error handling has been omitted in this example.
077.-->
078.<enricher target="#[variable:outboundServer]">
079.<scripting:component doc:name="Groovy">
080.<!--
081.If storing mapping data in a database, this Groovy script
082.should be replaced with a database query.
083.-->
084.<scripting:script engine="Groovy">
085.<![CDATA[
086.def theMap = muleContext.getRegistry().lookupObject("pathToServerAndPortMapping")
087.def String theOutboundPath = message.getOutboundProperty("outboundPath")
088.def theServerBean = theMap[theOutboundPath]
089.theServerBean
090.]]>
091.</scripting:script>
092.</scripting:component>
093.</enricher>
094. 
095.<logger
096.message="#[string:Server address = #[groovy:message.getInvocationProperty('outboundServer').serverAddress]]"
097.level="DEBUG"/>
098.<logger
099.message="#[string:Server port = #[groovy:message.getInvocationProperty('outboundServer').serverPort]]"
100.level="DEBUG"/>
101.<logger
102.message="#[string:Server name = #[groovy:message.getInvocationProperty('outboundServer').serverName]]"
103.level="DEBUG"/>
104. 
105.<!-- Log the request and its metadata for development purposes, -->
106.<test:component logMessageDetails="true"/>
107. 
108.<!--
109.Cannot use a MEL expression in the value of the method attribute
110.on the HTTP outbound endpoints so have to revert to this way of
111.selecting HTTP method in the outgoing request.
112.In this example, only support for GET and POST has been implemented.
113.This can of course easily be extended to support additional HTTP
114.verbs as desired.
115.-->
116.<choice doc:name="Choice">
117.<!-- Forward HTTP GET requests. -->
118.<when expression="#[message.inboundProperties['http.method']=='GET']">
119.<http:outbound-endpoint
120.exchange-pattern="request-response"
121.host="#[groovy:message.getInvocationProperty('outboundServer').serverAddress]"
122.port="#[groovy:message.getInvocationProperty('outboundServer').serverPort]"
123.method="GET"
124.path="#[message.outboundProperties['outboundPath']]"
125.doc:name="Send HTTP GET"/>
126.</when>
127.<!-- Forward HTTP POST requests. -->
128.<when expression="#[message.inboundProperties['http.method']=='POST']">
129.<http:outbound-endpoint
130.exchange-pattern="request-response"
131.host="#[groovy:message.getInvocationProperty('outboundServer').serverAddress]"
132.port="#[groovy:message.getInvocationProperty('outboundServer').serverPort]"
133.method="POST"
134.path="#[message.outboundProperties['outboundPath']]"
135.doc:name="Send HTTP POST"/>
136.</when>
137.<!-- If HTTP method not recognized, use GET. -->
138.<otherwise>
139.<http:outbound-endpoint
140.exchange-pattern="request-response"
141.host="#[groovy:message.getInvocationProperty('outboundServer').serverAddress]"
142.port="#[groovy:message.getInvocationProperty('outboundServer').serverPort]"
143.method="GET"
144.path="#[message.outboundProperties['outboundPath']]"
145.doc:name="Default: Send HTTP GET"/>
146.</otherwise>
147.</choice>
148.</flow>
149.</mule>

 

 

注意:

  • 一个名称为“pathToServerAndPortMapping”用Spring XML配置了路径与服务器地址的映射
  • <set-property>元素设置了outboundPath属性的值,outboundPath即服务的相对路径,用于检索目标服务器,并对目标服务器发起http:outbound-endpoint.
  • <enricher>元素部分是使用outboundpath检索对应的ServerInformationBean实例
  • <choice>元素包含了多个outbound HTTP endpoints。

 

启动Mule工程服务后,现在访问真正的目标服务

http://localhost:8182/services/GreetingService?wsdl

应该能看到WSDL文件内容了。通过soapUI访问,应该能收到包含日期和时间的问候了。

 

接下来,通过soapUI访问代理服务

http://localhost:8981/dynamicHttpProxy/services/GreetingService

 

控制台上会打印如下内容:

1.... Outbound path = services/GreetingService
2.... Server address = localhost
3.... Server port = 8182
4.... Server name = MyServer

 

转载请注明原创首发地址:如何用Mule创建动态HTTP代理服务

 




发表评论 发送引用通报