JSP基礎知識總結(通俗易懂)

JSP 第一篇:

概述、原理、週期、指令、行爲、內置對象、JavaBean

(一) JSP概述以及簡單使用

什麼是JSP?html

JSP全名爲Java Server Pages,java服務器頁面。JSP是一種基於文本的程序,其特色就是HTMLjava

和Java代碼共同存在!web

爲何須要JSP?數據庫

JSP是爲了簡化Servlet的工做出現的替代品,Servlet輸出HTML很是困難,JSP就是替代Servlet輸出HTML的express

JSP還有必要學嗎apache

在MVC中,JSP屬於展現層,可是JSP卻又能夠寫必定的業務,甚至跑去作數據層的事情,這樣開發中就會變得無比混亂,也增長了開發的困難程度,因此將展現層與業務層分開就成爲了主流,也就是咱們說的先後端分離,可是事無絕對,確實一些比較老的項目仍然在跑jsp,無論你會不會寫,你總得碰到能看懂吧,若是已經接近找工做,確實仍是以比較流行的技術學習比較好,可是若做爲學生,時間仍是比較富裕的,不少本科也必然都會講,學習一下也是挺好的,何況JSP與Servlet也是息息相關的,我認爲,學它就是爲了知道爲何之後會用別的技術代替它(狗頭保命),廢話有點多了,仍是有一點須要的朋友能夠簡單看一看,但願給你能有一點幫助後端

(二) JSP的工做原理

Tomcat訪問任何的資源都是在訪問Servlet!,固然了,JSP也不例外!JSP自己就是一種Servlet。爲何說JSP自己就是一種Servlet呢?設計模式

其實JSP在第一次被訪問的時候會被編譯爲HttpJspPage類(該類是HttpServlet的一個子類)數組

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>簡單使用JSP</title>
</head>
<body>
<%
    String s = "HelloWorld";
    out.println(s);
%>

編譯過程是這樣子的:瀏覽器

瀏覽器第一次請求1.jsp時,Tomcat會將1.jsp轉化成1_jsp.java這麼一個類,並將該文件編譯成class文件。編譯完畢後再運行class文件來響應瀏覽器的請求。

之後訪問1.jsp就再也不從新編譯jsp文件了,直接調用class文件來響應瀏覽器。固然了,若是Tomcat檢測到JSP頁面改動了的話,會從新編譯的。

既然JSP是一個Servlet,那JSP頁面中的HTML排版標籤是怎麼樣被髮送到瀏覽器的?咱們來看下上面1_jsp.java的源碼就知道了。原來就是用write()出去的罷了。說到底,JSP就是封裝了Servlet的java程序罷了

out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<title>簡單使用JSP</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n")

有人可能也會問:JSP頁面的代碼服務器是怎麼執行的?再看回1_jsp.java文件,java代碼就直接在類中的service()中

String s = "HelloWorld";
out.println(s);

(三) 聲明週期

JSP也是Servlet,運行時只有一個實例,JSP初始化和銷燬時也會調用Servlet的init()和destroy()方法。另外,JSP還有本身初始化和銷燬的方法

public void _jspInit() {
    _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
    _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
  }

  public void _jspDestroy() {
  }

(四) 指令

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

做用:用於配置JSP頁面,導入資源文件

格式: <%@ 指令名稱 屬性名1=屬性值1 屬性名2=屬性值2 ... %>

  • contentType:至關於response.setContentType()

    • 設置響應體的mime類型以及字符集
    • 設置當前jsp頁面的編碼(只能是高級的IDE才能生效,若是使用低級工具,則須要設置pageEncoding屬性設置當前頁面的字符集)

      pageEncoding="characterSet | ISO-8859-1"
  • import:導包

    import="{package.class | package.*}, ..."
  • errorPage:當前頁面發生異常後,會自動跳轉到指定的錯誤頁面

    //主頁面
    <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" %>
    
    //錯誤後轉到的頁面
    <%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true"   %>
    
    咱們發現地址欄是沒有變化的,因此屬因而服務器跳轉。以上的作法是單個頁面設置的,若是我會有不少錯誤(JSP多的狀況下,錯誤就會多),單個設置太麻煩了!
    
    咱們能夠在web.xml文件中全局設置錯誤頁,只要發生了404錯誤或者空指針異常的錯誤都會跳轉到error.jsp頁面上
    
    <error-page>
        <error-code>404</error-code>
        <location>/error.jsp</location>
    </error-page>
    
    <error-page>
        <exception-type>java.lang.NullPointerException</exception-type>
        <location>/error.jsp</location>
    </error-page>
  • isErrorPage:標識當前也是是不是錯誤頁面

    • true:是,可使用內置對象exception
    • false:否。默認值。不可使用內置對象exception

(五) 行爲

JSP行爲(JSP Actions)是一組JSP內置的標籤,只書寫少許的標記代碼就可以使用JSP提供豐富的功能,JSP行爲是對經常使用的JSP功能的抽象和封裝。

JSP內置的標籤稱之爲JSP行爲,是爲了可以和JSTL標籤區分開來。(叫作JSP標籤也行)

(1) include 行爲

上面已經說起到了,include指令是靜態包含,include行爲是動態包含。其實include行爲就是封裝了request.getRequestDispatcher(String url).include(request,response)

include行爲語法是這樣的:

<jsp:include page=""/>

靜態包含:<%@ include file="被包含頁面"%>
動態包含:<jsp:include page="被包含頁面" flush="true">
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>包含頁頭和頁尾進來</title>
    </head>
    <body>
        <jsp:include page="head.jsp"/>
        <jsp:include page="foot.jsp"/>
    </body>

jsp行爲包含文件就是先編譯被包含的頁面,再將頁面的結果寫入到包含的頁面中(1.jsp)

固然了,如今有靜態包含和動態包含,使用哪個更好呢?答案是:動態包含。

動態包含能夠向被包含的頁面傳遞參數(用處不大),而且是分別處理包含頁面的(將被包含頁面編譯後得出的結果再寫進包含頁面)

【若是有相同名稱的參數,使用靜態包含就會報錯!】!

(2) Param 行爲

當使用<jsp:include>和<jsp:forward>行爲引入或將請求轉發給其它資源時,可使用<jsp:param>行爲向這個資源傳遞參數

(3) forward 行爲

在Servlet中咱們使用request.getRequestDispatcher(String url).forward(request,response)進行跳轉。其實forward行爲就是對其封裝!

咱們來看一下forward的語法

<jsp:forward page=""/>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>訪問1.jsp就跳轉到head.jsp</title>
    </head>
    <body>
    
    <jsp:forward page="head.jsp"/>
    
    </body>
    </html>

若是我要傳遞參數,就要在forward行爲嵌套param行爲

在跳轉到head.jsp時傳入參數username值爲aaa

<jsp:forward page="head.jsp">
    <jsp:param name="username" value="aaa"/>
 </jsp:forward>
<%
    String ss = request.getParameter("username");
%>
獲取到的參數是:
    <%=ss%>

(4) directive 行爲

directive的中文意思就是指令。該行爲就是替代指令<%@%>的語法的

· <jsp:directive.include file=""/> 至關於<%@include file="" %>

· jsp:directive.page/ 至關於<%@page %>

· jsp:directive.taglib/ 至關於<%@taglib %>

使用該指令可讓JSP頁面更加美觀!

使用scriptlet行爲<jsp:scriptlet>替代<%%>是一樣一個道理

(5) javaBean 行爲

JSP還提供了操做javaBean對象的行爲,暫時記住JSP提供了javaBean行爲來操做簡單類便可!後面詳細解釋:

<jsp:useBean id=""/>
<jsp:setProperty name="" property=""/>
<jsp:getProperty name="" property=""/>

(六) JSP內置對象(直接使用)

JSP引擎在調用JSP對應的jspServlet時,會傳遞或建立9個與web開發相關的對象供jspServlet使用。JSP技術的設計者爲便於開發人員在編寫JSP頁面時得到這些web對象的引用,特地定義了9個相應的變量,開發人員在JSP頁面中經過這些變量就能夠快速得到這9大對象的引用

變量名 真實類型 做用
pageContext PageContext 當前頁面共享數據,還能夠獲取其餘八個內置對象
request HttpServletRequest 一次請求訪問的多個資源(轉發)
session HttpSession 一次會話的多個請求間
application ServletContext 全部用戶間共享數據
response HttpServletResponse 響應對象
page Object 當前頁面(Servlet)的對象 this
out JspWriter 輸出對象,數據輸出到頁面上
config ServletConfig Servlet的配置對象
exception Throwable 內置對象exception是java.lang.Exception類的對象

(七) 四種屬性範圍

到目前爲止,咱們已經學了4種屬性範圍了。

page【只在一個頁面中保存屬性,跳轉頁面無效】

requet【只在一次請求中保存屬性,服務器跳轉有效,瀏覽器跳轉無效】

session【在一個會話範圍中保存屬性,不管何種跳轉均有效,關閉瀏覽器後無效】

application【在整個服務器中保存,全部用戶均可以使用】

4個內置對象都支持如下的方法:

  • setAttribute(String name, Object o )
  • getAttribute(String name)
  • removeAttribute(String name)

※ 應用場景

  1. request:若是客戶向服務器發請求,產生的數據,用戶看完就沒用了,像這樣的數據就存在request域,像新聞數據,屬於用戶看完就沒用的
  2. session:若是客戶向服務器發請求,產生的數據,用戶用完了等一下子還有用,像這樣的數據就存在session域中,像購物數據,用戶須要看到本身購物信息,而且等一下子,還要用這個購物數據結賬
  3. servletContext:若是客戶向服務器發請求,產生的數據,用戶用完了,還要給其它用戶用,像這樣的數據就存在servletContext域中,像聊天數據

(八) JavaBean

avaBean就是一個普通的java類,也稱之爲簡單java對象--POJO(Plain Ordinary Java Object),是Java程序設計中一種設計模式,是一種基於 Java 平臺的軟件組件思想

JavaBean遵循着特定的寫法,一般有如下的規則:

有無參的構造函數

成員屬性私有化

封裝的屬性若是須要被外所操做,必須編寫public類型的setter、getter方法

上面的文字看起來好像很高大上,javaBean其實很是簡單,常見的學生類,書籍類就是按照特定寫法、規則編寫的一個JavaBean對象

爲何須要使用Javabean

使用javaBean的好處:封裝,重用,可讀!

JaveBean你能夠理解爲一輛貨車,在你的java端和web頁面進行數據傳遞的載體,你固然能夠每一個變量單獨傳遞,或者使用集合傳遞,可是javabean可使你的數據更有可讀性,方便開發時明確變量的意義,也使其餘閱讀你代碼的人能直接你的意圖

若是bean類與數據庫聯合使用,一張表使用bean類,可使你的代碼更加簡潔高效,易於理解,如今大多數框架都會使用這種機制。

JSP行爲--JavaBean

JSP技術提供了三個關於JavaBean組件的動做元素,即JSP行爲(標籤),它們分別爲:

jsp:useBean【在JSP頁面中查找javaBean對象或者實例化javaBean對象】

jsp:setProperty【設置javaBean的屬性】

jsp:getProperty【獲取javaBean的屬性】

※ JSP:useBean

<jsp:useBean>

標籤用於在指定的域範圍內查找指定名稱的JavaBean對象:

存在則直接返回該JavaBean對象的引用。

不存在則實例化一個新的JavaBean對象並將它以指定的名稱存儲到指定的域範圍中。

語法:

jsp:useBean id="實例化對象的名稱" class="類的全名" scope="保存範圍"/>

果JSP不支持<jsp:useBean>這個行爲,咱們要使用Person類是這樣使用的

<%--這裏須要導入Person類--%>
    <%@ page import="domain.Person" %>

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title></title>
    </head>
    <body>
    
    <%
        //new出對象
        Person person = new Person();

        person.setName("admin");
        System.out.println(person.getName());
    %>
    </body>

可是咱們使用<jsp:useBean>就很是整潔,不用導包,不用new對象

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title></title>
    </head>
    <body>
    
    <jsp:useBean id="person" class="domain.Person" scope="page"/>
    <%
        person.setName("zhongfucheng");
        System.out.println(person.getName());
    %>
    </body>
    </html>

JavaBean中無參的構造函數改爲有參的,會出現異常,這是由於<jsp:useBean>

的內部原理是 new了一個無參的構造函數

※ JSP:setProperty

<jsp:setProerty name="對象名稱" property="屬性名" param="參數名" value="值">

四種模式

<jsp:setProperty name="對象名稱" property="*"/>自動匹配
<jsp:setProperty name="對象名稱" property="屬性名稱"/>指定屬性
<jsp:setProperty name="對象名稱" property="屬性名稱" param="參數名稱"/>指定參    數【不多用】
<jsp:setProperty name="對象名稱" property="屬性名稱" value="內容"/>指定內容【很    少用】

當咱們沒有學習到<jsp:setProperty>時,咱們獲取表單的信息,而後導入到javaBean對象中是這樣的一種狀況:

<jsp:useBean id="person" class="domain.Person" scope="page"/>
<%
    int age = Integer.parseInt(request.getParameter("age"));        
     person.setAge(age);    
     System.out.println(person.getAge());
%>

而咱們使用<jsp:setProperty>後,代碼更少,功能更強大

<jsp:useBean id="person" class="domain.Person" scope="page"/>

<%--指定屬性名稱爲age--%>
<jsp:setProperty name="person" property="age"/>
 <%
        System.out.println(person.getAge());
 %>

代碼少很直觀的能夠看出來,可是強大在什麼地方呢?

表單提交過來的數據都是字符串,在咱們沒有用<jsp:setProperty>前,咱們存儲設置int類型或其餘非字符串類型的數據是須要強轉的!可是<jsp:setProperty>不須要咱們強轉,它內部自動幫咱們轉換了!

下面再經過自動匹配來感覺它的強大

<jsp:useBean id="person" class="domain.Person" scope="page"/>

<%--property的值設置爲*就表明自動匹配--%>
<jsp:setProperty name="person" property="*"/>
<%
    System.out.println(person.getAge());
    System.out.println(person.getName());
%>

爲何Property的值能夠將表單傳遞過來的數據封裝到JavaBean對象中?

JavaBean屬性名要和表單的name的名稱一致

是經過反射來作的,調用了內省的方法!

※ JSP:getProperty

<jsp:getProperty name="對象名" property="屬性名"/>
<%--使用<jsp:getProperty>輸出--%>
<jsp:getProperty name="person" property="username"/>
<jsp:getProperty name="person" property="age"/>

JSP 第二篇:

EL運算符:概述、內置對象、數據回顯、自定義函數、EL函數庫

(一) 概述

EL:Expression Language 表達式語言

它的做用就是替換和簡化jsp頁面中java代碼的編寫

EL表達式支持簡單的運算符:加減乘除取摸,邏輯運算符。empty運算符(判斷是否爲null),三目運算符


empty運算符能夠判斷對象是否爲null,用做於流程控制!

三目運算符簡化了if和else語句,簡化代碼書寫

<%
    List<Person> list = null;
%>
${list==null?"list集合爲空":"list集合不爲空"}

(二) 內置對象

EL表達式主要是來對內容的顯示,爲了顯示的方便,EL表達式提供了11個內置對象

pageContext 對應於JSP頁面中的pageContext對象(注意:取的是pageContext對象)

pageScope 表明page域中用於保存屬性的Map對象

requestScope 表明request域中用於保存屬性的Map對象
 sessionScope 表明session域中用於保存屬性的Map對象

applicationScope 表明application域中用於保存屬性的Map對象

param 表示一個保存了全部請求參數的Map對象

paramValues 表示一個保存了全部請求參數的Map對象,它對於某個請求參數,返回的是一個string[]

header 表示一個保存了全部http請求頭字段的Map對象

headerValues 同上,返回string[]數組。

cookie 表示一個保存了全部cookie的Map對象

initParam 表示一個保存了全部web應用初始化參數的map對象

(三) 數據回顯

<%--模擬數據回顯場景--%>
<%
    User user = new User();
    user.setGender("male");

    //數據回顯
    request.setAttribute("user",user);
%>


<input type="radio" name="gender" value="male" ${user.gender=='male'?'checked':'' }>男
<input type="radio" name="gender" value="female" ${user.gender=='female'?'checked':'' }>女

(四) 自定義函數

EL自定義函數用於擴展EL表達式的功能,可讓EL表達式完成普通Java程序代碼所能完成的功能

開發HTML轉義的EL函數

咱們有時候想在JSP頁面中輸出JSP代碼,可是JSP引擎會自動把HTML代碼解析, 輸出給瀏覽器。此時咱們就要對HTML代碼轉義。

步驟:

編寫一個包含靜態方法的類(EL表達式只能調用靜態方法),該方法很經常使用,Tomcat都有此方法,可在webappsexamplesWEB-INFclassesutil中找到

public static String filter(String message) {

        if (message == null)
            return (null);

        char content[] = new char[message.length()];
        message.getChars(0, message.length(), content, 0);
        StringBuilder result = new StringBuilder(content.length + 50);
        for (int i = 0; i < content.length; i++) {
            switch (content[i]) {
            case '<':
                result.append("&lt;");
                break;
            case '>':
                result.append("&gt;");
                break;
            case '&':
                result.append("&amp;");
                break;
            case '"':
                result.append("&quot;");
                break;
            default:
                result.append(content[i]);
            }
      }
    return (result.toString());

在WEB/INF下建立tld(taglib description)文件,在tld文件中描述自定義函數

<?xml version="1.0" encoding="ISO-8859-1"?>

<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.0</tlib-version>
    <short-name>myshortname</short-name>
    <uri>/zhongfucheng</uri>

    <!--函數的描述-->
    <function>

        <!--函數的名字-->
        <name>filter</name>

        <!--函數位置-->
        <function-class>utils.HTMLFilter</function-class>

        <!--函數的方法聲明-->
        <function-signature>java.lang.String filter(java.lang.String)</function-signature>
    </function>

</taglib>

在JSP頁面中導入和使用自定義函數,EL自定義的函數通常前綴爲"fn",uri是"/WEB-INF/tld文件名稱"

<%@ page language="java" contentType="text/html" pageEncoding="UTF-8" %>
<%@taglib prefix="fn" uri="/WEB-INF/ideal.tld" %>

<html>
<head>
    <title></title>
</head>
<body>

//完成了HTML轉義的功能
${fn:filter("<a href='#'>點這裏</a>")}

</body>
</html>

(五) EL函數庫(fn方法庫)

  • 因爲在JSP頁面中顯示數據時,常常須要對顯示的字符串進行處理,SUN公司針對於一些常見處理定義了一套EL函數庫供開發者使用。
  • 其實EL函數庫就是fn方法庫,是JSTL標籤庫中的一個庫,也有人稱之爲fn標籤庫,可是該庫長得不像是標籤,因此稱之爲fn方法庫
  • 既然做爲JSTL標籤庫中的一個庫,要使用fn方法庫就須要導入JSTL標籤!要想使用JSTL標籤庫就要導入jstl.jar和standard.jar包!
  • 因此,要對fn方法庫作測試,首先導入開發包(jstl.jar、standard.jar)

在JSP頁面中指明使用標籤庫

<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>

JSP 第三篇:

JSTLd的簡單認識、三個經常使用對象

JSTL全稱爲 JSP Standard Tag Library 即JSP標準標籤庫

JSTL做爲最基本的標籤庫,提供了一系列的JSP標籤,實現了基本的功能:集合的遍歷、數據的輸出、字符串的處理、數據的格式化等等!

爲何使用

EL表達式能夠很方便地引用一些JavaBean以及其屬性可是仍然不夠完美,它不能遍歷集合,作邏輯的控制。

Scriptlet的可讀性,維護性,重用性都十分差!JSTL與HTML代碼十分相似,遵循着XML標籤語法,使用JSTL讓JSP頁面顯得整潔,可讀性很是好,重用性很是高,能夠完成複雜的功能!

在JSP中不推薦使用scriptlet輸出,推薦使用JSP標籤

使用JSTL標籤庫步驟

  • 導入jstl相關jar包
  • 引入標籤庫:taglib指令:<%@ taglib %>
  • 使用標籤

Core標籤庫

core標籤庫是JSTL的核心標籤庫,實現了最基本的功能:流程控制、迭代輸出等操做

core標籤庫的前綴通常是c

經常使用的三個JSTL標籤

(一) c:if

屬性:

test 必須屬性,接受boolean表達式

若是表達式爲true,則顯示if標籤體內容,若是爲false,則不顯示標籤體內容

  • 注意:c:if 標籤沒有else狀況,想要else狀況,則能夠在定義一個c:if標籤
<%--若是帶過來的名字是admin,那麼能夠登錄--%>
    <c:if test="${param.name=='admin'}">
        用戶名:<input type="text" name="username"><br>
        密碼:<input type="password" name="password"><br>
        <input type="submit" value="登錄">
    </c:if>
    
    <%--若是帶過來的名字是admin888,那麼就是註冊--%>
    <c:if test="${param.name=='admin888'}">
        用戶名:<input type="text" name="username"><br>
        密碼:<input type="password" name="password"><br>
        <input type="submit" value="註冊">
    </c:if>

(二) c:choose

它至關於java代碼的switch語句

使用choose標籤聲明,至關於switch聲明
使用when標籤作判斷,至關於case
使用otherwise標籤作其餘狀況的聲明,至關於default

<c:choose>
        <c:when test="${param.name=='admin'}">
            歡迎管理員
        </c:when>
        <c:when test="${param.name=='user'}">
            歡迎用戶
        </c:when>
        <c:otherwise>
            識別不出你是誰
        </c:otherwise>
</c:choose>

(三) c:forEach

forEach爲循環標籤,至關於Java中的while和for

以前咱們在使用EL表達式獲取到集合的數據,遍歷集合都是用scriptlet代碼循環,如今咱們學了forEach標籤就能夠捨棄scriptlet代碼

向Session中設置屬性,屬性的類型是List集合

向Session中設置屬性,屬性的類型是List集合

遍歷session屬性中的List集合,items:即將要迭代的集合。var:當前迭代到的元素

<%
    List list = new ArrayList<>();
    list.add("admin");
    list.add("zhangsan");
    list.add("lisi");
    
    session.setAttribute("list", list);
%>

=====================================================
 <c:forEach  var="list" items="${list}" >
    ${list}<br>
</c:forEach>

Map對象有稍微地不同保存的不是每一個迭代的對象,而是Map.Entry

<%
    Map map = new HashMap();
    map.put("1", "tom");
    map.put("2", "jack");
    map.put("3", "jack」);
    
    session.setAttribute("map",map);
%>
    
<c:forEach  var="me" items="${map}" >   
    ${me.key}  ${me.value}<br>
</c:forEach>

特別說明:本篇中 第二 第三篇部份內容轉載來自 java3y 所寫jsp第四篇內容,在做者基礎上摘出片斷,附上連接

https://juejin.im/post/5a7919...

結尾:

若是內容中有什麼不足,或者錯誤的地方,歡迎你們給我留言提出意見, 蟹蟹你們 !^_^

若是能幫到你的話,那就來關注我吧!(系列文章均會在公衆號第一時間更新)

在這裏的咱們素不相識,卻都在爲了本身的夢而努力 ❤

一個堅持推送原創Java技術的公衆號:理想二旬不止

相關文章
相關標籤/搜索