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文件中查詢是否存在
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>