簡體   English   中英

沒有HTTP的Tomcat JSP / JSTL

[英]Tomcat JSP/JSTL without HTTP

我有一個在Tomcat 7下運行的非常標准的Web應用程序。

我現在要做的是利用JSP / JSTL作為獨立於Tomcat的HTTP / Web服務方面的模板語言來生成可以通過電子郵件發送並轉換為PDF的HTML。

有沒有其他人試圖這樣做,可以幫助我一些指示?

提前致謝。

與Stephen C所說的相反,是的,JSP是Servlets等等(並且Velocity非常好且易於使用)

但是,什么是Servlet?

這是一個界面。 一個主要方法的接口:

service(ServletRequest req, ServletResponse res)

找到JSP類,將其轉換為Servlet,創建ServletRequest和ServletResponse的實現,然后......

String jspClassName = findJspClassForJSP("your.jsp");
Class jspClass = Class.forName(jspClassName);
Servlet jspServlet = (Servlet)jspClass.newInstance();
MyServletRequest req = new MyServletRequest();
MyServletResponse resp = new MyServletResponse();
jspServlet.init();
jspServlet.service(req, resp);
jspServlet.destroy();
String results = reps.getContent();

這會有用嗎? 好吧,經過一些工作,它會。 顯然,您需要實現ServletRequest / Response的最小外觀以及您需要的JSP。 但是,您可能只需要屬性和流量。 如果你讓你的Response返回一個StringWriter,你就到了一半。

下一部分是從JSP創建servlet。 很方便,Jasper編譯器為您做到了 - 游戲正在調用它。 我從來沒有直接完成它,但顯然可以完成,因為servlet容器都可以完成它,以及JSPC腳本/ bat文件,ant任務,以及大多數使用Jasper的Servlet容器。 所以,那可以做到。 一旦你知道如何調用它,你就會知道JSP的最終生成的類名。 (參見樣本的第一行。)

我做過這個嗎? 不。但我打賭在不到一天的時間里,你會知道這是否可行。 我敢打賭,特別是如果你沒有參加任何類加載器惡作劇。 如果讓用戶更改並重新生成JSP,那么您可能會遇到問題(因此MyEmail.jsp會被編譯到MyEmail.class,MyEmail_2.class等)。 但是如果你自己調用Jasper,你可能會對此有更多的控制權。 另一個難點是確定JSP的類名。 大多數容器都遵循這里的基本模式,因此如果您在WAR生成的代碼中找到它,您可能會發現它。

保持JSP相當簡單(並且電子郵件模板不需要超級復雜的嵌入式Java或任何隨機調用),它更有可能工作。

您的解決方案可能無法從Tomcat開箱即用,但您可能不會關心。 我與之交談的人使用JSP作為模板,只需打開一個套接字到他們自己的服務器並提出請求。 他們也沒走這么遠。

但從表面上看,保存一些糟糕的類裝載機黑洞地獄,我打賭你可以很快地使用它。 盡可能少地執行請求和響應,打幾個NPE作為JSP和JSTL調用你沒有計划的東西,並且正如聖誕老人所說,

劈開,劈開,劈開所有!

附加物:

所以,對於所有的反對者......

public void runJsp() {
    JspC jspc = new JspC();
    jspc.setUriroot("/tmp/app");
    jspc.setOutputDir("/tmp/dest");
    jspc.setJspFiles("newjsp.jsp");
    jspc.setCompile(true);
    try {
        jspc.execute();
        Class cls = Class.forName("org.apache.jsp.newjsp_jsp");
        Servlet s = (Servlet) cls.newInstance();
        MyRequest req = new MyRequest();
        MyResponse resp = new MyResponse();

        s.init(getServletConfig());
        s.service(req, resp);
        s.destroy();
        System.out.println(resp.getSw().toString());
    } catch (JasperException ex) {
        throw new RuntimeException(ex);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(ex);
    } catch (InstantiationException ex) {
        throw new RuntimeException(ex);
    } catch (IllegalAccessException ex) {
        throw new RuntimeException(ex);
    } catch (ServletException ex) {
        throw new RuntimeException(ex);
    } catch (IOException ex) {
        throw new RuntimeException(ex);
    }
}

令人驚訝的是,調試器中的源代碼和1/2小時將為您做什么。

我在/tmp/app/newjsp.jsp中創建了一個簡單的JSP。

jspc.setUriroot告訴編譯器“web app”的基礎所在的位置。 jspc.setOutputDir告訴jspc將生成的Java和Class文件放在何處。 jspc.setJspFiles根據URI Root告訴jspc要編譯哪些文件。 jspc.setCompile告訴它實際編譯代碼。 最后,jspc.execute()執行契約。

默認情況下,Jasper使用包org.apache.jsp,並根據JSP文件名創建一個新類。 對於我的簡單實驗,我只需將“/ tmp / dest”放到我的Glassfish容器的類路徑上,這樣容器就可以找到生成的類。

我加載類,並獲得一個實例。

最后,我創建了MyRequest,MyRequest,最終創建了MySession。 我的IDE方便地為各個接口創建了存根。 在這種情況下,我實現了:MyRequest.getSession(),MyResponse.setContentType(),MyResponse.setBufferSize()和MyResponse.getWriter()。

public PrintWriter getWriter() throws IOException {
    if (sw == null) {
        sw = new StringWriter();
        pw = new PrintWriter(sw);
    }
    return pw;
}

顯然,sw和pw是MyResponse的實例變量。

MyRequest返回了MySession的一個實例。 我對MySession的實現確實沒有。 但是運行時需要一個Session,它本身並不是為了我的非常簡單的JSP而單獨使用它,而且我沒有動機從Servlet中填充它。

我在Glassfish v2.1上測試了這個。 我只是將appserv_rt.jar(來自glassfish / lib)添加到我的構建類路徑(因此它可以找到JspC jar),但我沒有將它捆綁在WAR中(因為它已經在容器中)。

而且,shazam,它的工作原理。 在“現實生活”中,假設想要利用JSP的進程實際上來自Web請求,我只需創建一個HttpServletResponseWrapper並覆蓋之前的三種方法,其余的可能就是Just Work。 如果Web請求根本不在圖片中,那么您需要創建自己的Session實現(真的沒什么大不了的,它只是一張地圖)。

我還使用私有URLClassLoader來加載虛假的JSP類。 如果我知道我永遠不會重新加載JSP,那么只需將目標作為我的WEB-INF / classes目錄並給它自己的包並讓系統加載它們。

但是,是的,它有效。 沒什么大不了。 這只是java。

這沒有多大意義。 JSP是一種很好的語法,可以生成Java EE servlet類。 實際上,JSP的“servlet”/“http”特性通過API和JSP和JSTL的語義模型完全交織在一起。

如果您想獨立於Web請求生成HTML,那么您最好使用不同的模板技術; 例如Velocity或FreeMarker。 如果您希望HTML也作為Web響應傳遞,請安排您的servlet調用模板引擎來生成響應。 (如果你使用的是Spring,那么現有的基礎設施就可以了。其他框架可能有類似的支持,但如果沒有,那么自己實現一些粘合代碼並不難。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM