天天看點

使用嵌入式Jetty遇到的自定義标簽問題

公司舊項目,使用<#assign shi=JspTaglibs["http://shiro.apache.org/tags"]/>來引入自定義标簽,使用Java代碼進行啟動時,提示TLD檔案無法加載。

原因可能是:

Jetty的jsp處理引擎來自于Glassfish,要求JSF标簽必須位于Jetty容器的classpath中,不能位于Web應用的classpath中,而Jetty的WebAppClassLoader優先使用父classloader加載類,導緻tld檔案都被加載到父classloader中,在Jetty的classpath中根本掃描不到,是以會出現找不到tld檔案的情況。

嘗試在啟動代碼中處理,但是不生效,文章後邊的啟動代碼中,注釋部分為嘗試的解決方法,都未成功。

最後通過使用相對路徑引入标簽解決:<#assign shi=JspTaglibs["/WEB-INF/tld/shiro.tld"]/>

Jetty啟動代碼:

public static final String[] TLD_JAR_NAMES = new String[] { "sitemesh", "spring-webmvc", "shiro-web", "springside-core", "shiro" };

    public static void main(String[] args) {

        /* fix jetty8.x, jetty 9.x can't load jstl library */

//        try {
//            Field f = TldScanner.class.getDeclaredField("systemUris");
//            f.setAccessible(true);
//            ((Set<?>) f.get(null)).clear();
//            f.setAccessible(false);
//        } catch (NoSuchFieldException e) {
//            e.printStackTrace();
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        }

        // 伺服器的監聽端口
        Server server = new Server(9999);
        // 設定在JVM退出時關閉Jetty的鈎子。
        server.setStopAtShutdown(true);
        // 關聯一個已經存在的上下文
        WebAppContext context = new WebAppContext();
        // 設定描述符位置
        context.setDescriptor("src/main/webapp/WEB-INF/web.xml");
        // 設定Web内容上下文路徑
        context.setResourceBase("src/main/webapp");
        // 設定上下文路徑
        context.setContextPath("/");
        context.setParentLoaderPriority(true);

//        WebAppContext context = new WebAppContext("src/main/webapp", "/");

//        context.setClassLoader(Thread.currentThread().getContextClassLoader());
//        context.setDescriptor("src/main/webapp/WEB-INF/web.xml");

        server.setHandler(context);

//        JettyFactory.setTldJarNames(server, TLD_JAR_NAMES);
//        context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*/[^/]*servlet-api-[^/]*\.jar$|.*/javax.servlet.jsp.jstl-.*\.jar$|.*/org.apache.taglibs.taglibs-standard-impl-.*\.jar$");
//        Server server = JettyFactory.createServerInSource(9999, "/");

        try {
            server.start();
//            server.join();
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("server is  start");
    }

    /**
     * 設定除jstl-*.jar外其他含tld檔案的jar包的名稱.
     * jar名稱不需要版本号,如sitemesh, shiro-web
     */
    public static void setTldJarNames(Server server, String... jarNames) {
        WebAppContext context = (WebAppContext) server.getHandler();
        List<String> jarNameExprssions = Lists.newArrayList(".*/jstl-[^/]*\.jar$", ".*/.*taglibs[^/]*\.jar$");
        for (String jarName : jarNames) {
            jarNameExprssions.add(".*/" + jarName + "-[^/]*\.jar$");
        }

        context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",
                StringUtils.join(jarNameExprssions, '|'));

    }