突然想到一个问题,在tomcat容器中访问index.jsp时,容器是怎么做的呢

今天看到tomcat conf中的web.xml的这样一段配置:


<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>

<!-- The mapping for the JSP servlet -->
<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>

<servlet-mapping>
<servlet-name>jsp</servlet-name>
<url-pattern>*.jspx</url-pattern>
</servlet-mapping>

这个servlet什么用呢?他拦截所有后缀时.jsp或.jspx后缀的请求,原来如此,以前是以为访问一个jspy页面,还以为是直接找到这个文件,原来是经过这个servlet来转发请求的。
看看这个servlet代码:



package org.apache.jasper.servlet;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.PeriodicEventListener;

import org.apache.jasper.Constants;
import org.apache.jasper.EmbeddedServletOptions;
import org.apache.jasper.Options;
import org.apache.jasper.compiler.JspRuntimeContext;
import org.apache.jasper.compiler.Localizer;
import org.apache.jasper.security.SecurityUtil;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;

/**
* The JSP engine (a.k.a Jasper).
*
* The servlet container is responsible for providing a
* URLClassLoader for the web application context Jasper
* is being used in. Jasper will try get the Tomcat
* ServletContext attribute for its ServletContext class
* loader, if that fails, it uses the parent class loader.
* In either case, it must be a URLClassLoader.
*
* @author Anil K. Vijendran
* @author Harish Prabandham
* @author Remy Maucherat
* @author Kin-man Chung
* @author Glenn Nielsen
*/
public class JspServlet extends HttpServlet implements PeriodicEventListener {

// Logger
private Log log = LogFactory.getLog(JspServlet.class);

private ServletContext context;
private ServletConfig config;
private Options options;
private JspRuntimeContext rctxt;


/*
* Initializes this JspServlet.
*/
public void init(ServletConfig config) throws ServletException {

super.init(config);
this.config = config;
this.context = config.getServletContext();

// Initialize the JSP Runtime Context
// Check for a custom Options implementation
String engineOptionsName =
config.getInitParameter("engineOptionsClass");
if (engineOptionsName != null) {
// Instantiate the indicated Options implementation
try {
ClassLoader loader = Thread.currentThread()
.getContextClassLoader();
Class engineOptionsClass = loader.loadClass(engineOptionsName);
Class[] ctorSig = { ServletConfig.class, ServletContext.class };
Constructor ctor = engineOptionsClass.getConstructor(ctorSig);
Object[] args = { config, context };
options = (Options) ctor.newInstance(args);
} catch (Throwable e) {
// Need to localize this.
log.warn("Failed to load engineOptionsClass", e);
// Use the default Options implementation
options = new EmbeddedServletOptions(config, context);
}
} else {
// Use the default Options implementation
options = new EmbeddedServletOptions(config, context);
}
rctxt = new JspRuntimeContext(context, options);

if (log.isDebugEnabled()) {
log.debug(Localizer.getMessage("jsp.message.scratch.dir.is",
options.getScratchDir().toString()));
log.debug(Localizer.getMessage("jsp.message.dont.modify.servlets"));
}
}


/**
* Returns the number of JSPs for which JspServletWrappers exist, i.e.,
* the number of JSPs that have been loaded into the webapp with which
* this JspServlet is associated.
*
* <p>This info may be used for monitoring purposes.
*
* @return The number of JSPs that have been loaded into the webapp with
* which this JspServlet is associated
*/
public int getJspCount() {
return this.rctxt.getJspCount();
}


/**
* Resets the JSP reload counter.
*
* @param count Value to which to reset the JSP reload counter
*/
public void setJspReloadCount(int count) {
this.rctxt.setJspReloadCount(count);
}


/**
* Gets the number of JSPs that have been reloaded.
*
* <p>This info may be used for monitoring purposes.
*
* @return The number of JSPs (in the webapp with which this JspServlet is
* associated) that have been reloaded
*/
public int getJspReloadCount() {
return this.rctxt.getJspReloadCount();
}


/**
* <p>Look for a <em>precompilation request</em> as described in
* Section 8.4.2 of the JSP 1.2 Specification. <strong>WARNING</strong> -
* we cannot use <code>request.getParameter()</code> for this, because
* that will trigger parsing all of the request parameters, and not give
* a servlet the opportunity to call
* <code>request.setCharacterEncoding()</code> first.</p>
*
* @param request The servlet requset we are processing
*
* @exception ServletException if an invalid parameter value for the
* <code>jsp_precompile</code> parameter name is specified
*/
boolean preCompile(HttpServletRequest request) throws ServletException {

String queryString = request.getQueryString();
if (queryString == null) {
return (false);
}
int start = queryString.indexOf(Constants.PRECOMPILE);
if (start < 0) {
return (false);
}
queryString =
queryString.substring(start + Constants.PRECOMPILE.length());
if (queryString.length() == 0) {
return (true); // ?jsp_precompile
}
if (queryString.startsWith("&")) {
return (true); // ?jsp_precompile&foo=bar...
}
if (!queryString.startsWith("=")) {
return (false); // part of some other name or value
}
int limit = queryString.length();
int ampersand = queryString.indexOf("&");
if (ampersand > 0) {
limit = ampersand;
}
String value = queryString.substring(1, limit);
if (value.equals("true")) {
return (true); // ?jsp_precompile=true
} else if (value.equals("false")) {
// Spec says if jsp_precompile=false, the request should not
// be delivered to the JSP page; the easiest way to implement
// this is to set the flag to true, and precompile the page anyway.
// This still conforms to the spec, since it says the
// precompilation request can be ignored.
return (true); // ?jsp_precompile=false
} else {
throw new ServletException("Cannot have request parameter " +
Constants.PRECOMPILE + " set to " +
value);
}

}


public void service (HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {

String jspUri = null;

String jspFile = (String) request.getAttribute(Constants.JSP_FILE);
if (jspFile != null) {
// JSP is specified via <jsp-file> in <servlet> declaration
jspUri = jspFile;
} else {
/*
* Check to see if the requested JSP has been the target of a
* RequestDispatcher.include()
*/
jspUri = (String) request.getAttribute(Constants.INC_SERVLET_PATH);
if (jspUri != null) {
/*
* Requested JSP has been target of
* RequestDispatcher.include(). Its path is assembled from the
* relevant javax.servlet.include.* request attributes
*/
String pathInfo = (String) request.getAttribute(
"javax.servlet.include.path_info");
if (pathInfo != null) {
jspUri += pathInfo;
}
} else {
/*
* Requested JSP has not been the target of a
* RequestDispatcher.include(). Reconstruct its path from the
* request's getServletPath() and getPathInfo()
*/
jspUri = request.getServletPath();
String pathInfo = request.getPathInfo();
if (pathInfo != null) {
jspUri += pathInfo;
}
}
}

if (log.isDebugEnabled()) {
log.debug("JspEngine --> " + jspUri);
log.debug("\t ServletPath: " + request.getServletPath());
log.debug("\t PathInfo: " + request.getPathInfo());
log.debug("\t RealPath: " + context.getRealPath(jspUri));
log.debug("\t RequestURI: " + request.getRequestURI());
log.debug("\t QueryString: " + request.getQueryString());
}

try {
boolean precompile = preCompile(request);
serviceJspFile(request, response, jspUri, null, precompile);
} catch (RuntimeException e) {
throw e;
} catch (ServletException e) {
throw e;
} catch (IOException e) {
throw e;
} catch (Throwable e) {
throw new ServletException(e);
}

}

public void destroy() {
if (log.isDebugEnabled()) {
log.debug("JspServlet.destroy()");
}

rctxt.destroy();
}


public void periodicEvent() {
rctxt.checkCompile();
}

// -------------------------------------------------------- Private Methods

private void serviceJspFile(HttpServletRequest request,
HttpServletResponse response, String jspUri,
Throwable exception, boolean precompile)
throws ServletException, IOException {

JspServletWrapper wrapper = rctxt.getWrapper(jspUri);
if (wrapper == null) {
synchronized(this) {
wrapper = rctxt.getWrapper(jspUri);
if (wrapper == null) {
// Check if the requested JSP page exists, to avoid
// creating unnecessary directories and files.
if (null == context.getResource(jspUri)) {
handleMissingResource(request, response, jspUri);
return;
}
boolean isErrorPage = exception != null;
wrapper = new JspServletWrapper(config, options, jspUri,
isErrorPage, rctxt);
rctxt.addWrapper(jspUri,wrapper);
}
}
}

try {
wrapper.service(request, response, precompile);
} catch (FileNotFoundException fnfe) {
handleMissingResource(request, response, jspUri);
}

}


private void handleMissingResource(HttpServletRequest request,
HttpServletResponse response, String jspUri)
throws ServletException, IOException {

String includeRequestUri =
(String)request.getAttribute("javax.servlet.include.request_uri");

if (includeRequestUri != null) {
// This file was included. Throw an exception as
// a response.sendError() will be ignored
String msg =
Localizer.getMessage("jsp.error.file.not.found",jspUri);
// Strictly, filtering this is an application
// responsibility but just in case...
throw new ServletException(SecurityUtil.filter(msg));
} else {
try {
response.sendError(HttpServletResponse.SC_NOT_FOUND,
request.getRequestURI());
} catch (IllegalStateException ise) {
log.error(Localizer.getMessage("jsp.error.file.not.found",
jspUri));
}
}
return;
}


}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 宝塔面板是一个用于管理服务器的开源控制面板,可以方便地安装和管理各种应用程序。当在宝塔安装Tomcat后,出现"java.lang.ClassNotFoundException: org.apache.jsp.index_j"错误,可能是由于以下原因: 1. 缺少依赖库:在运行JSP页面Tomcat会尝试加载JSP页面所依赖的类库。如果缺少了某个类库,就会抛出"Class Not Found"异常。解决方法是找到缺失的类库,并将其添加到项目的类路径。 2. JSP编译错误:JSP页面的编译错误也可能导致"Class Not Found"异常。通常这是由于JSP页面的语法错误或逻辑错误引起的。应该仔细检查JSP页面的代码,并修复其的错误。 3. Tomcat配置问题:如果Tomcat的配置文件有问题,例如web.xml的servlet配置不正确,也可能导致"Class Not Found"异常。需要检查和修复Tomcat的配置文件。 综上所述,解决该问题的方法包括检查并添加缺失的依赖库、修复JSP页面的编译错误和检查和修复Tomcat的配置文件。如果以上方法都无效,可以尝试重新安装Tomcat或更新宝塔面板。同,还可以查看Tomcat的日志文件,以获取更多的错误信息,帮助定位并解决问题。 ### 回答2: 当使用宝塔面板安装并配置Tomcat后,访问Tomcat应用程序出现"ava.lang.ClassNotFoundException: org.apache.jsp.index_j"错误。此错误表明Tomcat无法找到指定JSP文件的Java类。 出现该错误的原因可能有以下几种: 1. JSP文件不存在:请检查您的Tomcat应用程序是否存在名为index.jsp的文件。确保文件路径和名称正确,并位于正确的目录。 2. 缺少关联的Java类文件:JSP文件可能使用了Java类,但相关的类文件可能缺失。请确保JSP文件涉及的类文件存在,并位于正确的目录。 3. 编译错误:如果JSP文件包含Java代码,那么在首次访问该文件Tomcat会将其编译为Java类。如果编译过程遇到错误,可能会导致类文件不存在。您可以尝试重启Tomcat,以便重新编译JSP文件。 4. 类路径问题Tomcat可能无法在类路径找到所需的类文件。请确保相关的jar文件位于Tomcat的lib目录,或者将jars添加到应用程序的WEB-INF/lib目录。 5. Tomcat版本不兼容:检查您使用的Tomcat版本是否与您的应用程序兼容。某些Tomcat版本可能不支持特定JSP功能或特性。 为了解决该问题,您可以按照以下步骤进行操作: 1. 检查index.jsp文件是否存在于正确的位置,并确保文件名和路径没有拼写错误。 2. 检查JSP文件使用的Java类是否存在,并确保相关的类文件位于正确的目录。 3. 尝试重启Tomcat服务器,以便重新编译JSP文件。 4. 检查Tomcat的lib目录和应用程序的WEB-INF/lib目录,确保所需的jar文件存在。 5. 如果问题仍然存在,请尝试将Tomcat升级到与您的应用程序兼容的版本。 通过以上步骤,您应该能够解决"ava.lang.ClassNotFoundException: org.apache.jsp.index_j"错误,并成功访问Tomcat应用程序。 ### 回答3: 宝塔安装tomcat后,当访问页面出现"ava.lang.ClassNotFoundException: org.apache.jsp.index_j"错误。 这个错误通常是由于编译错误或者缺少相关的库文件导致的。出现这个错误可能有以下几个原因: 1. 编译错误:当我们部署JSP候,服务器会将JSP文件编译成一个可执行的Java文件。如果编译过程出现错误,就会导致该错误。我们需要检查JSP文件的代码逻辑,确保没有语法错误。 2. 缺少库文件:另一个可能的原因是缺少相关的库文件。在tomcat的lib目录下,有一些核心的JAR文件,确保这些文件存在且正确。另外,还需要检查WEB-INF/lib目录下是否有其他必要的JAR文件。 解决这个问题可以采取以下几个步骤: 1. 检查JSP代码:使用编辑器打开index.jsp文件,仔细检查代码逻辑,确保没有语法错误或逻辑错误。 2. 查看日志文件:在tomcat的logs目录下,找到catalina.out文件,查看里面的错误信息,看是否有其他错误导致的。 3. 检查JAR文件:检查tomcat的lib目录下的核心JAR文件,确保没有缺失或损坏的文件。另外,检查WEB-INF/lib目录下是否有其他必要的JAR文件,根据需要添加缺失的文件。 4. 清除缓存:有候,清除tomcat的缓存文件可以解决问题。可以尝试删除tomcat的work目录下的内容,然后重启tomcat。 温馨提示:在解决问题之前,建议备份相关文件,以防止操作失误造成数据丢失。如果问题依然存在,可以参考官方文档或寻求相关技术支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值