整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          JSP的前生今世

          礎(chǔ)知識,servlet是什么?

          官方解釋:Servlet 是運(yùn)行在 Web 服務(wù)器或應(yīng)用服務(wù)器上的程序,它是作為來自 Web 瀏覽器或其他 HTTP 客戶端的請求和 HTTP 服務(wù)器上的數(shù)據(jù)庫或應(yīng)用程序之間的中間層

          簡單來說,servlet是運(yùn)行在web服務(wù)器如tomcat,jetty這樣應(yīng)用服務(wù)器上的一段程序,他可以響應(yīng)http協(xié)議的請求,并且實(shí)現(xiàn)用戶自己的邏輯,最終將結(jié)果返回到用戶的客戶端(瀏覽器)

          Java Servlet 通常情況下與使用 CGI(Common Gateway Interface,公共網(wǎng)關(guān)接口)實(shí)現(xiàn)的程序可以達(dá)到異曲同工的效果。但是相比于 CGI,Servlet 有以下幾點(diǎn)優(yōu)勢:

          1、性能明顯更好。

          2、Servlet 在 Web 服務(wù)器的地址空間內(nèi)執(zhí)行。這樣它就沒有必要再創(chuàng)建一個單獨(dú)的進(jìn)程來處理每個客戶端請求。

          3、Servlet 是獨(dú)立于平臺的,因?yàn)樗鼈兪怯?Java 編寫的。

          4、服務(wù)器上的 Java 安全管理器執(zhí)行了一系列限制,以保護(hù)服務(wù)器計(jì)算機(jī)上的資源。因此,Servlet 是可信的。

          5、Java 類庫的全部功能對 Servlet 來說都是可用的。它可以通過 sockets 和 RMI 機(jī)制與 applets、數(shù)據(jù)庫或其他軟件進(jìn)行交互。

          Servlet的生命周期

          Servlet 生命周期可被定義為從創(chuàng)建直到毀滅的整個過程。以下是 Servlet 遵循的過程:

          1、Servlet 通過調(diào)用 init () 方法進(jìn)行初始化。

          2、Servlet 調(diào)用 service() 方法來處理客戶端的請求。

          3、Servlet 通過調(diào)用 destroy() 方法終止(結(jié)束)。

          4、最后,Servlet 是由 JVM 的垃圾回收器進(jìn)行垃圾回收的

          init() 方法

          init 方法被設(shè)計(jì)成只調(diào)用一次。它在第一次創(chuàng)建 Servlet 時(shí)被調(diào)用,在后續(xù)每次用戶請求時(shí)不再調(diào)用。因此,它是用于一次性初始化,就像 Applet 的 init 方法一樣。

          Servlet 創(chuàng)建于用戶第一次調(diào)用對應(yīng)于該 Servlet 的 URL 時(shí),但是您也可以指定 Servlet 在服務(wù)器第一次啟動時(shí)被加載。

          service() 方法

          service() 方法是執(zhí)行實(shí)際任務(wù)的主要方法。Servlet 容器(即 Web 服務(wù)器)調(diào)用 service() 方法來處理來自客戶端(瀏覽器)的請求,并把格式化的響應(yīng)寫回給客戶端。

          每次服務(wù)器接收到一個 Servlet 請求時(shí),服務(wù)器會產(chǎn)生一個新的線程并調(diào)用服務(wù)。service() 方法檢查 HTTP 請求類型(GET、POST、PUT、DELETE 等),并在適當(dāng)?shù)臅r(shí)候調(diào)用 doGet、doPost、doPut,doDelete 等方法。

          destroy() 方法

          destroy() 方法只會被調(diào)用一次,在 Servlet 生命周期結(jié)束時(shí)被調(diào)用。destroy() 方法可以讓您的 Servlet 關(guān)閉數(shù)據(jù)庫連接、停止后臺線程、把 Cookie 列表或點(diǎn)擊計(jì)數(shù)器寫入到磁盤,并執(zhí)行其他類似的清理活動。

          在調(diào)用 destroy() 方法之后,servlet 對象被標(biāo)記為垃圾回收。

          JSP是什么?

          JSP全稱Java Server Pages,是一種動態(tài)網(wǎng)頁開發(fā)技術(shù)。它使用JSP標(biāo)簽在HTML網(wǎng)頁中插入Java代碼。標(biāo)簽通常以<%開頭以%>結(jié)束。

          JSP是一種Java servlet,主要用于實(shí)現(xiàn)Java web應(yīng)用程序的用戶界面部分。網(wǎng)頁開發(fā)者們通過結(jié)合HTML代碼、XHTML代碼、XML元素以及嵌入JSP操作和命令來編寫JSP。

          JSP通過網(wǎng)頁表單獲取用戶輸入數(shù)據(jù)、訪問數(shù)據(jù)庫及其他數(shù)據(jù)源,然后動態(tài)地創(chuàng)建網(wǎng)頁。

          JSP標(biāo)簽有多種功能,比如訪問數(shù)據(jù)庫、記錄用戶選擇信息、訪問JavaBeans組件等,還可以在不同的網(wǎng)頁中傳遞控制信息和共享信息。


          servlet和jsp的區(qū)別

          1、Servlet在Java代碼中可以通過HttpServletResponse對象動態(tài)輸出HTML內(nèi)容。

          2、JSP是在靜態(tài)HTML內(nèi)容中嵌入Java代碼,然后Java代碼在被動態(tài)執(zhí)行后生成HTML內(nèi)容。

          servlet和jsp各自的特點(diǎn)

          1、Servlet雖然能夠很好地組織業(yè)務(wù)邏輯代碼,但是在Java源文件中,因?yàn)槭峭ㄟ^字符串拼接的方式生成動態(tài)HTML內(nèi)容,這樣就容易導(dǎo)致代碼維護(hù)困難、可讀性差。

          2、JSP雖然規(guī)避了Servlet在生成HTML內(nèi)容方面的劣勢,但是在HTML中混入大量、復(fù)雜的業(yè)務(wù)邏輯。

          MVC的誕生

          JSP和Servlet都有自身的適用環(huán)境,那么有沒有什么辦法能夠讓它們發(fā)揮各自的優(yōu)勢呢?答案是肯有的,MVC模式就能夠完美解決這一問題。

          MVC模式,是Model-View-Controller的簡稱,是軟件工程中的一種軟件架構(gòu)模式,分為三個基本部分,分別是:模型(Model)、視圖(View)和控制器(Controller):

          Controller——負(fù)責(zé)轉(zhuǎn)發(fā)請求,對請求進(jìn)行處理

          View——負(fù)責(zé)界面顯示

          Model——業(yè)務(wù)功能編寫(例如算法實(shí)現(xiàn))、數(shù)據(jù)庫設(shè)計(jì)以及數(shù)據(jù)存取操作實(shí)現(xiàn)

          在JSP/Servlet開發(fā)的軟件系統(tǒng)中,這三個部分的描述如下所示:


          MVC模型

          1、Web瀏覽器發(fā)送HTTP請求到服務(wù)端,然后被Controller(Servlet)獲取并進(jìn)行處理(例如參數(shù)解析、請求轉(zhuǎn)發(fā))

          2、Controller(Servlet)調(diào)用核心業(yè)務(wù)邏輯——Model部分,獲得結(jié)果

          3、Controller(Servlet)將邏輯處理結(jié)果交給View(JSP),動態(tài)輸出HTML內(nèi)容

          4、動態(tài)生成的HTML內(nèi)容返回到瀏覽器顯示

          MVC模式在Web開發(fā)中有很大的優(yōu)勢,它完美規(guī)避了JSP與Servlet各自的缺點(diǎn),讓Servlet只負(fù)責(zé)業(yè)務(wù)邏輯部分,而不會生成HTML代碼;同時(shí)JSP中也不會充斥著大量的業(yè)務(wù)代碼,這樣大大提高了代碼的可讀性和可維護(hù)性。


          相關(guān)面試題



          如何讀取Servlet的初始化參數(shù)?

          ServletConfig中定義了如下的方法用來讀取初始化參數(shù)的信息:

          public String getInitParameter(String name)

          參數(shù):初始化參數(shù)的名稱。
          返回:初始化參數(shù)的值,如果沒有配置,返回null。

          init(ServletConfig)方法執(zhí)行次數(shù)

          在Servlet的生命周期中,該方法執(zhí)行一次。

          service()方法的職責(zé)

          service()方法為Servlet的核心方法,客戶端的業(yè)務(wù)邏輯應(yīng)該在該方法內(nèi)執(zhí)行,典型的服務(wù)方法的開發(fā)流程為:

          解析客戶端請求-〉執(zhí)行業(yè)務(wù)邏輯-〉輸出響應(yīng)頁面到客戶端

          get方式和post方式有何區(qū)別

          數(shù)據(jù)攜帶上:

          GET方式:在URL地址后附帶的參數(shù)是有限制的,其數(shù)據(jù)容量通常不能超過1K。

          POST方式:可以在請求的實(shí)體內(nèi)容中向服務(wù)器發(fā)送數(shù)據(jù),傳送的數(shù)據(jù)量無限制。

          請求參數(shù)的位置上:

          GET方式:請求參數(shù)放在URL地址后面,以?的方式來進(jìn)行拼接

          POST方式:請求參數(shù)放在HTTP請求包中

          用途上:

          GET方式一般用來獲取數(shù)據(jù)

          POST方式一般用來提交數(shù)據(jù)

          原因:

          首先是因?yàn)镚ET方式攜帶的數(shù)據(jù)量比較小,無法帶過去很大的數(shù)量

          POST方式提交的參數(shù)后臺更加容易解析(使用POST方式提交的中文數(shù)據(jù),后臺也更加容易解決)

          GET方式比POST方式要快

          Servlet相關(guān) API

          HttpServletRequest:封裝了與請求相關(guān)的信息

          HttpServletResponse:封裝了與響應(yīng)相關(guān)的信息


          獲取頁面的元素的值有幾種方式,分別說一下

          request.getParameter() 返回客戶端的請求參數(shù)的值

          request.getParameterNames() 返回所有可用屬性名的枚舉

          request.getParameterValues() 返回包含參數(shù)的所有值的數(shù)組

          request.getAttribute()和request.getParameter()區(qū)別

          用途上:

          request.getAttribute(), 一般用于獲取request域?qū)ο蟮臄?shù)據(jù)(在跳轉(zhuǎn)之前把數(shù)據(jù)使用setAttribute來放到request對象上)

          request.getParameter(), 一般用于獲取客戶端提交的參數(shù)

          存儲數(shù)據(jù)上:

          request.getAttribute()可以獲取Objcet對象

          request.getParameter()只能獲取字符串(這也是為什么它一般用于獲取客戶端提交的參數(shù))


          forward和redirect的區(qū)別

          實(shí)際發(fā)生位置不同,地址欄不同

          轉(zhuǎn)發(fā)是發(fā)生在服務(wù)器的

          轉(zhuǎn)發(fā)是由服務(wù)器進(jìn)行跳轉(zhuǎn)的,細(xì)心的朋友會發(fā)現(xiàn),在轉(zhuǎn)發(fā)的時(shí)候,瀏覽器的地址欄是沒有發(fā)生變化的,在我訪問Servlet111的時(shí)候,即使跳轉(zhuǎn)到了Servlet222的頁面,瀏覽器的地址還是Servlet111的。也就是說瀏覽器是不知道該跳轉(zhuǎn)的動作,轉(zhuǎn)發(fā)是對瀏覽器透明的。通過上面的轉(zhuǎn)發(fā)時(shí)序圖我們也可以發(fā)現(xiàn),實(shí)現(xiàn)轉(zhuǎn)發(fā)只是一次的http請求,一次轉(zhuǎn)發(fā)中request和response對象都是同一個。這也解釋了,為什么可以使用request作為域?qū)ο筮M(jìn)行Servlet之間的通訊。

          重定向是發(fā)生在瀏覽器的

          重定向是由瀏覽器進(jìn)行跳轉(zhuǎn)的,進(jìn)行重定向跳轉(zhuǎn)的時(shí)候,瀏覽器的地址會發(fā)生變化的。曾經(jīng)介紹過:實(shí)現(xiàn)重定向的原理是由response的狀態(tài)碼和Location頭組合而實(shí)現(xiàn)的。這是由瀏覽器進(jìn)行的頁面跳轉(zhuǎn)實(shí)現(xiàn)重定向會發(fā)出兩個http請求,**request域?qū)ο笫菬o效的,因?yàn)樗皇峭粋€request對象

          用法不同:

          很多人都搞不清楚轉(zhuǎn)發(fā)和重定向的時(shí)候,資源地址究竟怎么寫。有的時(shí)候要把應(yīng)用名寫上,有的時(shí)候不用把應(yīng)用名寫上。很容易把人搞暈。記住一個原則: 給服務(wù)器用的直接從資源名開始寫,給瀏覽器用的要把應(yīng)用名寫上

          request.getRequestDispatcher("/資源名 URI").forward(request,response)

          轉(zhuǎn)發(fā)時(shí)"/"代表的是本應(yīng)用程序的根目錄【zhongfucheng】

          response.send("/web應(yīng)用/資源名 URI");

          重定向時(shí)"/"代表的是webapps目錄


          能夠去往的URL的范圍不一樣:

          轉(zhuǎn)發(fā)是服務(wù)器跳轉(zhuǎn)只能去往當(dāng)前web應(yīng)用的資源

          重定向是服務(wù)器跳轉(zhuǎn),可以去往任何的資源


          傳遞數(shù)據(jù)的類型不同

          轉(zhuǎn)發(fā)的request對象可以傳遞各種類型的數(shù)據(jù),包括對象

          重定向只能傳遞字符串


          跳轉(zhuǎn)的時(shí)間不同

          轉(zhuǎn)發(fā)時(shí):執(zhí)行到跳轉(zhuǎn)語句時(shí)就會立刻跳轉(zhuǎn)

          重定向:整個頁面執(zhí)行完之后才執(zhí)行跳轉(zhuǎn)


          典型的應(yīng)用場景:

          轉(zhuǎn)發(fā): 訪問 Servlet 處理業(yè)務(wù)邏輯,然后 forward 到 jsp 顯示處理結(jié)果,瀏覽器里 URL 不變

          重定向: 提交表單,處理成功后 redirect 到另一個 jsp,防止表單重復(fù)提交,瀏覽器里 URL 變了

          SP

          JSP的基礎(chǔ)語法

          簡介

          JSP:Java Server Page SUN 公司提供的動態(tài)網(wǎng)頁編程技術(shù),是 Java Web 服務(wù)器端的動態(tài)資源。

          它相比 html 而言,html 只能為用戶提供靜態(tài)數(shù)據(jù),而 Jsp 技術(shù)允許在頁面中嵌套 java 代碼,為用戶提供動態(tài)數(shù)據(jù)。

          相比 servlet 而言,servlet 很難對數(shù)據(jù)進(jìn)行排版,而 jsp 除了可以用 java 代碼產(chǎn)生動態(tài)數(shù)據(jù)的同時(shí),也很容易對數(shù)據(jù)進(jìn)行排版。

          不管是 JSP 還是 Servlet,雖然都可以用于開發(fā)動態(tài) web 資源。但由于這 2 門技術(shù)各自的特點(diǎn),在長期的軟件實(shí)踐中,人們逐漸把 servlet 作為 web 應(yīng)用中的控制器組件來使用, 而把 JSP 技術(shù)作為數(shù)據(jù)顯示模板來使用。

          其實(shí) Jsp 就是一個 Servlet,當(dāng)我們第一次訪問 Jsp 的時(shí)候,Jsp 引擎都會將這個 Jsp 翻譯 成一個 Servlet,這個文件存放在tomcat(源碼目錄) 中的 work 目錄中。



          準(zhǔn)備工作

          配置IDEA

          這一步不是必須的,當(dāng)然由于 編輯器中有些默認(rèn)的配置項(xiàng)我們覺得不是很完美,比如"編碼格式"、頁面模板等。我們可以在新建 JSP 頁面之前就先修改為我們需要的。

          1.選擇"File" —> "Settings..."



          2.設(shè)置編碼格式。搜索"encode",選擇"File Encoding"

          [

          3.設(shè)置頁面模板。搜索"template",選擇"File and Code Templates",選擇右側(cè)的"Other",選擇下方的"Jsp File"



          新建JSP頁面



          注釋

          在 JSP 中支持兩種注釋的語法操作:

          一種是顯示注釋,這種注釋是允許客戶端看見的; 另一種是隱式注釋,此種注釋是客戶端無法看見的

          ① 顯示注釋語法:從 HTML 風(fēng)格繼承而來

          ② 隱式注釋語法:從 JAVA 風(fēng)格繼承;JSP 自己的注釋


          JSP 的三種注釋方式:

          1) // 注釋,單行注釋  /* 多行注釋*/ 
          ?
          2)<!--  HTML風(fēng)格的注釋 -->
          ?
          3)<%--   JSP注釋  --%>


          Scriptlet

          在 JSP 中最重要的部分就是 Scriptlet(腳本小程序),所有嵌入在 HTML 代碼中的 Java 程序。

          在 JSP 中一共有三種 Scriptlet 代碼:都必須使用 Scriptlet 標(biāo)記出來

          第一種:<%    %>: java 腳本段,可以定義局部變量、編寫語句
          ?
          第二種:<%!   %>:聲明,可以定義全局(成員)變量、方法、類
          ?
          第三種:<%=  %>:表達(dá)式,數(shù)據(jù)一個變量或具體內(nèi)容

          通過觀察解析為 java 文件的 jsp 代碼理解三種小腳本

          <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
          <!DOCTYPE >
          <html>
              <head>
                  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
                  <title>Scriptlet</title>
              </head>
              <body>
                  <%
                      String str = "Hello JSP";
                      System.out.println(str);
                      response.getWriter().write(str);
                  %>
                  <%!
                      String memberStr = "a member String";
                  %>
                  <%=memberStr%>
                  <h1>This is a JSP page!!</h1>
              </body>
          </html>


          JSP的指令標(biāo)簽

          使用包含操作,可以將一些重復(fù)的代碼包含進(jìn)來繼續(xù)使用,從正常的頁面組成來看,有時(shí)可能分為幾個區(qū)域。而其中的一些區(qū)域可能是一直不需要改變的,改變的就其中的一個具體內(nèi)容區(qū)域?,F(xiàn)在有兩種方法可以實(shí)現(xiàn)上述功能。

          方法一:在每個 JSP 頁面(HTML)都包含工具欄、頭部信息、尾部信息、具體內(nèi)容

          方法二:將工具欄、頭部信息、尾部信息都分成各個獨(dú)立的文件,使用的時(shí)候直接導(dǎo)入

          很明顯,第二種方法比第一種更好,第一種會存在很多重復(fù)的代碼,并且修改很不方便,在 JSP 中如果要想實(shí)現(xiàn)包含的操作,有兩種做法:靜態(tài)包含、動態(tài)包含,靜態(tài)包含使用 include 指令即可,動態(tài)包含則需要使用 include 動作標(biāo)簽。


          include 靜態(tài)包含

          <%@ include file="要包含的文件路徑" %>  <!-- 相對路徑 -->

          例如:

          <%@include file="include.jsp" %>
          或
          <%@include file="include.html" %>

          靜態(tài)包含就是將內(nèi)容進(jìn)行了直接的替換,就好比程序中定義的變量一樣,是在 servlet 引擎轉(zhuǎn)譯時(shí),就把此文件內(nèi)容包含了進(jìn)去(兩個文件的源代碼整合到一起, 全部放到_jspService 方法中),所以只生成了一個 servlet,所以兩個頁面不能有同名的變量。 運(yùn)行效率高一點(diǎn)點(diǎn)。耦合性較高,不夠靈活。


          include 動態(tài)包含

          動態(tài)包含在代碼的編譯階段,包含和被包含部分是兩個獨(dú)立的部分,只有當(dāng)運(yùn)行時(shí),才會動態(tài)包含進(jìn)來,好比方法的調(diào)用。

          <jsp:include page="include.jsp"></jsp:include>

          注意:動態(tài)包含,中間不要加任何內(nèi)容,包括空格,除非確認(rèn)要使用參數(shù),否則報(bào)錯!

          <jsp:include page="include.html"></jsp:include>
          <%
              String a = "hello.jsp";
          %>
          <jsp:include page="<%=a %>"></jsp:include>

          使用動態(tài)包含還可以通過在頁面之間傳參。

          接收參數(shù)通過 request.getParameter(name);

          <jsp:include page="hello.jsp" flush="true">
              <jsp:param name="uname" value="zhangsan"/>
          </jsp:include>

          hello.jsp

          <!-- 接收參數(shù) -->
          <%=request.getParameter("uname")%>


          JSP的四大域?qū)ο?/h3>

          四種屬性范圍

          在JSP中提供了四種屬性的保存范圍,所謂的屬性保存范圍,指的就是一個設(shè)置的對象,可以再多少個頁面中保存并可以繼續(xù)使用

          1. page范圍 pageContext : 只在一個頁面中保存屬性,跳轉(zhuǎn)之后無效
          2. request范圍 request : 只在一次請求中保存,服務(wù)器跳轉(zhuǎn)后依然有效
          3. session范圍 session : 在一次會話范圍中,無論何種跳轉(zhuǎn)都可以使用
          4. application范圍 application : 在整個服務(wù)器上保存

          方法類型描述public void setAttribute(String name, Object o)普通設(shè)置屬性的名稱及內(nèi)容public Object getAttribute(String name)普通根據(jù)屬性名稱取屬性public void removeAttribute(String name)普通刪除指定的屬性


          驗(yàn)證屬性范圍的特點(diǎn)

          1. page

          本頁面取得,服務(wù)器端跳轉(zhuǎn)(<jsp :forward>)后無效


          1. request 服務(wù)器跳轉(zhuǎn)有效,客戶端跳轉(zhuǎn)無效如果是客戶端跳轉(zhuǎn),則相當(dāng)于發(fā)出了兩次請求,那么第一次的請求將不存在了;如果希望不管是客戶端還是服務(wù)器跳轉(zhuǎn),都能保存的話,就需要繼續(xù)擴(kuò)大范圍。


          1. session無論客戶端還是服務(wù)器端都可以取得,但是現(xiàn)在重新開啟一個新的瀏覽器,則無法取得之前設(shè)置的session了,因?yàn)槊恳粋€session只保存在當(dāng)前的瀏覽器當(dāng)中,并在相關(guān)的頁面取得。對于服務(wù)器而言,每一個連接到它的客戶端都是一個session如果想要讓屬性設(shè)置一次之后,不管是否是新的瀏覽器打開都能取得則可以使用application


          1. application所有的application屬性直接保存在服務(wù)器上,所有的用戶(每一個session)都可以直接訪問取得 只要是通過application設(shè)置的屬性,則所有的session都可以取得,表示公共的內(nèi)容,但是如果此時(shí)服務(wù)器重啟了,則無法取得了,因?yàn)殛P(guān)閉服務(wù)器后,所有的屬性都消失了,所以需要重新設(shè)置。


          問:使用哪個范圍呢?

          答:在合理范圍盡可能小


          EL表達(dá)式的使用

          EL表達(dá)式的語法

          EL(Expression Language) 是為了使 JSP 寫起來更加簡單。表達(dá)式語言的靈感來自于 ECMAScript 和 XPath 表達(dá)式語言,它提供了在 JSP 中簡化表達(dá)式的方法,讓 Jsp 的代碼更加簡化。

          語法結(jié)構(gòu)非常簡單: ${expression}

          EL 表達(dá)式一般操作的都是域?qū)ο笾械臄?shù)據(jù),操作不了局部變量。

          域?qū)ο蟮母拍钤?JSP 中一共有四個:pageContext, request, session, application;范圍依次是,本頁面,一次請求, 一次會話整個應(yīng)用程序。

          當(dāng)需要指定從某個特定的域?qū)ο笾胁檎覕?shù)據(jù)時(shí)可以使用四個域?qū)ο髮?yīng)的空間對象,分別是:pageScope, requestScope, sessionScope, applicationScope。

          而 EL 默認(rèn)的查找方式為從小到大查找,找到即可。當(dāng)域?qū)ο笕彝炅诉€未找到則返回空字符串""。


          EL表達(dá)式的使用

          獲取數(shù)據(jù)

          設(shè)置域?qū)ο笾械臄?shù)據(jù)

          <%
              pageContext.setAttribute("uname","zhangsan"); // page作用域
              request.setAttribute("uname","lisi"); // request作用域
              session.setAttribute("uname","wangwu"); // session作用域
              application.setAttribute("uname","zaholiu"); // application
          %>

          獲取域?qū)ο蟮闹?/strong>

          <%-- 獲取域?qū)ο笾械臄?shù)據(jù):默認(rèn)查找方式為從小到大,找到即止。若四個范圍都未找到,則返回空字符串。--%>
          ${uname} <!-- 輸出結(jié)果為:zhangsan -->

          獲取指定域?qū)ο蟮闹?/strong>

          ${pageScope.uname}          <!-- page作用域 -->
          ${requestScope.uname}       <!-- request作用域 -->
          ${sessionScope.uname}       <!-- session作用域 -->
          ${applicationScope.uname}   <!-- application作用域 -->

          獲取List

          <%
              List<String> list = new ArrayList<String>();
              list.add("aaa");
              list.add("bbb");
              list.add("ccc");
              request.setAttribute("list", list);
          %>
          <%--
              獲取List中指定下標(biāo)的數(shù)據(jù)
                  ${list[下標(biāo)] }
              獲取集合的長度
                  ${list.size()}
              注:
                 list代表的是存在域?qū)ο笾械淖兞棵ㄏ抻蜃兞棵?--%>
          ${list[1] }  

          獲取Map

          <%
              Map map = new HashMap();
              map.put("aaa", "111");
              map.put("bbb", 2222);
              map.put("ccc-a", 333);
              request.setAttribute("map", map);
          %>
          <%--
              獲取Map中指定值
                 ${map["key"] } 或 ${map.key }
              注:
                  map代表的是存在域?qū)ο笾械淖兞棵ㄏ抻蜃兞棵?--%>
          ${map.aaa }
          ${map["bbb"]}

          獲取JavaBean對象

          User.java

          public class User {
          ?
              private Integer userId;
              private String uname;
              private String upwd;
          ?
              public Integer getUserId() {
                  return userId;
              }
          ?
              public void setUserId(Integer userId) {
                  this.userId = userId;
              }
          ?
              public String getUname() {
                  return uname;
              }
          ?
              public void setUname(String uname) {
                  this.uname = uname;
              }
          ?
              public String getUpwd() {
                  return upwd;
              }
          ?
              public void setUpwd(String upwd) {
                  this.upwd = upwd;
              }
          }
          <%
              User user = new User();
              user.setUserId(1);
              user.setUname("zhangsan");
              user.setUpwd("123456");
              request.setAttribute("user",user);
          %>
          <%-- JavBean中的屬性字段需要提供get方法 --%>
          ${user} <%-- 獲取對象 --%>
          ${user.uname} <%--獲取對象中的屬性--%>
          empty
          <%--
              empty
                  判斷域?qū)ο笫欠駷榭?。為空,返回true;不為空返回false;
                      ${empty 限域變量名 }
                  判斷對象是否不為空。
                      ${!empty 限域變量名 }
          --%>
          ${empty uname}
          ${empty list}
          ${empty map}
          ${empty user}


          EL運(yùn)算
          <%
              request.setAttribute("a", 10);
              request.setAttribute("b", 2);
              request.setAttribute("c", "aa");
              request.setAttribute("d", "bb");
          %>

          等值判斷

          <%--
              比較兩個值是否相等,返回true或false
                  ==  或  eq
          --%>
          ${a == b }
          ${c == d }
          ${c eq d }
          ${a == 5 }
          ${c == 'aa' }

          算術(shù)運(yùn)算

          <%--
              加法: +
              減法: -
              乘法: *
              除法: / 或 div
          --%>
          ${a + b }
          ${a / b } 或 ${a div b }

          大小比較

          SP常見面試題

          jsp靜態(tài)包含和動態(tài)包含的區(qū)別

          jsp靜態(tài)包含和動態(tài)包含的區(qū)別
          • 在講解request對象的時(shí)候,我們曾經(jīng)使用過request.getRequestDispatcher(String url).include(request,response)來對頁頭和頁尾面進(jìn)行包含
          • inclue指令也是做這樣的事情,我們來試驗(yàn)一下吧!
          • 這是頁頭

          • 這是頁尾

          • 在1.jsp中把頁頭和頁尾包含進(jìn)來

          • 訪問1.jsp

          • include指令是靜態(tài)包含。靜態(tài)包含的意思就是:把文件的代碼內(nèi)容都包含進(jìn)來,再編譯!,看一下jsp的源代碼就知道了!

          • 上面已經(jīng)提及到了,include指令是靜態(tài)包含,include行為是動態(tài)包含。其實(shí)include行為就是封裝了request.getRequestDispatcher(String url).include(request,response)
          • include行為語法是這個樣子的
          <jsp:include page=""/>
          
          • 我們先來使用一下把,在1.jsp頁面中也將頁頭和頁尾包含進(jìn)來。

          • 訪問1.jsp頁面看一下效果:

          • 使用jsp行為來包含文件,jsp源文件是這樣子的:

          • jsp行為包含文件就是先編譯被包含的頁面,再將頁面的結(jié)果寫入到包含的頁面中(1.jsp)
          • 當(dāng)然了,現(xiàn)在有靜態(tài)包含和動態(tài)包含,使用哪一個更好呢?答案是:動態(tài)包含。
          • 動態(tài)包含可以向包含的頁面?zhèn)鬟f參數(shù)(用處不大),并且是分別處理兩個頁面的(將被包含頁面編譯后得出的結(jié)果再寫進(jìn)包含頁面)【如果有相同名稱的參數(shù),使用靜態(tài)包含就會報(bào)錯!】!
          • 模擬一下場景吧,現(xiàn)在我的頭頁面有個名為s的字符串變量

          • 我的頁尾也有個名為s的字符串變量

          • 現(xiàn)在我使用靜態(tài)包含看看會發(fā)生什么,出現(xiàn)異常了。

          • 出現(xiàn)異常的原因很簡單,就是同一個文件中有兩個相同的變量s

          • 使用動態(tài)包含就可以避免這種情況

          總結(jié)

          1. <%@include file="xxx.jsp"%>為jsp中的編譯指令,其文件的包含是發(fā)生在jsp向servlet轉(zhuǎn)換的時(shí)期,而<jsp:include page="xxx.jsp">是jsp中的動作指令,其文件的包含是發(fā)生在編譯時(shí)期,也就是將java文件編譯為class文件的時(shí)期
          2. 使用靜態(tài)包含只會產(chǎn)生一個class文件,而使用動態(tài)包含會產(chǎn)生多個class文件
          3. 使用靜態(tài)包含,包含頁面和被包含頁面的request對象為同一對象,因?yàn)殪o態(tài)包含只是將被包含的頁面的內(nèi)容復(fù)制到包含的頁面中去;而動態(tài)包含包含頁面和被包含頁面不是同一個頁面,被包含的頁面的request對象可以取到的參數(shù)范圍要相對大些,不僅可以取到傳遞到包含頁面的參數(shù),同樣也能取得在包含頁面向下傳遞的參數(shù)

          jsp有哪些內(nèi)置對象?作用分別是什么?

          jsp有哪些內(nèi)置對象?作用分別是什么?

          九個內(nèi)置對象:

          • pageContext
          • page
          • config
          • request
          • response
          • session
          • application
          • exception
          • out

          其中,request、response、session、application、config這五個對象和Servlet的API是一樣的。這5個對象我就不解釋了。

          在JSP中,尤其重要的是pageContext對象。

          pageContext是內(nèi)置對象中最重要的一個對象,它代表著JSP頁面編譯后的內(nèi)容(也就是JSP頁面的運(yùn)行環(huán)境)!

          pageContext對象
          • 既然它代表了JSP頁面編譯后的內(nèi)容,理所當(dāng)然的:它封裝了對其他8大內(nèi)置對象的引用!,也就是說,通過pageContext可以獲取到其他的8個內(nèi)置對象!

          • 看下效果:

          pageContext作為域?qū)ο?/blockquote>
          • 類似于request,session,ServletContext作為域?qū)ο蠖?strong>都有以下三個方法
          • setAttribute(String name,Objcet o)
          • getAttribute(String name)
          • removeAttribute(String name)
          • 當(dāng)然了,pageContext也不例外,pageContext也有這三個方法!
          • pageContext本質(zhì)上代表的是當(dāng)前JSP頁面編譯后的內(nèi)容,作為域?qū)ο蠖?,它就代表著?dāng)前JSP頁面(也就是page)!也就是說:pageContext域?qū)ο笾辉趐age范圍內(nèi)有效,超出了page范圍就無效了!
          • 首先來看看在page范圍內(nèi)能不能使用

          • 效果如下:

          • 我們現(xiàn)在來試驗(yàn)一下是不是超出了page范圍就無效了!
          • 在2.jsp中request域?qū)ο笤O(shè)置屬性

          • 企圖在1.jsp中pageContext取出request存進(jìn)去的屬性

          • 效果如下:



          • pageContext本質(zhì)上代表著編譯后JSP的內(nèi)容,pageContext還可以封裝了訪問其他域的方法!
          • 上面的pageContext默認(rèn)是page范圍的但pageContext對象重載了set、get、removeAttribute這三個方法
          • getAttribute(String name,int scope)
          • setAttribute(String name,Object value,int scope)
          • removeAttribute(String name,int scope)
          • 多了一個設(shè)置域范圍的一個參數(shù),如果不指定默認(rèn)就是page。當(dāng)然了,pageContext把request、session、application、page這幾個域?qū)ο蠓庋b著了靜態(tài)變量供我們使用。
          • PageContext.APPLICATION_SCOPE
          • PageContext.SESSION_SCOPE
          • PageContext.REQUEST_SCOPE
          • PageContext.PAGE_SCOPE
          • 剛才我們沒有使用重載方法的時(shí)候,使用pageContext是無法獲取到request域?qū)ο笤O(shè)置的屬性的。現(xiàn)在我們使用重載后的方法看一下能不能獲取得到!

          • 效果:



          • pageContexst還有這么一個方法:
          • findAttribute(String name)

          • 該方法會查找各個域的屬性,從小到大開始尋找!也就是page—>request->session->application。
          • 我們用此方法看能不能查找出request域?qū)ο蟮膶傩园桑?/li>

          • 效果如下:

          out對象:
          • out對象用于向?yàn)g覽器輸出數(shù)據(jù),與之對應(yīng)的是Servlet的PrintWriter對象。然而這個out對象的類型并不是PrintWriter,是JspWriter

          • 我們可以簡單理解為:JspWriter就是帶緩存的PrintWrieter。
          • out對象的原理如下:

          • 只有向out對象中寫入了內(nèi)容,且滿足如下任何一個條件時(shí),out對象才去調(diào)用ServletResponse.getWriter方法,并通過該方法返回的PrintWriter對象將out對象的緩沖區(qū)中的內(nèi)容真正寫入到Servlet引擎提供的緩沖區(qū)中
          • 設(shè)置page指令的buffer屬性關(guān)閉了out對象的緩存功能
          • out對象的緩沖區(qū)已滿
          • 整個JSP頁面結(jié)束
          • 一般我們在JSP頁面輸出都是用表達(dá)式(<%=%>),所以out對象用得并不是很多!
          page對象

          內(nèi)置對象page是HttpJasPage對象,其實(shí)page對象代表的就是當(dāng)前JSP頁面,是當(dāng)前JSP編譯后的Servlet類的對象。也就是說:page對象相當(dāng)于普通java類的this

          exception對象
          • 內(nèi)置對象exception是java.lang.Exception類的對象,exception封裝了JSP頁面拋出的異常信息。exception經(jīng)常被用來處理錯誤頁面
          • 前面我們已經(jīng)講過了怎么設(shè)置錯誤頁面了,下面我們就來簡單使用一下exception對象吧
          • 1.jsp頁面

          • error.jsp頁面

          • 效果:

          總結(jié):

          1. request 用戶端請求,此請求會包含來自GET/POST請求的參數(shù)
          2. response 網(wǎng)頁傳回用戶端的回應(yīng)
          3. pageContext 網(wǎng)頁的屬性是在這里管理,代表的編譯后JSP內(nèi)容
          4. session 與請求有關(guān)的會話期
          5. application servlet 正在執(zhí)行的內(nèi)容
          6. out 用來傳送回應(yīng)的輸出
          7. config servlet的構(gòu)架部件
          8. page JSP網(wǎng)頁本身
          9. exception 針對錯誤網(wǎng)頁,未捕捉的例外

          jsp和servlet的區(qū)別、共同點(diǎn)、各自應(yīng)用的范圍?

          jsp和servlet的區(qū)別、共同點(diǎn)、各自應(yīng)用的范圍?
          1. JSP是Servlet技術(shù)的擴(kuò)展,本質(zhì)上就是Servlet的簡易方式。JSP編譯后是“類servlet”。
          2. Servlet和JSP最主要的不同點(diǎn)在于:Servlet的應(yīng)用邏輯是在Java文件中,并且完全從表示層中的HTML里分離開來。而JSP的情況是Java和HTML可以組合成一個擴(kuò)展名為.jsp的文件。
          3. JSP側(cè)重于視圖,Servlet主要用于控制邏輯。


          屬性作用域范圍

          屬性作用域范圍
          1. page【只在一個頁面中保存屬性,跳轉(zhuǎn)頁面無效】
          2. requet【只在一次請求中保存屬性,服務(wù)器跳轉(zhuǎn)有效,瀏覽器跳轉(zhuǎn)無效】
          3. session【在一個會話范圍中保存屬性,無論何種跳轉(zhuǎn)均有效,關(guān)閉瀏覽器后無效】
          4. application【在整個服務(wù)器中保存,所有用戶都可以使用】

          應(yīng)用場景:

          1. request:如果客戶向服務(wù)器發(fā)請求,產(chǎn)生的數(shù)據(jù),用戶看完就沒用了,像這樣的數(shù)據(jù)就存在request域,像新聞數(shù)據(jù),屬于用戶看完就沒用的
          2. session:如果客戶向服務(wù)器發(fā)請求,產(chǎn)生的數(shù)據(jù),用戶用完了等一會兒還有用,像這樣的數(shù)據(jù)就存在session域中,像購物數(shù)據(jù),用戶需要看到自己購物信息,并且等一會兒,還要用這個購物數(shù)據(jù)結(jié)帳
          3. servletContext:如果客戶向服務(wù)器發(fā)請求,產(chǎn)生的數(shù)據(jù),用戶用完了,還要給其它用戶用,像這樣的數(shù)據(jù)就存在servletContext域中,像聊天數(shù)據(jù)


          寫出5種JSTL常用標(biāo)簽

          寫出5種JSTL常用標(biāo)簽
          <c:if>,<c:item>,<c:foreach>,<c:out>,<c:set>
          


          寫一個自定義標(biāo)簽要繼承什么類

          寫一個自定義標(biāo)簽要繼承什么類

          我們可以有兩種方式來實(shí)現(xiàn)自定義標(biāo)簽:

          • 傳統(tǒng)方式,實(shí)現(xiàn)Tag接口(老方法)
          • 簡單方式,繼承SimpleTagSupport類


          SimpleTagSupport類的執(zhí)行順序(原理):

          • ①WEB容器調(diào)用標(biāo)簽處理器對象的setJspContext方法,將代表JSP頁面的pageContext對象傳遞給標(biāo)簽處理器對象
          • ②WEB容器調(diào)用標(biāo)簽處理器對象的setParent方法,將父標(biāo)簽處理器對象傳遞給這個標(biāo)簽處理器對象。【注意,只有在標(biāo)簽存在父標(biāo)簽的情況下,WEB容器才會調(diào)用這個方法】
          • ③如果調(diào)用標(biāo)簽時(shí)設(shè)置了屬性,容器將調(diào)用每個屬性對應(yīng)的setter方法把屬性值傳遞給標(biāo)簽處理器對象。如果標(biāo)簽的屬性值是EL表達(dá)式或腳本表達(dá)式,則WEB容器首先計(jì)算表達(dá)式的值,然后把值傳遞給標(biāo)簽處理器對象。
          • ④如果簡單標(biāo)簽有標(biāo)簽體,容器將調(diào)用setJspBody方法把代表標(biāo)簽體的JspFragment對象傳遞進(jìn)來
          • ⑤執(zhí)行標(biāo)簽時(shí):容器調(diào)用標(biāo)簽處理器的doTag()方法,開發(fā)人員在方法體內(nèi)通過操作JspFragment對象,就可以實(shí)現(xiàn)是否執(zhí)行、迭代、修改標(biāo)簽體的目的。

          總結(jié)

          SimpleTagSupport,一般調(diào)用doTag方法或者實(shí)現(xiàn)SimpleTag接口

          JSP是如何被執(zhí)行的?執(zhí)行效率比SERVLET低嗎?

          JSP是如何被執(zhí)行的?執(zhí)行效率比SERVLET低嗎?
          • 當(dāng)客戶端向一個jsp頁面發(fā)送請求時(shí),Web Container將jsp轉(zhuǎn)化成servlet的源代碼(只在第一次請求時(shí)),然后編譯轉(zhuǎn)化后的servlet并加載到內(nèi)存中執(zhí)行,執(zhí)行的結(jié)果response到客戶端
          • jsp只在第一次執(zhí)行的時(shí)候會轉(zhuǎn)化成servlet,以后每次執(zhí)行,web容器都是直接執(zhí)行編譯后的servlet,所以jsp和servlet只是在第一次執(zhí)行的時(shí)候不一樣,jsp慢一點(diǎn),以后的執(zhí)行都是相同的


          如何避免jsp頁面自動生成session對象?為什么要這么做?

          如何避免jsp頁面自動生成session對象?為什么要這么做?

          可以使用頁面指令顯式關(guān)掉,代碼如下:

          <%@ page session="false" %>

          jsp的缺點(diǎn)?

          jsp的缺點(diǎn)?
          • 1)不好調(diào)試
          • 2)與其他腳本語言的交互(可讀性差)


          說出Servlet和CGI的區(qū)別?

          說出Servlet和CGI的區(qū)別?
          • Servlet處于服務(wù)器進(jìn)程中,只會有一個servlet實(shí)例,每個請求都會產(chǎn)生一個新的線程,而且servlet實(shí)例一般不會銷毀
          • CGI:來一個請求就創(chuàng)建一個進(jìn)程,用完就銷毀,效率低于servlet


          簡述JSP的設(shè)計(jì)模式。

          簡述JSP的設(shè)計(jì)模式。

          在Web開發(fā)模式中,有兩個主要的開發(fā)結(jié)構(gòu),稱為模式一(Mode I)和模式二(Mode II)

          首先我們來理清一些概念吧:

          • DAO(Data Access Object):主要對數(shù)據(jù)的操作,增加、修改、刪除等原子性操作。
          • Web層:界面+控制器,也就是說JSP【界面】+Servlet【控制器】
          • Service業(yè)務(wù)層:將多個原子性的DAO操作進(jìn)行組合,組合成一個完整的業(yè)務(wù)邏輯
          • 控制層:主要使用Servlet進(jìn)行控制
          • 數(shù)據(jù)訪問層:使用DAO、Hibernate、JDBC技術(shù)實(shí)現(xiàn)對數(shù)據(jù)的增刪改查
          • JavaBean用于封裝數(shù)據(jù),處理部分核心邏輯,每一層中都用到!

          模式一指的就是在開發(fā)中將顯示層、控制層、數(shù)據(jù)層的操作統(tǒng)一交給JSP或者JavaBean來進(jìn)行處理!

          模式一有兩種情況:

          完全使用JSP做開發(fā):

          • 優(yōu)點(diǎn):
          • 開發(fā)速度賊快,只要寫JSP就行了,JavaBean和Servlet都不用設(shè)計(jì)!
          • 小幅度修改代碼方便,直接修改JSP頁面交給WEB容器就行了,不像Servlet還要編譯成.class文件再交給服務(wù)器!【當(dāng)然了,在ide下開發(fā)這個也不算是事】

          • 缺點(diǎn):
          • 程序的可讀性差、復(fù)用性低、代碼復(fù)雜!什么jsp代碼、html代碼都往上面寫,這肯定很難閱讀,很難重用!

          使用JSP+JavaBean做開發(fā):

          • 優(yōu)點(diǎn):
          • 程序的可讀性較高,大部分的代碼都寫在JavaBean上,不會和HTML代碼混合在一起,可讀性還行的
          • 可重復(fù)利用高,核心的代碼都由JavaBean開發(fā)了,JavaBean的設(shè)計(jì)就是用來重用、封裝,大大減少編寫重復(fù)代碼的工作!

          • 缺點(diǎn):
          • 沒有流程控制,程序中的JSP頁面都需要檢查請求的參數(shù)是否正確,異常發(fā)生時(shí)的處理。顯示操作和業(yè)務(wù)邏輯代碼工作會緊密耦合在一起的!日后維護(hù)會困難

          Mode II 中所有的開發(fā)都是以Servlet為主體展開的,由Servlet接收所有的客戶端請求,然后根據(jù)請求調(diào)用相對應(yīng)的JavaBean,并所有的顯示結(jié)果交給JSP完成!,也就是俗稱的MVC設(shè)計(jì)模式!

          MVC設(shè)計(jì)模式:

          • 顯示層(View):主要負(fù)責(zé)接受Servlet傳遞的內(nèi)容,調(diào)用JavaBean,將內(nèi)容顯示給用戶
          • 控制層(Controller):主要負(fù)責(zé)所有用戶的請求參數(shù),判斷請求參數(shù)是否合法,根據(jù)請求的類型調(diào)用JavaBean,將最終的處理結(jié)果交給顯示層顯示!
          • 模型層(Mode):模型層包括了業(yè)務(wù)層,DAO層。

          總結(jié)

          • (1)ModelI,JSP+JavaBean設(shè)計(jì)模式。
          • (2)ModelII,MVC設(shè)計(jì)模式。


          原文地址:https://dwz.cn/NhBjgHRk作者:Java3y

          主站蜘蛛池模板: 亚洲一区二区三区在线观看精品中文| 久久亚洲综合色一区二区三区| 亚洲色婷婷一区二区三区| 久久精品免费一区二区三区| 日韩精品免费一区二区三区| 亚洲午夜在线一区| 亚洲日本一区二区三区在线| 亚洲国产精品成人一区| 亚洲国产成人久久一区WWW| 女同一区二区在线观看| 怡红院一区二区在线观看| 伊人久久精品一区二区三区| 蜜臀AV在线播放一区二区三区| 无码少妇一区二区| 亚洲国产精品一区二区久| 亚洲一区二区三区电影| 精品一区二区三区无码免费视频| 久久婷婷色一区二区三区| 国产在线无码视频一区二区三区| 日韩精品无码一区二区三区AV| 久久亚洲色一区二区三区| 国产在线观看一区精品| 在线精品亚洲一区二区小说| 在线精品亚洲一区二区小说| 久久精品国产一区| 日韩免费一区二区三区在线| 亚洲中文字幕乱码一区| 日韩精品一区二区三区在线观看l| 无码aⅴ精品一区二区三区| 日韩伦理一区二区| 国产福利电影一区二区三区久久老子无码午夜伦不 | 韩国美女vip福利一区| 精品一区二区视频在线观看| 国产成人综合亚洲一区| 一区二区三区四区精品| 亚洲AV午夜福利精品一区二区| 亚洲国产成人精品无码一区二区| 国产怡春院无码一区二区| 一区二区三区AV高清免费波多| 亚洲一区爱区精品无码| 亚洲av综合av一区二区三区|