Java语言诞生,由于其很好的跨平台特性,加速了Web应用的发展。与传统的C/S模式相比,Java对整个Web应用提供了一整套的解决方案:在客户端,Applet的应用;在Server端,有Servlet的应用。
一、Applet:Applet(小应用程序)采用Java创建的基于HTML的程序。浏览器将其暂时下载到用户的硬盘上,并在Web页打开时在本地运行。一般的Applet只能通过appletviewer或者浏览器来运行,一般的Java程序通过继承Applet类也可以嵌入网页运行。
二、Servlet:先看传统的Server端处理程序CGI,CGI运行在服务器端,当监听到用户请求时,针对每个请求Server端将启用一个新的进程来完成相应请求的逻辑运算。而Servlet出现替换了Server端的处理程序。Servlet由Java编写,具有CGI相同的扩展Server功能。但比之CGI,Servlet有如下两个优势:
(1)、当在服务器端采用Servlet处理程序时,当监听到一个用户请求时,服务器将会启动一个Java线程,由该Java线程来完成用户请求的逻辑运算。这与CGI采用的进程相比,由于进程相对Java线程的重量级,当并发访问量达到一定的数量后,服务器的开销将有很大的差距。使得利用Servlet作为服务器端的处理程序时,可以得到较好的运行效率。
(2)、由于Servlet由Java编写,而CGI虽然可以用任何一种语言编写,但大多数实现都是C或C++编写。所以利用Servlet作为Web应用的服务器端处理程序使得Web应用具有更好的跨平台特性,众所周知,只要在服务器上安装了Java虚拟机,任何平台都可以运行Java应用。
三、Servlet的实现:继承javax.servlet.http.HttpServlet类的一个Java类即可。但需注意HttpServlet类是一个抽象类,所以写Servlet类时需要实现其声明的一些方法。常用的方法有:doGet,doPost,doPut,doHead,分别为处理方法为Http GET(Post、Head、Put)的请求。Servlet的配置需在web.xml中进行相应的配置。
四、JSP与Servlet的关系:大家不难发现其关系。在Tomcat中部署一个Web应用,对应每个Webapps文件夹下的Web应用,在Tomcat根目录中用一个work文件夹下的相应文件对应,一个JSP页面,对应一个Java文件。例如:D:\Tomcat 6.0\work\Catalina\localhost\examples\org\apache\jsp\jsp\jsp2\simpletag\hello_jsp.java与D:\Tomcat 6.0\webapps\examples\jsp\jsp2\simpletag\hello.jsp.注意他们的路径和文件名。将jsp文件中的“.”替换为“_”并在后面加上后缀“.java”.这里的Java文件就是相应JSP页面转换的Servlet。
package org.apache.jsp.jsp.jsp2.simpletag; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; public final class hello_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; static { _jspx_dependants = new java.util.ArrayList(1); _jspx_dependants.add("/WEB-INF/jsp2/jsp2-example-taglib.tld"); } 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("<!--\n"); out.write(" Licensed to the Apache Software Foundation (ASF) under one or more\n"); out.write(" contributor license agreements. See the NOTICE file distributed with\n"); out.write(" this work for additional information regarding copyright ownership.\n"); out.write(" The ASF licenses this file to You under the Apache License, Version 2.0\n"); out.write(" (the \"License\"); you may not use this file except in compliance with\n"); out.write(" the License. You may obtain a copy of the License at\n"); out.write("\n"); out.write(" http://www.apache.org/licenses/LICENSE-2.0\n"); out.write("\n"); out.write(" Unless required by applicable law or agreed to in writing, software\n"); out.write(" distributed under the License is distributed on an \"AS IS\" BASIS,\n"); out.write(" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n"); out.write(" See the License for the specific language governing permissions and\n"); out.write(" limitations under the License.\n"); out.write("-->\n"); out.write("\n"); out.write("<html>\n"); out.write(" <head>\n"); out.write(" <title>JSP 2.0 Examples - Hello World SimpleTag Handler</title>\n"); out.write(" </head>\n"); out.write(" <body>\n"); out.write(" <h1>JSP 2.0 Examples - Hello World SimpleTag Handler</h1>\n"); out.write(" <hr>\n"); out.write(" <p>This tag handler simply echos \"Hello, World!\" It's an example of\n"); out.write(" a very basic SimpleTag handler with no body.</p>\n"); out.write(" <br>\n"); out.write(" <b><u>Result:</u></b>\n"); out.write(" "); if (_jspx_meth_mytag_005fhelloWorld_005f0(_jspx_page_context)) return; out.write("\n"); out.write(" </body>\n"); out.write("</html>\n"); } 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); } } private boolean _jspx_meth_mytag_005fhelloWorld_005f0(PageContext _jspx_page_context) throws Throwable { PageContext pageContext = _jspx_page_context; JspWriter out = _jspx_page_context.getOut(); // mytag:helloWorld jsp2.examples.simpletag.HelloWorldSimpleTag _jspx_th_mytag_005fhelloWorld_005f0 = new jsp2.examples.simpletag.HelloWorldSimpleTag(); org.apache.jasper.runtime.AnnotationHelper.postConstruct(_jsp_annotationprocessor, _jspx_th_mytag_005fhelloWorld_005f0); _jspx_th_mytag_005fhelloWorld_005f0.setJspContext(_jspx_page_context); _jspx_th_mytag_005fhelloWorld_005f0.doTag(); org.apache.jasper.runtime.AnnotationHelper.preDestroy(_jsp_annotationprocessor, _jspx_th_mytag_005fhelloWorld_005f0); return false; } }
JSP转换后的Servlet不是继承HttpServlet而是HttpJspBase,并实现了JspSourceDependent接口。这个Servlet中有个方法为_jspService():这是Servlet执行业务逻辑的接口。我们可以看出JSP文件的内置对象application\request\response\session是怎么来的。(在对应的Servelt的_jspService()方法中创建的)
五、Servlet的生命周期:加载、初始化、请求执行、销毁。
(1)加载:分为自动加载和调用时加载两种加载方式,这两种方式都是通过Web应用的web.xml配置文件来配置完成的。自动加载表示在服务器启动时,Servlet自动加载到内存。直到服务器重新启动Servelt才会被删除。自动加载的配置:
<servlet> <serlvet-name></servlet-name> <servlet-class></serlvet-class> <load-on-startup>1</load-on-startup> </servlet>
只要load-on-startup标记的值大于等于0时,就是自动加载。并且数值越大,加载的优先级(次序)越高。
同理,调用时加载只要不配置load-on-startup标记即可。调用时加载表示只有通过浏览器端访问在Servlet-mapping中配置的URL时,对应的servlet-class才被调用,即被加载到内存。第一次调用Servlet时,系统响应较慢,这是因为服务器要进行内存配置,当加载后,系统响应效率就会大大提高。
(2)初始化-init()
(3)请求处理—service()
(4)销毁—destroy().