В отличие от того, что сказал Стивен С. Да, JSP - это сервлеты и т. Д. И т. Д. (И Velocity довольно хорош и прост в использовании)
Но что такое сервлет?
Это интерфейс. Интерфейс с одним основным методом:
service(ServletRequest req, ServletResponse res)
Найдите класс JSP, приведите его к сервлету, создайте реализации 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. Но, вероятно, вам, вероятно, понадобится немного больше, чем атрибуты и потоки. Если ваш ответ возвращает StringWriter, вы на полпути.
Следующая часть создает сервлет из JSP. Удобно, компилятор Jasper сделает это за вас - игра вызывает его. Я никогда не делал этого напрямую, но это, безусловно, можно сделать, так как это делает и контейнер сервлета, и файл сценария / bat JSPC, задача ant, а также большинство контейнеров сервлета, использующих Jasper. Итак, это можно сделать. Как только вы узнаете, как это вызывать, вы узнаете окончательное имя сгенерированного класса для JSP. (См. Первую строку образца.)
Я когда-нибудь делал это? Нет. Но я держу пари, что меньше чем через день возни, ты узнаешь, выполнимо это или нет. Могу поспорить, что это так, особенно если вы не столкнетесь с махинациями в классе. Возможно, у вас возникнет проблема, если вы позволите своим пользователям изменять и восстанавливать JSP (поэтому MyEmail.jsp скомпилируется в MyEmail.class, MyEmail_2.class и т. Д.). Но если вы сами призовете Джаспера, вы, вероятно, будете иметь больше контроля над этим.
Другая сложная часть - это определение имени класса JSP. Здесь большинство контейнеров следуют базовому шаблону, поэтому, если вы покопаетесь в сгенерированном коде из WAR, вы, скорее всего, найдете его.
Сделайте JSP достаточно простыми (шаблон электронной почты не должен слишком усложняться встроенной Java или чем-либо, выполняющим произвольные вызовы), и это еще более вероятно, что он будет работать.
Возможно, ваше решение не является переносимым из коробки из Tomcat, но, скорее всего, вам все равно. Люди, с которыми я говорил, которые используют JSP для шаблонов, просто открыли сокет для своего собственного сервера и сделали запрос. Они тоже не зашли так далеко.
Но на поверхности, за исключением какого-то дурацкого чёрного дырочного загрузчика класса, держу пари, вы можете заставить это работать довольно быстро. Реализуйте столько запросов и ответов, сколько вам нужно, сразитесь с несколькими NPE, как JSP и JSTL, которые вы не планировали, и, как говорит Санта,
Хак прочь, Хак прочь, хак прочь все!
Addenda:
Итак, для всех скептиков ...
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);
}
}
Удивительно, что исходный код и полчаса в отладчике сделают для вас.
Я создал простой JSP в /tmp/app/newjsp.jsp.
jspc.setUriroot сообщает компилятору, где находится база вашего "веб-приложения". jspc.setOutputDir сообщает jspc, куда поместить сгенерированные файлы Java и Class. jspc.setJspFiles сообщает jspc, какие файлы компилировать, основываясь на корне URI. 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 не работает - ничего.Но среда выполнения хотела сессию, она просто не использовала ее для моего очень простого JSP, и я не был заинтересован в том, чтобы заполнить тот из сервлета.
Я тестировал это на Glassfishv2.1.Я просто добавил appserv_rt.jar (из glassfish / lib) в мой путь к классу сборки (чтобы он мог найти jspC jars), но я не связываю его в WAR (так как он уже находится в контейнере).
И, шазам, это сработало.В «реальной жизни», предполагая, что процесс, который хотел использовать JSP, на самом деле был получен из веб-запроса, я просто создал бы HttpServletResponseWrapper и переопределил три предыдущих метода, остальные, вероятно, просто работали.Если веб-запроса вообще нет на картинке, вам нужно создать собственную реализацию Session (на самом деле ничего страшного, это просто карта).
Я бы также использовал частный URLClassLoaderзагрузить искусственные классы JSP.Если бы я ЗНАЛ, что я никогда не перезагрузил бы JSP, то просто сделал бы назначение моим каталогом WEB-INF / classes и предоставил бы ему свой собственный пакет и позволил бы системе загрузить их.
Но, да, это сработало.Ничего страшного.Это просто Java.