Apache Felix加上Jasper-JSP支持 - 如何以正确的方式实现?

时间:2016-02-28 15:49:55

标签: jsp tomcat osgi

实际上问题是:如何正确地将tomcat-jasper jsp支持添加到felix osgi容器中?

我已经设法找到了一种方法来编写最少的java自定义代码,但是我确信这不是最“干净”或“正确”的方法。这种方法仍有一些局限性,因此这篇文章将展示我是如何做到这一点并询问如何“正确”地做到这一点。使用eclipse链接到示例:sample

所以我所做的是:

  1. 在默认的http-whiteboard配置和webconsole支持中设置Felix(不是真的需要,但是......你可以用它来检查jsp servlet部署是否正常)。我使用了5.4.0 dist,因为它似乎是目前最新的。

  2. 添加了'jsp'和'jstl'api specs,'el'api spec + impl和'ecj'(已在maven repo中捆绑)。

  3. 使用<Embed-Dependency>'inline'<Import-Package>'*;resolution:=optional'<DynamicImport-Package>'*'对maven repos中发现的最新tomcat-jasper-8.0.32.jar(和依赖项)进行了Bundel化。是的,我知道,大'不 - 不',但人们不能指望贾斯珀提前知道它会编译什么。没有DI-P可能值得一试。后来。 Rebundelized相同(但没有DI-P)taglibs-standard-impl-1.2.5因为虽然pom指定xalan依赖项可选,但bundle清单却没有。而且体面/最近的java内置了xml解析,所以我'也可以选择'它的依赖关系。无论如何,我希望有一天tomcat能够成为它的罐子,并且还会产生一个更符合osgi的taglib-standard-impl。

  4. 结果是:

    felix.base
      |-- bin
        |-- felix.jar
      |-- bundle
        |-- ecj-4.4.2.jar
        |-- javax.el-3.0.0.jar
        |-- javax.servlet.jsp-api-2.3.1.jar
        |-- javax.servlet.jsp.jstl-api-1.2.1.jar
        |-- org.apache.felix.bundlerepository-2.0.6.jar
        |-- org.apache.felix.configadmin-1.8.8.jar
        |-- org.apache.felix.eventadmin-1.4.6.jar
        |-- org.apache.felix.gogo.command-0.16.0.jar
        |-- org.apache.felix.gogo.runtime-0.16.2.jar
        |-- org.apache.felix.gogo.shell-0.10.0.jar
        |-- org.apache.felix.http.api-3.0.0.jar
        |-- org.apache.felix.http.base-3.0.6.jar
        |-- org.apache.felix.http.jetty-3.1.6.jar
        |-- org.apache.felix.http.servlet-api-1.1.2.jar
        |-- org.apache.felix.webconsole-4.2.14-all.jar
        |-- taglibs-standard-impl-1.2.5.jar
        |-- tomcat-api-8.0.32.jar
        |-- tomcat-jasper-8.0.32.jar
        |-- tomcat-jasper-el-8.0.32.jar
        |-- tomcat-juli-8.0.32.jar
        |-- tomcat-util-8.0.32.jar
        |-- tomcat-util-scan-8.0.32.jar
    

    如果你正在查看附件,那么上面描述的所有内容都是通过'launcher / pom.xml'完成的。现在,如果你启动'启动器'(作为java应用程序运行),所有bundle都应该是活动的。到目前为止还没有java编码,只有'customization'是tomcat jar的bundelization和taglib-standard-impl的重新发布。

    现在为'jsp-magic':

    1. 创建了新的bundle(使用了'karaf-bundle'maven archetype)。下面的依赖和捆绑清单的Activator和pom.xml(取自附件)。
    2. 激活:

      public class Activator implements BundleActivator {
          public static String CONTEXT = "dummy";
          public static String BASE_URL = "/dummy";
      
          private ServletContextHelper servletContextHelper = null;
          private ServiceRegistration<?> schRegistration = null;
          private ServiceRegistration<Servlet> jspServletRegistration = null;
      
          public void start(BundleContext context) {
              // http support
              servletContextHelper = new ServletContextHelper() {
                  @Override
                  public URL getResource(String name) {
                      if (name.startsWith("file:")) {
                          // this is an absolute URL, so it is already rendered
                          try {
                              return new URL(name);
                          } catch (Exception e) {
                              return null;
                          }
                      }
                      // render it in the webcontet dir
                      return FrameworkUtil.getBundle(this.getClass()).getResource("/webcontent" + name);
                  }
      
                  @Override
                  public Set<String> getResourcePaths(String path) {
                      if ("/WEB-INF/lib/".equals(path)) {
                          // jasper scans for tag libraries so give him all bundles in the container
                          Set<String> jars = new HashSet<String>();
                          Bundle thisBundle = FrameworkUtil.getBundle(ServletContextHelper.class);
                          try {
                              // look in the location of current bundle (assume they're all in the same place)
                              File deployDir = new File(new URI(thisBundle.getLocation())).getParentFile();
                              File[] files = deployDir.listFiles();
                              for (File file : files)
                                  jars.add(file.toURI().toURL().toExternalForm());
                          } catch (Exception e) {
                              e.printStackTrace();
                          }
                          return jars;
                      }
                      return super.getResourcePaths(path);
                  }
              };
      
              Hashtable<String, Object> httpContextProps = new Hashtable<String, Object>();
              httpContextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, CONTEXT);
              httpContextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, BASE_URL);
              schRegistration = context.registerService(ServletContextHelper.class, servletContextHelper, httpContextProps);
      
              @SuppressWarnings("serial")
              JspServlet jspServlet = new JspServlet() {
                  @Override
                  public void init(ServletConfig config) throws ServletException {
                      JspFactory.setDefaultFactory(new JspFactoryImpl());
      
                      ClassLoader current = Thread.currentThread().getContextClassLoader();
                      Thread.currentThread().setContextClassLoader(JspServlet.class.getClassLoader());
                      ServletContainerInitializer sci = new JasperInitializer();
                      sci.onStartup(null, config.getServletContext());
                      super.init(config);
                      Thread.currentThread().setContextClassLoader(current);
                  }
      
                  @Override
                  public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                      ClassLoader current = Thread.currentThread().getContextClassLoader();
                      Thread.currentThread().setContextClassLoader(JspServlet.class.getClassLoader());
                      super.service(req, resp);
                      Thread.currentThread().setContextClassLoader(current);
                  }
      
              };
      
              Hashtable<String, Object> jspProps = new Hashtable<String, Object>();
              jspProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "JSP servlet");
              jspProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "*.jsp");
              jspProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=" + CONTEXT + ")");
              jspServletRegistration = context.registerService(Servlet.class, jspServlet, jspProps);
          }
      
          public void stop(BundleContext context) {
              jspServletRegistration.unregister();
              schRegistration.unregister();
          }
      }
      

      捆绑pom:

      <project>
          <modelVersion>4.0.0</modelVersion>
      
          <groupId>dummy.jsp</groupId>
          <artifactId>dummy.jsp.osgi</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <packaging>bundle</packaging>
      
          <name>dummy.jsp.osgi</name>
      
          <properties>
              <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
              <osgi.version>6.0.0</osgi.version>
              <osgi.http.whiteboard.version>1.0.0</osgi.http.whiteboard.version>
              <javax.servlet-api.version>3.1.0</javax.servlet-api.version>
              <javax.servlet.jsp-api.version>2.3.1</javax.servlet.jsp-api.version>
              <javax.servlet.jsp.jstl-api.version>1.2.1</javax.servlet.jsp.jstl-api.version>
              <javax.el-api.version>3.0.0</javax.el-api.version>
          </properties>
      
          <dependencies>
              <dependency>
                  <groupId>org.osgi</groupId>
                  <artifactId>org.osgi.core</artifactId>
                  <version>${osgi.version}</version>
                  <scope>provided</scope>
              </dependency>
              <dependency>
                  <groupId>org.osgi</groupId>
                  <artifactId>org.osgi.service.http.whiteboard</artifactId>
                  <version>${osgi.http.whiteboard.version}</version>
                  <scope>provided</scope>
              </dependency>
              <dependency>
                  <groupId>javax.servlet</groupId>
                  <artifactId>javax.servlet-api</artifactId>
                  <version>${javax.servlet-api.version}</version>
                  <scope>provided</scope>
              </dependency>
              <dependency>
                  <groupId>javax.servlet.jsp</groupId>
                  <artifactId>javax.servlet.jsp-api</artifactId>
                  <version>${javax.servlet.jsp-api.version}</version>
                  <scope>provided</scope>
              </dependency>
              <dependency>
                  <groupId>javax.servlet.jsp.jstl</groupId>
                  <artifactId>javax.servlet.jsp.jstl-api</artifactId>
                  <version>${javax.servlet.jsp.jstl-api.version}</version>
                  <scope>provided</scope>
              </dependency>
              <dependency>
                  <groupId>org.apache.tomcat</groupId>
                  <artifactId>tomcat-jasper</artifactId>
                  <version>8.0.32</version>
                  <scope>provided</scope>
              </dependency>
          </dependencies>
          <build>
              <plugins>
                  <plugin>
                      <groupId>org.apache.felix</groupId>
                      <artifactId>maven-bundle-plugin</artifactId>
                      <version>3.0.1</version>
                      <extensions>true</extensions>
                      <configuration>
                          <instructions>
                              <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                              <Bundle-Version>${project.version}</Bundle-Version>
                              <Bundle-Activator>dummy.jsp.osgi.Activator</Bundle-Activator>
                              <Export-Package>
                                  dummy.jsp.osgi;version=${project.version},
                              </Export-Package>
                              <Import-Package>
                                  *;resolution:=optional
                              </Import-Package>
                          </instructions>
                      </configuration>
                  </plugin>
              </plugins>
          </build>
      </project>
      

      打开浏览器并转到localhost:8080 / dummy / jsp / test.jsp和/testStandard.jsp。两者都应该很好。

      上述翻译:

      • JspServlet需要将JspFactory设置为JspFactoryImpl 来自jasper罐子,明确地说。
      • 必须在启动时显式调用JasperInitializer,因为这是 不是Tomcat servlet容器而是'bundelized'Jetty。除非 有人知道某种方式在某处以某种方式配置它。
      • JspServle t需要将ClassLoader设置为它的bundle init上的类加载器和service来电
      • ServletContextHelper必须解决中的/WEB-INF/lib/个罐子 为了向jasper提供taglib jar(示例将呈现 所有部署的捆绑包列表)
      • ServletContextHelper必须核心地解析被调用的'jsp' 文件到软件包中的资源

      到目前为止我发现的限制是虽然<jsp:include>有效,但包括<jsp:param> - s却没有。还没弄清楚它是否与我的设置,码头相关,与felix相关或与osgi相关。在这方面有任何暗示欢迎。

      问题是,如何以正确的方式做到这一点?可以执行哪些配置增强,例如允许跳过JasperInitializer调用或JspFactory显式init。没有找到很多关于这个主题的文档,大多数我已经'调试过'tomcat和felix。

0 个答案:

没有答案