Мне нужен программный рендеринг страницы JSP.
Какое функциональное требование в конце концов? Вы явно ищете решение в неправильном направлении. Что это, проблема / требование, для которого вы думаете, что это решение? Мы можем предложить лучшие предложения.
Вам, например, нужен только вывод ? Если так, то java.net.URLConnection
может быть достаточно.
Редактировать : вы редактировали свой вопрос:
Я хочу каким-то образом изменить исходную JSP перед компиляцией (для точного объединения двух JSP), поэтому мне нужен способ для компиляции результата JSP из InputStream (или Reader) с использованием компилятора JSP напрямую.
ОК, это бит более ясно. Но зачем тебе это? Что на самом деле представляют эти JSP? Для чего нужен конечный результат?
Вы, например, просто хотите включить один JSP в другой? Например. включая head.jsp
в main.jsp
? Если так, то <jsp:include>
может быть достаточно. Или, что еще хуже, они содержат сырой код Java с каким-то конкретным кодом, который вы хотели бы использовать повторно? Если это так, то вы должны использовать простые классы Java и, если необходимо, теги библиотеки для этого.
Редактировать 2 : как вы прокомментировали:
Но теперь нам нужен способ использовать эти страницы JSP (которые, кстати, хранятся в памяти) в качестве макетов для всех страниц JSP, которые пользователь запрашивает
Просто сохраните файлы JSP в файловой системе диска внутри веб-контента веб-приложения (здесь может прийти в помощь ServletContext#getRealPath()
) и перенаправьте запрос в свой собственный основной файл JSP, который включает в себя два файла JSP, например:
<jsp:include page="${page1}" />
<jsp:include page="${page2}" />
Редактировать 3 : я создал SSCCE , чтобы доказать его работу.
package mypackage;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
File root = new File(getServletContext().getRealPath("/"));
String main = "<jsp:include page=\"${page1}\" /><jsp:include page=\"${page2}\" />";
write(main, new File(root, "main.jsp"));
String page1 = "<p>We are in ${data1}";
write(page1, new File(root, "page1.jsp"));
request.setAttribute("page1", "page1.jsp");
request.setAttribute("data1", "first jsp");
String page2 = "<p>We are in ${data2}";
write(page2, new File(root, "page2.jsp"));
request.setAttribute("page2", "page2.jsp");
request.setAttribute("data2", "second jsp");
request.getRequestDispatcher("main.jsp").forward(request, response);
}
private static void write(String content, File file) throws IOException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
writer.write(content);
} finally {
if (writer != null) try { writer.close(); } catch (IOException ignore) {}
}
}
}
Выполните его на http://localhost:8080/playground/test (или любом другом имени хоста / контекста), и вы увидите
We are in first jsp
We are in second jsp
Чтобы сделать его более эффективным, я бы кэшировал каждый ресурс и использовал File#exists()
, чтобы проверить, сохранена ли конкретная страница на диске.