前面的文章已經覆蓋了Servlet核心知識,因爲JSP與Servlet在很大程度上是相通的,所以關於JSP只須要介紹語法以及一些獨特的性質。
一樣能夠參考菜鳥筆記。html
要回答這個問題,實際上只須要比較HTML、Servlet、JSP的優劣:java
HTML文件是靜態的,沒法返回動態結果。apache
Servlet能夠動態生成HTML頁面,可是在代碼裏寫HTML標記實在是不爽。session
因而反過來,在傳統的HTML文件中加入Java程序片斷和JSP標記,就構成了JSP文件。app
當容器接收到客戶端對JSP文件的請求時,會解析對應的JSP文件,把它翻譯成Servlet源文件,接着把Servlet源文件編譯成Servlet類,而後再初始化並運行Servlet。jsp
固然,一旦JSP文件已經被編譯過,下次運行時只須要找對應的Servlet類就好了。this
可見JSP和Servlet實際上是一回事,JSP只是一層外衣。其內容中不管是HTML標記仍是Java代碼,都大部分被編譯到了Servlet類的service()方法中。因而接下來就順便解釋了JSP的生命週期:spa
編譯階段:Servlet容器編譯servlet源文件,生成servlet類翻譯
初始化階段:加載與JSP對應的servlet類,建立其實例,並調用它的初始化方法code
執行階段:調用與JSP對應的servlet實例的服務方法
銷燬階段:調用與JSP對應的servlet實例的銷燬方法,而後銷燬servlet實例
下圖給出了後面三個階段的示意:
其中:編譯出來的Servlet類繼承自javax.servlet.jsp.HttpJspPage接口,該接口繼承了javax.servlet.Servlet接口。jspInit()就對應Servlet的init(), jspDestroy()就對應Servlet的destroy(), _jspService()自沒必要說。
下面給出一個JSP文件和編譯出來的代碼,就一目瞭然了。
<!-- Hello.jsp --> <html> <head> <title>helloapp</title> </head> <body> <b>Hello,<%= request.getParameter("username") %></b> </body> </html>
編譯出的Servlet文件:
public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase { ... public void _jspInit() { } public void _jspDestroy() { } public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { final java.lang.String _jspx_method = request.getMethod(); if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD"); return; } // 能夠看出JSP的隱含對象是這麼來的。 final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.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>helloapp</title>\r\n"); out.write("</head>\r\n"); out.write("<body>\r\n"); out.write(" <b>Hello,"); out.print( request.getParameter("username") ); out.write("</b>\r\n"); out.write("</body>\r\n"); out.write("</html>\r\n"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { if (response.isCommitted()) { out.flush(); } else { out.clearBuffer(); } } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
歸納地說,JSP文件中除了能夠直接包含HTML文本,還能夠包含如下內容:
JSP指令(Directive)
用來設置和整個JSP頁面相關的屬性。語法形式爲<%@ 指令 屬性1="值1" 屬性2="值2" %>
。包括三種指令:
Page: 能夠指定language、content_type、errorPage、session等,還能夠用import屬性引入包。
Include: 包含其餘文件。
Taglib: 指定自定義標籤。
JSP聲明
聲明一個或多個變量、方法,供後面的Java代碼使用。聲明中的變量會被編譯成Servlet的(私有)成員變量。示例:
<%! int i = 0; %> <%! int a, b, c; %> <%! Circle a = new Circle(2.0); %>
Java程序片斷
任何在"<%"和"%>"標記之間的Java代碼。默認會被編譯到Servlet類的service()方法中(若是用Page指定了method屬性,則會編到你指定的方法中)。若是你想複寫jspInit()和jspDestroy()方法,應該在前面的JSP聲明中寫。
Java表達式
語法形式爲<%= JAVA表達式 %>
。至關於被編譯成out.print(JAVA表達式)
。
JSP隱含對象
JSP隱含對象是JSP容器爲每一個頁面提供的Java對象,開發者能夠直接使用它們而不用顯式聲明。JSP隱含對象也被稱爲預約義變量。
JSP所支持的九大隱含對象:
對象 | 描述 |
---|---|
request | HttpServletRequest類的實例 |
response | HttpServletResponse類的實例 |
out | PrintWriter類的實例,用於把結果輸出至網頁上 |
session | HttpSession類的實例 |
application | ServletContext類的實例,與應用上下文有關 |
config | ServletConfig類的實例 |
pageContext | PageContext類的實例,提供對JSP頁面全部對象以及命名空間的訪問 |
page | 相似於Java類中的this關鍵字 |
Exception | Exception類的對象,表明發生錯誤的JSP頁面中對應的異常對象 |
看起來很犀利,但實際上從前面真實的Servlet代碼能夠看到,它們不過是在service()方法的最前面預先定義好的局部變量。