JSP入門基礎知識詳細版(通俗易懂)


JSP 第一篇:

概述、原理、周期、指令、行為、內置對象、JavaBean

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

什么是JSP?

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

和Java代碼共同存在!

為什么需要JSP?

JSP是為了簡化Servlet的工作出現的替代品,Servlet輸出HTML非常困難,JSP就是替代Servlet輸出HTML的

JSP還有必要學嗎

在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/5a7919045188257a76630a23

結尾:

如果內容中有什么不足,或者錯誤的地方,歡迎大家給我留言提出意見, 蟹蟹大家 !_

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

在這里的我們素不相識,卻都在為了自己的夢而努力 ❤

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


免責聲明!

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



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