Servlet、JSP对所有JAVA-WEB编程人员来说再熟悉不过了;但大家在使用的时候是否知道他们的关系呢?
?
略(详见[LXH]Http协议.pdf)
?
A、Server端:启动并监听某个端口号(如8080)
B、Client端:通过浏览器发起对服务端的请求
C、S:接收请求,并分配一个线程与之连接并开始相互通讯(HTTP,基于TCP)
D、通讯完毕,双方断开连接,回收资源。
(类似Socket的通讯过程,详见[LXH]Java网络编程.pdf)
Server端,都是通过java类取数据并返回html格式的字符串给浏览器解析
把html标签字符串写在servlet类里,最后response给浏览器
?????????????????? 如 doGet(…){
????????????????????????????????????? Out.println(“<html><head></head><body>”);
????????????????????????????????????? ….
????????????????????????????????????? Out.println(“</body></html>”)
????????????????????????????????????? …
}
这样的写法很麻烦,而且每次都要在.java类里修改,重新编译,再发布,不便于修改。
Provides an abstract class to be subclassed to create an HTTP servlet suitable for a Web site. A subclass of HttpServlet must override at least one method, usually one of these: 必须重写至少1个以下方法
service()接收标准HTTP请求,并将其转发给其所要执行的方法(如doGet,doPost),即先执行service()后自动执行其他方法
查看一下HttpServlet.java源码片段(tomcat源码里可以下载到)
protected void service(HttpServletRequest req, HttpServletResponse resp)
??????? throws ServletException, IOException {
??????? String method = req.getMethod();
????????????? //往下可以看出,最后还要负责转发原请求
??????? if (method.equals(METHOD_GET)) {
???????????????????? ...
???????????????????? doGet(req,resp);
}else if (method.equals(METHOD_HEAD)) {
??????????? ...
??????????? doHead(req, resp);
??????? } else if (method.equals(METHOD_POST)) {
??????????? doPost(req, resp);???????????
??????? } else if (method.equals(METHOD_PUT)) {
??????????? doPut(req, resp);???????????????????
??????? } else if (method.equals(METHOD_DELETE)) {
??????????? doDelete(req, resp);???????????
??????? } else if (method.equals(METHOD_OPTIONS)) {
??????????? doOptions(req,resp);???????????
??????? } else if (method.equals(METHOD_TRACE)) {
??????????? doTrace(req,resp);???????????
??????? } else {
????????????? ? ...
resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
因此重写service()方法后如果不再调用super.service(req,resp);则不会再做原有的动作了。
?
doGet()方法(默认返回错误,需子类自己重写)
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
??????? throws ServletException, IOException
??? {
??????? String protocol = req.getProtocol();
??????? String msg = lStrings.getString("http.method_get_not_supported");
??????? if (protocol.endsWith("1.1")) {
??????????? resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
??????? } else {
??????????? resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
??????? }
}
?
doPost()方法(默认返回错误,需子类自己重写)
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
??????? throws ServletException, IOException {
?
??????? String protocol = req.getProtocol();
??????? String msg = lStrings.getString("http.method_post_not_supported");
??????? if (protocol.endsWith("1.1")) {
??????????? resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
??????? } else {
??????????? resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
??????? }
??? }
JSP Parser:JSP解析器
????????????? 负责将*.jsp文件转换成一个Servlet类,并且编译供Servlet分析器来执行---最后又走到Servlet流程
Jasper.jar,jsp-api.jar,servlet-api.jar等包(一般java web server都会包含)
我们可以在jsp里把java代码嵌进去
如
<html><head></head><body>
<% 执行java代码%>
</body></html>
???????????????(JSP执行过程1)
从上图可以看出,*.jsp通过jsp parser会自动生成一个*.java类,并且编译成*.class文件,供Servlet使用,最后也是走servlet的流程---这个工作一般由web server来完成
?
以Tomcat为例
Work文件夹里面会为jsp生成相关的java类,并完成编译供运行调用
????????????? 如 index.jsp------àindex_jsp.java--àindex_jsp.class
????????????? 查看如下代码段:
????????????? public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
….
????????????????????? out.write("<html>\r\n");
??? out.write("<head>\r\n");
??? out.write("\t<title>\r\n");
??????? ….
}
????????? 查看HttpJspBase源码
org.apache.jasper.runtime
Class HttpJspBase
??????? java.lang.Object
?????? ?
javax.servlet.GenericServlet
???? ????????? ?
javax.servlet.http.HttpServlet
???????? ????????????? ?
org.apache.jasper.runtime.HttpJspBase
?
?? 其就是继承HttpServlet,所以说jsp其最终还是走servlet流程
?
?
Web Server 执行生成和编译的时机
--------并不是每次调用都执行,而是在文件创建或修改后的第一次调用,才会执行生成和编译操作.