Fork me on GitHub

osgi内嵌jetty容器添加过滤器

 一、 osgi内嵌jetty
     1、在MANIFEST.MF中添加"Service-Component : service.xml"
     2、通过注册HttpService的方式来注入eclipse自己的实现,然后通过httpService对象来添加servlet拦截请求。核心xml配置如下:
 
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr= "http://www.osgi.org/xmlns/scr/v1.1.0" name="org.guanmu.jetty"
    activate="startup" deactivate= "shutdown">
   <implementation class="org.guanmu.jetty.JettyService" />
   <reference bind="setHttpService" name= "httpService"
       interface="org.osgi.service.http.HttpService" policy="static"/>
</scr:component>
     
     3、通过httpService对象的registerServlet方法添加servlet。
 
二、问题描述
     httpService接口只提供了registerServlet、registerResources和unregister方法。没有添加过滤器的方法,所以当需要过滤需求(过滤非本地请求)时,则没法实现。
 
三、解决方案
     打断点可以发现,在jetty调用servlet的service方法之前,是由一个ProxyServlet类中完成的,调用时先判断是否有过滤器,没有过滤器时才走到service中。进一步发现ProxyServlet的过滤器list是在org.eclipse.equinox.http.servlet.internal.HttpServiceImpl中有添加过滤器的方法。打断点发现注入的httpService对象的实际就是该类实现的,所以将httpService对象强转为httpServiceImpl对象就可以添加过滤器了。由于是osgi插件开发,导入插件依赖后,发现还是无法导入该类,在build path中去掉插件访问权限的限制,就可以引入了。虽然检查没有错误,但是运行osgi时还是报错。
 
     1、由于能看到源码,所以尝试使用反射试试,没想到在有HttpServiceImpl 实例的情况下使用反射功能非常简单。实现如下:
 
            Class<?> implClass = httpService.getClass();
            Method method = implClass.getMethod("registerFilter", new Class[]{String.class,Filter.class,Dictionary.class,HttpContext.class});
            if (method == null) {
                logger.error("the httpService is not HttpServiceImpl.[" + httpService.getClass().getName() + "]");
                return;
            }
            method.invoke(httpService, new Object[]{"/", responseFilter, null, null});
     讲解:先获取到Classs对象(org.eclipse.equinox.http.servlet.internal.HttpServiceImpl类的),然后找到registerFilter方法,然后调用注册过滤器方法。该方案可以在不知道具体实现类的情况下直接调用某方法,如果没有该方法异常处理。
 
     2、通过看源码发现org.eclipse.equinox.http.servlet包有两个公开接口除了HttpService还有一个ExtendedHttpService,ExtendedHttpService继承HttpService接口,内部访问类HttpServiceImpl就是实现了ExtendedHttpService接口,且registerFilter方法就是在ExtendedHttpService接口中定义,所以直接将httpService对象转化为ExtendedHttpService类型的实例就可以调用registerFilter方法,比反射看起来更舒服。实现如下:
 
            if (!(httpService instanceof ExtendedHttpService)) {
                logger.error("the httpService is not ExtendedHttpService.[" + httpService.getClass().getName() + "]");
                return;               
            }
            ExtendedHttpService extendHttpService = (ExtendedHttpService) httpService;
            extendHttpService.registerFilter("/", responseFilter, null, null);
     
     3、通过service.xml配置发现,注入时指定了类型是HttpService,假如直接指定为ExtendedHttpService类型呢?实验结果是ok的,这样就可以直接使用ExtendedHttpService类型的对象。但这个方法通过配置将类型写死了,如果是另外一种实现可能会出问题,还是没有第二种好,兼容其他情况。
    
posted @ 2016-03-03 16:20  瓘木  阅读(1848)  评论(0编辑  收藏  举报