jsp技术基础

 

 


前言

一、JSP概述

1.1 Servlet使用的不足

Servlet是一个动态网页技术,客户端通过请求Servlet类可以相应给客户端一个动态网页,但是Servlet在使用过程中有什么不足之处呢?

  • 开发方式麻烦:继承HttpServlet父类、重写doGet/doPost、Servlet配置

  • 项目更新麻烦:Servlet类中的代码发生改变,需要重新编译、部署、启动Tomcat

  • 网页呈现复杂:需要进行HTML标签拼接,同时要通过输出流逐行打印

  • 协同开发困难:UI负责页面美化,但是页面是由Servlet类提供,如果UI不懂Java、则不能完成Servlet响应的页面的优化

1.2 JSP简介

JSP (Java Server Page) 基于Servlet技术的、运行在服务器之上、支持Java语言的动态网页技术。

背景:JSP简化了Servlet的设计,采用在HTML标签中嵌套代码的形式进行动态网页的呈现,用于高效开发web应用的动态网页。

作用:替换显示页面部分的Servlet(使用*.jsp网页文件替换*PageServlet.java类)

二、JSP入门案例

JSP入门案例流程:
6ddb0b4d19024808915c9158d4ed060e.png

2.1 案例准备

2.1.1 创建数据库数据表

  • 创建数据库 db_jsp

  • 创建图书信息表

create table books(
   book_id char(6) primary key,
     book_name varchar(50) not null,
     book_author varchar(20) not null,
     book_price DECIMAL(10,2),
     book_img_path varchar(100) not null,
     book_desc varchar(200),
     book_type int not null 
);

2.1.2 创建web项目

JSP必须依赖于服务器运行,因此只能在web应用中使用JSP技术

web项目名称jsp-demo1

2.1.3 完成JDBC准备

  • 导入jar包:mysql驱动、druid.jar、apache commons dbutils

  • 创建com.qfedu.jsp.utils包,在包中创建druid.properties文件配置连接池参数

    # 数据库连接信息
    driverClassName=com.mysql.cj.jdbc.Driver
    url=jdbc:mysql://localhost:3306/db_jsp?characterEncoding=utf8
    username=root
    password=@QFedu123
    ​
    # 连接池属性
    # 连接池的初始化连接数<创建数据库连接池时默认初始化的连接的个数>
    initialSize=10
    # 连接池的最大连接数
    maxActive=50
    # 最小空闲连接数(当数据库连接使用率很低时,连接池中的连接会被释放一部分)
    minIdle=5
    # 超时等待时间(单位:ms)
    maxWait=30000
  • 在utils包中连接池工具类DruidUtils

    package com.qfedu.jsp.utils;
    ​
    import com.alibaba.druid.pool.DruidDataSource;
    import com.alibaba.druid.pool.DruidDataSourceFactory;
    ​
    import javax.sql.*;
    import java.io.InputStream;
    import java.sql.*;
    import java.util.Properties;
    ​
    /**
     * @Description 数据库连接池工具类
      @Author 小温
     */
    public class DruidUtils {
    ​
        private static DruidDataSource druidDataSource;
    ​
        static{
            try {
                InputStream is = DruidUtils.class.getResourceAsStream("druid.properties");
                Properties properties = new Properties();
                properties.load(is);
                druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    ​
        /**
         * 获取数据库连接池数据源对象
         * @return
         */
        public static DataSource getDataSource(){
            return druidDataSource;
        }
    ​
        /**
         * 从数据库连接池中获取数据库连接对象
         * @return
         */
        public static Connection getConnection(){
            Connection connection = null;
            try {
                connection = druidDataSource.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }
    ​
    }

2.2 完成案例的数据库操作

2.2.1 创建实体类

  • 创建com.qfedu.jsp.dto

  • 创建实体类

    package com.qfedu.jsp.dto;
    ​
    /**
     * @Description 图书信息实体类
     * @Author 小温
     */
    public class Book {
    ​
        private String bookId;
        private String bookName;
        private String bookAuthor;
        private double bookPrice;
        private String bookImgPath;
        private String bookDesc;
        private int bookType;
    ​
    }

2.2.2 创建DAO类完成操作

  • 创建com.qfedu.jsp.dao

  • 创建BookDAO类,完成查询操作

    package com.qfedu.jsp.dao;
    ​
    import com.qfedu.jsp.dto.Book;
    import com.qfedu.jsp.utils.DruidUtils;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanListHandler;
    ​
    import java.sql.SQLException;
    import java.util.List;
    ​
    /**
     * @Description
     *@Author 小温
     */
    public class BookDAO {
    ​
        public List<Book> listBooks(){
            List<Book> bookList = null;
            try {
                String sql = "select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_type bookType from books";
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                bookList = queryRunner.query(sql, new BeanListHandler<Book>(Book.class));
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return bookList;
        }
        
    }

2.3 JSP呈现动态网页

2.3.1 创建BookListServlet

  • 创建BookListServlet类,接收用户请求

  • 调用BookDAO查询图书信息,并将数据转发到 book-list.jsp

    package com.qfedu.jsp.servlets;
    ​
    /**
     * @Description 接收客户端请求场、查询图书信息,将图书信息转发到一个JSP文件进行显示
     * @Author 小温
     */
    @WebServlet("/BookListServlet")
    public class BookListServlet extends HttpServlet {
    ​
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    ​
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //1.调用BookDAO查询图书信息
            BookDAO bookDAO = new BookDAO();
            List<Book> bookList = bookDAO.listBooks();
    ​
            //2.将数据转发到book-list.jsp进行动态显示
            request.setAttribute("bookList",bookList);
            request.getRequestDispatcher("book-list.jsp").forward(request,response);
        }
    }

2.3.2 创建JSP页面

  • 在项目的web目录下右键 --- 新建 --- JSP --- 输入名称book-list.jsp --- OK

  • book-list.jsp进行网页界面设计(HTML+CSS+JS)

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
    ​
            <table width="80%" align="center" border="1" cellspacing="0">
                <caption>图书信息列表</caption>
                <tr>
                    <th>图书ID</th>
                    <th>图书名称</th>
                    <th>作者</th>
                    <th>价格</th>
                    <th>封面</th>
                    <th>描述</th>
                    <th>类型</th>
                </tr>
                <tr>
                    <td>10001</td>
                    <td>Java</td>
                    <td>张三</td>
                    <td>11.11</td>
                    <td>files/aaa.jpg</td>
                    <td>这本书真香</td>
                    <td>1</td>
                </tr>
            </table>
    ​
        </body>
    </html>

2.3.3 在JSP页面中显示动态数据

  • 在JSP页面文件中,通过Java代码接收图书信息,并遍历显示在HTML标签中

<%@ page import="java.util.List" %>
<%@ page import="com.qfedu.jsp.dto.Book" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
​
        <table width="80%" align="center" border="1" cellspacing="0">
            <caption>图书信息列表</caption>
            <tr>
                <th>图书ID</th>
                <th>图书名称</th>
                <th>作者</th>
                <th>价格</th>
                <th>封面</th>
                <th>描述</th>
                <th>类型</th>
            </tr>
            <%-- 在JSP中可以写Java代码,但是代码必须写在<%%>符号中 --%>
            <%
            //1.通过Java代码,接收BookListServlet转发时传递的 图书信息集合的数据
            List<Book> bookList = (List<Book>) request.getAttribute("bookList");
            for(int i=0; i< bookList.size() ; i++){
                //book是java代码中的变量
                Book book = bookList.get(i);
            %>
                <tr>
                    <%-- 如果需要将JSP中java代码的变量显示在HTML标签中,则需要使用<%=attr%> --%>
                    <td><%=book.getBookId() %></td>
                    <td><%=book.getBookName() %></td>
                    <td><%=book.getBookAuthor() %></td>
                    <td><%=book.getBookPrice() %></td>
                    <td><%=book.getBookImgPath() %></td>
                    <td><%=book.getBookDesc() %></td>
                    <td><%=book.getBookType() %></td>
                </tr>
            <%
            }
            %>
        </table>
​
    </body>
</html>

三、JSP开发详解

3.1 JSP和Servlet

JSP和Servlet一样可以接受客户端请求,并响应一个动态网页。

JSP是对Servlet的一种高级封装,一个JSP文件底层就是一个Servlet类。

JSP文件需要依赖服务器运行,当客户端请求一个JSP文件时,JSP文件会在服务器中转换成Servlet来执行。

98fc80c046a24020b1f1d35bb72529be.png

使用JSP的必要性:

我们将动态网页显示使用JSP完成,在HTML标签中嵌入Java代码的形式开发动态网页更为便捷。

3.2 JSP开发的语法规则

3.2.1 JSP文档规范

  • JSP文件和HTML文档一样是一个视图文件,JSP文件创建在项目的web目录

  • JSP文件以.jsp后缀名结尾

  • JSP文档内容结构:

    • 在JSP文件的第一行需要通过 <%@ page %>声明使用java语言

    • JSP文件的主体内容是一个HTML文档,符合HTML的文档规范

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

3.2.2 Java脚本

JSP页面可以嵌入java代码,java代码就是这个页面的脚本

  • java代码:在jsp中的java代码必须写在<% %>中,代码可以写在JSP文件的任何位置,而且可以包含多段代码

    <%
       java代码
    %>
  • 变量输出

    <img src="<%=attr %>"/>
  • 声明成员变量和方法:

    <%! int i = 5;%>
    
    <%! 
      public void method(){
         System.out.println("hello");  
      }  
    %>

3.2.3 JSP注释

  • HTML文档注释

    <!-- HTML文档注释:这种注释会出现在jsp编译之后的Java代码中 -->
  • JSP注释

    <%-- JSP 注释: 这种注释不会出现在编译后的java代码  --%>

3.3 JSP编译指令

编译指令:在JSP文件转换成Java代码之后,编译成.class文件的过程中执行的指令

<%@ page %> : 声明当前JSP页面在web容器中的配置、引用;

<%@ include %> : 在当前JSP中引用其他的资源(JSP\HTML)作为当前JSP的一部分;

<%@ taglib %> : 引用第三方标签库、扩展JSP文件中的标签;

3.3.1 <%@ page%>

标签属性说明示例
contentType用于声明当前JSP文档的MIME类型和字符集编码contentType="text/html;charset=UTF-8"
language定义JSP中所用的脚本语言类型,默认javalanguage="java"
import声明当前JSP中的Java代码依赖的类import="java.util.List"
pageEncoding声明当前JSP文档的解码格式pageEncoding="UTF-8"
errorPage如果当前JSP出现异常则跳转到errorPage指向页面errorPage="error.jsp"
isErrorPage定义当前页面是否可以作为错误页面isErrorPage="true"

3.3.2 <%@ include %>

在当前JSP中引用其他的资源(JSP\HTML)作为当前JSP的一部分,被引入的页面不会单独作为一个JSP编译,而是将引入的页面中的代码插入到当前JSP之后作为一个整体进行编译。

被引入的页面只需要是一个HTML片段即可。

静态引入:将被页面引入到当前JSP之后再进行整体的编译,被引入的页面不会单独编译。

  • header.jsp

    <div style="height: 100px; background: deepskyblue" >header</div>
  • footer.jsp

    <div style="height: 50px; background: lightgray" >footer</div>
  • index.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@ page import="java.util.Date"%>
    <html>
      <head>
        <title>$Title$</title>
      </head>
      <body>
       
        <%@ include file="header.jsp"%>
        <div style="height: 400px; background: orange">index</div>
        <%@ include file="footer.jsp"%>
      </body>
    </html>

3.3.3 <%@ taglib %>

引用第三方标签库、扩展JSP文件中的标签

<!--引入JSTL标签库-->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

3.4 JSP动作指令

在JSP文件中,除了支持标准的HTML标签库和编译指令之外,还支持JSP特有的动作指令(动作标签)。

动作指令:在JSP中以jsp:开头的、在JSP页面运行期间执行的指令。

3.4.1 jsp:include

<%-- 动态引入 --%>
<jsp:include page="test1.jsp"/>

动态引入JSP文件文件:被引入的JSP文件先单独编译执行,将执行的结果引入到当前JSP文件。

因为被引入的JSP页面需要独立的编译执行,因此被引入的页面需要是一个完整的JSP文件。

在动态引入的页面中不能访问主页面中定义的Java变量。

静态引入和动态引入的区别:

  • 静态引入,使用<%@include file=""%>编译指令将HTML或者JSP页面引入到当前文件,静态引入是先引入再执行,因此被引入的页面可以是一个HTML片段,也可在被引入的页面中访问主页面定义的Java变量;

  • 动态引入,使用<jsp:include page=""/>动作指令将JSP页面引入到当前文件,动态引入是先独立编译执行被引入的页面,将执行结果引入到当前页面,被引入的页面需要独立执行因此必须是一个完成的JSP,同时在被引入的JSP中不能访问主页面定义的Java变量。

3.4.2 jsp:userBean

在JSP页面中构造Java对象

<%-- 相当于 Book book = new Book(); --%>
<jsp:useBean id="book" class="com.qfedu.jsp.dto.Book"></jsp:useBean>
  • id属性, 创建的对象的变量名

  • class属性,类的全限定名

3.4.3 jsp:setProperty

给创建的Java对象属性赋值

<%-- 相当于 book.setBookId("100001")   --%>
<jsp:setProperty name="book" property="bookId" value="100001"></jsp:setProperty>
<jsp:setProperty name="book" property="bookName" value="Java"></jsp:setProperty>
  • name属性,对象的变量名

  • property属性,对象的属性名

  • values属性,属性的值

3.4.4 jsp:getProperty

获取创建的对象的值,并输出到网页

<%-- 相当于 book.getBookId(),并将获取的值输出到页面   --%>
<jsp:getProperty name="book" property="bookId"/>
  • name属性,对象的变量名

  • property属性,对象的属性名

3.4.5 jsp:forward

用于转发客户端请求

<jsp:forward page="test2.jsp"></jsp:forward>

3.4.6 jsp:param

在JSP页面转发过程中进行参数传递

<%--  从当前JSP转发到另一个JSP   --%>
<jsp:forward page="test2.jsp">
    <%-- 转发的同时携带参数  --%>
    <jsp:param name="name" value="zhangsan"/>
    <jsp:param name="sex" value="nan"/>
</jsp:forward>

3.5 JSP九大内置对象

一个JSP文件在服务器上是转换成Java文件(Servlet类)编译执行的,我们在JSP文件中嵌入的Java代码都会转换到这个Java文件的方法中(_jspService),因此这个方法的参数、方法中定义的变量以及当前类继承的父类中定义的变量,我们的代码都可以使用。

在JSP中编写Java代码可以不用创建、直接使用的对象我们称之为JSP内置对象。

对象名类型 
requestjavax.servlet.http.HttpServletRequest表示客户端请求对象,用户获取HTTP请求信息
responsejavax.servlet.http.HttpServletResponse表示服务器对客户端的响应对象,用于将JSP处理的数据响应给客户端
sessionjavax.servlet.http.HttpSession表示当前客户端与服务器的会话对象
applicationjavax.servlet.ServletContext当前web应用在服务器上的全局对象
configjavax.servlet.ServletConfig表示当前Servlet类的配置信息
pageContextjavax.servlet.jsp.PageContext当前JSP的上下文,可以获取当前JSP的任何信息
outjavax.servlet.jsp.JspWriter指向当前JSP文档的输出流
exceptionjava.lang.Throwable只有在设置了isErrorPage=“true”的JSP可使用
pagejava.lang.Object当前JSP转换的servlet类的实例,相当于this

3.6 JSP四大域对象

域对象——可以用来存取数据的对象

  • pageContext

  • request

  • session

  • application

3.6.1 pageContext

pageConext对象 只作用于当前JSP文件

57a9b499de5e4f088620f4e504716655.png

3.6.2 request

request作用于一次请求

95ee1d68c3954f37a77a473c974354f1.png

3.6.3 session

session对象作用于用户一次连接的多次请求

095cbc6b4ec240b1b3014cb861fcfbaf.png

3.6.4 application

application实际上就是servletContext对象,作用于一个web应用的所有用户

65a9356728e247b8bdfa47b2988b0d00.png

3.6.5 使用域对象传值示例

  • Servlet类

    package com.qfedu.jsp.servlets;
    /**
     * @Description
     * @Author 小温
     */
    @WebServlet("/TestServlet")
    public class TestServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req, resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            //1.分别通过 request、session、application传值
            request.setAttribute("key1","value1");
    
            HttpSession session = request.getSession();
            session.setAttribute("key2","value2");
    
            ServletContext application = getServletContext();
            application.setAttribute("key3","value3");
    
            //2.转发到test3.jsp
            request.getRequestDispatcher("test3.jsp").forward(request,response);
        }
    }
  • JSP页面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    Test3
    <hr/>
    
    <%
        String s1 = (String) request.getAttribute("key1");
        String s2 = (String) session.getAttribute("key2");
        String s3 = (String) application.getAttribute("key3");
    %>
    request取出的数据:<%=s1%> <br/>
    session取出的数据:<%=s2%> <br/>
    application取出的数据:<%=s3%> <br/>
    </body>
    </html>

3.7 JSP开发应用

9166420a2ce64e359f3b8f3a13437b9a.png

  • JSP负责项目中的视图呈现

  • Servlet负责接收、处理用户请求

  • Servlet类查询的数据转发并传递给JSP页面进行显示

注意:当将进行页面显示的Servlet类转换成jsp文件之后,要修改对应跳转的路径;同时注意修改登录过滤器的放行路径,以及未登录时要跳转到login.jsp(而不是原来的LoginPageServlet)

四、EL表达式

思考问题:JSP相较于Servlet来说,在动态网页的数据渲染方面要便捷很多,但是依然要进行HTML和Java代码的混合编程,代码的可读性和维护性依然有待提高,能不能做HTML和Java代码的完全分离呢?

4.1 什么是EL?

Expression Language 表达式语言,应用于JSP页面,可以更简单、便捷的获取page、request、session、application等作用域的值,进行渲染。

EL表达式就是替代以下代码的作用

  • pageContext.getAttribute("key");

  • request.getAttribute("key");

  • session.getAttribute("key");

  • application.getAttribute("key");

EL表达式使用示例:

  • Servlet类:

    /**
     * @Description
     *@Author 小温
     */
    @WebServlet("/TestServlet")
    public class TestServlet extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            doPost(request, response);
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            //1.传递数据
            request.setAttribute("str","Hello EL!");
            //2.转发到JSP页面
            request.getRequestDispatcher("test.jsp").forward(request,response);
    
        }
    }
  • JSP文件:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>Title</title>
        </head>
        <body>
            <%-- 使用Java代码接收数据 --%>
            <%
                String s = (String) request.getAttribute("str");
            %>
            Java脚本获取的数据:<%=s %>
    
            <%--  通过EL获取并显示TestServlet传递的数据  --%>
            EL表达式获取的数据:${str}
        </body>
    </html>

4.2 EL表达式应用

4.2.1 实体类

package com.qfedu.dto;

/**
 * @Description 图书信息实体类
 * @Author 小温
 */
public class Book {

    private String bookId;
    private String bookName;
    private String bookAuthor;
    private double bookPrice;

    //无参构造器
    //全参构造器
    //toString
    //get和set方法

}

4.2.2 TestServlet类

  • 在TestServlet类传递各种数据,并转发到test.jsp页面

package com.qfedu.servlets;

import com.qfedu.dto.Book;

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.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description
 *@Author 小温
 */
@WebServlet("/TestServlet")
public class TestServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //1.传递数据
        //简单类型
        request.setAttribute("key1",123);
        //字符串
        request.setAttribute("key2","Hello EL!");
        //对象
        request.setAttribute("key3",new Book("1001","Java","亮亮",20.00));
        //数组
        String[] arr = {"aaa","bbb","ccc"};
        request.setAttribute("key4",arr);
        //集合
        List<Book> bookList = new ArrayList<>();
        bookList.add(new Book("1001","Java","亮亮",20.00));
        bookList.add(new Book("1002","C++","张三",21.00));
        bookList.add(new Book("1003","Python","李四",22.00));
        request.setAttribute("key5",bookList);
        //Map
        Map<String,Book> map = new HashMap<>();
        map.put("a1001",new Book("1001","Java","亮亮",20.00));
        map.put("a1002",new Book("1002","C++","张三",21.00));
        map.put("a1003",new Book("1003","Python","李四",22.00));
        request.setAttribute("key6",map);

        //2.转发到JSP页面
        request.getRequestDispatcher("test.jsp").forward(request,response);

    }
}

4.2.3 test.jsp

  • 在test.jsp页面通过EL表达式获取各种类型数据

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Title</title>
    </head>
    <body>
<%--  1.接收简单类型及字符串 ${key}  --%>
    ${key1}<br/>
    ${key2}<br/>

<%--  2.接收对象数据  ${key}获取对象的toString方法输出,
      我们可以通过 ${key.attrName}获取对象属性值,通过反射调用类中属性的get方法获取属性值
       因此传递到JSP页面、使用EL表达式获取属性值的对象必须提供get方法 --%>
    ${key3}<br/>
    ${key3.bookId}<br/>
    ${key3.bookName}<br/>
    ${key3.bookAuthor}<br/>
    ${key3.bookPrice}<br/>

<%-- 3.接收数组数据  ${key[index]} --%>
    ${key4[0]}-${key4[1]}-${key4[2]}<br/>

<%-- 4.接收集合中的数据:${key[index]}
     如何集合中的元素是对象 ,可以进一步使用 ${key[index].attrName} 获取集合中对象的属性--%>
    ${key5[0].bookName}- ${key5[0].bookAuthor}<br/>
    ${key5[1].bookName}- ${key5[1].bookAuthor}<br/>
    ${key5[2].bookName}- ${key5[2].bookAuthor}<br/>

<%-- 5.接收Map中的数据: 使用${key}获取整个map
                    使用${key.mapKey} 根据可以获取元素
                    如果map中的key是以数字开头,可以使用${key['mapKey']}
     如果map中的value是对象,我们还可以进一步使用 ${key.mapKey.attrName}获取对象属性值--%>
    ${key6['a1001']}<br/>
    ${key6.a1001}<br/>
    ${key6.a1001.bookName}<br/>

    </body>
</html>

4.3 EL访问域对象

如果从Servlet分别使用request、session、application同时向JSP页面传递数据,并且key都相同;那么在JSP页面直接使用${key}获取的是什么数据呢? 如何能够获取我们想要访问的域对象中的数据呢?

a8dd1ea254294c6cad3a489970b7ef8a.png

4.3.1 ${key}获取哪个域对象的数据呢?

  • 四个域对象的访问从小到大依次是:pageContext-->request-->session-->application

  • 如果没有指定域对象,${key}默认获取最小域对象中的数据

4.3.2 如何使用EL获取指定域对象数据?

  • 在EL表达式中,分别为四个域对象各自取了一个名字

    • pageContext对象 ---> pageScope

    • request对象--->requestScope

    • session对象--->sessionScope

    • application对象--->applicationScope

  • 在JSP中如果多个域对象都有相同的key,可以通过${***Scope.key}来获取指定域对象中数据,如果获取不到则返回"",显示到页面为空白

    ${sessionScope.key}

4.4 EL的隐式对象

EL语法中提供的隐藏对象——隐式对象

除了四个域对象pageScope、requestScope、sessionScope、applicationScope之外,EL中还提供了另外七个隐式对象,分别用于获取不同的数据

隐式对象说明
param获取Rquest对象的参数,返回String, ${param.key}等价于request.getParameter("key")
paramValues获取Rquest对象传递的所有的参数值,返回字符串集合 ${paramValues}等价于request.getParameterValues()
header获取HTTP请求头 ${header.contentPosition}
headerValues获取HTTP请求头中所有的值
initParam获取上下文初始化参数
pageContext获取当前页面的pageContext对象: ${pageContext.request.contextPath}当前web项目在服务器的访问路径
cookie获取cookie中的值,${cookie.username}

4.5 EL的运算符

EL表达式不能能够从域对象获取数据,同时可以对取出的数据进行算术运算、关系比较、逻辑运算等运算

4.5.1 算术运算

运算符描述/示例
+${key1+key2} 表示根据key1获取的值然后加上key2获取的值,显示到网页
-减法
*乘法
/ or div除法, ${key/4} 等价于 ${key div 4}
% or mod取模

4.5.2 关系比较

运算符描述/示例
== or eq${key == v} 表示比较根据key获取的值是否等于v,返回结果为true/false 等价于 ${key eq v}
!= or ne不等于
> or gt大于
< or lt小于
>= or ge大于等于
<= or le小于等于

4.5.3 逻辑运算

运算符描述/示例
&& or and逻辑与,用于连接两个条件
||or or逻辑或
! or not逻辑非

4.5.4 判空

运算符描述/示例
empty${empty key} 如果key对应取出的值为空,则返回true

 

五、JSTL

如果EL表达式在JSP页面中获取的集合中的元素个数不确定,我们该如何将集合中的数据全部显示呢?

5.1 JSTL简介

JSTL (JSP Standard Tag Library) JSP标准标签库,用于扩展JSP中的标签,能够为JSP页面提供流程控制、类型转换等功能的标签。

作用:在JSP中通常是JSTL+EL的组合来进行数据的提取及渲染。

JSTL标签库提供了多类标签:

  • c ,核心标签库,提供流程控制的标签

  • fmt,转换标签库,提供了日期、数值类型转换的标签

  • sql

  • fn

  • x

5.2 JSTL的引入步骤

需要在JSP中引用JSTL标签库之后,才可以使用JSTL提供的标签

  1. 下载JSTL标签库的依赖jar https://mvnrepository.com/

    • f373f5df9e48402a84725294caefc485.png
  2. 将jar文件引入到当前web项目

  3. 在需要使用JSTL标签的JSP文件,通过<%@taglib%>引入JSTL标签库(JSTL包含多种标签,每种标签需要单独引入)

    <!--引入JSTL的核心标签库-->
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <!--引入JSTL的转换标签库-->
    <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

5.3 JSTL核心标签库

c标签,主要用于完成JSP页面中逻辑控制/流程控制

  • 分支

  • 循环

5.3.1 c:if

<c:if test="EL表达式条件">

html

</c:if>

<%--  如果test属性的el表达式返回的为true,则显示c:if标签包含的HTML  --%>
<c:if test="${score >= 60}">
    <label style="color: green">通过</label>
</c:if>
<c:if test="${score < 60}">
    <label style="color: red">不通过</label>
</c:if>

5.3.2 c:choose

c:choose为多分支语句,可以包含多个c:when和一个c:otherwise , 寻找并执行第一个条件成立的c:when,如果所有c:when的条件都不成立则执行c:otherwise

<c:choose>
    <c:when test="${score>=90}">
        <label style="color: green">优秀</label>
    </c:when>
    <c:when test="${score>=80}">
        <label style="color: green">良好</label>
    </c:when>
    <c:when test="${score>=70}">
        <label style="color: green">中等</label>
    </c:when>
    <c:when test="${score>=60}">
        <label style="color: green">及格</label>
    </c:when>
    <c:otherwise>
        <label style="color: red">不及格</label>
    </c:otherwise>
</c:choose>

5.3.3 c:forEach

迭代标签、循环标签

 <%--  遍历传递过来的集合中的图书信息,显示在一个表格中  --%>
<table align="center" border="1" cellspacing="0">
    <tr>
        <th>图书编号</th>
        <th>图书名称</th>
        <th>图书作者</th>
        <th>图书价格</th>
    </tr>
    <%--    获取传递过来的集合,集合中有几个图书信息,table就显示几行
    items 指定要遍历的集合
    var  指定从集合中每次取出的数据的变量
    begin 指定从集合中的哪个元素开始显示,0表示第一个
    end 指定取到哪个索引对应的集合元素
    step 指定元素的间隔个数(默认为1,依次取出所有元素)
    --%>
    <c:forEach items="${bookList}" var="book" begin="1" end="4" step="2">
        <tr>
            <td>${book.bookId}</td>
            <td>${book.bookName}</td>
            <td>${book.bookAuthor}</td>
            <td>${book.bookPrice}</td>
        </tr>
    </c:forEach>
</table>

5.4 JSTL转换标签

fmt标签,提供了用于日期、数字等类型数据的格式转换的标签

<%--  格式化数字输出 --%>
<fmt:formatNumber value="${num}" pattern="#.0000"></fmt:formatNumber><br/>
<fmt:formatNumber value="${num}" type="currency"></fmt:formatNumber><br/>

<%-- 格式化日期输出 --%>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd"></fmt:formatDate><br/>
<fmt:formatDate value="${date}" pattern="hh:mm:ss"></fmt:formatDate><br/>
<fmt:formatDate value="${date}" pattern="yyyy-MM-dd HH:mm:ss"></fmt:formatDate><br/>

 

六、Servlet和JSP的综合案例

图书信息管理系统:管理员登录,对图书信息进行管理

  • 管理员登录

  • 添加图书信息

  • 图书信息列表

  • 修改图书信息

  • 删除图书信息

6.1 书城后台管理系统业务流程

152f1d3898c546628047894ac6c54e5b.png

6.2 项目的MVC分层架构

将项目中实现不同业务的代码进行分离:

  • 视图View — jsp负责进行客户端的页面呈现

  • 控制器Controller — servlet负责接收用户请求,调用service进行处理,根据处理结果进行流程跳转

  • 模型Model — service对数据的业务处理、DAO对数据的持久化操作

6.3 数据库设计

  1. 根据项目业务功能抽象数据实体

    • 管理员

    • 图书

  2. 提取实体的数据项

    • 管理员(ID,登录名,登录密码,真实姓名,性别,电话,备注)

    • 图书(编号,名称,作者,价格,封面图片,描述,库存,分类...)

  3. 使用三范式约束的实体数据项(???)

  4. E-R图

  5. 数据库建模

  6. 建库建表

    create database db_bookmall;
    
    create table users(
        user_id int primary key auto_increment,
        user_name varchar(40) not null unique,
        user_pwd varchar(40) not null,
        real_name varchar(20) not null,
        user_gender char(2) not null,
        user_tel char(11) not null unique,
        user_desc varchar(200)
    );
    
    create table books(
         book_id char(6) primary key,
    	 book_name varchar(50) not null,
    	 book_author varchar(20) not null,
    	 book_price DECIMAL(10,2),
    	 book_img_path varchar(100) not null,
    	 book_desc varchar(200),
         book_stcok int not null,
    	 book_type int not null 
    );

6.4 web项目环境搭建

  1. 创建web项目

  2. 搭建JDBC环境

    • 驱动

    • 连接池

    • DBUtils

6.5 数据库访问实现

6.5.1 管理员登录的数据库操作

  • 根据登录名查询用户信息 (根据用户名查询用户,将查询出来的用户的密码和输入的密码进行对别)

  1. 创建实体类

    package com.qfedu.bookmall.ms.dto;
    
    /**
     * @Description 管理员实体类
     * @Author 小温
     */
    public class User {
    
        private int userId;
        private String userName;
        private String userPwd;
        private String realName;
        private String userGender;
        private String userTel;
        private String userDesc;
    	//....
    }
  2. 创建DAO类实现数据库操作

    package com.qfedu.bookmall.ms.dao;
    
    import com.qfedu.bookmall.ms.dto.User;
    import com.qfedu.bookmall.ms.utils.DruidUtils;
    import org.apache.commons.dbutils.QueryRunner;
    import org.apache.commons.dbutils.handlers.BeanHandler;
    
    import java.sql.SQLException;
    
    /**
     * @Description 用于实现管理员的数据库操作
     * @Author 小温
     */
    public class UserDAO {
    
        /**
         * 根据管理员登录名查询管理员信息
         * @param userName
         * @return
         */
        public User selectUserByUserName(String userName){
            User user = null;
            try {
                String sql = "select user_id userId,user_name userName,user_pwd userPwd,real_name realName,user_gender userGender,user_tel userTel,user_desc userDesc from users where user_name=?";
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                user = queryRunner.query(sql, new BeanHandler<User>(User.class));
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return user;
        }
    
    }

     

6.5.2 图书管理的数据库操作

  • 添加图书信息

  • 查询所有图书信息

  • 根据图书ID删除一个图书信息

  • 根据图书ID查询一个图书信息

  • 根据图书ID修改一个图书信息

  1. 创建图书实体类

    package com.qfedu.bookmall.ms.dto;
    
    /**
     * @Description 图书信息实体类
     * @Author 小温
     */
    public class Book {
        
        private String bookId;
        private String bookName;
        private String bookAuthor;
        private double bookPrice;
        private String bookImgPath;
        private String bookDesc;
        private int bookStock;
        private int bookType;
    
    }
  2. 创建DAO类完成数据库操作

    package com.qfedu.bookmall.ms.dao;
    
    import com.qfedu.bookmall.ms.dto.Book;
    import com.qfedu.bookmall.ms.utils.DruidUtils;
    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;
    
    /**
     * @Description 完成图书信息的数据库操作
     * @Author 小温
     */
    public class BookDAO {
    
        /**
         * 添加图书信息
         * @param book
         * @return
         */
        public int insertBook(Book book){
            int i = 0;
            try {
                String sql = "insert into books(book_id,book_name,book_author,book_price,book_img_path,book_desc,book_stcok,book_type) values(?,?,?,?,?,?,?,?)";
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                //给SQL中的参数赋值
                Object[] params = {book.getBookId(),book.getBookName(),book.getBookAuthor(),book.getBookPrice(),book.getBookImgPath(),book.getBookDesc(),book.getBookStock(),book.getBookType()};
                i = queryRunner.update(sql, params);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return i;
        }
    
        /**
         * 查询所有图书信息
         * @return
         */
        public List<Book> selectBooks(){
            List<Book> bookList = null;
            try {
                String sql = "select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_stcok bookStock,book_type bookType from books";
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                bookList = queryRunner.query(sql, new BeanListHandler<Book>(Book.class));
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return bookList;
        }
    
        /**
         * 根据图书ID删除一个图书信息
         * @param bookId
         * @return
         */
        public int deleteBook(String bookId){
            int i = 0;
            try {
                String sql = "delete from books where book_id=?";
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                i = queryRunner.update(sql, bookId);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return i;
        }
    
        /**
         * 根据图书ID查询一个图书信息
         */
        public Book selectBookByBookId(String bookId){
            Book book = null;
            try {
                String sql = "select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_stcok bookStock,book_type bookType from books where book_id=?";
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                book = queryRunner.query(sql, new BeanHandler<Book>(Book.class),bookId);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return book;
        }
    
        /**
         * 根据图书ID修改一个图书信息
         * @param book
         * @return
         */
        public int updateBook(Book book){
            int i = 0;
            try {
                String sql = "update books set book_name=?,book_author=?,book_price=?,book_img_path=?,book_desc=?,book_stcok=?,book_type=? where book_id=?";
                QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
                Object[] params = {book.getBookName(),book.getBookAuthor(),book.getBookPrice(),book.getBookImgPath(),book.getBookDesc(),book.getBookStock(),book.getBookType(),book.getBookId()};
                i = queryRunner.update(sql, params);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return i;
        }
    }

6.6 网页设计

  • login.html

  • index.html

  • prompt.html

  • book-add.html

  • book-list.html

  • book-modify.html

6.7 业务层实现

6.7.1 管理员登录业务

package com.qfedu.bookmall.ms.service;

import com.qfedu.bookmall.ms.dao.UserDAO;
import com.qfedu.bookmall.ms.dto.User;

/**
 * @Description 管理员相关业务实现
 * @Author 小温
 */
public class UserService {

    /**
     * 管理员登录业务:根据账号密码验证管理登录,验证通过返回user对象,否则返回null
     * @param userName
     * @param userPwd
     * @return
     */
    public User checkLogin(String userName, String userPwd){
        //1.根据userName查询管理员信息
        UserDAO userDAO = new UserDAO();
        User user = userDAO.selectUserByUserName(userName);
        //2.判断密码
        if(user != null && user.getUserPwd() .equals(userPwd)){
            return user;
        }else{
            return null;
        }
    }
    
}

6.7.2 图书管理业务实现

package com.qfedu.bookmall.ms.service;

import com.qfedu.bookmall.ms.dao.BookDAO;
import com.qfedu.bookmall.ms.dto.Book;

import java.util.List;

/**
 * @Description 图书管理的业务实现
 * @Author 小温
 */
public class BookService {

    private BookDAO bookDAO = new BookDAO();

    /**
     * 添加图书业务实现
     * @param book
     * @return
     */
    public boolean saveBook(Book book){
        int i = bookDAO.insertBook(book);
        return i>0?true:false;
    }

    /**
     * 删除图书业务实现
     * @param bookId
     * @return
     */
    public boolean deleteBook(String bookId){
        int i = bookDAO.deleteBook(bookId);
        return i>0?true:false;
    }

    /**
     * 根据ID查询一个图书的业务实现
     * @param bookId
     * @return
     */
    public Book getBook(String bookId){
        Book book = bookDAO.selectBookByBookId(bookId);
        return book;
    }


    /**
     * 修改图书业务实现
     * @param book
     * @return
     */
    public boolean modifyBook(Book book){
        int i = bookDAO.updateBook(book);
        return i>0?true:false;
    }

    /**
     * 查询所有图书信息
     * @return
     */
    public List<Book> listBooks(){
        List<Book> bookList = bookDAO.selectBooks();
        return bookList;
    }

}

6.8 功能流程实现

6.8.1 创建JSP及Servlet类

  1. 在项目创建所需的JSP文件,将设计好的HTML整合到JSP中

  2. 创建servlets包,在servlets中创建业务流程实现所需的Servlet类

7.3.1 BookDAO

  • 分页查询数据

    /**
    * 分页查询图书信息
    * @param start 查询数据的起始行索引
    * @param limit 最多返回的数据记录数(每页显示的条数)
    * @return 返回的集合中只包含一页的数据
    */
    public List<Book> selectBooks(int start,int limit){
        List<Book> bookList = null;
        try {
            String sql = "select book_id bookId,book_name bookName,book_author bookAuthor,book_price bookPrice,book_img_path bookImgPath,book_desc bookDesc,book_stcok bookStock,book_type bookType from books limit ?,?";
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
            bookList = 
                queryRunner.query(sql, new BeanListHandler<Book>(Book.class),start,limit);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return bookList;
    }
  • 查询总记录数

    /**
    * 查询图书的总记录数
    * @return
    */
    public long selectBookCount(){
        long count = 0;
        try {
            String sql = "select count(1) from books";
            QueryRunner queryRunner = new QueryRunner(DruidUtils.getDataSource());
            count = queryRunner.query(sql,new ScalarHandler<Long>());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return count;
    }

7.3.2 BookService

  • 根据页码、每页条数查询当前页的数据

  • 根据每页条数计算总页数

    /**
         * 分页查询图书信息
         * @param pageNum 页码
         * @param pageSize 每页显示的条数
         * @return
         */
    public List<Book> listBooksByPage( int pageNum,int pageSize){
        int start = (pageNum-1)*pageSize;
        int limit = pageSize;
        List<Book> bookList = bookDAO.selectBooks(start,limit);
        return bookList;
    }
    
    /**
         * 查询图书总页数
         * @param pageSize 每页显示的条数
         * @return
         */
    public int getPageCount(int pageSize){
        //1.查询总记录
        long count = bookDAO.selectBookCount();
        //2.根据总记录数和每页显示的条数,计算总页数
        long pageCount = count%pageSize == 0 ? count/pageSize: count/pageSize+1;
        return (int)pageCount;
    }

7.3.3 BookListServlet

1.接收页码 pageNum

2.定义每页显示条数 pageSize

3.查询当前页数据 bookList

4.查询总记录数 pageCount

5.转发到列表页面

package com.qfedu.bookmall.ms.servlets;

import com.qfedu.bookmall.ms.dto.Book;
import com.qfedu.bookmall.ms.service.BookService;

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.List;

/**
 * @Description  分页查询图书信息
 *@Author 小温
 */
@WebServlet("/BookListServlet")
public class BookListServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        //1.接收客户端传递的页码
        //  (如果客户端没有传递页码,则默认页码为1,如果传递了则使用客户端传递的页码)
        String num = request.getParameter("pageNum");
        int pageNum = num==null? 1: Integer.parseInt( num );
        //2.定义pageSize
        int pageSize = 10;

        //3.调用BookService查询这一页的图书信息
        BookService bookService = new BookService();
        List<Book> bookList = bookService.listBooksByPage(pageNum,pageSize);
        //4.调用BookService查询图书的总页数
        int pageCount = bookService.getPageCount(pageSize);


        //5.将查询到的当前页数据的集合、当前页码、总页数  转发到book-list.jsp
        request.setAttribute("bookList",bookList);
        request.setAttribute("pageNum",pageNum);
        request.setAttribute("pageCount",pageCount);
        request.getRequestDispatcher("book-list.jsp").forward(request,response);
    }
}

7.4 book-list.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
  <h3>图书信息列表</h3>
    <table width="90%" align="center" border="1" cellspacing="0">
      <tr>
        <th>编号</th>
        <th>封面</th>
        <th>名称</th>
        <th>作者</th>
        <th>价格</th>
        <th>库存</th>
        <th>描述</th>
        <th>类型</th>
        <th>操作</th>
      </tr>
      <c:forEach items="${bookList}" var="book">
        <tr>
          <td>${book.bookId}</td>
          <td><img src="${book.bookImgPath}" height="50"></td>
          <td>${book.bookName}</td>
          <td>${book.bookAuthor}</td>
          <td><fmt:formatNumber value="${book.bookPrice}" type="currency" /></td>
          <td>${book.bookStock}</td>
          <td>${book.bookDesc}</td>
          <td>
            <c:if test="${book.bookType ==1}">原创</c:if>
            <c:if test="${book.bookType ==2}">翻译</c:if>
          </td>
          <td>
            <a href="BookQueryServlet?bookId=${book.bookId}">修改</a>
            <a href="BookDeleteServlet?bookId=${book.bookId}"
               οnclick="javascript:return confirm('你确定删除吗?')">删除</a>
          </td>
        </tr>
      </c:forEach>
      <!--  显示分页效果及页码切换 -->
      <tr height="50">
        <td colspan="9" align="center">
            <!--显示首页、上一页:如果当前页就是第一页,则不显示超链接-->
            <c:if test="${pageNum ==1 }">
                <label style="color:gray">首页</label>
                <label style="color:gray">上一页</label>
            </c:if>
            <c:if test="${pageNum > 1 }">
                <a href="BookListServlet?pageNum=1">首页</a>
              <a href="BookListServlet?pageNum=${pageNum-1}">上一页</a>
            </c:if>

            <!-- 显示页码 和总页数 -->
            当前第${pageNum}页/共${pageCount}页

            <!-- 显示下一页 和 尾页 -->
            <c:if test="${pageNum < pageCount}">
              <a href="BookListServlet?pageNum=${pageNum+1}">下一页</a>
              <a href="BookListServlet?pageNum=${pageCount}">尾页</a>
            </c:if>
            <c:if test="${pageNum == pageCount}">
                <label style="color:gray">下一页</label>
                <label style="color:gray">尾页</label>
            </c:if>
        </td>
      </tr>
    </table>
  </body>
</html>

7.4 PageHelper封装

思考:

  1. 分页操作在Service查询页面数据及总页码都属同一个分页业务,为什么要携程两个方法呢?能不能在一个方法完成呢?

  2. Servlet类主要负责流程控制,在上述代码实现过程中也涉及到了分页业务,不可理。该如何解决呢?

7.4.1 

7.4.2 创建分页帮助类PageHelper

package com.qfedu.bookmall.ms.utils;

import java.util.List;

/**
 * @Description 分页帮助类
 * @Author 小温
 */
public class PageHelper<T> {
    
    //存放页面数据的List集合
    public List<T> list;
    
    //存放当前页码
    public int pageNum;
    
    //存放总页数
    public int pageCount;

    //无参构造器
    //全参构造器
    //get和set
}

7.4.3 BookService

/**
     * 分页查询图书信息
     * @param pageNum 页码
     * @param pageSize 每页显示的条数
     * @return
     */
public PageHelper<Book> listBooksByPage( int pageNum,int pageSize){
    //1.查询当前页码的数据
    int start = (pageNum-1)*pageSize;
    int limit = pageSize;
    List<Book> bookList = bookDAO.selectBooks(start,limit);

    //2.查询并计算图书总页数
    //a.查询总记录
    long count = bookDAO.selectBookCount();
    //b.根据总记录数和每页显示的条数,计算总页数
    long pageCount = count%pageSize == 0 ? count/pageSize: count/pageSize+1;

    //3.将分页数据都放到一个PageHelper对象
    PageHelper<Book> bookPageHelper = new PageHelper<Book>(bookList, pageNum, (int)pageCount);

    return bookPageHelper;
}

7.4.4 BookListServlet

/**
 * @Description  分页查询图书信息
 * @Author 小温
 */
@WebServlet("/BookListServlet")
public class BookListServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1.接收客户端传递的页码
        //  (如果客户端没有传递页码,则默认页码为1,如果传递了则使用客户端传递的页码)
        String num = request.getParameter("pageNum");
        int pageNum = num==null? 1: Integer.parseInt( num );
        //2.定义pageSize
        int pageSize = 10;

        //3.调用BookService查询这一页的图书信息
        BookService bookService = new BookService();
        PageHelper<Book> bookPageHelper = bookService.listBooksByPage(pageNum, pageSize);

        //5.将查询到的bookPageHelper(当前页数据的集合、当前页码、总页数)  转发到book-list.jsp
        request.setAttribute("bookPageHelper",bookPageHelper);
        request.getRequestDispatcher("book-list.jsp").forward(request,response);
    }
}

7.4.5 book-list.jsp

book-list.jsp 页面的数据都从bookPageHelper对象获取

20230724024159.png?origin_url=file%3A%2F%2FE%3A%5CBaiduNetdiskDownload%5CJavaWeb%25E5%2585%25A8%25E5%25A5%2597%25E7%25AC%2594%25E8%25AE%25B0%25E8%25B5%2584%25E6%2596%2599%5C%25E7%25AC%2594%25E8%25AE%25B0%5C07-JSP%5Cimgs%5Cimage-20211117024307271.png%3FlastModify%3D1704547316&pos_id=6KHQ8DDE

 


提示:以下是本篇文章正文内容,下面案例可供参考

一、pandas是什么?

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。

二、使用步骤

1.引入库

代码如下(示例):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
import  ssl
ssl._create_default_https_context = ssl._create_unverified_context

2.读入数据

代码如下(示例):

data = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

该处使用的url网络请求的数据。


总结

以上就是今天要讲的内容,本文仅仅简单介绍了JSP的使用,而JavaWeb提供了大量能使我们快速便捷地处理数据的函数和方法。

 

  • 17
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

╰つ小③╮扼当吥起

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值