Это продолжение вопроса 'overhead of jsp include' ниже:
Производительность JSP с использованием jsp: include
В нашем приложении разработчики имеют «модульные» фрагменты jsp, интенсивно используя «jsp: includes» для «общего» кода jsp, повторяемого в приложении.
1010 * Pros *
Плюсы:
это СУХОЙ - мы определяем фрагмент jsp один раз. Это большая помощь, когда вам нужно изменить html и не нужно искать / заменять / искать / уничтожать.
за ним довольно легко следить: вы четко передаете параметры. Когда вы редактируете «включенную» страницу, вы «знаете, что вы получаете», то есть против некоторых «глобальных переменных», объявленных на странице «включающие / вызывающие».
Против
- накладные расходы на выполнение дополнительного запроса
Вопросы
Итак, как продолжение:
- сколько накладных расходов несет «jsp: include»? Это не очевидно из кода Tomcat (хотя вы видите, что он делает гораздо больше, чем встроенный вызов). Также при профилировании приложения я никогда не запрашиваю методы requestDispatcher.include () или invoke () как горячие точки.
- Может ли кто-нибудь указать, где именно находится основная часть накладных расходов? (то есть метод X в классе Y) Или это просто все "мелочи" (например, установка атрибутов или создание объектов и последующий сборщик мусора), которые происходят с каждым запросом?
- какие есть альтернативы? (AFAIK @include и jsp: включить. Что-нибудь еще?)
- (глупый бонусный вопрос), почему движок сервлета не может «включать» jsp во время компиляции, то есть как «встроенный макрос с параметрами», чтобы мы, разработчики, могли получить ясность «jsp: include» и производительности из @include.
Некоторое время я задавался вопросом об этом последнем вопросе. В прошлой жизни я пользовался инструментами генерации кода и никогда не понимал недостатка вариантов включения фрагментов jsp.
Для удобства читателя я включил метод tomcat 'applicationDispatcher.invoke ()' (tomcat 5.5. Извините, если он устарел). Для ясности я сократил обработку исключений.
заранее спасибо
будет
private void invoke(ServletRequest request, ServletResponse response,
State state) throws IOException, ServletException {
// Checking to see if the context classloader is the current context
// classloader. If it's not, we're saving it, and setting the context
// classloader to the Context classloader
ClassLoader oldCCL = Thread.currentThread().getContextClassLoader();
ClassLoader contextClassLoader = context.getLoader().getClassLoader();
if (oldCCL != contextClassLoader) {
Thread.currentThread().setContextClassLoader(contextClassLoader);
} else {
oldCCL = null;
}
// Initialize local variables we may need
HttpServletResponse hresponse = (HttpServletResponse) response;
Servlet servlet = null;
IOException ioException = null;
ServletException servletException = null;
RuntimeException runtimeException = null;
boolean unavailable = false;
// Check for the servlet being marked unavailable
if (wrapper.isUnavailable()) {
wrapper.getLogger().warn(
sm.getString("applicationDispatcher.isUnavailable",
wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE))
hresponse.setDateHeader("Retry-After", available);
hresponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm
.getString("applicationDispatcher.isUnavailable", wrapper
.getName()));
unavailable = true;
}
// Allocate a servlet instance to process this request
try {
if (!unavailable) {
servlet = wrapper.allocate();
}
}
...exception handling here....
// Get the FilterChain Here
ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain = factory.createFilterChain(request,
wrapper,servlet);
// Call the service() method for the allocated servlet instance
try {
String jspFile = wrapper.getJspFile();
if (jspFile != null)
request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
else
request.removeAttribute(Globals.JSP_FILE_ATTR);
support.fireInstanceEvent(InstanceEvent.BEFORE_DISPATCH_EVENT,
servlet, request, response);
// for includes/forwards
if ((servlet != null) && (filterChain != null)) {
filterChain.doFilter(request, response);
}
// Servlet Service Method is called by the FilterChain
request.removeAttribute(Globals.JSP_FILE_ATTR);
support.fireInstanceEvent(InstanceEvent.AFTER_DISPATCH_EVENT,
servlet, request, response);
}
...exception handling here....
// Release the filter chain (if any) for this request
try {
if (filterChain != null)
filterChain.release();
}
...exception handling here....
// Deallocate the allocated servlet instance
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
}
...exception handling here....
// Reset the old context class loader
if (oldCCL != null)
Thread.currentThread().setContextClassLoader(oldCCL);
// Unwrap request/response if needed
// See Bugzilla 30949
unwrapRequest(state);
unwrapResponse(state);
// Rethrow an exception if one was thrown by the invoked servlet
if (ioException != null)
throw ioException;
if (servletException != null)
throw servletException;
if (runtimeException != null)
throw runtimeException;
}