java的JSP技術


java的JSP技術

1.JSP簡介

Jsp技術是用來開發java web的頁面顯示的,所有MVC模型里面的視圖層,所以視圖層的開發
jsp不是編程語言,三個英文是java server pages的縮寫
Jsp其實也是繼承Servlet的,屬於在服務器上的開發。Servlet是用於java語言的動態資源開發的技術,而Jsp是把java和html結合,在html中可以寫java語言,主要用在頁面的顯示開發上。

1.1.Jsp的特點

1.Jsp的運行必須交給tomcat服務器。tomcat的work目錄就是服務器用來存放jsp運行時的臨時文件的
2.Jsp頁面即可直接寫html代碼,也可以直接寫java代碼

2.Jsp的執行過程

問題1:訪問http://localhost:8080/hello/index.jsp 如何顯示效果?
1.訪問到index.jsp頁面,tomcat掃描到jsp文件,在tomcat/work目錄下把jsp文件翻譯成java源文件

index.jsp-->_index.java(翻譯)

2.tomcat服務器把java源文件編譯成class字節碼文件(編譯)

_index.java-->_index.class

3.tomcat服務器構造_index_jsp類對象
4.tomcat服務器調用_index_jsp類里面的方法,返回內容顯示到瀏覽器
如果是第一次訪問當前jsp文件時,執行步驟是:1-->2-->3-->4
第N次訪問jsp時,執行步驟是:4,不再執行其他步驟

注意:jsp文件被修改或者jsp的臨時文件被刪除了,要重新走翻譯(1)和編譯(2)的過程

問題2:既然jsp是servlet,那么jsp的生命周期和servlet的生命周期是不是一樣的?
當jsp文件被翻譯成java的源碼時,可以在翻譯出來的源碼文件里看到當前訪問的jsp文件繼承HttpJspBase類,再通過查詢JDK,可以發現HttpJspBase又是繼承於HttpServlet的。所以,可以得到結論,jsp既是一個servlet的程序,而servlet的技術可以用在jsp程序中,但是並不是所有的servlet技術全部適用於jsp程序

Servlet的生命周期:
1.構造方法(第一次訪問時執行)
2.init方法(第一次訪問時執行)
3.service方法(每次訪問都會執行)
4.destory方法(退出時執行)

Jsp的生命周期:
1.翻譯:Jsp-->java源文件
2.編譯:java文件-->class文件(servlet程序)
3.構造方法(第一次訪問時執行)
4.init方法(第一次訪問):JspInit()
5.service方法:JspService()
6.destory方法:jspDestory()

3.Jsp語法

3.1.Jsp模板

JSP頁面中的HTML內容就是JSP的模板
這些模板定義了網頁的基本骨架,也就是說定義了頁面的結構和外觀

3.2.Jsp表達式

JSP的表達式作用是向瀏覽器輸出變量的值或表達式計算的結果

語法:<%=變量或表達式 %>
例如<% String name="Eric";%>

<%=name%>
注意:
1.表達式的原理即使翻譯成out.print("變量“);通過該方法向瀏覽器寫出內容。
2.表達式后面不需要帶分好結束

3.3.Jsp的腳本

腳本是指在JSP頁面編寫多行java代碼的,可以執行java代碼

語法:<%多行java代碼; %>

注意
1.原理是把腳本中的java代碼原封不動的拷貝到jspService方法中執行
2.jsp腳本中寫的java是需要加分好的,語法跟java語法是一樣的
3.多個腳本片段中的代碼可以相互訪問
4.單個腳本片段中的java語句可以是不完整的,但是,多個腳本片段組合后的結必須是完整的java語句

3.4.Jsp的聲明

JSP的聲明是用來聲明變量或者方法的,如果在index.jsp頁面內聲明一個變量或者方法,則該變量或者方法是index_jsp類的成員變量,成員方法,即是全局變量。這個其實就是在類中寫好方法,然后可以在jsp_service方法中調用其他方法。
jsp通過腳本也可以定義一個變量,但是這個變量是保存在index_jsp類下的jspService方法下的一個變量,由於是保存在方法下面,所有腳本里是不可以定義一個方法的,只能通過聲明來定義方法。
注意以上兩者的區別,一個是保存在類下面,稱為成員變量或者成員方法,另一個則是保存在方法中,稱之為局部變量

語法:<%! 變量或方法%>

作用:聲明JSP的變量和方法
注意:
1.變量翻譯成成員變量,方法翻譯成成員方法

3.5.Jsp的注釋

jsp的注釋格式:

jsp的注釋:<%!--jsp注釋 --%>
html的注釋:

注意:
1.html的注釋會被翻譯和執行,無論在jsp的頁面翻譯之后的源碼還是在瀏覽器上查看網站的源碼,都是可以查看到的。但是jsp的注釋是不會被翻譯和執行的,在翻譯之后源碼里是不能找到的,從瀏覽器查看源碼也是查看不到的‘

4.Jsp的三大指令

JSP指令是為JSP引擎而設計的,他們並不產生任何可見的輸出,只是告訴引擎如何處理jsp頁面中的其余部分。jsp定義的有三大指令,分別是:include,page,tagllb

4.1.Include指令

Include指令的作用是當前頁面包含其他頁面,主要是導入其他jsp文件

語法:<%@include file="common/header.jsp%>

注意:
1.原理是把被包含的頁面(header.jsp)的內容翻譯到包含頁面(index.jsp)中,合並並翻譯成一個java源文件,再編譯運行!!,這種包含就加叫靜態包含(源碼包含)
2.如果使用靜態包含,被包含頁面中不需要出現全局的html標簽了,(如html,body,head)

4.2.page指令

page指令的作用是告訴tomcat服務器如何翻譯jsp文件

語法:<%@ page contentType="text/html;charset=UTF-8" language="java" %>

language="java"--告訴服務器只用什么動態語言來翻譯jsp文件
import="java.util.*" --告訴服務器java文件使用什么包,導入多個包時,用逗號隔開
pageEncoding="utf-8" --告訴服務器使用什么編碼把jsp翻譯成java文件
contentType="text/html; charset=utf-8" --服務器發送瀏覽器的數據類型和內容編碼,在開發工具中,只需要設置pageEncoding即可解決中文亂碼的問題
errorPage="error.jsp" --如果當前頁面出現錯誤信息,則自動調用此處指定的錯誤頁面
isErrorPage="false" --意思是當前頁面為錯誤頁面,默認為false,當設置為true時就認為是一個錯誤處理頁面,就可以在頁面中使用<%=exception.getMessage()%>方法來獲取錯誤異常信息,使其在頁面上可以顯示
全局配置錯誤處理頁面
在web.xml中配置如下:

    <!--全局錯誤處理頁面配置-->
    <error-page>
        <error-code>500</error-code>
        <location>common/500.jsp</location>
    </error-page>
    <error-page>
        <error-code>404</error-code>
        <location>common/404.html</location>
    </error-page>

配置之后,不用在jsp頁面中特別指明,會自動跳轉的
session="true" --是否開啟Session功能,false時不能使用Session內置對象,ture時可以使用。默認為true
buffer="8kb" --頁面的緩存區大小。
isELIgnored="false" --是否忽略EL表達式。

4.3.tagllb指令

5.JSP的內置對象

5.1.什么是內置的對象

在Service開發中會經常用到一些常用的類比如:HttpSession,ServletConfig,ServletContext,HttpServletRequet,用的時候,我們會直接創建就可以了,但是在jsp中這會經常使用到這些類。為了開發的方便,sun公司在設計jsp的時候,在jsp頁面加載完畢以后就自動幫開發者創建好了這些對象,而開發者只需要直接使用這些對象就可以了,那么這些已經創建好的對象有一個統一的名字叫做內置對象,內置對象一共有九個

例如:
在Service中要使用Session,需要先HttpSession session = request.getSession(true); 來創建一個Session對象,然后在使用對象的方法
但是在JSP中,可以直接使用Session的方法,如session.getId();

九大內置對象分別為:
1.對象名(request)-->類型HttpServletRequest :HTTP請求的時候使用到
2.對象名(response)-->類型HttpServletResponse :HTTP響應的時候用到
3.對象名(config)-->類型ServletConfig :獲取屬於自己的參數
4.對象名(session)-->類型HttpServletSession :會話管理使用
5.對象名(application)-->類型ServletContext :獲取全局參數
6.對象名(exception)-->類型Throwable :異常
7.對象名(page)-->類型 Object(this) :本jsp對象
8.對象名(out)-->類型JspWriter :打印到瀏覽器
9.對象名(pageContext)-->類型PageContext :

5.2.Out對象

Out對象類型是JspWrite類,相當於帶緩存的PrintWriter
PrintWriter
用write(內容)直接向瀏覽器寫出內容,有一句寫一句
JspWrite(內容):
用write(內容)向jsp的緩沖區寫出內容,當緩沖區滿足一下條件的時候,把內容一起寫到瀏覽器上,性能高於PrintWriter
當滿足一下條件之一,JSP緩沖區內容寫出到瀏覽器:

  • 緩沖區滿了
  • 刷新緩存去:out.flush();
  • 關閉緩沖區:buffer="0kb";
  • 執行完畢JSP頁面

5.3.pageContext對象

前面已經有了8個內置對象,這些對象都是在jsp_service方法中被創建的,然后直接只用,但是由於是在方法中被創建,屬於局部變量,所以很難在其他方法被調用,所有,使用了PageContext把這八個內置對象分裝起來,這樣傳參的時候只需要傳一個就可以了,然后通過這個PageContext來調用
除了調用其他八個內置對象意外,PageContext本身也是一個域對象,可以傳遞參數,准確的說PageContext是jsp的上下文對象,只可以在當前jsp文件內傳參

分別介紹PageContext的兩個方法:
1.可以獲取其他八個內置對象
源碼分析:

public class 01_hello_jsp {
					public void _jspService(request,response){
						創建內置對象
						HttpSession session =....;
						ServletConfig config = ....;

						把8個經常使用的內置對象封裝到PageContext對象中
						PageContext pageContext  = 封裝;
						調用method1方法
						method1(pageContext);
					}
					
					public void method1(PageContext pageContext){
						希望使用內置對象
						從PageContext對象中獲取其他8個內置對象
						JspWriter out =pageContext.getOut();
						HttpServletRequest rquest = 	pageContext.getRequest();
						........
					}
			}

注意:調用的時候,使用getout,getrequest等方法來調用
使用場景:在自定義標簽的時候,PageContext對象對象頻繁使用到

2.PageContext本身就是一個域對象
經常使用的域對象有4個,分別是
ServletContext context域
HttpServletRequest request對象
HttpSession session域
PageContext page域

PageContext域的作用是保存數據和獲取數據,用於共享數據
常用方法如下:
保存數據
1.默認情況下,保存到page域

pageContext.setAttribute("name");

2.可以向四個域對象保存數據

pageContext.setAttribute("name",域范圍常量)

獲取數據
1.默認情況下,從page域獲取

pageContext.getAttribute("name")

2.可以從四個域中獲取數據

pageContext.getAttribute("name",域范圍常量)

3.自動在四個域中搜索數據

pageContext.findAttribute("name");
順序: page域 -> request域 -> session域- > context域(application域)

域范圍常量:
PageContext.PAGE_SCOPE
PageContext.REQUEST_SCOPE
PageContext.SESSION_SCOPE
PageContext.APPLICATION_SCOPE

5.4.JSP中的四個域對象

四個域度對象

  • pageContext page域
  • request request域
  • session session域
  • application context域

1.域對象作用
保存數據和獲取數據,用於數據共享

2.域對象方法
setAttribute("name",Object)保存數據
getAttribute("name")獲取數據
removeAttribute("name")消除數據

域對象的作用范圍

  • page域 :只能在當前jsp頁面中使用(當前頁面)
  • request : 只能在同一個請求中使用(轉發)
  • Session : 只能在同一個會話(session對象)中使用(私有的)
  • context : 只能在同一個web應用中使用(全局的)

5.5.JSP的最佳實踐

Servlet技術:開發動態資源。是一個java類,最擅長寫java代碼
JSP技術:開發動態資源,通過java代碼最擅長輸出html代碼

一個在web項目中涉及到的邏輯:
1.接收參數
2.處理業務邏輯
3.顯示數據到瀏覽器
4.跳轉到其他頁面

最佳實踐中,對上述邏輯進行分工,由Servlet和JSP聯合完成
Servlet:
1.接收參數
2.處理業務邏輯
3.把結果保存到域對象中
4.跳轉到jsp頁面

JSP:
1.從域對象中取出數據
2.把數據顯示到瀏覽器

Servlet的數據-->JSP頁面

6.EL表達式

6.1.EL表達式的作用

EL表達式也是用在html頁面中的,目的是簡化JSP操作,代碼。
在最佳實踐中,總結得出JSP中盡量不要寫java代碼,最好的方法就是不寫,所以的邏輯全部放到Servlet中,所有的數據展示放在JSP中
JSP的核心語法: jsp表達式 <%=%>和 jsp腳本<% %>。

現在使用EL表達式來替換到JSP的表達式

EL表達式的作用:向瀏覽器輸出”域對象中的“變量值或表達式計算的結果!,注意一定要是域對象中的

語法:${變量或表達式}

6.2.EL語法

1.輸出基本數據類型便變量
1.1.從四個域獲取

輸出普通字符串: ${name}
若沒有指定域,則域的搜索先后順序: pageScoep / requestScope / sessionScope / applicationScope

1.2.指定域獲取

${pageScope.name},在pageScope域中查找name

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>測試jsp文件</title>
</head>
<body>
<%
    String name = "roso";
    pageContext.setAttribute("name",name,PageContext.REQUEST_SCOPE);
    %>
<br>
EL表達式:${requestScope.name};
<%--
    ${name}等價於pageContext.findAtribute("name")
--%>
</body>
</html>

2.輸出對象的屬性值
輸出對象屬性: ${student.name} 注意: .name 相當於 .getName()方法
如果我們定義了一個Student類,並定義了name成員變量,這個時候可以通過${student.name}來獲取name值
**點 . **方法是其實是調用getXX()方法

3.輸出集合對象
集合對象有List和Map
輸出List集合: ${list[0].name } 注意: [0] 相當於 get(下標)方法
輸出map集合: ${map[key].name} 注意: [key]相當於get(key)方法
中括號[]其實是調用get
EL表達式沒有遍歷功能,但是可以結合標簽使用遍歷

4.EL表達式計算
表達式中需要注意的是字符串判空的一種方法${empty name}<br>

示例代碼:

<%@ page import="servers.Student" contentType="text/html;charset=UTF-8" language="java" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<html>
<head>
    <title>測試IE表達式</title>
</head>
<body>

<%--1.EL輸出對象的屬性--%>
<%
    //保存數據
    Student student = new Student("eric", 20);
    //放入域中
    pageContext.setAttribute("student",student);
%>

<%--2.EL輸出集合List對象--%>
<%
    //List
    List<Student> list = new ArrayList<Student>();
    list.add(new Student("rose",18));
    list.add(new Student("jack",20));
    list.add(new Student("luck",38));
    //List放到域中
    pageContext.setAttribute("list",list);
%>

<%--3.EL輸出集合Map對象--%>
<%
    //Map
    Map<String,Student> map = new HashMap<String, Student>();
    map.put("100",new Student("mark",20));
    map.put("101",new Student("maxwell",30));
    map.put("102",new Student("Eric",40));
    //放入域中
    pageContext.setAttribute("map",map);
%>

<%--3.EL表達式--%>
    <%--3.1.算術表達式--%>
    ${10+5}<br>
    <%--3.2.比較運算--%>
    ${10>5} <br>
    <%--3.3.邏輯運算--%>
    ${true && false} <br>
    <%--3.4.判空,null或空字符串--%>
    判斷null:${name==null}<br>
    判斷空字符串:${name==""}<br>
    判空: ${name==null || name==""}<br>
    判空的另一個種寫法: ${empty name}<br>

<%--1.使用EL獲取對象--%>
<%--實際調用student的getName方法獲取的值--%>
獲取student的name屬性值:${student.name}
<%--${student.name}的點相當於調用getXX()方法--%>
<br>


<%--2.使用EL獲取List對象--%>
list對象:${list} <br>
獲取list的第一個對象:${list[0]} <br>
獲取list的第一個對象的name和age屬性:${list[0].name} - ${list[0].age}
<br>
<%--${list[0]}等價於(ListpageContext.findAttribute("list)--%>
<%--${list[0]}的中括號相當於調用get()方法--%>

<%--3.使用EL獲取Map對象--%>
獲取Map對象:${map}<br>
獲取key=100的值:${map['100'].name} - ${map['100'].age}
</body>
</html>

7.JSP標簽

7.1.JSP標簽的作用

我們使用EL表達式來替換JSP的表達式,但是JSP還有一個經常會使用的語法,就是JSP腳本,出於和EL表達式同樣的目的,我們使用標簽來替代JSP腳本,以達到簡化JSP頁面的目的
所以JSP標簽作用:替換JSP腳本
主要功能有:
1.路程判斷(if,for, 循環)
2.跳轉頁面(轉發,重定向)
3.…………

7.2.JSP標簽的分類

JSP的標簽也分為幾種類型的

  • 1.內置標簽:,也叫動作標簽,不需要在jsp頁面中導入的標簽
  • 2.JSTL標簽:需要在jsp頁面中導入的標簽
  • 3.自定義標簽:開發者自行定義,需要在jsp頁面導入標簽

7.3.動作標簽

轉發標簽: <jsp:forward />
參數標簽: jsp:pararm/
包含標簽: jsp:include/
包含標簽的原理:
包含與被包含的頁面先各自翻譯成java源文件,然后在運行時再合並在一起。(先翻譯再合並),動態包含,使用include指令包含是靜態包含
靜態包含 VS 動態包含
1.語法不同

靜態包含語法:<%@inclue file="被包含的頁面"%>
動態包含語法: <jsp:include page="被包含的頁面">

2.參數傳遞不同

靜態包含不能向被包含頁面傳遞參數
動態包含可以向被包含頁面傳遞參數

3.原理不同

靜態包含: 先合並再翻譯
動態包含: 先翻譯再合並

7.4.JSTL標簽

JSTL的全名是:Java Standard Tag Libarary ---java標准標簽庫
java標准標簽庫有五類,常用的是前三類

  • 標簽核心庫(c標簽庫) 天天用
  • 國際化標簽(fmt標簽庫)
  • EL函數庫(fn函數庫)
  • xml標簽庫(x標簽庫)
  • sql標簽庫(sqp標簽庫)

7.5.使用JSTL標簽的步驟

1.導入jstl支持的jar包(標簽背后隱藏的java代碼)
把包放在WEB-INF下的lib包
2.使用tablib指令導入標簽庫

<%@taglib prefix="簡寫" uri="tld文件的uri名稱" %>
uri從jstl.jar包下的META-INF下的tld文件中查找,把uri的值復制過來,prefix的值也是在tld中查找

3.在jsp中使用標簽
核心標簽庫的重點標簽
保存數據:
<c:set></c:set>
獲取數據:
<c:out value=""></c:out>
單條件判斷:
<c:if test=""></c:if>
多條件判斷:
<c:choose></c:choose>
<c:when test=""></c:when>
<c:otherwise></c:otherwise>
循環數據:
<c:forEach></c:forEach>
<c:forTokens items="" delims=""></c:forTokens>
重定向:
<c:redirect></c:redirect>
代碼示例:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%--導入標簽庫--%>
<%@taglib prefix="c"   uri="http://java.sun.com/jsp/jstl/core"%>
<html>
  <head>
    <title>JSTL核心標簽</title>
  </head>
  <body>
  <%--使用標簽--%>
  <%--1.set標簽:保存數據(保存到域中),默認保存到page域中,可以指定--%>
  <c:set var="name" value="Eric" scope="request"></c:set>
  ${name}<br>
  ${requestScope.name}<br>
  <%--2.out標簽:獲取數據(從域中),當value值為null時,可以使用default指定的默認值,escapeXml標明默認值是原樣輸出還是轉化為之后再輸出,默認為true,表示原樣輸出--%>
  <%--雙引號內雖然是name,但是現實的是字符串name,因為是在雙引號內--%>
  <c:out value="name"/>
  <%--調用name的值正確寫法--%>
  <c:out value="${name}" default="<h3>標題3</h3>" escapeXml="false"/><br>

  <%--3.if標簽:單條件判斷,如果test里面的EL表達式為真,則運行if包含的代碼--%>
  <c:if test="${10>5}">
    條件成立
  </c:if>

  <%--4.choose標簽+when標簽+otherwirse標簽:多條件的判斷--%>
  <c:set var="score" value="86"></c:set>
  <c:choose>
    <c:when test="${score>=90 && score<=100}">
      優秀
    </c:when>
    <c:when test="${score>=80 && score<=90}">
      良好
    </c:when>
    <c:when test="${score>=70 && score<=80}">
      一般
    </c:when>
    <c:when test="${score>=60 && score<=70}">
      及格
    </c:when>
    <c:otherwise>
      不及格
    </c:otherwise>
  </c:choose>
<br>
<%--5.forEach:循環--%>
  <%
    //List
    List<Student> list = new ArrayList<Student>();
    list.add(new Student("rose",18));
    list.add(new Student("jack",20));
    list.add(new Student("luck",38));
    //List放到域中
    pageContext.setAttribute("list",list);
  %>
  <%
    //Map
    Map<String,Student> map = new HashMap<String, Student>();
    map.put("100",new Student("mark",20));
    map.put("101",new Student("maxwell",30));
    map.put("102",new Student("Eric",40));
    //放入域中
    pageContext.setAttribute("map",map);
  %>
  <%--<c:forEach
  begin="從哪個元素開始遍歷,默認從0開始,可以不寫"
  end="到哪個元素結束,默認到最后一個元素,可以不寫"
  step="步長,默認是1,可以不寫"
  var="每個元素的名稱"
  items="需要遍歷的數據(集合)"
  varStatus="當前正在遍歷的元素的狀態對象(count屬性:當前位置,從1開始)"/>--%>
  <%--遍歷list--%>
  <c:forEach begin="0" end="2" step="1" items="${list}" var="student" varStatus="varSta">
    姓名:${varSta.count}--${student.name}--年齡:${student.age}<br>
  </c:forEach>
  <%--遍歷Map--%>
  <c:forEach items="${map}" var="entry">
    ${entry.key}--姓名:${entry.value.name}--年齡:${entry.value.age}<br>
  </c:forEach>

  <%--6.forToken標簽:循環特殊字符串--%>
  <%
    String str = "java-php-net-平面";
    pageContext.setAttribute("str",str);
  %>
  <c:forTokens items="${str}" delims="-" var="s">
    ${s}<br>
  </c:forTokens>

  <%--7.重定向--%>
  <c:redirect url="http://www.baidu.com"/>
  </body>
</html>

8.自定義標簽

8.1.引入

當現有的標簽無法滿足我們的需求時,就需要自己開發一個適合的標簽
例如,需要向瀏覽器輸入當前客戶端的IP地址,雖然用java程序是可以的,但是用標簽是沒有這個功能的,現在,我們來自定以這個標簽

8.2.第一個自定義標簽開發步驟

1.編寫一個普通的類,繼承SimpleTagSupport類,叫做標簽處理器類

/**
 * 標簽處理類
 * 1.繼承SimpleTagSupport
 */

public class ShowIpTag extends SimpleTagSupport {

    /**
     * 2.覆蓋doTag方法
     */
    @Override
    public void doTag() throws JspException, IOException {
        //向瀏覽器輸出客戶的IP地址
        PageContext pageContext = (PageContext)this.getJspContext();
        HttpServletRequest request = (HttpServletRequest)pageContext.getRequest();
        String ip = request.getRemoteHost();
        JspWriter out = pageContext.getOut();
        out.write("使用自定義標簽輸出客戶的IP地址:"+ip);
    }
}

2.在web項目的WEB-INF目錄下建立net.tld文件,這個tld叫標簽的聲明文件(參考核心標簽庫的寫法)

<?xml version="1.0" encoding="UTF-8" ?>

<taglib 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-jsptaglibrary_2_1.xsd"
        version="2.1">

    <!--標簽庫的版本-->
    <tlib-version>1.1</tlib-version>
    <!--標簽庫前綴-->
    <short-name>net</short-name>
    <!--tld文件的唯一標記-->
    <uri>http://gz.itcast.cn</uri>

    <!--一個標簽的聲明-->
    <tag>
        <!--標簽名-->
        <name>ShoeIp</name>
        <!--標簽處理器類的全名-->
        <tag-class>tag.ShowIpTag</tag-class>
        <!--輸出標簽體內容格式-->
        <body-content>scriptless</body-content>
    </tag>
</taglib>

3.在jsp頁面的頭部導入自定義標簽庫

<%@taglib prefix="net" uri="http://gz.itcast.cn" %>

4.在jsp中使用自定義標簽

net:ShoeIp</net:ShoeIp>

8.3.自定義標簽的執行過程

問題: http://localhost:8080/hello/tag.jsp 如何訪問到自定義標簽?
前提:tomcat服務器啟動時,加載到每個web應用,加載每個web應用的WEB-INF目錄下的所有文件,如web.xml, tld文件
訪問步驟:
1.訪問tag.jsp資源
2.tomcat服務器把jsp文件翻譯成java源文件-->編譯class-->構造類對象-->調用_jspService()方法
3.檢查jsp文件的taglib指令,是否存在名為http://gz.itcast.cn的tld文件,如果沒有,則報錯
4.上一步已經讀取到net.tld文件
5.在tag.jsp中讀到net:ShoeIp,到net.tld文件中查詢是否存在 為ShoeIp的 標簽
6.找到對應的 標簽,則讀到 內容
7.得到tag.ShowIpTag
8.構造ShowIpTag對象,然后調用ShowIpTag里面的方法

8.4.自定義標簽處理類的生命周期

標簽處理器本質上實現的還是SimpleTag接口,只是對里面的方法進行了重寫。
SimpleTag接口:
void setJspContext(JspContext pc)
設置pageContext對象,傳入pageContext(一定調用)
void setParent(JspTag parent)
設置父標簽對象,傳入父標簽對象,如果沒有父標簽對象,則調用此方法。通過geetParent()方法得到父標簽對象
void setXX(值)
設置屬性值
void setJspBody(JSpFragment jspBody)
設置標簽體內容。標簽提內容封裝到JspFragment中,然后傳入JspFragment對象,通過getJspBody()方法得到標簽體內容,如果沒有標簽體內容,則不會調用此方法
void doTag()
執行標簽時調用的方法(一定會調用)

8.5.自定義標簽的作用

1.控制標簽體內容的是否輸出
2.控制標簽余下內容是否輸出
3.控制重復輸出標簽體內容
4.改變標簽體內容
5.帶屬性的標簽

	//1.聲明屬性的成員變量
	private Integer num;
	
	//2.關鍵點: 必須提供公開的setter方法,用於給屬性賦值
	public void setNum(Integer num) {
		this.num = num;
	}

自定義標簽的作用代碼示例:


/**
 * 標簽處理器類
 */
public class TagDemo extends SimpleTagSupport {
    @Override
    public void doTag() throws JspException, IOException {
        System.out.println("執行了標簽");
        /**
         *1. 控制標簽內容是否輸出
         * 輸出:調用jspFrament.invoke();
         * 不輸出:不調用jspFrament.invoke();
         */
        //1.1.得到標簽體內容
        JspFragment jspBody = this.getJspBody();
        //執行invoke方法:會把標簽體的內容輸出到指定的Writer對象
        //1.2.往瀏覽器輸出,writer為null就是默認往瀏覽器輸出
//        JspWriter out = this.getJspContext().getOut();
//        jspBody.invoke(out);
        jspBody.invoke(null);//等價於上面的兩行代碼

        /**
         * 3.控制重復輸出標簽體內容
         * 方法:執行多次jspBody.invoke()方法
         */
        for (int i=1; i <= 5 ; i++) {
            jspBody.invoke(null);
        }


        /**
         * 4.改變標簽提內容
         */
        //4.1.創建StringWriter臨時容器
        StringWriter sw = new StringWriter();
        //4.2.把標簽提內容拷貝到臨時容器
        jspBody.invoke(sw);
        //4.3.從臨時容器中得到的標簽
        String content = sw.toString();
        //4.4.改變內容
        content = content.toLowerCase();
        //4.5.把改變的內容輸出到瀏覽器
        //不能使用jspBody.invoke()來輸出,因為標簽體內的內容並沒有改變,改變的是容器里面的
        this.getJspContext().getOut().write(content);
        

        /**
         * 2.控制標簽余下內容是否輸出
         * 輸出:什么都不做就會默認輸出
         * 不輸出:拋出有SkipPageException()異常則不輸出
         */
        throw new SkipPageException();
        
    }
}

8.6.輸出標簽體內容格式

JSP:在傳統標簽中使用。可以寫和執行jsp的java代碼
scriptless:標簽體不可以寫jsp的java代碼
empty:必須是空標簽
tagdependent:標簽體內容可以寫jsp的java代碼,但不會執行

9.JavaBean

JavaBaen,咖啡豆,是一種開發規范,可以說是一種技術

JavaBaen就是一個普通的java類,只要符合以下規定才能稱之為javaBean:
1.必須提供無參構造方法
2.類中屬性都必須私有化
3.該類提供公開的getter和setter方法

javaBean的作用:
用於方法數據,保存數據
方法javaBean只能使用getter和seetter方法

javaBean的使用場景:
1.項目中用到實體對象(entity)符合javaBean規范
2.EL表達式訪問對象屬性,${student.name}滴啊用getName()方法,符合javaBean規范
3.jsp標簽中的屬性賦值,setNum(Integet num)。符合javaBean規范
4.jsp頁面中使用javaBean,符合javaBean規范

javaBean在jsp頁面中的使用

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>jsp頁面中使用javabean</title>
</head>
<body>
<%--創建對象,使用無參構造器--%>
<jsp:useBean id="stu" class="servers.Student"/>

<%--賦值--%>
<jsp:setProperty name="stu" property="name" value="jacky"/>

<%--獲取--%>
<jsp:getProperty name="stu" property="name"/>

</body>
</html>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM