osgi實戰項目(osmp)一步一步玩轉osgi之攔截器(8)

在osmp裏,osmp-http對外發布了統一的訪問接口,接受請求解析後從osmp-service容器裏獲取服務,調用並將結果返回,在這個過程當中,咱們經過編寫自定義的攔截器對請求進行攔截,主要應用如下場景 (安全、權限、數據過濾、數據格式化、記錄入參、出參日誌、調用統計分析、全鏈路日誌等AOP形爲)。java

下面咱們介紹怎樣在osmp框架下編寫咱們的第一個攔截器對非法IP的請求進行攔截。web

 

一、參照前面講的第一個服務的開發,搭建組件開發環境,把沒有的類和包刪除。spring

二、新增攔截器實現類OsmpDemoInterceptor.javaapache

 

/*   
 * Project: 基礎組件 
 * FileName: SicentTestServiceImpl.java
 * Company: Chengdu Sicent Technology Co.,Ltd
 * version: V1.0
 */
package com.osmp.demo.interceptor;

import org.springframework.stereotype.Component;

import com.osmp.intf.define.config.FrameConst;
import com.osmp.intf.define.interceptor.ServiceInterceptor;
import com.osmp.intf.define.interceptor.ServiceInvocation;
import com.osmp.intf.define.model.ServiceContext;


/**
 * Description:日誌攔截用於統計日誌訪問提供支撐數據
 * 
 * @author: wangkaiping
 * @date: 2014年9月26日 下午3:03:55
 */
@Component
public class OsmpDemoInterceptor implements ServiceInterceptor {


	@Override
	public Object invock(ServiceInvocation invocation) {
		ServiceContext context = invocation.getContext();
		String ip = context.getClientInfo().get(FrameConst.CLIENT_IP);
		String serviceName = context.getServiceName();
		System.out.println("serviceName : " + serviceName);
		System.out.println("IP攔截 : " + ip);
		if ("192.168.1.1".equals(ip)) {
			return "IP非法!";
		} else {
			return invocation.process();
		}
	}
}

 

 

實現osmp-intf-define 定義的攔截器接口 ServiceInterceptor.java, 這裏咱們從ServiceInvocation裏獲取ServiceContext 上下文,並獲得客戶端信息。安全

 

從客戶端信息裏獲取客戶端IP 判斷 客戶端IP是否爲 "192.168.1.1" 若是是的話咱們返回IP非法,若是不是則執行請求並返回!框架

 

攔截器接口定義 ServiceInterceptor.javamaven

 

/*   
 * Project: OSMP
 * FileName: ServiceInterceptor.java
 * version: V1.0
 */
package com.osmp.intf.define.interceptor;

/**
 * Description:攔截器
 * 全部基於osmp的攔截器都須要實現該接口,攔截器按做用域分爲全局攔截器,BUNDLE攔截器,SERVICE攔截器三種類型。
 *        全局攔截器(ALL):      做用於osmp的全部BUNDLE和服務。
 *   BUNDLE攔截器(BUNDLE):     做用於osmp指定BUNDLE下的全部服務。
 * SERVICE攔截器(SERVICE):     做用於osmp指定的SERVICE服務。
 * 
 * 攔截器適用於 接口安全、權限校驗、全局日誌、調用鏈日誌Track、特定服務AOP攔截等業務場景
 * 
 * 服務發佈時,須要在service-properties 裏指定攔截器的類型(type)和匹配的攔截策略(pattern)
 * 
 * <osgi:service interface="com.osmp.intf.define.interceptor.ServiceInterceptor" ref="osmp.demo.interceptor">
		<osgi:service-properties>
			<entry key="name" value="Interceptor_demo" />
			<entry key="mark" value="攔截器demo"/>
			<entry key="type" value="SERVICE"/> //type:ALL、BUNDLE、SERVICE
			<entry key="pattern" value="這裏是發佈的服務名稱"/>  //支持正則匹配、   AAAService*  、  *AAA* 、   
		</osgi:service-properties>
	</osgi:service>
 * 
 * 攔截器與bundle、服務兩種綁定方式:
 * 一、攔截器被安裝時osmp-service組件進行bundle監聽時,經過bundle獲取interface service 後解析type和 pattern並注入到ServiceContainer中。
 * 二、經過osmp-web在線能夠綁定和解綁攔截器與bundle、服務。
 * 
 * @author: wangkaiping
 * @date: 2016年8月9日 上午9:26:32上午10:51:30
 */
public interface ServiceInterceptor {
    Object invock(ServiceInvocation invocation);
}

 

 

ServiceInvocation定義了  ServiceContext getContext(); Object process(); 兩個接口,ide

 

getContext()接口獲取服務上下文,上下文包含了 請求客戶端基本信息、請求參數、服務名稱、及請求的url字符串等信息ui

 

process()請求執行接口,默認實現爲,先從攔截器鏈裏獲取此服務對應的攔截器,若是攔截器鏈爲空則直接執行BaseDataService的execture() 調用服務,若是不爲空則執行調用攔截器鏈執行。this

 

默認爲 Invocation 實現 DefaultServiceInvocation.java

 

/*   
 * Project: OSMP
 * FileName: DefaultServiceInvocation.java
 * version: V1.0
 */
package com.osmp.http.tool;

import java.util.List;

import com.osmp.intf.define.interceptor.ServiceInterceptor;
import com.osmp.intf.define.interceptor.ServiceInvocation;
import com.osmp.intf.define.model.ServiceContext;
import com.osmp.intf.define.service.BaseDataService;

/**
 * 服務攔截器調用
 * @author heyu
 *
 */
public class DefaultServiceInvocation implements ServiceInvocation {
    private int currentInterceptorIndex = 0;
    private List<ServiceInterceptor> interceptorChain;
    private BaseDataService dataService;
    private ServiceContext context;
    private boolean isError = true;
    
    @Override
    public Object process() {
        if(interceptorChain == null || interceptorChain.isEmpty()){
            isError = false;
            return dataService.execute(context.getParameter());
        }
        if(currentInterceptorIndex == interceptorChain.size()){
            isError =false;
            return dataService.execute(context.getParameter());
        }
        ++currentInterceptorIndex;
        return interceptorChain.get(currentInterceptorIndex-1).invock(this);
    }

    public DefaultServiceInvocation(List<ServiceInterceptor> interceptorChain,
            BaseDataService dataService, ServiceContext context) {
        super();
        this.interceptorChain = interceptorChain;
        this.dataService = dataService;
        this.context = context;
    }

    @Override
    public ServiceContext getContext() {
        return context;
    }

    public boolean isError() {
        return isError;
    }
    

}

 

三、編寫spirng配置文件 /src/main/resources/META-INF/spring/spirng-context.xml

 

<?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:osgi="http://www.springframework.org/schema/osgi"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi-1.2.xsd">

	<context:component-scan base-package="com.osmp.demo.interceptor"></context:component-scan>

	<bean id="osmp.demo.interceptor" class="com.osmp.demo.interceptor.OsmpDemoInterceptor" />
	<osgi:service interface="com.osmp.intf.define.interceptor.ServiceInterceptor" ref="osmp.demo.interceptor">
		<osgi:service-properties>
			<entry key="name" value="Interceptor_demo" />
			<entry key="mark" value="攔截器demo"/>
			<entry key="type" value="ALL"/>
			<entry key="pattern" value=""/>
		</osgi:service-properties>
	</osgi:service>
	
</beans>

 

  • 將攔截器實現發佈爲服務
  • 服務屬性包括 name、mark、type、pattern
  • name:攔截器名稱
  • mark:攔截器註釋 
  • type:攔截器類型(ALL:全局攔截   BUNDLE:bundle攔截器  SERVICE:服務攔截器)能夠省略,默認爲ALL 全局攔截
  • pattern:攔截匹配 (只有type 不爲 ALL生效,能夠省略 eg: 正則匹配、   AAAService*  、  *AAA* )

四、pom.xml 配置

 

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>com.osmp.baseweb</groupId>
		<artifactId>osmp-parent</artifactId>
		<version>1.0.0</version>
	</parent>

	<artifactId>osmp-interceptor-demo</artifactId>
	<packaging>bundle</packaging>
	<name>osmp-interceptor-demo</name>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.felix</groupId>
				<artifactId>maven-bundle-plugin</artifactId>
				<extensions>true</extensions>
				<configuration>
					<instructions>
						<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
						<Export-Package></Export-Package>
						<Import-Package>
							*;resolution:=optional
						</Import-Package>
					</instructions>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>com.osmp.baseweb</groupId>
			<artifactId>osmp-intf-define</artifactId>
			<version>${osmp.version}</version>
		</dependency>
	</dependencies>
</project>

 

五、打包部署 mvn install ,將打好的bundle包(osmp-interceptor-demo-1.0.0.jar)部署到servicemix裏

 

 

六、將攔截器綁定,自動綁定、手動綁定兩種方式:

  • 自動綁定:在將攔截器部署到servicemix的時候 osmp-service會監聽攔截器接口服務,解析 typ、pattern進行自動綁定
  • 手動綁定:咱們將攔截器部署後,若是沒有添加type、pattern攔截器屬性時,能夠經過調用osmp-config提供的接口手動綁定。

 

 

 

 七、訪問請求

 

 

 攔截器已經 生效,咱們再停掉攔截器



 

再次訪問



 

 正常返回請求

 

至此基於osmp的攔截器開發已經完成。

相關文章
相關標籤/搜索