我以Tomcat6.0为例讲解Tomcat的结构,目地是理解和使用Tomcat。
当我们启动Tomcat后(手动启动是双击Tomcat 6.0/bin/startup.bat文件),在浏览器中输入http://localhost:8080/,我们会看到Tomcat的主页面,这个页面就是Tomcat 6.0/webapps/ROOT/index.jsp,这是由于我们没有输入项目名,所以服务器就运行默认的项目(ROOT项目)。在主页面中我们可以查看Tomcat下的Web应用的连接情况、管理Tomcat、查看Tomcat文档、Serlvet示例和JSP示例等等(下图)。
当然我们也能直接输入地址http://localhost:8080/manager/html访问管理页面,它实际运行的就是Tomcat 6.0/webapps/manager/项目。
假设我们点击上图的JSP Examples,它请求的URL是http://localhost:8080/examples/jsp/index.html,也就是Tomcat提供的JSP项目示例,Tomcat 6.0/webapps/examples/jsp/index.html。这些都是Tomcat为我们提供的项目。
下面让我们自己来创建一个项目:
在Tomcat 6.0/webapps/下创建一下名为myapp的项目(也称Web应用),在该项目下新建一个index.jsp文件,完整目录为Tomcat 6.0/webapps/myapp/index.jsp,输入代码内容如下
<html> <head><title>Tomcat Study</title></head> <body> This is JSP Page. </body> </html>
然后在浏览器地址栏中输入http://localhost:8080/myapp/或者http://localhost:8080/myapp/index.jsp访问(注意:前提是Tomcat是启动状态),会看到如下页面
最后在Tomcat 6.0/webapps/myapp目录下新建名为jsp的目录,在新建的目录下新建link.jsp文件,完整目录为Tomcat 6.0/webapps/myapp/jsp/link.jsp。输入代码内容如下
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=GBK"> <title>Link Page</title> </head> <body> 作者:谌冬华 </body> </html>
在浏览器地址栏中输入http://localhost:8080/myapp/jsp/link.jsp,会看到如下页面
好了,JSP的用法就到这里,下面我们运行Servlet玩玩
在Tomcat 6.0/webapps/myapp/目录下新建名为WEB-INF的目录,再在WEB-INF的目录下新建classes目录和lib目录。编写一个HelloServlet.java文件并将其编译成HelloServlet.class文件放到Tomcat 6.0/webapps/myapp/WEB-INF/class/目录下,HelloServlet引用Tomcat 6.0/lib/servlet-api.jar包的HttpServlet类。HelloServlet.java文件代码如下
import java.io.IOException; import java.io.PrintWriter; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HelloServlet extends HttpServlet { public void init() { System.out.println("HelloServlet类中的init()方法被执行!"); } public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter pw = response.getWriter(); pw.append("<html>"); pw.append("<head><title>Servlet For Fun</title></head>"); pw.append("<body>"); pw.append("All from HttpServletRequest Object"); pw.append("<br/>Scheme:" + request.getScheme()); pw.append("<br/>ServerName:" + request.getServerName()); pw.append("<br/>ServerPort:" + request.getServerPort()); pw.append("<br/>ContextPath:" + request.getContextPath()); pw.append("<br/>ServletPath:" + request.getServletPath()); pw.append("<br/>Method:" + request.getMethod()); pw.append("<br/>Protocol:" + request.getProtocol()); pw.append("<br/>RequestURI:" + request.getRequestURI()); pw.append("<br/>PathInfo:" + request.getPathInfo()); pw.append("</body>"); pw.append("</html>"); pw.close(); } }
在Tomcat 6.0/webapps/myapp/WEB-INF/目录下新建web.xml文件,内容如下
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <servlet> <servlet-name>helloservlet</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloservlet</servlet-name> <url-pattern>/myservlet</url-pattern> </servlet-mapping> </web-app>
好了,现在看看myapp项目的整个目录结构,呵呵,它就是我们用IDE(如Eclipse)开发时的目录结构,这个目录结构也是发部项目的目录结构。
下面是访问该Servlet的输出页面
注意:Tomcat 6.0/lib/目录下的jar包可供所有项目引用,而某个项目myapp/WEB-INF/lib/下的jar包只供该项目引用。
发布项目
一般我们会把开发好的Web应用打成war包,然后发布。现在就让我们来把刚刚创建好的myapp应用打成war包。
打开命令提示符,进入到应用所在目录,我这里是C:\Tomcat 6.0\webapps\myapp,输入并执行jar cvf myapp.war *
在C:\Tomcat 6.0\webapps\myapp目录下会出现myapp.war包,把这个war包拷贝到C:\Tomcat 6.0\webapps\目录下。有了myapp.war包,我们可以把myapp目录删除掉或者移到其它地方。重新启动Tomcat,再次访问之前的jsp和servlet,就和上面访问的显示一样了。
查看转换后的JSP
Tomcat容器会把JSP转换成java文件并编译成class。现在我们去看看,进入Tomcat 6.0\work\Catalina\localhost\myapp\org\apache\jsp目录,可以看到有一个index_jsp.java文件和一个index_jsp.class文件,这就是index.jsp转换过来的。再进入下一级的jsp目录,还有link_jsp.java和link_jsp.class文件,这是link.jsp转换过来的。转换的命名规则我就不解释了,相信大家一看就知道。下图是link.jsp的转换图
下面贴出index_jsp.java代码,如此简单的JSP页面转换后居然有这么多的代码
package org.apache.jsp; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent { private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory(); private static java.util.List _jspx_dependants; private javax.el.ExpressionFactory _el_expressionfactory; private org.apache.AnnotationProcessor _jsp_annotationprocessor; public Object getDependants() { return _jspx_dependants; } public void _jspInit() { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); _jsp_annotationprocessor = (org.apache.AnnotationProcessor) getServletConfig().getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName()); } public void _jspDestroy() { } public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null; try { response.setContentType("text/html"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("<html>\r\n"); out.write("<head>\r\n"); out.write("<title>Tomcat Study</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); out.write("\tThis is JSP Page.\r\n"); out.write("</body>\r\n"); out.write("</html>"); } catch (Throwable t) { if (!(t instanceof SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { out.clearBuffer(); } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
查看日志
Tomcat 6.0/log目录下存放的是运行Tomcat服务器和所有Web应用的日志信息,如下图
如localhost.2010-09-19.log就是我2010年9月19日运行的日志,看看部分日志的内容
2010-9-19 22:02:46 org.apache.catalina.core.ApplicationContext log 信息: SessionListener: contextInitialized() 2010-9-19 22:02:47 org.apache.catalina.core.ApplicationContext log 信息: SessionListener: contextDestroyed() 警告: Error unregistering MBeanServerDelegate java.lang.NullPointerException at org.apache.catalina.connector.MapperListener.destroy(MapperListener.java:176) at org.apache.catalina.connector.Connector.stop(Connector.java:1135) at org.apache.catalina.core.StandardService.stop(StandardService.java:596) at org.apache.catalina.core.StandardServer.stop(StandardServer.java:744) at org.apache.catalina.startup.Catalina.stop(Catalina.java:648) at org.apache.catalina.startup.Catalina$CatalinaShutdownHook.run(Catalina.java:692)
通过查看日志,可以知道Tomcat服务器和Web应用运行的状况,如某一天是否抛出过异常