Ответ 1
Мне нужно программно отобразить страницу JSP.
Какое функциональное требование в конце концов? Вы явно ищете решение в неправильном направлении. Что это, проблема/требование, для которого вы думаете, что это решение? Мы можем придумать лучшие предложения.
Вам, например, нужен только его выход? Если да, то java.net.URLConnection
может быть достаточно.
Изменить: вы отредактировали свой вопрос:
Я хочу изменить исходный JSP до компиляции в некотором роде (объединить два JSP вместе, чтобы быть точным), поэтому мне нужен способ скомпилировать результат JSP из InputStream (или Reader) с помощью JSP-компилятора напрямую.
ОК, это немного более понятно. Но зачем вам это нужно? Что представляют собой эти JSP? Каков конечный результат, который должен использоваться для?
Вы, например, просто хотите включить один JSP в другой? Например. включая a head.jsp
в main.jsp
? Если да, то <jsp:include>
может быть достаточно. Или это еще хуже, содержат ли они необработанный код Java с определенным кодом, который вы хотели бы использовать повторно? Если это так, то вам следует использовать простые классы Java и, если необходимо, теги для этого.
Изменить 2: как вы прокомментировали:
Но теперь нам нужен способ использовать эти JSP-страницы (которые хранятся в памяти, кстати) как макеты для всех страниц JSP, которые пользователь запрашивает
Просто сохраните JSP файлы в файловой системе диска в webapp webcontent (здесь может появиться 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()
, чтобы проверить, сохранена ли эта страница на диске.