OSGI Http轉發

在企業中,往往有很多的Http接口很多的服務,那就需要很多的ip地址或者域名以及端口號了,那是不現實的,就算現實了,對於運維人員和開發人員來說也是很不好的,多起來的時候,最後誰知道哪個域名哪個端口對於的是哪個服務呀,最終還是害慘了自己。

所以,下面,我就介紹一個http轉發的實現,我們可以監聽一個端口號,對於是這個端口號的所有地址進行一個攔截,然後再統一的轉發出去,這樣子是不是很靠譜呀,那該如何實現呢??下面來看看這個例子:


一、首先,我們先建立一個blueprint.xml文件,因爲這是OSGI環境的橋樑,少不了。

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
           xmlns:camel="http://camel.apache.org/schema/blueprint"
           xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
    
    <bean id="httpDispatchErrorHandleBean" class="jmust.Common.HttpDispatchErrorHandle" />
    
    <bean id="httpDispatchErrorHandle" class="org.apache.camel.builder.DeadLetterChannelBuilder">  
        <property name="deadLetterUri" value="bean:httpDispatchErrorHandleBean"/>  
    </bean>
    
    <camelContext id="httpCamelContext" errorHandlerRef="httpDispatchErrorHandle" xmlns="http://camel.apache.org/schema/blueprint">
    
        <restConfiguration bindingMode="auto" component="restlet" port="8888" />
        
        <!-- 攔截所有的請求(timeout = 1分鐘) 一個地址支持四種請求 -->
        <rest>  
            <get uri="/">  
                <to uri="vm:http-dispatch?timeout=18000" />
            </get>  
            <post uri="/">  
                <to uri="vm:http-dispatch?timeout=18000" />  
            </post>
            <delete uri="/">
                <to uri="vm:http-dispatch?timeout=18000" />
            </delete>
            <head uri="/">
                <to uri="vm:http-dispatch?timeout=18000" />
            </head>
            <put uri="/">
                <to uri="vm:http-dispatch?timeout=18000" />
            </put>
        </rest>
        
        <!-- 通用的http調度處理 -->
        <route>
            <from uri="vm:http-dispatch" />
            <to uri="log:httpDispatchProcessor?showAll=true;&multiline=true" />
            <to uri="bean:httpDispatchProcessor" />
        </route>
        
        <!-- 請求地址 -->
        <route>
            <from uri="direct-vm:/demo/test" />
            <to uri="bean:httpTestProcessor"/>
        </route>

        <!-- 請求地址 -->
        <route>
            <from uri="direct-vm:/demo/test1"/>
            <to uri="bean:httpTest1Processor"/>
        </route>
    </camelContext>
    
    <bean id="httpProducerTemplate" class="org.apache.camel.impl.DefaultProducerTemplate" init-method="start">  
         <argument ref="httpCamelContext" />  
    </bean>
    <!-- 服務註冊 -->
    <bean id="httpDispatchProcessor" class="jmust.Common.HttpDispatchProcessor">
        <property name="producerTemplate" ref="httpProducerTemplate" />
    </bean>
    
    
    <bean id="httpTestProcessor" class="jmust.Common.TestProcessor">
    </bean>
    <bean id="httpTest1Processor" class="jmust.Common.Test1Processor">
    </bean> 
</blueprint>


二、增加一個接收轉發請求的Processor,讓它去處理所有的請求,最終返回固定ip、端口號

import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.component.restlet.RestletConstants;
import org.restlet.engine.adapter.HttpRequest;

import jmust.Common.Utils.ExchangeUtil;
import jmust.Common.Utils.PathUtil;

/**
 * 監聽特定端口轉發
 * @author lvkun
 *
 */
public class HttpDispatchProcessor implements Processor{
    private CamelContext camelContext ;
    private ProducerTemplate producerTemplate;

    public void process(Exchange exchange) throws Exception {
        HttpRequest request = exchange.getIn().getHeader(RestletConstants.RESTLET_REQUEST, HttpRequest.class);
        String contextPath = PathUtil.getAbsPath(request.getHttpCall().getRequestUri());
        ExchangeUtil.sendExchage(camelContext, producerTemplate, exchange, contextPath);
    }

    public CamelContext getCamelContext() {
        return camelContext;
    }

    public void setCamelContext(CamelContext camelContext) {
        this.camelContext = camelContext;
    }

    public ProducerTemplate getProducerTemplate() {
        return producerTemplate;
    }

    public void setProducerTemplate(ProducerTemplate producerTemplate) {
        this.producerTemplate = producerTemplate;
    }
}


三、Exchange公用工具

import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.ProducerTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Exchange公用工具
 * @author lvkun
 *
 */
public class ExchangeUtil {
    private static final String DEST_COMPONENT = "direct-vm";
    private static final String FAVICON = "/favicon.ico";
    private static final Logger log = LoggerFactory.getLogger(ExchangeUtil.class);
    
    public static void sendExchage(CamelContext camelContext,ProducerTemplate producerTemplate,Exchange exchange,String contextPath){
        if(!FAVICON.equals(contextPath)&&!"/".equals(contextPath))
        {
            String route = DEST_COMPONENT + ":" +contextPath;
            log.info("redirect endpoint {}", route);
            Exchange exch = producerTemplate.send(route, exchange);
            if(exch != null && exch.getOut() != null){
                exchange.getOut().setBody(exch.getOut().getBody());
            }
        }
        else if(FAVICON.equals(contextPath))
        {
            exchange.getOut().setBody("");
        }
    }
    
}


四、封裝獲取相對路徑的工具

import javax.servlet.http.HttpServletRequest;

/**
 * 獲取路徑方法
 * @author lvkun
 *
 */
public class PathUtil {
    /**
     * 獲取相對路徑
     * @param contextPath
     * @return
     */
    public static String getAbsPath(String contextPath)
    {
        int index = contextPath.indexOf('?');
        if(index > -1)
        {
            return contextPath.substring(0, index);
        }
        return contextPath;
    }
    
    /**
     * 獲取方式
     * @param request
     * @return
     */
    public static String getContentType(HttpServletRequest request){
        String contentType = request.getContentType();
        if(contentType!=null&&contentType.contains("multipart/form-data")){
            contentType = "multipart/form-data";
        }else if(contentType!=null&&contentType.contains("text/plain")){
            contentType = "text/plain";
        }
        return contentType;
    }
}


五、
jmust.Common.TestProcessor   <pre name="code" class="html">jmust.Common.Test1Processor

就不創建了,運用的時候創建,並繼承Camel的Processor即可。


完畢!

發佈了75 篇原創文章 · 獲贊 8 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章