【JSP教科書】JSP知識在線指南(記錄知識JSP體系、EL表達式、JSTL標籤庫、JSP開發模型和分頁查詢)

文章目錄

溫馨提示: 由於CSDN沒有jsp代碼塊,這裏jsp代碼我一致使用的java代碼塊編寫。所以大家再查看之餘要注意一下jsp代碼中的註釋!

一、JSP簡介

1.1 什麼是JSP?

JSP全稱Java Server Pages,是一種動態網頁開發技術。它使用JSP標籤在HTML網頁中插入Java代碼。標籤通常以<%開頭以%>結束。

1.2 JSP的特點

JSP是一種Java servlet,主要用於實現Java web應用程序的用戶界面部分。可以通過結合HTML代碼、XHTML代碼、XML元素以及嵌入JSP操作和命令來編寫JSP。

JSP通過網頁表單獲取用戶輸入數據、訪問數據庫及其他數據源,然後動態地創建網頁。

JSP標籤有多種功能,比如訪問數據庫、記錄用戶選擇信息、訪問JavaBeans組件等,還可以在不同的網頁中傳遞控制信息和共享信息。

1.3 JSP爲什麼也是Servlet

  • 當jsp頁面顯示後,會在在tomcat中有一個目錄叫work,它裏面就存儲了jsp頁面生成的源代碼。jsp文件會轉義成對應的java文件

  • 比如:demo01.jsp轉義成demo01_jsp.java,類demo01_jsp會繼承於HttpJspPage,HttpJspPage又繼承了HttpServlet。也就可以說demo01.jsp就是Servlet(所有的jsp都是Servlet)

1.4 tomact服務器中的資源分析

tomact服務器資源中可以分爲靜態技術資源和動態技術資源

1.4.1 tomact服務器中的靜態資源分析
  • 靜態資源分爲:
    • HTML:靜態頁面
    • CSS:渲染美化靜態HTML頁面的樣式
    • Java Script:動態修改HTML頁面和CSS樣式
1.4.2 tomact服務器中的動態資源分析
  • Servlet:運行在服務器上的Java小程序。適合編寫Java代碼,適合業務處理,寫網頁比較困難
    • Servlet的三個用途:接受瀏覽器發送的數據、負責調用業務層、請求轉發及重定向的使用
  • JSP:適合編寫動態內容,不適合寫java代碼,主要用於顯示頁面

1.5 爲什麼要使用JSP

  1. JSP性能好,可以在html頁面中動態嵌入元素
  2. 服務器調用的是已經編譯好的JSP文件
  3. JSP基於Java Servlet Api,有很多強大企業的支持
  4. JSP可以與處理業務邏輯的Servlet一起使用,該模式被Java Servlet模版引擎所支持

1.6 JSP的優點

與純 Servlet 相比:JSP可以很方便的編寫或者修改HTML網頁而不用去面對大量的println語句

與JavaScript相比:雖然JavaScript可以在客戶端動態生成HTML,但是很難與服務器交互,因此不能提供複雜的服務,比如訪問數據庫和圖像處理等等

與靜態HTML相比:靜態HTML不包含動態信息

1.7 JSP的原理

  1. 當在瀏覽器上輸入http://localhost/jspdemo/index.jsp
  2. 服務器tomcat得到請示,會通過JspServlet將後綴名是.jsp的請求處理
  3. 處理將index.jsp翻譯成index_jsp.java文件
  4. 再將index_jsp.java文件編譯成index_jsp.class文件
  5. jvm將.class加載運行
  6. 服務器生成響應,響應信息中就包含了jsp頁面上的html代碼

二、JSP的基本結構

2.1 JSP的結構

JSP頁面中可以包含指令、Java語句、變量、方法或表達式、靜態內容(HTML、CSS、Java Script)

  • 腳本元素(Scripting Elements):聲明、腳本段、表達式
  • 註釋指令(Comment Elements):HTML註釋、Java註釋、JSP隱式註釋
  • 指令元素(Directive Elements):page、include、taglib等
  • 動作元素(Action Elements):jsp:include、jsp:forward、jsp:useBean等

2.2 JSP腳本元素

2.2.1 JSP腳本的作用

可以在頁面上編寫java代碼,實現頁面與Java代碼數據的交互

2.2.2 JSP腳本的分類

聲明腳本: <%! Java代碼 %>

片段腳本: <% Java代碼 %>

輸出腳本: <%= 變量值 %>

2.2.2.1 聲明腳本

聲明腳本里的變量是全局變量,也就是在jsp對應java類中,生成一個成員變量

<%!
	定義方法
%>     
2.2.2.2 片段腳本

在jsp對應的java類的_jspService方法中,生成一個局部變量

<% int i=10; %>
2.2.2.3 輸出腳本

向瀏覽器輸出內容,相當於response.getWriter().write()

注意:輸出腳本等價於輸出語句,不能使用分號來結束表達式

<%= 2+3 %>

2.3 JSP頁面中的註釋

2.3.1 JSP頁面中的註釋分類

JSP頁面中可以包含以下幾種註釋種類:Java代碼註釋、HTML網頁註釋、JSP頁面註釋

2.3.2 Java代碼註釋

Java代碼註釋用來註釋Java代碼,會將註釋內容生成到jsp對應的java文件中。也就是說註釋內容在Java文件中可見。所以不安全 、比較耗費流量

//Java代碼註釋
2.3.3 HTML網頁註釋

HTML網頁註釋用來註釋HTML代碼,會將註釋內容生成到jsp對應的java文件中。也就是說和HTML文件類似,在網頁查看源代碼中,註釋可見。所以不安全 、比較耗費流量

<!-- HTML網頁註釋 -->
2.3.4 JSP頁面註釋

JSP頁面註釋用來註釋HTML代碼,不會將註釋內容生成到jsp對應的java文件中。所以,安全、省流量、僅在JSP文件中可見

<%-- JSP頁面註釋 --%>

2.4 JSP指令

2.4.1 JSP中指令分類

JSP中的指令分爲三種:page指令、taglib指令、include指令

2.4.2 JSP中的指令的作用

JSP指令用於指示jsp執行某些操作 、用於指示jsp表現特定行爲或效果

2.4.3 page指令

page指令用於定義JSP頁面的各種屬性

屬性 描述
session 是否會自動創建session對象;默認值爲true
buffer JSP中有javax.servlet.jsp.JspWriter輸出字符流。設置輸出數據的緩存大小;默認8kb
errorPage 如果頁面中有錯誤,跳轉到指定的資源;errorPage=“項目資源路徑”
isErrorPage 是否創建throwable對象;默認是false
contentType 等價於response.setContentType(“text/html”;charset=utf-8);告知瀏覽器應該以utf-8解碼響應正文,以utf-8對響應正文進行編碼
pageEncoding Jsp文件自身的編碼
isELIgnored 是否支持EL表達式。 默認是false,支持表達式;true表示不支持表達式;例如:${1+1}; 爲false時,輸出結果爲2;爲true時按照原樣輸出
import 與Java代碼中無差別,等價於導包;例如:<%@ page import=“java.util.Date,java.util.List”%> 或者分開導入需要的包<%@ page import=“java.util.List”%>
2.4.4 taglib指令

taglib指令用於在當前jsp頁面中導入jstl標籤庫

例如:導入jstl標籤庫

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
2.4.5 include指令

include指令用於將外部引入到jsp文件中

2.4.5.1 include指令引入靜態資源

例如:引入靜態資源

<%@ include file="static.jsp"%>
2.4.5.2 include指令引入動態資源

例如:引入動態資源

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

2.5 JSP的九大內置對象

對象名 描述 類型
request 請求對象 javax.servlet.http.HttpServletRequest
response 響應對象 javax.servlet.http.HttpServletResponse
session Session會話對象 javax.servlet.http.HttpSession(由session=“true”開關)
application Servlet上下文對象 javax.servlet.ServletContext
config ServletConfig對象 javax.servlet.ServletConfig
exception 異常對象 java.lang.Throwable(由isErrorPage=“false”開關)
out JspWriter對象 javax.servlet.jsp.JspWriter
pageContext 當前頁面上下文對象 javax.servlet.jsp.PageContext
page 當前頁面對象 java.lang.Object(當前頁面對象,this爲當前servlet實例)
<%--
  Created by IntelliJ IDEA.
  User: Ziph
  Date: 2020/4/27
  Time: 12:40
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
<html>
<head>
    <title>jsp九大內置對象的使用</title>
</head>
<body>
<%
    /**
     * Request對象
     * 在地址欄中以GET請求的方式拼即可獲取到request對象中的username參數
     */
    String username = request.getParameter("username");
    System.out.println(username);
    /**
     * Response對象
     * 可以實現響應瀏覽器內容
     */
    response.getWriter().println("username : " + username);
    /**
     * Session對象
     * 在Session域中存儲username,可以實現在另一個jsp中取出Session域中的username參數
     */
    request.getSession().setAttribute("username", "ziph");
    /**
     * application對象(ServletContext)
     * 在application對象中存儲一個username參數,可以實現在另一個jsp中取出application對象中的username參數
     */
    application.setAttribute("username", "ziph");
    /**
     * 使用out對象在瀏覽器上輸出內容
     */
    out.write("<br>out : ziph");
    /**
     * config配置對象
     * 可以獲取初始化參數ServletName名稱爲jsp
     */
    System.out.println("config : " + config.getServletName());
    /**
     * exception異常對象
     * 可以獲取異常對象(此時沒有異常對象所以打印null)
     */
    System.out.println("exception : " + exception);
    /**
     * page當前頁面對象
     * 打印了當前頁面對象
     */
    System.out.println(page.getClass());
    /**
     * pageContext頁面上下文對象
     */
    pageContext.setAttribute("pageContext", "ziph");
    System.out.println(pageContext.getAttribute("pageContext"));
%>
</body>
</html>

test.jsp

<%
    /**
     * 可以取出另一個jspSession中域中的username參數值
     */
    String username = (String) request.getSession().getAttribute("username");
    System.out.println("Session : " + username);
    /**
     * 可以取出application對象中的username參數值
     */
    String applicationAttribute = (String) application.getAttribute("username");
    System.out.println("application : " + applicationAttribute);
%>
2.5.1 jsp的out和getWriter()方法的區別
  • out是JspWriter類型;getWriter()是PrintWriter類型
  • out輸出到緩衝區中,沒有寫到response中;getWriter()直接寫到response中
  • out一般用在jsp中;getWriter()用在Servlet中
2.5.2 爲什麼jsp可以直接使用內置對象

在jsp對應的java文件中,已經提前聲明好了這些內置對象,所以可以直接使用

在這裏插入圖片描述

2.5.3 怎樣找到jsp頁面的class文件

jsp頁面的class文件一般都保存在tomact目錄下的,路徑爲:\apache-tomcat-8.5.45\work ;是在work文件夾中

但是使用IDEA的小夥伴也知道,IDEA部署後的項目資源是保存在IDEA自動生成的鏡像中的。所以我們要去找到鏡像的位置。一般IDEA鏡像位置會在電腦的C盤中放置,你可以在啓動tomact 服務器的時候去找鏡像的路徑所在,找到鏡像就好辦了,就可以找到jsp頁面的class文件了!

這是我電腦中IDEA自動生成項目資源鏡像的位置:(大家可以在tomact啓動的時候,去尋找類似的路徑!)

C:\Users\Ziph\AppData\Local\JetBrains\IntelliJIdea2020.1\tomcat\Tomcat_8_5_45_webdemoplus\work\Catalina\localhost\webdemoplus\org\apache\jsp

2.6 JSP中的域對象

2.6.1 JSP中有哪幾個域對象

jsp中有四個域對象分別是pageContext、request、session、application

2.6.2 JSP四大域對象的作用範圍及描述
域對象 域對象描述 作用範圍 應用場景
request 等價於HttpServletRquest域對象 一次請求 本次請求後數據不再使用,可用於查詢
session 等價於HttpSession域對象 一次會話 同一個會話中共享數據,可用於登錄信息
application 等價於ServletContext域對象 整個項目 所有用戶共享數據,可用於程序的配置信息
pageContext JSP獨有的域對象 當前頁面 單獨作用於JSP當前頁面

注意:pageContext域對象可以操作其他三個域對象的數據!

2.6.3 pageContext域對象獲取內置對象和操作其他域對象
  • pageContext域對象可以獲取其他內置域對象
  • pageContext域對象不僅可以操作page域對象,還可以操作request、session和application域對象
  • 使用pageContext域對象實現轉發 pageContext.forward(“test.jsp”);
  • 使用pageContext域對象實現動態包含 pageContext.include(“dynamic.jsp”);
<%--
  Created by IntelliJ IDEA.
  User: Ziph
  Date: 2020/4/27
  Time: 13:36
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>pageContext域對象</title>
</head>
<body>
<%
    /**
     * pageContext域對象獲取jsp中九大內置對象
     */
    pageContext.getPage();
    pageContext.getRequest();
    pageContext.getResponse();
    pageContext.getSession();
    pageContext.getServletConfig();
    pageContext.getServletContext();
    pageContext.getException();
    pageContext.getOut();
%>

<%
    /**
     * 操作Request域對象
     * <p>
     * 方法:setAttribute(String name, Object value, int scope);
     * 參數說明:
     * String name:參數名稱
     * Object value:參數值
     * int scope:操作的域
     * <p>
     * 指定操作域的參數,可以傳入操作域對象的對應數字編號
     * public static final int PAGE_SCOPE = 1;
     * public static final int REQUEST_SCOPE = 2;
     * public static final int SESSION_SCOPE = 3;
     * public static final int APPLICATION_SCOPE = 4;
     * <p>
     * 也可以使用PageContext域對象獲取該參數傳入
     * 例如:PageContext.REQUEST_SCOPE
     */
    pageContext.setAttribute("request", "request", PageContext.REQUEST_SCOPE);
    //因爲本次操作的是Request對象,操作頁面的默認重定向是不在Request對象的作用範圍的,所以我們使用請求轉發
    //Request對象作用範圍是一次請求;請求轉發是內部操作,所以符合Request對象的作用範圍
	pageContext.forward("/test.jsp");
    //等價於request.getRequestDispatcher("/test.jsp").forward(request, response);

    /**
     * 操作Session域對象
     */
    pageContext.setAttribute("session", "session", PageContext.SESSION_SCOPE);

    /**
     * 操作application域對象
     */
    pageContext.setAttribute("application", "application", PageContext.APPLICATION_SCOPE);
%>
</body>
</html>

test.jsp

<%
    /**
     * 操作Reuqest域對象(獲取)
     */
    String requestAttribute = (String) request.getAttribute("request");
    System.out.println(requestAttribute);
    String pageContextAttribute = (String) pageContext.getAttribute("request", PageContext.REQUEST_SCOPE);
    System.out.println(pageContextAttribute);

    /**
     * 操作Session域對象(獲取)
     */
    String pageContextAttribute1 = (String) pageContext.getAttribute("session", PageContext.SESSION_SCOPE);
    System.out.println(pageContextAttribute1);

    /**
     * 操作application域對象(獲取)
     */
    String pageContextAttribute2 = (String) pageContext.getAttribute("application", PageContext.APPLICATION_SCOPE);
    System.out.println(pageContextAttribute2);
%>

三、EL表達式

3.1 什麼是EL表達式

表達式語言(Expression Language),或稱EL表達式,簡稱EL,是Java中的一種特殊的通用編程語言,借鑑於JavaScript和XPath。 主要作用是在Java Web應用程序嵌入到網頁(如JSP)中,用以訪問頁面的上下文以及不同作用域中的對象,取得對象屬性的值,或執行簡單的運算或判斷操作。

3.2 瞭解EL表達式和注意事項

EL表達式簡化JSP中Java代碼開發,代替腳本表達式<%=輸出腳本%>。它不是一種開發語言,是jsp中獲取數據的一種規範。格式: ${EL表達式}等價於pageContext.findAttribute(name)

注意:EL表達式是jsp2.0中的規範,要使用el表達式必須使用支持jsp2.0技術的web服務器 (tomcat) ,jsp2.0對應的servlet版本是servlet2.4。如果不能使用el表達式請檢查isELIgnored屬性

3.3 EL表達式獲取域數據

注意:使用el表達式獲取時,如果沒有查找到結果,返回的不是null,而是一個""

EL表達式
page域 ${pageScope.name}
request域 ${requestScope.name}
session域 ${sessionScope.name}
application域 ${applicationScope.name}
3.3.1 EL表達式基本獲取域數據

使用最基本的方式來獲取域數據

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL獲取域數據</title>
</head>
<body>
<%
    //設置page域
    pageContext.setAttribute("username1", "pageScope");
    //設置request域
    request.setAttribute("username2", "request");
    //設置session域
    session.setAttribute("username3", "session");
    //設置application域
    application.setAttribute("username4", "application");
%>
<%--使用el表達式從page域中獲取usernmae1變量--%>
${pageScope.username1}<br>
<%--使用el表達式從request域中獲取username2變量--%>
${requestScope.username2}<br>
<%--使用el表達式從session域中獲取username3變量--%>
${sessionScope.username3}<br>
<%--使用el表達式從application域中獲取username4變量--%>
${applicationScope.username4}<br>
</body>
</html>

3.3.2 EL表達式簡單獲取域數據

使用簡單的方法來獲取域數據

自動精確匹配: 使用${username}沒有指明域,那麼就按照此順序pageScop->requestScop->sessionScop- >applicationScop從中依次查找。

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL表達式獲取域數據</title>
</head>
<body>
<%
    request.setAttribute("username", "request");
%>
<%--自動精確匹配:從pageScope、requestScope、sessionScope、applicationScope逐個找擁有username變量的域數據--%>
${username}
</body>
</html>
3.3.3 EL表達式獲取複雜域數據(數組、集合、Java對象)

使用EL表達式獲取數組、List集合、Map集合和Java對象

<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="com.mylifes1110.java.bean.User" %><%--
  Created by IntelliJ IDEA.
  User: Ziph
  Date: 2020/4/27
  Time: 20:19
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL表達式獲取域數據</title>
</head>
<body>
<%--數組--%>
<%
    String[] username = {"Ziph", "Join", "Marry", "Jack"};
    pageContext.setAttribute("username", username);
%>
<%--JSP輸出腳本取出數組中下標0的username值--%>
<%--步驟:取數組中的域數據、強轉爲字符串數組、取出下標爲0的域數據--%>
<%=
((String[]) pageContext.getAttribute("username"))[0]
%>
${username[0]}

<%--List集合--%>
<%
    List<String> fruits = new ArrayList<>();
    fruits.add("蘋果");
    fruits.add("香蕉");
    fruits.add("橘子");
    request.setAttribute("fruitsName", fruits);
%>
<%--取出List的集合中的第一個數據--%>
<%=
((List<String>) request.getAttribute("fruitsName")).get(0)
%>
<%--兩種方法都可以,相同作用--%>
${fruitsName.get(0)}
${fruitsName[0]}

<%--Map集合--%>
<%
    Map<String, String> vegetables = new HashMap<>();
    vegetables.put("tomato", "西紅柿");
    vegetables.put("cucumber", "黃瓜");
    vegetables.put("lettuce", "萵筍");
    session.setAttribute("vegetablesName", vegetables);
%>
<%--取出Map集合中的西紅柿--%>
<%=
((Map<String, String>) session.getAttribute("vegetablesName")).get("tomato")
%>
${vegetablesName.tomato}

<%--Java對象--%>
<%
    User user = new User(1, "Ziph", "123456");
    application.setAttribute("user", user);
%>
<%--獲取User對象的用戶名--%>
<%=
((User) application.getAttribute("user")).getUsername()
%>
${user.username}
</body>
</html>
public class User {
    private int    id;
    private String username;
    private String password;

    public User(int id, String username, String password) {
        this.id = id;
        this.username = username;
        this.password = password;
    }

    public int getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    @Override
    public String toString() {
        return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}';
    }
}

3.4 使用EL表達式執行運算

  • 算數運算符:+-*/(div)%(mod)
    • 注意在el表達式中不能使用+號進行字符串的拼接,只能執行加法操作
  • 關係運算符:>(gt)>=(ge)<(lt)<=(le)==(eq)!=(ne)
    • 執行關係運算得到的結果是boolean類型
  • 邏輯運算符:&&(and)||(or)!(not)
    • 執行邏輯運算得到的結果是boolean 類型
  • 三目運算符(三元運算符):表達式 ? 結果1 : 結果2
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL執行運算</title>
</head>
<body>
<%--算數運算--%>
${10+20 }<br/>
${10-20 }<br/>
${10*20 }<br/>
${3%5}<br/>

<%--關係運算--%>
${10==9 }<br/>
${"abc"=="abc" }<br/>
${s1==s2}<br/>
${s1 eq s2 }<br/>
${10>20}<br/>
${10 gt 20}<br/>
${5 < 10}<br/>
${5 lt 10}<br/>
${5 != 10}<br/>
${5 ne 10}<br/>

<%--三目運算--%>
${20>10?"正確":"錯誤" }<br/>

<%--邏輯運算--%>
${true &&  false}<br/>
${true || false}<br/>
${!true}<br/>
${true and  false}<br/>
${true or false}<br/>
${not true}<br/>
</body>
</html>

3.5 EL表達式中的Empty關鍵字的使用

被empty關鍵字修飾的EL表達式中,只要內容是空,結果就爲true,反之,爲false

<%--
  Created by IntelliJ IDEA.
  User: Ziph
  Date: 2020/4/27
  Time: 21:52
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>EL表達式中使用Empty關鍵字</title>
</head>
<body>
<%
    String username = "ziph";
    String password = null;
    pageContext.setAttribute("username", username);
    pageContext.setAttribute("password", password);
%>
${empty username}<br>
${empty password}<br>
</body>
</html>

3.6 EL表達式中11個的Web對象

常用操作:

  • 獲取根路徑: ${pageContext.request.contextPath}
  • 獲取Cookie對象: ${cookie.get(key).value} (獲取Cookie中鍵爲key的對象的value值)
Web對象名稱 描述
pageScope pageScope域對象,可以獲取域中屬性
requestScope requestScope域對象,可以獲取域中屬性
sessionScope sessionScope域對象,可以獲取域中屬性
applicationScope applicationScope域對象,可以獲取域中屬性
param 對應參數(鍵值對形式),可獲取單個參數值,等價於request.getParameter(“xxx”)
paramValues 對應參數(鍵值對形式),獲取多個參數值,等價於request.getParameterValues(“xxx”)
header 對應請求頭(鍵值對形式),可獲取單個請求頭,等價於request.getHeader(“xxx”)
headerValues 對應請求頭(鍵值對形式),可獲取多個請求頭,等價於 request.getHeaders(“xxx”)
initParam ServletContext(application)全局初始化參數,可獲取web.xml中內的初始化參數
cookie Cookie(鍵值對形式),可獲取Cookie對象
pageContext 可以獲取JSP八個內置對象(內置對象共九個,application除外)

四、JSTL標籤庫

4.1 什麼是JSTL標籤庫

JSP標準標籤庫(JSP Standard Tag Library )是一個JSP標籤集合,它封裝了JSP應用的通用核心功能。 JSTL支持通用的、結構化的任務,比如迭代,條件判斷,XML文檔操作,國際化標籤,SQL標籤。 除了這些,它還提供了一個框架來使用集成JSTL的自定義標籤。

4.2 JSTL標籤庫的作用

可以利用迭代,條件判斷,XML文檔操作,國際化標籤,SQL標籤這些標籤取代JSP頁面上的Java代碼,從而提高程序的可讀性,降低程序的維護難度。

4.3 JSTL標籤庫的使用

  • 從Apache的標準標籤庫中下載的jakarta-taglibs-standard-current.zip
  • 下載 jakarta-taglibs-standard-1.1.2.zip 包並解壓,將 jakarta-taglibs-standard-1.1.2/lib/ 下的兩個 jar 文件:standard.jarjstl.jar 文件拷貝到 /WEB-INF/lib/ 下,再使用Add as Librarys即可使用。
  • 在JSP頁面添加tablib指令庫,引用核心標籤庫的語法如下:
<% @taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core">

4.3 JSTL核心標籤

核心標籤是最常用的 JSTL標籤。

標籤 描述
<c:out> 用於在JSP中顯示數據,就像<%= … >
<c:set> 用於保存數據
<c:remove> 用於刪除數據
<c:catch> 用來處理產生錯誤的異常狀況,並且將錯誤信息儲存起來
<c:if> 與我們在一般程序中用的if一樣
<c:choose> 本身只當做<c:when>和<c:otherwise>的父標籤
<c:when> <c:choose>的子標籤,用來判斷條件是否成立
<c:otherwise> <c:choose>的子標籤,接在<c:when>標籤後,當<c:when>標籤判斷爲false時被執行
<c:import> 檢索一個絕對或相對 URL,然後將其內容暴露給頁面
<c:forEach> 基礎迭代標籤,接受多種集合類型
<c:forTokens> 根據指定的分隔符來分隔內容並迭代輸出
<c:param> 用來給包含或重定向的頁面傳遞參數
<c:redirect> 重定向至一個新的URL.
<c:url> 使用可選的查詢參數來創造一個URL
<%@ page import="java.util.List" %>
<%@ page import="java.util.ArrayList" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>JSTL標籤</title>
</head>
<body>
<%--
Set標籤
向某個域中存儲對象或參數

var:參數名稱
scope:域名稱;page、request、session、application
value:參數值
--%>
<c:set var="message" scope="request" value="hello"></c:set>
${message}<br>

<%--
reomve標籤
移除某個域中的對象或參數

var:要移除的參數名稱
scope:域名稱
--%>
<c:remove var="message" scope="request"></c:remove>
${message}<br>

<%--
catch標籤
捕獲jsp頁面中的異常,可用來打印堆棧跟蹤信息和異常詳細信息
注意:在jsp頁面中捕獲的異常,如果不打印任何信息,頁面將忽略這個錯誤(沒有捕獲代碼的任何信息和錯誤提示)

var:異常對象名稱
--%>
<c:catch var="e">
    <%
        //算數異常
        int num = 1 / 0;
    %>
</c:catch>
<%--打印捕獲的異常詳細信息--%>
${e.message}<br>

<%--
if標籤
if條件判斷

test:條件判斷的條件
--%>
<c:set var="i" value="1" scope="session"></c:set>
<c:if test="${i>2}">
    i大於2
</c:if>
<c:if test="${i<2}">
    <%--執行1<2--%>
    i小於2
</c:if>
<br>

<%--
forEach標籤
支持for循環遍歷形式和增強for循環遍歷形式

var:變量名
step:步長
begin:開始
end:結束
注意:在模擬for循環的時候是有侷限性的,step步長必須大於0,而且begin必須小於end!
items:遍歷的集合或數組
varStatus:元素狀態對象(varStatus屬性還包含以下屬性參數)
    current:當前元素
    index:當前索引
    first:是否是第一個元素
    last:是否是最後一個元素
--%>
<%--for循環:打印1~10--%>
<c:forEach var="i" begin="1" end="10" step="1">
    ${i}
</c:forEach>
<br>
<%--增強for循環:打印集合內元素--%>
<%
    List<String> fruits = new ArrayList<>();
    fruits.add("apple");
    fruits.add("banana");
    fruits.add("strawberry");
    request.setAttribute("fruitsName", fruits);
%>
<%--普通for循環--%>
<c:forEach var="i" begin="0" end="${fruitsName.size() - 1}" step="1">
    ${fruitsName[i]}
</c:forEach>
<br>
<%--增強for循環--%>
<c:forEach var="j" items="${fruitsName}" varStatus="status">
    ${j}<br>
    開始:${status.begin}<br>
    結束${status.end}<br>
    步長:${status.step}<br>
    是第幾個元素:${status.count}<br>
    是否是第一個元素:${status.first}<br>
    是否是最後一個元素:${status.last}<br>
    當前索引:${status.index}<br>
    當前元素:${status.current}<br>
</c:forEach>

<%--
forTokens標籤
切割字符串

items:要分割的字符串
delims:分割字符串依據
var:分割後的元素對象
--%>
<%
    String str = "111-222-333";
    request.setAttribute("str", str);
%>
<%--按”-“拆分字符串str並打印分割後的字符串信息--%>
<c:forTokens var="str" items="${str}" delims="-">
${str}
</c:forTokens>
</body>
</html>

4.4 JSTL綜合案例

使用Servlet、JSP、JDBC、JSTL等所學知識完成以下內容

在這裏插入圖片描述

c3p0配置文件
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/temp
c3p0.user=root
c3p0.password=Mylifes1110
MySQL數據庫庫表操作
use temp;

create table product
(
    id    int primary key auto_increment,
    name  varchar(30),
    price double,
    count int
) charset = utf8;

insert into product (id, name, price, count)
VALUES (1, '電視機', 3000, 2);

insert into product (id, name, price, count)
VALUES (2, '電冰箱', 5000, 4);

insert into product (id, name, price, count)
VALUES (3, '空調', 10000, 1);

insert into product (id, name, price, count)
VALUES (4, '微波爐', 1500, 2);
DBUtils連接池工具類
package com.mylifes1110.java.utils;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class DBUtils {
    private static ComboPooledDataSource dataSource;

    static {
        dataSource = new ComboPooledDataSource();
    }

    public static ComboPooledDataSource getDataSource() {
        return dataSource;
    }
}
Product實體類
package com.mylifes1110.java.bean;

public class Product {
    private Integer id;
    private String name;
    private Double price;
    private Integer count;

    public Product() {
    }

    public Product(Integer id, String name, Double price, Integer count) {
        this.id = id;
        this.name = name;
        this.price = price;
        this.count = count;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    public Integer getCount() {
        return count;
    }

    public void setCount(Integer count) {
        this.count = count;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", price=" + price +
                ", count=" + count +
                '}';
    }
}
Dao層接口
package com.mylifes1110.java.dao;

import com.mylifes1110.java.bean.Product;

import java.sql.SQLException;
import java.util.List;

public interface ProductDao {
    List<Product> selectProductList() throws SQLException;
}
Dao層實現類
package com.mylifes1110.java.dao.impl;

import com.mylifes1110.java.bean.Product;
import com.mylifes1110.java.dao.ProductDao;
import com.mylifes1110.java.utils.DBUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class ProductDaoImpl implements ProductDao {
    @Override
    public List<Product> selectProductList() throws SQLException {
        return new QueryRunner(DBUtils.getDataSource()).query("select * from product",
                                                              new BeanListHandler<Product>(Product.class));
    }
}
Dao層單元測試
package com.mylifes1110.java.test;

import com.mylifes1110.java.bean.Product;
import com.mylifes1110.java.dao.ProductDao;
import com.mylifes1110.java.dao.impl.ProductDaoImpl;
import org.junit.Before;
import org.junit.Test;

import java.sql.SQLException;
import java.util.List;

public class ProductDaoTest {
    ProductDao productDao;

    /**
     * @Before註解 在@Test單元測試之前初始化
     */
    @Before
    public void init() {
        productDao = new ProductDaoImpl();
    }

    public void selectProductById() throws SQLException {
        Product product = productDao.selectProductById(1);

        System.out.println(product);
    }

    @Test
    public void selectProductList() throws SQLException {
        List<Product> products = productDao.selectProductList();

        System.out.println(products);
    }
}
ProductServlet
package com.mylifes1110.java.servlet;

import com.mylifes1110.java.bean.Product;
import com.mylifes1110.java.dao.ProductDao;
import com.mylifes1110.java.dao.impl.ProductDaoImpl;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;

@WebServlet(
    name  = "ProductServlet",
    value = "/SelectProductList"
)
public class ProductServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ProductDao productDao = new ProductDaoImpl();

        try {
            List<Product> products = productDao.selectProductList();

            request.setAttribute("productList", products);
            request.getRequestDispatcher("/product/productList.jsp").forward(request, response);
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}
productList.jsp頁面
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%--
  Created by IntelliJ IDEA.
  User: Ziph
  Date: 2020/4/28
  Time: 22:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>商品列表</title>
</head>
<body>
<table border="1px" cellpadding="10px" cellspacing="0px" width="400px" height="200px">
    <tr>
        <td align="center">ID</td>
        <td>名稱</td>
        <td>價格</td>
        <td>數量</td>
        <td>小計</td>
    </tr>

    <%--循環之前,總價爲0--%>
    <c:set var="total" value="0" scope="page"></c:set>
    <c:forEach items="${productList}" var="product">
        <tr>
            <td align="center">${product.id}</td>
            <td>${product.name}</td>
            <td>${product.price}</td>
            <td>${product.count}</td>
            <td>${product.price * product.count}</td>
        </tr>
        <%--forEach標籤,循環一次就是一個小計!然後更新一下計算總價的計數器中!--%>
        <c:set var="total" value="${total + product.price * product.count}" scope="page"></c:set>
    </c:forEach>
    <%--循環之後,計算出總價--%>
    <tr>
        <td colspan="5" align="right">
            總價:${total}</td>
    </tr>
</table>
</body>
</html>

五、JSP開發模型

Sun公司在推出jsp後,也爲我們提供了兩種jsp開發模式。分別是JSP Model1、JSP Model2,但是在JSP Model1開發模型中經歷過一次優化。而兩種開發模型都不是最終版,只是在技術上做起了過度作用,爲MVC模式做了技術鋪墊!

5.1 JSP Model1開發模型

JSP Model1是JavaWeb早期的模型,它適合小型Web項目,開發成本低!Model1第一代時期,服務器端只有JSP頁面,所有的操作都在JSP頁面中,連訪問數據庫的API也在JSP頁面中完成。

在這裏插入圖片描述

5.1.1 JSP Model1開發模型的優缺點
  • 優點: 開發成本低、使用簡單快捷,對開發人員要求不高
  • 缺點: 不適合完成比較複雜的項目, 所有的東西都耦合在一起,對後期的維護和擴展極爲不利

5.2 JSP Model1優化版開發模型

JSP Model1優化後有所改進,把業務邏輯和數據訪問的內容放到了JavaBeans(狹義JavaBeans:實體類;廣義JavaBeans:實體類、dao層、service層和工具類)中,而JSP頁面負責顯示以及請求調度的工作。雖然第二代比第一代好了些,但還讓JSP做了過多的工作,JSP中把視圖工作和請求調度(控制器)的工作耦合在了一起。

在這裏插入圖片描述

5.2.1 JSP Model1優化版開發模型的優缺點

優點: 開發成本低、使用簡單快捷,對開發人員要求不高,而且在技術中使用Java Beans層面達到了一定程度的解耦

缺點: 解耦程度還是不夠高,JSP頁面的耦合度還有很待解決

5.3 JSP Model2開發模型

JSP Model2開發模型中,可見把JSP頁面的耦合度大大降低。在此JSP頁面(視圖層)用來接收數據,爲用戶提供顯示頁面的功能。JavaBean(模型層)用來完成數據庫的業務功能,同時將業務交接給Servlet。而Servlet(控制層)來實現處理模型對象的業務和對相應業務JSP頁面的轉發。

注意:在JSP Model2開發模型中,已經看到了MAC模式的影子(MAC結構)。準確來說,JSP Model2開發模型就是MAC模式的一種雛形!

在這裏插入圖片描述

5.4 JSP Model2開發模型優缺點
  • 優點: 再一次實現瞭解耦,使得維護方便,開發人員可各司其職。有利於進行分工操作,它比較適合開發一些比較複雜項目,因爲它的很多組件可以重用
  • 缺點: Web項目的開發難度加大,同時對開發人員的技術要求也有相應提高

六、BeanUtils工具類的使用

6.1 參數問題

我們在獲取瀏覽器參數的時候,通過Bean實體類封裝成對象,實現數據的交互。而問題是,瀏覽器請求參數少的時候自己編碼代碼還可以,但是如果在面臨大量瀏覽器請求參數時,麻煩就來了。我們需要書寫大量的getParameter和setXxx來封裝實體類對象實現數據交互。而目前導入第三方jar包,使用它可以解決此問題!

6.2 beanutils.jar工具類jar包的下載

由於此工具類的版本不同,我們需要下載的jar包也不同。經過jar包的迭代,也出現了需要jar包的輔助包等等,我們可以把核心jar包和輔助包一起導入,來實現功能。需要下載並導入的jar包如下:

  • commons-beanutils-1.9.4.jar(核心jar包)
  • commons-collections-3.2.2.jar
  • commons-logging-1.2.jar

注意:此版本需要導入三個jar包,其他版本有的只需要導入兩個,大家可以搜索核心jar包(beanutils)來進行下載

6.3 第三方jar包beanutils工具類使用

此次只是測試使用了BeanUtils工具類

User實體類
package com.mylifes1110.java.bean;

public class User {
    private Integer id;
    private String  username;
    private String  password;
    private Integer age;

    public User() {}

    public User(Integer id, String username, String password, Integer age) {
        this.id       = id;
        this.username = username;
        this.password = password;
        this.age      = age;
    }

    @Override
    public String toString() {
        return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", age="
               + age + '}';
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}
JSP註冊頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>註冊</title>
</head>
<body>
<form action="/firstjsp/register" method="post">
    賬戶:<input type="text" name="username"/><br>
    密碼:<input type="text" name="password"/><br>
    年齡:<input type="text" name="age"/><br>
    <button type="submit">註冊</button>
</form>
</body>
</html>

Servlet
package com.mylifes1110.java.servlet;

import com.mylifes1110.java.bean.User;
import org.apache.commons.beanutils.BeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@WebServlet(
    name  = "RegisterServlet1Servlet",
    value = "/register"
)
public class RegisterServlet1Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        /**
         * 底層代碼:
         * public static void populate(Object bean, Map<String, ? extends Object> properties) throws IllegalAccessException, InvocationTargetException {
         *      BeanUtilsBean.getInstance().populate(bean, properties);
         * }
         * <p>
         * 解釋:
         * populate(Object bean, Map<String, ? extends Object> properties) : 將map集合轉換成java對象
         * Object bean : 要封裝的java對象
         * Map<String, ? extends Object> properties : 請求參數
         * 注意:String[]是Object的子類
         * </p>
         */
        Map<String, String[]> map  = request.getParameterMap();
        User                  user = new User();

        try {
            BeanUtils.populate(user, map);
            System.out.println(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

6.4 自定義beanutils工具類

register註冊頁面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>註冊</title>
</head>
<body>
<form action="/firstjsp/register" method="post">
    賬戶:<input type="text" name="username"/><br>
    密碼:<input type="text" name="password"/><br>
    年齡:<input type="text" name="age"/><br>
    <button type="submit">註冊</button>
</form>
</body>
</html>
RegisterServlet
package com.mylifes1110.java.servlet;

import com.mylifes1110.java.bean.User;
import com.mylifes1110.java.utils.MyBeanUtils;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;

@WebServlet(name = "RegisterServlet", value = "/register")
public class RegisterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //map轉換爲user對象
        Map<String, String[]> map = request.getParameterMap();
        User user = new User();
        try {
            MyBeanUtils.populate(user, map);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        System.out.println(user);

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }
}
自定義MyBeanUtils工具類
package com.mylifes1110.java.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.util.Map;

/**
 * 自定義MyBeanUtils工具類
 */
public class MyBeanUtils {

    /**
     * 將map集合中的請求參數值封裝到對象t中
     *
     * @param t   傳入的泛型對象
     * @param map 鍵:參數名稱;值:一組參數值
     * @param <T> 自定義泛型
     */
    public static <T> void populate(T t, Map<String, ? extends Object> map)
            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        // 獲取泛型對象的Class對象
        Class<?> tClass = t.getClass();

        // 獲取對應對象的所有方法對象
        Field[] fields = tClass.getDeclaredFields();

        // 遍歷所有方法對象
        for (Field field : fields) {

            // 獲取方法名稱
            String fieldName = field.getName();

            // 獲取set方法名稱
            String methodName = "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);

            // 獲取對應的set方法類型
            Class<?> type = field.getType();

            // 獲取對應的set方法
            Method method = tClass.getMethod(methodName, type);

            // 判斷對應set方法是否爲空
            if (method != null) {

                // 獲取對應方法參數值(參數類型)
                Object o = map.get(fieldName);

                // 參數值不爲空
                if (o != null) {

                    // 把自身本應該是String類型參數值(此時是Object類型)強轉
                    String[] str = (String[]) o;

                    // 如果參數類型是Integer類型
                    if (type.getName().equals("java.lang.Integer")) {

                        // 把參數值轉換爲Integer類型並執行方法
                        method.invoke(t, Integer.parseInt(str[0]));
                    } else {

                        // 參數爲String類型直接執行方法
                        method.invoke(t, str[0]);
                    }
                }
            }
        }
    }
}

七、MVC模式

7.1 什麼是MVC模式

首先要需要知道MVC模式並不是Java Web項目中獨有的,MVC是一種軟件工程中的一種設計模式,把軟件系統分爲三個基本部分:模型(Model)、視圖(View)和控制器(Controller),即爲MVC。它是一種軟件設計的典範,最早爲Trygve Reenskaug提出,爲施樂帕羅奧多研究中心(Xerox PARC)的Smalltalk語言發明的一種軟件設計模式。

7.2 MVC模式詳解

雖然MVC並不是Java當中獨有的,但是現在幾乎所有的B/S的架構都採用了MVC框架模式。

  • Controller(控制器):控制器即是控制請求的處理邏輯,對請求進行處理,負責請求轉發和重定向;
  • View(視圖): 視圖即是用戶看到並與之交互的界面,比如HTML(靜態資源),JSP(動態資源)等等;
  • Model(模型): 模型代表着一種企業規範,就是業務流程/狀態的處理以及業務規則的規定。業務流程的處理過程對其他層來說是不透明的,模型接受的請求,並返回最終的處理結果。業務模型的設計可以說是MVC的核心。

7.3 什麼是MVC架構模型

  • 在“三層架構”中,爲了面向對象編程,將各層傳遞的數據封裝成實體類,便於數據傳遞和提高可讀性
  • MVC(模型Model-視圖View-控制器Controller)模式中,Model代表模型,是業務流程**/**狀態的處理以及業務規則的制定,接受視圖請求的數據,並返回最終的處理結果。業務模型的設計可以說是MVC最主要的核心

在這裏插入圖片描述

7.4 MVC架構和三層架構的區別

7.4.1 架構模式思想

首先,我們要認識到區分層次的目的即爲了“高內聚低耦合”的思想。

同樣是架構級別的,相同的地方在於他們都有一個表現層,但是他們不同的地方在於其他的兩個層。

在三層架構中沒有定義Controller的概念。這是最不同的地方。而MVC也沒有把業務的邏輯訪問看成兩個層,這是採用三層架構或MVC搭建程序最主要的區別。當然了。在三層中也提到了Model,但是三層架構中Model的概念與MVC中Model的概念是不一樣的,“三層”中典型的Model層是由業務邏輯與訪問數據組成的。而MVC裏,則是以實體類構成的。

7.4.2 剖析架構主體

MVC架構主體:

Model(模型層),主要負責處理業務邏輯以及數據庫的交互

View(視圖層),主要負責顯示數據和提交數據

Controller(控制層),主要是用作輔助捕獲請求並控制請求轉發

附:MVC 分層有助於管理複雜的應用程序,因爲您可以在一個時間內專門關注一個方面。例如,您可以在不依賴業務邏輯的情況下專注於視圖設計。同時也讓應用程序的測試更加容易。

三層架構主體:

UI(界面層/表示層),主要功能是顯示數據和接受傳輸用戶的數據,可以在爲網站的系統運行提供交互式操作界面,表示層的應用方式比較常見,例如Windows窗體和Web頁面。

BLL(業務邏輯層),將用戶的輸入信息進行甄別處理,分別保存。建立新的數據存儲方式,在存儲過程中對數據進行讀取,將“商業邏輯”描述代碼進行包含。

DAL(數據訪問層),數據訪問層在作業過程中訪問數據系統中的文件,實現對數據庫中數據的讀取保存操作。

附:三層架構軟件系統爲用戶的數據傳輸、提取、儲存創造了便利條件。在應用數據時,信息劃分架構開發項目,對各層次之間的工作職責進行清晰規劃,這樣就降低了網站系統的維護風險。

7.4.3 架構和模式劃分

架構劃分:

  • 三層架構是基於業務邏輯來分的;而MVC是基於頁面來分的。
  • 三層架構是一種軟件架構,通過接口實現編程;而MVC架構是一種複合設計模式,一種解決方案

模式劃分:

  • 三層架構模式是體系結構模式;而MVC架構模式是設計模式
  • 三層架構模式又可歸於部署模式;而MVC架構模式可歸於表示模式
7.4.4 架構和設計模式的區別

框架、設計模式這兩個概念總容易被混淆,其實它們之間還是有區別的。框架通常是代碼重用,而設計模式是設計重用,架構則介於兩者之間,部分代碼重用,部分設計重用,有時分析也可重用。

在軟件生產中有三種級別的重用: 內部重用,即在同一應用中能公共使用的抽象塊;代碼重用,即將通用模塊組合成庫或工具集,以便在多個應用和領域都能使用;應用框架的重用,即爲專用領域提供通用的或現成的基礎結構,以獲得最高級別的重用性。

框架與設計模式雖然相似,但卻有着根本的不同。設計模式是對在某種環境中反覆出現的問題以及解決該問題的方案的描述,它比框架更抽象;框架可以用代碼表示,也能直接執行或複用,而對模式而言只有實例才能用代碼表示;設計模式是比框架更小的元素,一個框架中往往含有一個或多個設計模式,框架總是針對某一特定應用領域,但同一模式卻可適用於各種應用。可以說,框架是軟件,而設計模式是軟件的知識。

7.5 基於MAC的三層架構實現

雖然MVC把程序分成三部分,每個部分負責不同的功能,但是這只是邏輯的分離,實際代碼並沒有真正分離,特別是Model(包括業務、數據訪問和實體類、工具類等)部分的代碼,爲了增強代碼的維護性和降低代碼耦合性,需要把代碼分層管理,於是就有了三層架構:分別是web層(表示|界面層)service層(業務邏輯層)dao層(數據訪問層)

注意:web層對應MVC中的Servlet和JSP;而其他層都屬於MVC中的Model

在這裏插入圖片描述

7.6 MAC高級框架應用

MVC模式被廣泛用於Java的各種框架中,比如Struts2、Spring MVC等等都用到了這種思想。

Struts2是基於MVC的輕量級的web應用框架。基於MVC,說明基於Struts2開發的Web應用自然就能實現MVC,也說明Struts2着力於在MVC的各個部分爲我們的開發提供相應幫助。

八、分頁

8.1 生活中的分頁

我們在生活中到處課件分頁,各種瀏覽器、查詢系統、電商系統的商品展示等等所有領域的訪問數據千千萬,它都是用分頁來顯示的!我這裏舉例貼圖一下,那麼問題來了爲什麼要分頁顯示呢?

在這裏插入圖片描述

8.2 爲什麼要有分頁?

如果沒有使用分頁查詢的話,存在三個問題:

  • 瀏覽器的加載數據過多,容易導致瀏覽器崩潰
  • 查詢數據庫的數據量過大,查詢時間會非常長
  • 數據庫查詢時間長,用戶等待的時間也就變得很長,用戶使用產品的體驗效果差

8.3 分頁的分類

分頁的分類也有兩種:邏輯分頁物理分頁

8.3.1 什麼是邏輯分頁?

概念:一次性將所有數據查詢出來,保存到List集合中,後續,如果有分頁請求,再對List集合進行拆分

8.3.1.1 邏輯分頁的優缺點
  • 優點:減少了操作數據庫的次數
  • 缺點:單次查詢數據庫的時間過長
8.3.2 什麼是物理分頁?(常用)

不是一次性將所有數據全部查詢出來。查詢第一頁:發送一條查詢10條的SQL語句。查詢下 一頁數據:又發送一條查詢後10條的SQL語句

8.3.2.1 物理分頁的優缺點
  • 優點:單次查詢數據庫的時間非常短
  • 缺點:操作數據庫的次數增加
8.3.2.2 物理分頁SQL語句實現

分頁的SQL語句如下:

  • 第一個?:開始查詢索引(從0開始)
  • 第二個?:一頁顯示多少條數據,也就是單次查詢多少條數據
select * from 表名 limit ? , ?;
8.3.2.3 SQL語句分頁舉例

查詢員工表,要求每頁顯示10條員工數據

假設有100條員工數據,每頁顯示10條員工數據,分出的頁數就爲10頁;

假設有101條員工數據,每頁顯示10條員工數據,分出的頁數就爲11頁;

注意: 最後1頁的數據我們不可能棄掉,也必須得單佔一頁進程承載該數據!

再次注意: SQL語句中是使用LIMIT來進行分頁操作的,分頁操作的起始索引爲0

-- 第一頁顯示第一個10條數據(查詢10條);開始索引爲0
-- 從索引爲0的數據開始,向後查10條數據
SELECT * FROM employee LIMIT 0 , 10;

-- 第二頁顯示從第11條數據開始到第20條;開始索引爲10
SELECT * FROM employee LIMIT 10 , 10;

-- 第三頁顯示從第21條數據開始到第30條;開始索引爲20
SELECT * FROM employee LIMIT 20 , 10;

-- 第四頁顯示從第31條數據開始到第40條;開始索引爲30
SELECT * FROM employee LIMIT 30 , 10;

8.1 分頁查詢流程分析與問題

8.1.1 分頁的兩種情況

假設數據有N條,要求每頁有x條數據,進行分頁處理有兩種情況如下:

  1. 當N除以x整除時,也就是意味着我們分了N/x頁,每頁顯示數據平均爲10條,不多不少
  2. 當N除以x有餘數時,也就是意味着我們分了N/x頁,前面的N/x-1頁每頁顯示數據平均爲10條,而最後一頁顯示餘數頁
8.1.2 分頁的流程步驟
  1. 確定每頁顯示的數據條數
  2. 確定分頁顯示所需的總頁數(數據庫中的總數據條數)
  3. 編寫SQL查詢語句,實現數據查詢
  4. 編寫JSP頁面代碼進行分頁功能顯示
8.1.3 分頁查詢在Web項目中的一些問題

問題一: 當瀏覽器發起分頁請求時,瀏覽器需要傳遞什麼參數給服務器?

Answer: 當前頁數

問題二: 當服務器響應瀏覽器時,服務器需要傳遞什麼參數給瀏覽器?

Answer: 都是瀏覽器需要的數據;如下:

  • 當前頁數(currentPage)
  • 總頁數(totalPage)
  • 總記錄數(totalSize)
  • 每頁記錄數(pageSize)
  • 當前頁數據(list)

問題三: 當服務器向瀏覽器響應上面的五個參數時,是將五個參數作爲整體傳遞還是獨立傳遞?

Answer: 將五個參數封裝成一個Bean對象,來進行域中的存儲與傳遞

  • 服務器向瀏覽器傳遞參數,無非是通過域!
  • 如果是獨立傳遞,那麼就需要在域中存儲五個參數(currentPage、totalPage、totalSize、pageSize、list)會給我們帶來很大的不便
  • 如果是整體傳遞,那麼只需要在域中存儲一個參數(封裝好的PageBean對象)
8.1.4 分頁查詢的綜合案例

登錄賬號、密碼正確後顯示執行效果圖如下:
注意: 指定頁數跳轉需要使用到Java Script的方法實現、過濾非法頁數,所以在此JSP章節先不施加代碼和展開講解
再次注意: 下方代碼實現,注意的點與流程解釋我適當的在標題處做了內容註釋!

在這裏插入圖片描述

IDEA架構與jar包

在這裏插入圖片描述

庫表操作
use temp;
create table user
(
    id       int auto_increment
        primary key,
    username varchar(30) null,
    password varchar(30) not null,
    constraint username
        unique (username)
);
c3p0.properties
    c3p0.driverClass=com.mysql.jdbc.Driver
    c3p0.jdbcUrl=jdbc:mysql://localhost:3306/temp
    c3p0.user=root
    c3p0.password=Mylifes1110
連接池工具類DBUtils
    package com.mylifes1110.java.utils;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    /**
     * 連接池工具類
     */
    public class DBUtils {
        private static ComboPooledDataSource dataSource;
    
        static {
            dataSource = new ComboPooledDataSource();
        }
    
        public static ComboPooledDataSource getDataSource() {
            return dataSource;
        }
    }
實體類User
    package com.mylifes1110.java.bean;
    
    /**
     * User實體類
     */
    public class User {
        private Integer id;
        private String  username;
        private String  password;
    
        public User() {}
    
        public User(Integer id, String username, String password) {
            this.id       = id;
            this.username = username;
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + '}';
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    }
登錄頁面login.jsp
    <%--
      Created by IntelliJ IDEA.
      User: Ziph
      Date: 2020/4/30
      Time: 19:30
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>登錄頁面</title>
    </head>
    <body>
    <font color="red"><b>${error}</b></font>
    <form action="${pageContext.request.contextPath}/user" method="post">
        <input type="hidden" name="methodName" value="login">
        賬號:<input type="text" name="username"><br>
        密碼:<input type="text" name="password"><br>
        <button type="submit">登錄</button>
    </form>
    </body>
    </html>
分頁查詢顯示頁面index.jsp
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--
      Created by IntelliJ IDEA.
      User: Ziph
      Date: 2020/4/30
      Time: 19:13
      To change this template use File | Settings | File Templates.
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>分頁查詢顯示主頁</title>
        <style>
            a {
                text-decoration: none;
            }
    
            #inputPage {
                width: 40px;
            }
            .top_div {
                position: relative;
                top: 5px;
            }
        </style>
    </head>
    <body>
    <div class="top_div">
        歡迎~${sessionScope.user.username}&nbsp;&nbsp;
        <a href="${pageContext.request.contextPath}/user?methodName=logout">註銷</a>
    </div>
    <br>
    <font color="red"><b>${logoutError}</b></font>
    <table border="1px" cellspacing="0px" cellpadding="10px" width="600px" height="200px">
        <tr>
            <td><b>ID</b></td>
            <td><b>賬號</b></td>
            <td><b>密碼</b></td>
        </tr>
        <c:forEach items="${pageBean.list}" var="user">
            <tr>
                <td>${user.id}</td>
                <td>${user.username}</td>
                <td>${user.password}</td>
            </tr>
        </c:forEach>
        <tr>
            <td colspan="3" align="center">
                <c:if test="${pageBean.currentPage != 1}">
                    <a href="${pageContext.request.contextPath}/user?methodName=selectUserListByPage&currentPage=1">[首頁]</a>
                    <a href="${pageContext.request.contextPath}/user?methodName=selectUserListByPage&currentPage=${pageBean.currentPage - 1}">上一頁</a>
                </c:if>
                <c:forEach var="i" begin="1" end="${pageBean.totalPage}" step="1">
                    <a href="${pageContext.request.contextPath}/user?methodName=selectUserListByPage&currentPage=${i}">${i}</a>
                </c:forEach>
                <c:if test="${pageBean.currentPage != pageBean.totalPage}">
                    <a href="${pageContext.request.contextPath}/user?methodName=selectUserListByPage&currentPage=${pageBean.currentPage + 1}">下一頁</a>
                    <a href="${pageContext.request.contextPath}/user?methodName=selectUserListByPage&currentPage=${pageBean.totalPage}">[尾頁]</a>
                </c:if>
                <input type="text" name="inputPage" id="inputPage">
                <button type="submit" name="inputPage">跳轉</button>
                第${pageBean.currentPage}/${pageBean.totalPage}頁
            </td>
        </tr>
    </table>
    </body>
    </html>
封裝好的PageBean對象
    package com.mylifes1110.java.bean;
    
    import java.util.List;
    
    /**
     * 分頁對象
     * @param <T> 可以傳入任何對象進行分頁處理
     */
    public class PageBean<T> {
        private Integer currentPage;    // 當前頁數
        private Integer totalPage;      // 總頁數
        private Integer totalSize;      // 總數據條數
        private Integer pageSize;       // 每頁數據條數
        private List<T> list;           // 當前頁數據
    
        public PageBean() {}
    
        public PageBean(Integer currentPage, Integer totalPage, Integer totalSize, Integer pageSize, List<T> list) {
            this.currentPage = currentPage;
            this.totalPage   = totalPage;
            this.totalSize   = totalSize;
            this.pageSize    = pageSize;
            this.list        = list;
        }
    
        @Override
        public String toString() {
            return "PageBean{" + "currentPage=" + currentPage + ", totalPage=" + totalPage + ", totalSize=" + totalSize
                   + ", pageSize=" + pageSize + ", list=" + list + '}';
        }
    
        public Integer getCurrentPage() {
            return currentPage;
        }
    
        public void setCurrentPage(Integer currentPage) {
            this.currentPage = currentPage;
        }
    
        public List<T> getList() {
            return list;
        }
    
        public void setList(List<T> list) {
            this.list = list;
        }
    
        public Integer getPageSize() {
            return pageSize;
        }
    
        public void setPageSize(Integer pageSize) {
            this.pageSize = pageSize;
        }
    
        public Integer getTotalPage() {
            return totalPage;
        }
    
        public void setTotalPage(Integer totalPage) {
            this.totalPage = totalPage;
        }
    
        public Integer getTotalSize() {
            return totalSize;
        }
    
        public void setTotalSize(Integer totalSize) {
            this.totalSize = totalSize;
        }
    }
通用Servlet
    package com.mylifes1110.java.controller;
    
    import java.io.IOException;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 通用Servlet
     */
    @WebServlet(
        name  = "BeanServlet",
        value = "/bean"
    )
    public class BeanServlet extends HttpServlet {
        protected void service(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            String methodName = request.getParameter("methodName");
    
            try {
                Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
    
                if (method != null) {
                    String returnValue = (String) method.invoke(this, request, response);
    
                    if (returnValue != null) {
                        int index = returnValue.lastIndexOf(":");
    
                        if (index == -1) {
                            request.getRequestDispatcher(returnValue).forward(request, response);
                        } else {
                            String path = returnValue.substring(index + 1);
    
                            if (returnValue.startsWith("redirect")) {
                                response.sendRedirect(request.getContextPath() + path);
                            } else if (returnValue.startsWith("forward")) {
                                request.getRequestDispatcher(path).forward(request, response);
                            }
                        }
                    }
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
UserServlet
  • 處理當前頁數

  • 獲取分頁對象PageBean

  • 頁面跳轉

    package com.mylifes1110.java.controller;
    
    import java.lang.reflect.InvocationTargetException;
    
    import java.sql.SQLException;
    
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.commons.beanutils.BeanUtils;
    
    import com.mylifes1110.java.bean.PageBean;
    import com.mylifes1110.java.bean.User;
    import com.mylifes1110.java.service.UserService;
    import com.mylifes1110.java.service.UserServiceImpl;
    
    /**
     * User相關Servlet請求處理
     */
    @WebServlet(
        name  = "UserServlet",
        value = "/user"
    )
    public class UserServlet extends BeanServlet {
        private UserService userService = new UserServiceImpl();
    
        /**
         * 登錄
         *
         * @param request  請求對象
         * @param response 響應對象
         * @return 返回相應重定向或請求轉發地址
         */
        public String login(HttpServletRequest request, HttpServletResponse response) {
            User loginUser = new User();
    
            try {
                BeanUtils.populate(loginUser, request.getParameterMap());
    
                User checkUser = userService.login(loginUser);
    
                if (checkUser != null) {
                    request.getSession().setAttribute("user", checkUser);
    
                    return "/user?methodName=selectUserListByPage";
                } else {
                    request.setAttribute("error", "賬號或密碼錯誤!");
    
                    return "/login.jsp";
                }
            } catch (IllegalAccessException | InvocationTargetException | SQLException e) {
                e.printStackTrace();
            }
    
            return "/login.jsp";
        }
    
        /**
         * 註銷
         * @param request 請求對象
         * @param response 響應對象
         * @return 返回註銷成功與失敗的重定向和請求轉發地址
         */
        public String logout(HttpServletRequest request, HttpServletResponse response) {
            try {
                request.getSession().invalidate();
    
                return "redirect:/login.jsp";
            } catch (Exception e) {
                e.printStackTrace();
            }
    
            request.setAttribute("logoutError", "註銷失敗!");
    
            return "/index.jsp";
        }
    
        /**
         * 分頁查詢
         *
         * @param request  請求對象
         * @param response 響應對象
         * @return 返回相應重定向或請求轉發地址
         */
        public String selectUserListByPage(HttpServletRequest request, HttpServletResponse response) {
            String  currentPageStr = request.getParameter("currentPage");
            Integer currentPage    = getCurrentPage(currentPageStr);
    
            try {
                PageBean<User> pageBean = userService.selectUserListByPage(currentPage);
    
                request.setAttribute("pageBean", pageBean);
    
                return "/index.jsp";
            } catch (SQLException throwables) {
                throwables.printStackTrace();
            }
    
            return "/login.jsp";
        }
    
        /**
         * 獲取當前頁數
         *
         * @param currentPageStr 字符串類型的當前頁數
         * @return 返回Integer類型的當前頁數
         */
        public Integer getCurrentPage(String currentPageStr) {
            if (currentPageStr == null) {
    
                // 如果沒有傳遞當前頁數,默認第一頁
                currentPageStr = "1";
            }
    
            Integer currentPage = Integer.parseInt(currentPageStr);
    
            return currentPage;
        }
    }
訪問資源登錄校驗LoginFilter

一般登錄校驗的過濾器我們知道是要判斷是否在登錄狀態下的,通過取出域中的實體類對象是否爲空判斷。但是每一個Servlet都會經過Filter過濾,當我們訪問沒有在登錄狀態下的登錄頁面時,它本應該是跳轉Servlet進行請求處理,但是Servlet被Filter判斷爲不在登錄狀態而攔截反手就又是一個重定向到了登陸頁面,這種情況就像遞歸沒有出口一樣,無限的訪問下去,沒有盡頭!

爲了解決這個問題,我們還需要判斷一下路徑是否包含登錄頁面的login關鍵字,如果包含此關鍵字就執行放行。如果沒有包含關鍵字,再進一步去判斷取出域中的實體類對象是否爲空。如果爲空,證明不在登錄狀態,則重定向到登錄頁面讓用戶進行登錄;反之,如果不爲空,證明在登陸狀態,則直接放行,讓它回到Servlet中進行請求處理!

    package com.mylifes1110.java.filter;
    
    import java.io.IOException;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    /**
     * 訪問資源的登錄校驗
     */
    @WebFilter(
        filterName = "LoginFilter",
        value      = "/*"
    )
    public class LoginFilter implements Filter {
        public void destroy() {}
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
                throws ServletException, IOException {
            HttpServletRequest  request    = (HttpServletRequest) req;
            HttpServletResponse response   = (HttpServletResponse) resp;
            String              uri        = request.getRequestURI();
            String              methodName = request.getParameter("methodName");
    
            if (uri.contains("login") || ((methodName != null) && methodName.equals("login"))) {
                chain.doFilter(request, response);
            } else {
                Object checkUser = request.getSession().getAttribute("user");
    
                if (checkUser == null) {
                    response.sendRedirect(request.getContextPath() + "/login.jsp");
                } else {
                    chain.doFilter(request, response);
                }
            }
        }
    
        public void init(FilterConfig config) throws ServletException {}
    }
Dao層接口
    package com.mylifes1110.java.dao;
    
    import java.sql.SQLException;
    
    import java.util.List;
    
    import com.mylifes1110.java.bean.User;
    
    public interface UserDao {
        User login(User loginUser) throws SQLException;
    
        Integer selectTotalSize() throws SQLException;
    
        List<User> selectUserListByPage(Integer beginIndex, Integer pageSize) throws SQLException;
    }
Dao層實現類
  • 獲取總記錄數
  • 獲取當前頁數據
    package com.mylifes1110.java.dao;
    
    import java.sql.SQLException;
    
    import java.util.List;
    
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    
    import com.mylifes1110.java.bean.User;
    import com.mylifes1110.java.utils.DBUtils;
    
    public class UserDaoImpl implements UserDao {
        @Override
        public User login(User loginUser) throws SQLException {
            return new QueryRunner(DBUtils.getDataSource()).query("select * from user where username = ? and password = ?",
                                                                  new BeanHandler<User>(User.class),
                                                                  loginUser.getUsername(),
                                                                  loginUser.getPassword());
        }
    
        /**
         * 獲取集合中總記錄數
         * @return 返回集合中的總記錄數
         */
        @Override
        public Integer selectTotalSize() throws SQLException {
            return new QueryRunner(DBUtils.getDataSource()).query("select * from user",
                                                                  new BeanListHandler<User>(User.class))
                                                           .size();
        }
    
        @Override
        public List<User> selectUserListByPage(Integer beginIndex, Integer pageSize) throws SQLException {
            return new QueryRunner(DBUtils.getDataSource()).query("select * from user limit ?, ?",
                                                                  new BeanListHandler<User>(User.class),
                                                                  beginIndex,
                                                                  pageSize);
        }
    }
Service層接口
    package com.mylifes1110.java.service;
    
    import java.sql.SQLException;
    
    import com.mylifes1110.java.bean.PageBean;
    import com.mylifes1110.java.bean.User;
    
    public interface UserService {
        User login(User loginUser) throws SQLException;
    
        PageBean<User> selectUserListByPage(Integer currentPage) throws SQLException;
    }
Service層實現類
  • 設置當前頁數(currentPage)
  • 設置總記錄數(totalSize)
  • 設置每頁記錄數(pageSize)
  • 設置總頁數(totalPage)
    • 總頁數 = (總記錄數 % 每頁記錄數 == 0) ? 總記錄數/ 每頁記錄數 : 總記錄數/ 每頁記錄數 + 1;
  • 設置當前頁數據(list)
    • begin = (currentPage - 1) * pageSize
    package com.mylifes1110.java.service;
    
    import java.sql.SQLException;
    
    import java.util.List;
    
    import com.mylifes1110.java.bean.PageBean;
    import com.mylifes1110.java.bean.User;
    import com.mylifes1110.java.dao.UserDao;
    import com.mylifes1110.java.dao.UserDaoImpl;
    
    public class UserServiceImpl implements UserService {
        private UserDao userDao = new UserDaoImpl();
    
        @Override
        public User login(User loginUser) throws SQLException {
            User user = userDao.login(loginUser);
    
            return user;
        }
    
        @Override
        public PageBean<User> selectUserListByPage(Integer currentPage) throws SQLException {
            PageBean<User> pageBean = new PageBean<>();
    
            // 當前頁數
            pageBean.setCurrentPage(currentPage);
    
            Integer totalSize = userDao.selectTotalSize();
    
            // 數據庫總記錄數
            pageBean.setTotalSize(totalSize);
    
            // 每頁記錄數
            Integer pageSize = 5;
    
            pageBean.setPageSize(pageSize);
    
            // 總頁數
            // 總頁數 = 總記錄數 / 每頁記錄數
            Integer totalPage = (totalSize % pageSize == 0)
                                ? totalSize / pageSize
                                : totalSize / pageSize + 1;
    
            /*
             * Integer totalPage = 0;
             * if (totalSize % pageSize == 0) {
             * /            可以整除
             *   totalPage = totalSize / pageSize;
             * } else {
             * /            不可以整除
             *   totalPage = totalSize / pageSize + 1;
             * }
             */
            pageBean.setTotalPage(totalPage);
    
            /**
             * 當前頁數據
             * select * from user limit ?, ?;
             * 第一個?:開始索引 = (當前頁數 - 1) * 每頁記錄數
             * 第二個?:每頁記錄數pageSize
             */
            Integer    beginIndex = (currentPage - 1) * pageSize;
            List<User> list       = userDao.selectUserListByPage(beginIndex, pageSize);
    
            pageBean.setList(list);
    
            return pageBean;
        }
    }

九、總結

這難道不是總結,總結的還不夠全面?希望此文章能幫到你,能幫你解決學習中的疑惑!還請大家多多支持點贊、評論!如果有問題,可以評論,我隨時恭候你的光臨大家,看到評論的我會第一時間儘自己全力爲你排疑解難!

大家別忘了點贊!你靈活的小手將是我最大的動力!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章