嵌入式Jetty无法解析jstl核心

时间:2017-05-11 01:45:44

标签: jsp jetty jstl embedded-jetty

过去几天我一直在尝试不同的事情,但我还是没有设法让它发挥作用。

我正在尝试创建一个带有嵌入式jetty的jar,可以运行java -jar MyApp.jar。 Servlet工作,没有taglib行的jsp文件可以正常工作,否则我得到500 Server not found错误:

org.apache.jasper.JasperException: The absolute uri: http://java.sun.com/jsp/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application

的build.gradle

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'application'

sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = "hello.App"

jar {
    manifest {
        attributes 'Main-Class': 'hello.App'
    }
}

task fatJar(type: Jar) {
    manifest {
        attributes 'Main-Class': 'hello.App'
    }
    baseName = project.name + '-all'
    from { configurations.compile.collect { it.isDirectory() ? it :zipTree(it) } }
    with jar
}

repositories {
    mavenCentral()
}

def jettyVersion = '9.4.5.v20170502'
dependencies {
    compile group: 'org.eclipse.jetty', name: 'jetty-webapp', version: jettyVersion
    compile group: 'org.eclipse.jetty', name: 'jetty-servlets', version: jettyVersion
    compile group: 'org.eclipse.jetty', name: 'jetty-annotations', version: jettyVersion
    compile group: 'org.eclipse.jetty', name: 'apache-jsp', version: jettyVersion
    compile group: 'org.eclipse.jetty', name: 'apache-jstl', version: jettyVersion

    compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.2'
    compile group: 'org.slf4j', name: 'jcl-over-slf4j', version: '1.7.7'
}

的web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="
        http://java.sun.com/xml/ns/j2ee
        http://java.sun.com/xml/ns/j2ee/web-app_3_0.xsd" version="3.0">

    <servlet>
        <servlet-name>HelloWorld</servlet-name>
        <servlet-class>hello.HelloWorldServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloWorld</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

JettyServer.java

package hello.jetty;

import java.io.OutputStream;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.URL;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class JettyServer {
    private static final Logger log = LoggerFactory.getLogger(JettyServer.class);

    public static final String WEBAPP_RESOURCES_LOCATION = "webapp";
    private static final int DEFAULT_PORT_START = 8080;
    private static final int DEFAULT_PORT_STOP = 8090;
    private final int startPort;
    private final int stopPort;

    public JettyServer() {
        this(DEFAULT_PORT_START, DEFAULT_PORT_STOP);
    }

    public JettyServer(int startPort, int stopPort) {
        this.startPort = startPort;
        this.stopPort = stopPort;
    }

    public void start() throws Exception {
        Server server = new Server(startPort);
        WebAppContext root = new WebAppContext();

        root.setContextPath("/");
        root.setDescriptor(WEBAPP_RESOURCES_LOCATION + "/WEB-INF/web.xml");

        URL webAppDir = Thread.currentThread().getContextClassLoader().getResource(WEBAPP_RESOURCES_LOCATION);
        if (webAppDir == null) {
            throw new RuntimeException(String.format("No %s directory was found in the JAR file", WEBAPP_RESOURCES_LOCATION));
        }

        root.setResourceBase(webAppDir.toURI().toString());
        root.setParentLoaderPriority(true);

        //Enable JSP & JSTL support
        Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
        classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration",
        "org.eclipse.jetty.plus.webapp.EnvConfiguration",
        "org.eclipse.jetty.plus.webapp.PlusConfiguration");
        classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration",
            "org.eclipse.jetty.annotations.AnnotationConfiguration");
        root.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
            ".*/[^/]*servlet-api-[^/]*\\.jar$|.*/javax.servlet.jsp.jstl-.*\\.jar$|.*/[^/]*taglibs.*\\.jar$" );

        server.setHandler(root);
        server.start();

        log.info("Jetty server started");
        log.debug("Jetty web server port: {}", startPort);
        log.debug("Port to stop Jetty with the 'stop' operation: {}", stopPort);

        Monitor monitor = new Monitor(stopPort, new Server[]{server});
        monitor.start();

        server.join();

        log.info("Jetty server exited");
    }

    public void stop() {
        stop(DEFAULT_PORT_STOP);
    }

    public void stop(Integer stopPort) {
        try {
            Socket s = new Socket(InetAddress.getByName("127.0.0.1"), stopPort);
            log.info("Jetty stopping...");
            s.setSoLinger(false, 0);
            OutputStream out = s.getOutputStream();
            out.write(("stop\r\n").getBytes());
            out.flush();
            s.close();
        } catch (ConnectException e) {
            log.info("Jetty not running!");
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    public static void main(String[] args) throws Exception {
        JettyServer jettyServer = new JettyServer();
        jettyServer.start();
    }
}

的index.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<!DOCTYPE html>
<html lang="en">
    <body>
        <%= new java.util.Date() %>
        <br>
        <br>
        <c:out var="${1+2}" />
    </body>
</html>

如何让jetty显示index.jsp文件?

更新:以下是gradle拉入的jar文件:

jetty-webapp-9.4.5.v20170502.jar
jetty-servlets-9.4.5.v20170502.jar
jetty-annotations-9.4.5.v20170502.jar
apache-jsp-9.4.5.v20170502.jar
apache-jstl-9.4.5.v20170502.jar
logback-classic-1.1.2.jar
jcl-over-slf4j-1.7.7.jar
jetty-xml-9.4.5.v20170502.jar
jetty-servlet-9.4.5.v20170502.jar
jetty-continuation-9.4.5.v20170502.jar
jetty-http-9.4.5.v20170502.jar
jetty-util-9.4.5.v20170502.jar
jetty-io-9.4.5.v20170502.jar
jetty-plus-9.4.5.v20170502.jar
javax.annotation-api-1.2.jar
asm-5.1.jar
asm-commons-5.1.jar
jetty-schemas-3.1.jar
javax.servlet-api-3.1.0.jar
apache-jsp-8.5.9.1.jar
ecj-4.4.2.jar
taglibs-standard-spec-1.2.5.jar
taglibs-standard-impl-1.2.5.jar
logback-core-1.1.2.jar
jetty-security-9.4.5.v20170502.jar
jetty-jndi-9.4.5.v20170502.jar
asm-tree-5.1.jar
apache-el-8.5.9.1.jar
jetty-server-9.4.5.v20170502.jar
slf4j-api-1.7.7.jar

在阅读本文时,我注意到apache-jsp在那里有两个不同的版本。可能有重复的罐子是我的问题?如果是这样,我如何让gradle排除其中一个?

1 个答案:

答案 0 :(得分:0)

这些不是重复的罐子,它们是两个不同的组ID,分别来自org.eclipse.jetty,一个来自org.mortbay.jasper。

我假设您的胖罐包含已从依赖罐中解压缩的所有类等。因此,您将不得不向org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern添加一个模式,该模式引用jar中这些类的位置:通常该模式包含jar文件名的模式列表检查tlds,但在你的情况下,tlds不包含在jar文件中。此外,我会仔细检查类加载器是否是URLClassloader:jetty遍历类加载器层次结构,寻找URLClassLoaders,它应该询问并匹配模式。

最后,IIWY,我不会这样做:)我会预先编译所有的jsps并将它们打包到你的胖罐中,这样你就可以消除所有即时发现和编译的问题。