实际上问题是:如何正确地将tomcat-jasper jsp支持添加到felix osgi容器中?
我已经设法找到了一种方法来编写最少的java自定义代码,但是我确信这不是最“干净”或“正确”的方法。这种方法仍有一些局限性,因此这篇文章将展示我是如何做到这一点并询问如何“正确”地做到这一点。使用eclipse链接到示例:sample
所以我所做的是:
在默认的http-whiteboard配置和webconsole支持中设置Felix(不是真的需要,但是......你可以用它来检查jsp servlet部署是否正常)。我使用了5.4.0 dist,因为它似乎是目前最新的。
添加了'jsp'和'jstl'api specs,'el'api spec + impl和'ecj'(已在maven repo中捆绑)。
使用<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。
结果是:
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':
激活:
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。