一.JSP基本原理
jsp 的本質(zhì)就是servlet,當(dāng)用戶向指定的servlet 發(fā)送請求時(shí),Servlet利用輸出流動(dòng)態(tài)的生成html頁面
jsp頁面有兩部分組成:
- 靜態(tài)部分:標(biāo)準(zhǔn)的html標(biāo)簽韭脊,靜態(tài)的頁面內(nèi)容
- 動(dòng)態(tài)部分:受java程序控制的內(nèi)容,這些內(nèi)容有java程序動(dòng)態(tài)生成
jsp頁面必須放在web應(yīng)用中才有效,所有編寫jsp頁面之前應(yīng)該先構(gòu)建一個(gè)web應(yīng)用淮逊,每個(gè)jsp頁面就是一個(gè)servlet實(shí)例———JSP頁面由系統(tǒng)編譯成servlet,servlet在負(fù)責(zé)響應(yīng)用戶請求,
每個(gè)JSP的第一個(gè)訪問者是很慢的,因?yàn)楸仨毾鹊却齁SP編譯成Servlet
當(dāng)啟動(dòng)Tomcat之后,可以在Tomcat的work\Catalina\localhost目錄下找到編譯成的test_jsp.java和test_jsp.class文件赃份,這兩個(gè)文件都是有tomcat自動(dòng)生成的,是與jsp相對應(yīng)的
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.35
* Generated at: 2017-04-27 14:39:39 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.util.*;
public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
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 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;charset=ISO-8859-1");
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('\r');
out.write('\n');
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
out.write("\r\n");
out.write("\r\n");
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <base href=\"");
out.print(basePath);
out.write("\">\r\n");
out.write(" \r\n");
out.write(" <title>My JSP 'test.jsp' starting page</title>\r\n");
out.write(" \r\n");
out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n");
out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
out.write("\t<!--\r\n");
out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
out.write("\t-->\r\n");
out.write("\r\n");
out.write(" </head>\r\n");
out.write(" \r\n");
out.write(" <body>\r\n");
out.write(" This is my JSP page. <br>\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 { 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);
}
}
}
該java類主要包含三個(gè)方法:
- init() 初始化JSP/Servlet的方法
- destroy() 銷毀JSP/Servlet之前的方法
- service() 對用戶請求生成響應(yīng)的方法
二.JSP聲明
JSP聲明用于聲明變量和方法奢米,JSP聲明將會(huì)轉(zhuǎn)換成對應(yīng)的Servlet的成員變量或成員方法抓韩,JSP聲明變量或方法可以使用private,public 等訪問控制修飾符,也可以使用static修飾,但不能使用abstract修飾聲明部分方法 鬓长。JSP聲明的語法格式如下:
<%! 聲明部分%>
三.JSP表達(dá)式
JSP提供了一種輸出表達(dá)式的簡單方式谒拴,但表達(dá)式語法后不能有分號,語法格式如下:
<%= 輸出表達(dá)式 %>
三.JSP腳本
語法格式:
<% java 代碼 %>
四.JSP 的三個(gè)編譯指令
JSP 的編譯指令是通知JSP引擎的消息涉波,它不直接生成輸出
- page 該指令針對當(dāng)前頁面的指令
- include 用于指定包含另一個(gè)頁面‘
- taglib 用戶定義和訪問自定義標(biāo)簽
page指令 各屬性的意義:
- language 聲明當(dāng)前JSP頁面使用的腳本語言的種類
- extends 指定JSP頁面編譯所產(chǎn)生的java所繼承的父類
- import 用來導(dǎo)入包
- session 設(shè)定這個(gè)JSP 頁面是否需要HTTP session
- buffer 指定輸出緩沖區(qū)的大小
- autoFlush 當(dāng)輸出緩沖區(qū)即將溢出時(shí)英上,是否需要強(qiáng)制輸出緩沖區(qū)的內(nèi)容
- info 設(shè)置jsp 頁面信息
- 指定錯(cuò)誤頁面
include 指令
使用include 指令可以將一個(gè)外部文件嵌入到當(dāng)前的jsp文件中,融合成一個(gè)頁面啤覆。這個(gè)是靜態(tài)的include語句苍日,它會(huì)把目標(biāo)頁面的其他編譯指令也包含進(jìn)來,而動(dòng)態(tài)的include則不會(huì)城侧。
如果被嵌入的文件經(jīng)常需要改易遣,建議使用<jsp:include>操作指令
五.JSP的七個(gè)動(dòng)作指令
動(dòng)作指令與編譯指令不同,編譯指令是通知Servlet引擎的處理消息嫌佑,而動(dòng)作指令只是運(yùn)行時(shí)的動(dòng)作,編譯指令再將JSP編譯成Servlet時(shí)起作用
- jsp:forward 執(zhí)行頁面轉(zhuǎn)向侨歉,將請求的處理轉(zhuǎn)發(fā)到下一個(gè)頁面
- jsp:param 用于傳遞參數(shù)屋摇,必須與其他支持參數(shù)的標(biāo)簽一起使用
- jsp:include 用于動(dòng)態(tài)引入一個(gè)jsp文件
- jsp:plugin 用于下載javabean 或Applet到客戶端執(zhí)行
- jsp:userBean 創(chuàng)建一個(gè)javaBean的實(shí)例
- jsp:setProperty 用于設(shè)置javabean實(shí)例的屬性值
- jsp:getProperty 輸出javabean實(shí)例的屬性值
六.forward和redirect對比
轉(zhuǎn)發(fā)(forward) | 重定向(redirect) |
---|---|
執(zhí)行forward后依然是上一次請求 | 執(zhí)行redirect后生產(chǎn)第二次請求 |
forward目標(biāo)也可以訪問原有 的請求參數(shù),因?yàn)橐廊皇峭粋€(gè)請求 | redirect的目標(biāo)業(yè)面不能訪問原來的請求參數(shù)幽邓,因?yàn)檫@是第二次請求了 |
地址欄里請求的URL不會(huì)改變 | 地址欄改為重定向的目標(biāo)URL,相當(dāng)于在地址欄里重新輸入了URL |
七.JSP 的九個(gè)內(nèi)置對象
JSP腳本中包含九個(gè)內(nèi)置對象痕檬,這九個(gè)內(nèi)置對象都是Servlet API 接口的實(shí)例瘫想,只是JSP規(guī)范對他們進(jìn)行了初始化,也就是說它們已經(jīng)是對象了,可以直接使用
- application javax.servlet.ServletContext 的實(shí)例热鞍,該實(shí)例代表JSP所屬的WEB應(yīng)用實(shí)例本身
- config javax.servlet.ServletConfig 的實(shí)例,該實(shí)例代表JSP的配置信息
- **exception **java.lang.Throwable 的實(shí)例該實(shí)例代表其他頁面中的異常和錯(cuò)誤趣斤,只有當(dāng)頁面是錯(cuò)誤處理頁面讨衣,即編譯指令page的isErrorPage屬性為True時(shí) 該對象才可以用
- **out ** javax.servlet.jsp.JspWrite的實(shí)例 該實(shí)例代表JSP頁面的輸出流
- page 代表該頁面本身 通常沒多大用處
- pageContext javax.servlet.jsp.PageContext 的實(shí)例 該對象代表JSP頁面上下文,使用該對象可以訪問頁面中的共享數(shù)據(jù)
- request javax.servlet.http.HttpServletRequest的實(shí)例没炒,該對象封裝了一次請求涛癌,客戶端的請求參數(shù)都封裝在該對象里,是一個(gè)常用對象
- response javax.servlet.http.HttpServletResponse 的實(shí)例 代表服務(wù)器對客戶端的響應(yīng)
- session javax.servlet.http.HttpSession 的實(shí)例 該對象代表一次會(huì)話,當(dāng)客戶端瀏覽器與站點(diǎn)建立連接時(shí)拳话,會(huì)話開始
八.Filter介紹
Filter可認(rèn)為是Servlet 的一種加強(qiáng)版先匪,他主要是對用戶的請求進(jìn)行預(yù)處理,也可以對HttpServletResponse進(jìn)行后處理弃衍,是個(gè)典型的處理鏈
Filter有如下幾個(gè)用處:
- 在HtttpServletRequest到達(dá)Servlet之前呀非,攔截客戶的HttpServletRequest
- 根據(jù)需要檢查HttpServletRequest,也可以修改HttpServletRequest頭和數(shù)據(jù)
- 在HtttpServletResponse到達(dá)Servlet之前镜盯,攔截客戶的HtttpServletResponse
- 根據(jù)需要檢查HtttpServletResponse岸裙,也可以修改HtttpServletResponse頭和數(shù)據(jù)
創(chuàng)建Filter類
一個(gè)filter必須實(shí)現(xiàn)javax.servlet.Filter。
三個(gè)方法
- voidsetFilterConfig(FilterConfig config) //設(shè)置filter 的配置對象形耗;
- FilterConfiggetFilterConfig() //返回filter的配置對象哥桥;
- voiddoFilter(ServletRequest req,ServletResponse res,FilterChain chain) //執(zhí)行filter的工作
public class EncodingFilter implements Filter {
private String encoding = null;
public void destroy() {
encoding = null;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
String encoding = getEncoding();
if (encoding == null){
encoding = "gb2312";
}
request.setCharacterEncoding(encoding);// 在請求里設(shè)置上指定的編碼
chain.doFilter(request, response); //通過控制對chain.doFilter的方法的調(diào)用,來決定是否需要訪問目標(biāo)資源
}
public void init(FilterConfig filterConfig) throws ServletException {
this.encoding = filterConfig.getInitParameter("encoding");
}
private String getEncoding() {
return this.encoding;
}
}
XML 配置
<filter>
<filter-name>EncodingFilter</filter-name>
<filter-class>com.logcd.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>gb2312</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>EncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Filter生命周期
和Servlet一樣激涤,F(xiàn)ilter的創(chuàng)建和銷毀也是由WEB服務(wù)器負(fù)責(zé)拟糕。
與Servlet區(qū)別的是
- 在應(yīng)用啟動(dòng)的時(shí)候就進(jìn)行裝載Filter類而servlet是在請求時(shí)才創(chuàng)建(但filter與Servlet的load-on-startup配置效果相同)。
- 容器創(chuàng)建好Filter對象實(shí)例后倦踢,調(diào)用init()方法送滞。接著被Web容器保存進(jìn)應(yīng)用級的集合容器中去了等待著,用戶訪問資源辱挥。
- 當(dāng)用戶訪問的資源正好被Filter的url-pattern攔截時(shí)犁嗅,容器會(huì)取出Filter類調(diào)用doFilter方法,下次或多次訪問被攔截的資源時(shí)晤碘,Web容器會(huì)直接取出指定Filter對象實(shí)例調(diào)用doFilter方法(Filter對象常駐留Web容器了)褂微。
- 當(dāng)應(yīng)用服務(wù)被停止或重新裝載了,則會(huì)執(zhí)行Filter的destroy方法园爷,F(xiàn)ilter對象銷毀
九.Listener介紹
使用Listener只需要兩個(gè)步驟
- 定義Listener 實(shí)現(xiàn)類
- 通過Annotation 或在web.xml文件中配置Listener
實(shí)現(xiàn)Listener類
常用的Web事件監(jiān)聽器接口有如幾個(gè):
ServletContextListener 用于監(jiān)聽web應(yīng)用的啟動(dòng)或關(guān)閉
ServletContextAttributeListener 用于監(jiān)聽Servlet范圍(application)內(nèi)屬性的改變
ServletRequestListener 用于監(jiān)聽用戶請求
ServletRequestAttributeListener 用于監(jiān)聽Servlet范圍(request)內(nèi)屬性的改變
HttpSessionListener 用于監(jiān)聽session 的開始和結(jié)束
HttpSessionAttributeListener 用于監(jiān)聽Servlet范圍(session)內(nèi)屬性的改變
ServletContextListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent event) {
System.out.println("web應(yīng)用關(guān)閉時(shí)");
}
@Override
public void contextInitialized(ServletContextEvent event) {
System.out.println("web應(yīng)用啟動(dòng)時(shí)");
}
}
public class MyServletContextAttributeListener implements ServletContextAttributeListener{
@Override
public void attributeAdded(ServletContextAttributeEvent event) {
System.out.println("application 范圍內(nèi)屬性添加時(shí)");
}
@Override
public void attributeRemoved(ServletContextAttributeEvent event) {
System.out.println("application 范圍內(nèi)屬性移除時(shí)");
}
@verride
public void attributeReplaced(ServletContextAttributeEvent event) {
System.out.println("application 范圍內(nèi)屬性替換時(shí)");
}
}