zoukankan      html  css  js  c++  java
  • 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类型的对象。但这个方法通过配置将类型写死了,如果是另外一种实现可能会出问题,还是没有第二种好,兼容其他情况。
        
    每多学一点知识,就少写一行代码。
  • 相关阅读:
    oc kvc的模式:匹配搜索模式(模式匹配)、装包解包
    编程语言的多态与动态
    swift的@objc总结
    swift函数的调用约定
    PHP实现微信退款的分析与源码实现
    【MySQL】20个经典面试题,全部答对月薪10k+
    redis面试题总结
    【Redis缓存机制】1.Redis介绍和使用场景
    php四种文件加载语句
    做网站-mysql表字段设计
  • 原文地址:https://www.cnblogs.com/guanmu/p/5239089.html
Copyright © 2011-2022 走看看