問題重現:
今天一剛開始學Java的同學在接觸Jsp的時候遇到了一個比較詭異的問題,他在JSP中始終無法使用自己寫的類。簡單的演示問題代碼:
//沒有定義包名
public class MyDefaultClass {
}
//index.jsp文件
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Insert title here</title>
</head>
<body>
<%
MyDefaultClass cls = new MyDefaultClass();
%>
Load successful
</body>
</html>
出現的錯誤提示:
type Exception report
message
description The server encountered an internal error () that prevented it from fulfilling this request.
exception
org.apache.jasper.JasperException: Unable to compile class for JSP:
An error occurred at line: 12 in the jsp file: /index.jsp
MyDefaultClass cannot be resolved to a type
9: <body>
10:
11: <%
12: MyDefaultClass cls = new MyDefaultClass();
13: %>
14:
15: Load successful
An error occurred at line: 12 in the jsp file: /index.jsp
MyDefaultClass cannot be resolved to a type
9: <body>
10:
11: <%
12: MyDefaultClass cls = new MyDefaultClass();
13: %>
14:
15: Load successful
Stacktrace:
org.apache.jasper.compiler.DefaultErrorHandler.javacError(DefaultErrorHandler.java:92)
org.apache.jasper.compiler.ErrorDispatcher.javacError(ErrorDispatcher.java:330)
org.apache.jasper.compiler.JDTCompiler.generateClass(JDTCompiler.java:439)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:349)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:327)
org.apache.jasper.compiler.Compiler.compile(Compiler.java:314)
org.apache.jasper.JspCompilationContext.compile(JspCompilationContext.java:592)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:317)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
解決方案:
為什么要特別提示他是剛開始接觸Java呢?因為我是想強調一下他沒有定義包名的習慣,所以才會出現這個問題,而在Java中不定義包名是一個非常不好的編程習慣。這個問題本身是可以通過定義自己的包名,然后在JSP文件中導入自己的包解決。
問題原因:
由于JSP文件在請求時動態的生成Servlet類,然后動態的編譯新生成的Servlet類,并加載新編譯出的Servlet的class文件,運行相應的service方法,返回結果給客戶端。根據棧信息可以知道問題出在了動態編譯Servlet類的時候,而且是說MyDefaultClass無法被解析。
所以我猜測,可能是Tomcat在解析JSP文件的時候,沒有發現有用戶導入的類型(沒有使用命名空間,因而無法導入包,也不需要加包名的前綴,導致Tomcat在解析JSP文件的時候無法自動感知到當前是引用了用戶自定義的類的;也導致在編譯的時候卻能通過),所以在動態編譯的時候沒有設置ClassPath的值,然后導致了這個問題。然而對于這個“Bug”,Tomcat本身應該不會想不到,何況從邏輯上,默認的把/classes和/lib的目錄加入到ClassPath中去編譯動態生成的Servlet類也是合理的,那么Tomcat為什么要這樣做呢?我的猜測可能會有兩點吧:1. Tomcat也認為不定義包名是非常不好的習慣,因而故意留下這個缺陷,以驚醒編程人員。2. 也有可能是出于性能的考慮,如果不加ClassPath應該是可以提升編譯動態生成的Servlet類的速度的,因而只要不需要ClassPath的情況下,默認就不加。
2010-09-22
posted on 2011-07-20 23:08
DLevin 閱讀(888)
評論(0) 編輯 收藏 所屬分類:
Core Java