2020了,还要学JSP嘛?入个门呗!毕竟Servlet亲兄弟~
目錄
- 1、什么是JSP
- 2、JSP原理
- 3、JSP基礎(chǔ)語法
- jsp表達式
- jsp腳本片段
- jsp聲明
- jsp注釋
- 4、JSP指令
- 5、JSP行為
- 6、9大內(nèi)置對象
- 7、EL表達式
- 格式
- 變量
- [ ]與.運算符
- 8、JSTL表達式
- 9、JSP標(biāo)簽
ps:本文著重于一些重點(第二點原理)哦~ 畢竟2020了 ,JSP很少用到了!
1、什么是JSP
Java Server Pages:Java服務(wù)器端頁面,和Servlet一樣,用于動態(tài)Web技術(shù)!
JSP部署于網(wǎng)絡(luò)服務(wù)器上,可以響應(yīng)客戶端發(fā)送的請求,并根據(jù)請求內(nèi)容動態(tài)地生成HTML、XML或其他格式文檔的Web網(wǎng)頁,然后返回給請求者。
特點:
-
JSP 技術(shù)是以 Java 語言作為腳本語言的,JSP 網(wǎng)頁為整個服務(wù)器端的 Java 庫單元提供了一個接口來服務(wù)于HTTP的應(yīng)用程序。因此JSP里可以直接寫Java代碼!
-
寫JSP就像寫HTML
- HTML頁面是靜態(tài)頁面,固定內(nèi)容,不會變,由web服務(wù)器向客戶端發(fā)送。
- JSP頁面是有JSP容器執(zhí)行該頁面的Java代碼部分然后實時生成動態(tài)頁面,可動態(tài)更新頁面上的內(nèi)容。
- JSP頁面中可以嵌入Java代碼,為用戶提供動態(tài)數(shù)據(jù)
2、JSP原理
JSP是怎么執(zhí)行的?
在IDEA中使用Tomcat會在IDEA目錄下的tomcat中產(chǎn)生一個work目錄
IDEA的工作目錄位置:
C:\Users\zsr204\AppData\Local\JetBrains\IntelliJIdea2020.1
或者C:\Users\zsr204.IntelliJIdea2019.3
點進去,可以看到我們使用過tomcat的項目
點入一個項目,就可以看到對應(yīng)的work目錄
繼續(xù)點開,可以發(fā)現(xiàn)index.jsp頁面轉(zhuǎn)換成了Java程序
我們打開.java文件,發(fā)現(xiàn)繼承了HttpJspBase類
而HttpJspBase繼承了JspPage,JspPage又繼承了Servlet
所以:JSP最終會被轉(zhuǎn)換為Java類,JSP本質(zhì)上就是Servlet,瀏覽器向服務(wù)器發(fā)送請求,不管訪問什么資源,其實都是在訪問Servlet
經(jīng)過以上分析,我們可以得出以下原理圖
接下來我們分析一下index.java類
有以下三個主要的方法:
//初始化jsp頁面
public void _jspInit() {}//關(guān)閉jsp頁面
public void _jspDestroy() {}//JspService
public void _jspService(HttpServletRequest request,HttpServletResponse response)
關(guān)于**_jspService**方法:有幾個部分組成
- 判斷請求
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {final java.lang.String _jspx_method = request.getMethod();if ("OPTIONS".equals(_jspx_method)) {response.setHeader("Allow","GET, HEAD, POST, OPTIONS");return;}if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) {response.setHeader("Allow","GET, HEAD, POST, OPTIONS");response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允許 GET、POST 或 HEAD。Jasper 還允許 OPTIONS");return;}}
-
內(nèi)置一些對象
這些對象我們可以直接在JSP頁面中使用~
final javax.servlet.jsp.PageContext pageContext;//頁面上下文,包含整個頁面相聯(lián)系的數(shù)據(jù)
javax.servlet.http.HttpSession session = null; //session(服務(wù)端會話)對象
final javax.servlet.ServletContext application; //applicationContext
final javax.servlet.ServletConfig config; //config配置
javax.servlet.jsp.JspWriter out = null; //out輸出對象,用來寫入響應(yīng)流的數(shù)據(jù)
final java.lang.Object page = this; //page,servlet自身
HttpServletRequest request //HTTP request(請求)對象
HttpServletResponse response //HTTP response(響應(yīng))對象
- 輸出頁面前增加的代碼
response.setContentType("text/html"); //設(shè)置響應(yīng)的頁面類型
pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); //初始化pageContext對象
_jspx_page_context = pageContext; //賦值
application = pageContext.getServletContext(); //獲取servlet上下文
config = pageContext.getServletConfig(); //獲取配置對象
session = pageContext.getSession(); //獲取session對象
out = pageContext.getOut(); //獲取out輸出對象
_jspx_out = out; //賦值
- 輸出當(dāng)前頁面
out.write("<html>\n");
out.write("<body>\n");
out.write("<h2>Hello World!</h2>\n");
out.write("</body>\n");
out.write("</html>\n");
這時候,如果我們在IDEA中新加一個hello.jsp,我們點擊運行
我們會發(fā)現(xiàn),剛才打開index.jsp所在的的目錄不存在了,其實是原先的整個work目錄沒了,并生成了一個新的work目錄
我們繼續(xù)點開新的work目錄,同樣可以看到之前的index.jsp和index.java
這時候我們在瀏覽器訪問hello.jsp頁面,發(fā)現(xiàn)頁面輸出了我們jsp中用java代碼定義的name
然后可以發(fā)現(xiàn),我們多了hello.jsp和hello.java兩個文件
我們再點開hello.java,可以發(fā)現(xiàn)除了輸出頁面的代碼變成對應(yīng)hello.jsp的代碼以外,其他沒有區(qū)別
out.write("\r\n");out.write("<html>\r\n");out.write("<head>\r\n");out.write(" <title>Title</title>\r\n");out.write("</head>\r\n");out.write("<body>\r\n");out.write("hello\r\n");out.write('\r');out.write('\n');String name = "zsr";out.write('\r');out.write('\n');out.write("\r\n");out.write("name:");out.print(name);out.write("\r\n");out.write("</body>\r\n");out.write("</html>\r\n");
我們觀察這段段代碼,可以發(fā)現(xiàn)
在JSP頁面中:Java代碼會原封不動的輸出,如果是Html代碼,就會被轉(zhuǎn)換為以下形式
out.write("<html?\r\n");
3、JSP基礎(chǔ)語法
jsp表達式
用來將程序輸出到客戶端
<%= 變量或者表達式 %>
<%=new Date()%>
jsp腳本片段
- 腳本程序可以包含任意量的Java語句、變量、方法或表達式,只要它們在腳本語言中是有效的。
<% 代碼片段 %>
等價于
<jsp:scriptlet>代碼片段
</jsp:scriptlet>
<%int sum = 0;for (int i = 0; i < 100; i++) {sum += i;}out.print("<h1>總和為" + sum + "</h1>");
%>
腳本片段的嵌套
<%int x = 10;out.print(x);
%>
<p>這是一個jsp文檔</p>
<%out.println(x);
%>
<%for (int i = 0; i < 5; i++) {
%>
<h1>helloworld</h1>
<%}
%>
jsp聲明
- 一個聲明語句可以聲明一個或多個變量、方法,供后面的Java代碼使用
<%! declaration; [ declaration; ]…%>
等價于
<jsp:declaration>代碼片段
</jsp:declaration>
<%!static {System.out.println("加載中");}private int count = 0;public void function() {System.out.println("進入了方法");}
%>
會被編譯到j(luò)sp生成的Java類index_jsp中!
而上述jsp表達式和腳本片段都會生成到**_jspService**方法中
jsp注釋
<%--注釋--%>
| 語法 | 描述 |
|---|---|
| <%-- 注釋 --%> | JSP注釋,注釋內(nèi)容不會被發(fā)送至瀏覽器甚至不會被編譯 |
| HTML注釋,通過瀏覽器查看網(wǎng)頁源代碼時可以看見注釋內(nèi)容 |
4、JSP指令
JSP指令用來設(shè)置與整個JSP頁面相關(guān)的屬性。
| 指令 | 描述 |
|---|---|
| <%@ page … %> | 定義頁面的依賴屬性,比如腳本語言、error頁面、緩存需求等等 |
| <%@ include … %> | 包含其他文件 |
| <%@ taglib … %> | 引入標(biāo)簽庫的定義,可以是自定義標(biāo)簽 |
實例1:定制500錯誤頁面,利用<%@ page … %>指令跳轉(zhuǎn)
error.jsp(1/0會出現(xiàn)500錯誤,會跳轉(zhuǎn)到500錯誤頁面)
<%@ page contentType="text/html;charset=UTF-8" language="java" %><%--定制錯誤頁面--%>
<%@ page errorPage="error/500.jsp" %><html>
<head><title>出現(xiàn)錯誤</title>
</head>
<body>
<%int x = 1/0;
%>
</body>
</html>
500.jsp(自定義500錯誤頁面,顯示500錯誤圖片)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body><img src="../img/500.jpg" alt="500"></body>
</html>
測試:點擊運行,輸入地址localhost:8080/error.jsp,就會跳轉(zhuǎn)到自定義的500錯誤頁面
實現(xiàn)錯誤頁面的跳轉(zhuǎn)還可以再web.xml中配置
<error-page><error-code>404</error-code><location>/error/404.jsp</location>
</error-page>
<error-page><error-code>500</error-code><location>/error/500.jsp</location>
</error-page>
實例二 :效仿正常頁面,利用<%@ include … %>指令包含一個頭部一個尾部
header.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><h1>頁面頭部</h1>
footer.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<h1>頁面尾部</h1>
common.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>包含頭部尾部常規(guī)頁面</title>
</head>
<body><%--將兩個頁面合二為一--%>
<%@include file="common/header.jsp" %>
<h1>網(wǎng)頁主體</h1>
<%@include file="common/footer.jsp" %></body>
</html>
測試:點擊運行,輸入localhost:8080/common.jsp,發(fā)現(xiàn)如下結(jié)果
5、JSP行為
JSP行為標(biāo)簽使用XML語法結(jié)構(gòu)來控制servlet引擎。它能夠動態(tài)插入一個文件,重用JavaBean組件,引導(dǎo)用戶去另一個頁面,為Java插件產(chǎn)生相關(guān)的HTML等等。
行為標(biāo)簽只有一種語法格式,它嚴(yán)格遵守XML標(biāo)準(zhǔn):
<jsp:action_name attribute="value" />
行為標(biāo)簽基本上是一些預(yù)先就定義好的函數(shù),下表羅列出了一些可用的JSP行為標(biāo)簽:
| 語法 | 描述 |
|---|---|
| jsp:include | 用于在當(dāng)前頁面中包含靜態(tài)或動態(tài)資源 |
| jsp:useBean | 尋找和初始化一個JavaBean組件 |
| jsp:setProperty | 設(shè)置 JavaBean組件的值 |
| jsp:getProperty | 將 JavaBean組件的值插入到 output中 |
| jsp:forward | 從一個JSP文件向另一個文件傳遞一個包含用戶請求的request對象 |
| jsp:plugin | 用于在生成的HTML頁面中包含Applet和JavaBean對象 |
| jsp:element | 動態(tài)創(chuàng)建一個XML元素 |
| jsp:attribute | 定義動態(tài)創(chuàng)建的XML元素的屬性 |
| jsp:body | 定義動態(tài)創(chuàng)建的XML元素的主體 |
| jsp:text | 用于封裝模板數(shù)據(jù) |
例如上述實現(xiàn)正常頁面包含頭部尾部還可以通過以下代碼來實現(xiàn)
<%--jsp標(biāo)簽--%>
<%--拼接頁面,本質(zhì)還是三個頁面--%>
<jsp:include page="common/header.jsp"/>
<h1>網(wǎng)頁主體</h1>
<jsp:include page="common/footer.jsp"/>
6、9大內(nèi)置對象
| 對象 | 描述 |
|---|---|
| request | HttpServletRequest類的實例**(存東西)** |
| response | HttpServletResponse類的實例 |
| out | PrintWriter類的實例,用于把結(jié)果輸出至網(wǎng)頁上 |
| session | HttpSession類的實例**(存東西)** |
| application | ServletContext類的實例,與應(yīng)用上下文有關(guān)**(存東西)** |
| config | ServletConfig類的實例 |
| pageContext | PageContext類的實例,提供對JSP頁面所有對象以及命名空間的訪問**(存東西)** |
| page | 類似于Java類中的this關(guān)鍵字 |
| Exception | Exception類的對象,代表發(fā)生錯誤的JSP頁面中對應(yīng)的異常對象 |
其中request、session、application、pageContext可以存相應(yīng)信息
關(guān)于request、session、application、pageContext的層級關(guān)系圖:
作用域(scope)從低到高:pageContext—>request—>session—>application
案例測試:
test.jsp(用來存東西,并取出顯示)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>內(nèi)置對象的測試</title>
</head>
<body>
<%pageContext.setAttribute("name1", "zsr");//保存的數(shù)據(jù)只在一個頁面中有效request.setAttribute("name2", "barry");//保存的數(shù)據(jù)只在一次請求中有效,請求轉(zhuǎn)發(fā)會攜帶這個數(shù)據(jù)session.setAttribute("name3", "gcc");//保存的數(shù)據(jù)只在一次會話中有效,從打開瀏覽器到關(guān)閉瀏覽器application.setAttribute("name4", "marry");//保存的數(shù)據(jù)只在服務(wù)器中有效,從打開服務(wù)器到關(guān)閉服務(wù)器
%>
<%//從pageContext中取,利用尋找的方式//從底層到高層(作用域)String name1 = (String) pageContext.findAttribute("name1");String name2 = (String) pageContext.findAttribute("name2");String name3 = (String) pageContext.findAttribute("name3");String name4 = (String) pageContext.findAttribute("name4");
%>
<%--使用EL表達式輸出--%>
<h1>取出的值為:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3></body>
</html>
然后我們點擊運行,輸入localhost:8080/test.jsp,可以看到下圖所示結(jié)果
我們再新建一個頁面test2.jsp,取出上述test.jsp存進去的東西
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>內(nèi)置對象的測試</title>
</head>
<body><%//從pageContext中取,利用尋找的方式//從底層到高層(作用域)String name1 = (String) pageContext.findAttribute("name1");String name2 = (String) pageContext.findAttribute("name2");String name3 = (String) pageContext.findAttribute("name3");String name4 = (String) pageContext.findAttribute("name4");
%>
<%--使用EL表達式輸出--%>
<h1>取出的值為:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3></body>
</html>
然后我們點擊運行,輸入localhost:8080/test2.jsp,可以看到下圖所示結(jié)果
發(fā)現(xiàn)只取出了name3和name4,也就是存在session和application里的東西,這就是因為作用域的原因
-
pageContext的作用域最小,只在當(dāng)前頁面有效,所以換了新頁面,就找不到了
-
request的作用域其次,因為沒有進行轉(zhuǎn)發(fā),所以內(nèi)容也丟失了,所以沒有找到
這時候如果我們在test1.jsp里面加入轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)到test2.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>內(nèi)置對象的測試</title>
</head>
<body>
<%pageContext.setAttribute("name1", "zsr");//保存的數(shù)據(jù)只在一個頁面中有效request.setAttribute("name2", "barry");//保存的數(shù)據(jù)只在一次請求中有效,請求轉(zhuǎn)發(fā)會攜帶這個數(shù)據(jù)session.setAttribute("name3", "gcc");//保存的數(shù)據(jù)只在一次會話中有效,從打開瀏覽器到關(guān)閉瀏覽器application.setAttribute("name4", "marry");//保存的數(shù)據(jù)只在服務(wù)器中有效,從打開服務(wù)器到關(guān)閉服務(wù)器
%>
<%//從pageContext中取,利用尋找的方式//從底層到高層(作用域)String name1 = (String) pageContext.findAttribute("name1");String name2 = (String) pageContext.findAttribute("name2");String name3 = (String) pageContext.findAttribute("name3");String name4 = (String) pageContext.findAttribute("name4");pageContext.forward("/test2.jsp");
%>
<%--使用EL表達式輸出--%>
<h1>取出的值為:</h1>
<h3>${name1}</h3>
<h3>${name2}</h3>
<h3>${name3}</h3>
<h3>${name4}</h3></body>
</html>
然后我們點擊運行,輸入localhost:8080/test.jsp,可以看到下圖所示結(jié)果
可以發(fā)現(xiàn)我們?nèi)〕隽舜嬖?strong>request里的name2,這是因為我們進行了轉(zhuǎn)發(fā)
7、EL表達式
EL(Expression Language) 是為了使JSP寫起來更加簡單
<!--standard 標(biāo)簽庫-->
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version>
</dependency>
作用:
- 獲取數(shù)據(jù)
- 執(zhí)行運算
- 獲取web開發(fā)的常用對象
格式
${}
-
例如,${info}代表獲取變量info的值。
-
當(dāng)EL表達式中的變量不給定范圍時
則默認(rèn)在page范圍查找,然后依次在request、session、application范圍查找。
-
可以用范圍作為前綴表示屬于哪個范圍的變量
例如:${ pageScope. info}表示訪問page范圍中的info變量。
變量
-
EL存取變量數(shù)據(jù)的方法很簡單,例如:${name}。它的意思是取出某一范圍中名稱為name的變量。
-
因為并沒有指定哪一個范圍的name,所以會依序從Page、Request、Session、Application范圍查找。
-
假如找到name,就直接回傳,不再繼續(xù)找下去,但是假如全部的范圍都沒有找到時,就回傳""。
EL表達式的屬性如下:
| 屬性范圍在EL中的名稱 | |
|---|---|
| Page | PageScope |
| Request | RequestScope |
| Session | SessionScope |
| Application | ApplicationScope |
[ ]與.運算符
-
EL 提供“.“和“[ ]“兩種運算符來存取數(shù)據(jù)。
-
當(dāng)要存取的屬性名稱中包含一些特殊字符,如 . 或 - 等并非字母或數(shù)字的符號,就一定要使用“[ ]“。
例如:user.My?Name應(yīng)當(dāng)改為{ user. My-Name}應(yīng)當(dāng)改為user.My?Name應(yīng)當(dāng)改為{user[“My-Name”]}
-
如果要動態(tài)取值時,就可以用“[ ]“來做,而“.“無法做到動態(tài)取值。
例如:${sessionScope.user[data]}中data 是一個變量
8、JSTL表達式
JSTL(Java server pages standarded tag library,即JSP標(biāo)準(zhǔn)標(biāo)簽庫)
- JSTL標(biāo)簽庫的使用就是為了彌補HTML標(biāo)簽的不足;他自定義許多標(biāo)簽供使用,功能和Java代碼一樣。
<!--standard 標(biāo)簽庫-->
<!-- https://mvnrepository.com/artifact/taglibs/standard -->
<dependency><groupId>taglibs</groupId><artifactId>standard</artifactId><version>1.1.2</version>
</dependency>
<!--JSTL表達式的依賴-->
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl-api -->
<dependency><groupId>javax.servlet.jsp.jstl</groupId><artifactId>jstl-api</artifactId><version>1.2</version>
</dependency>
菜鳥教程JSTL
根據(jù)JSTL標(biāo)簽所提供的功能,可以將其分為5個類別。
- 核心標(biāo)簽
- 格式化標(biāo)簽
- SQL 標(biāo)簽
- XML 標(biāo)簽
- JSTL 函數(shù)
JSTL標(biāo)簽庫的使用步驟:
-
引入對應(yīng)的taglib
-
使用其中的方法
-
在Tomcat的lib目錄下也要引入對應(yīng)jstl的jar包,否則會報錯:JSTL解析錯誤
示例:
coreif.jsp(測試用戶登錄)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head><title>Title</title>
</head>
<body>
<h4>if測試</h4>
<hr>
<%--EL表達式獲取表單中的數(shù)據(jù)${param.參數(shù)名}
--%>
<form action="coreif.jsp" method="get"><input type="text" name="username" value="${param.username}"><input type="submit" value="登錄">
</form><%--判斷如果提交的用戶名是管理員,則登錄成功--%>
<c:if test="${param.username=='admin'}" var="isAdmin"><c:out value="管理員歡迎你"/>
</c:if>
<c:out value="${isAdmin}"/>
</body>
</html>
點擊運行,打開 http://localhost:8080/coreif.jsp,出現(xiàn)如下結(jié)果
如果我們輸入admin再點擊登錄
9、JSP標(biāo)簽
一共以下幾種標(biāo)簽
實例:
jsptag:(攜帶參數(shù),請求轉(zhuǎn)發(fā)到 jsptag2)
<html>
<head><title>Title</title>
</head>
<body><jsp:forward page="jsptag2.jsp"><jsp:param name="name" value="zsr"/><jsp:param name="age" value="20"/>
</jsp:forward></body>
</html>
jsptag2:(取出請求參數(shù))
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head><title>Title</title>
</head>
<body>
<%--取出參數(shù)--%>
名字:<%=request.getParameter("name")%>
年齡:<%=request.getParameter("age")%>
</body>
</html>
然后點擊運行,在瀏覽器訪問 http://localhost:8080/jsptag.jsp,可以看到對應(yīng)結(jié)果
到這就結(jié)束了!!謝謝大家支持哦~
總結(jié)
以上是生活随笔為你收集整理的2020了,还要学JSP嘛?入个门呗!毕竟Servlet亲兄弟~的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 8086汇编语言精华笔记总结~
- 下一篇: MySQL最新版8.0.21安装配置教程