前言:今天内容知道就行,因为有更好的技术(jstl)来实现今天的内容,在以后开发中基本不会用今天的东西(但是最好能理解今天的内容,虽然不用会敲)。

1 jsp

1.1 jsp概述

Java server pages,简称jsp。
中文名:java服务器页面技术。
可以帮我们完成页面标签及数据的字符串拼接,主要用于动态数据(通常是从数据库中查询的数据)的展示。

1.2 jsp的创建

使用eclipse的模板直接创建jsp文件即可。

1.3 jsp的执行原理

通过观察tomcat目录下的work目录中的,可以找到jsp编译后的.java和.class文件,证明jsp的实质就是一个servlet!!!

执行原理图:
image.png

1.4 Jsp的语法

1.4.1 基本语法—脚本标签

一共有3个,常用的有两个:
<% java代码 %> 常用
<%= 表达式或变量名 %> 常用
<%! 定义成员变量或定义方法 %> 了解

1.4.2 基本语法—注释

<%— jsp中的注释,这个注释会在翻译成.java文件的时候自动消失 —%>
<% java的注释 // /**/ ,会在.java文件中存在,在.class文件中消失 %>

建议使用jsp的注释,因为可以尽快的让注释消失。

1.4.3 指令

在jsp中的指令有3种:
<%@ page 属性名1=属性值1 属性名2=属性值2 … %>
用于页面控制,例如:页面编码、页面语言、页面使用的其他java类(导包)
常用的属性:
import=”包名.类名,包名2.类名2,….”
<%@ include file=”/其他jsp文件的路径” %>
用于静态包含,将其他的jsp页面内容,复制粘贴到本jsp页面中来(源码级别的复制粘贴)。
File的路径可以是绝对路径也可以是相对路径,建议使用绝对路径。
常用属性:
File=”/其他jsp文件的路径”
<%@ taglib prefix=”c” uri=”jstl/core…”%>
用于引入jstl的标签,可以在jsp页面使用jstl标签完成页面上的逻辑循环,与逻辑判断等。
注意:
指令可以写在jsp页面的任意位置。

1.4.4 九大内置对象(背会)(面试常问)

所谓的内置对象就是服务器在编译jsp文件的时候,就会直接创建出来的9个变量,程序员可以直接使用这9个变量,从而实现相应的效果。

9大内置对象:

对象名 数据类型
Request HttpServletRequest
Response HttpServletResponse
Out JspWriter (比我们自己的getWriter获取的流,输出的信息要慢)
Session HttpSession
Application ServletContext
Config ServletConfig
Page this(就是编译后的servlet对象)
Exception 必须在错误页面才能使用该对象,其他页面不能使用
pageContext PageContext 含义:上下文对象;(jsp的容器对象);

pageContext的作用:
1:可以获取其他的8个内置对象。(这是一个大管家)
2:可以操作4大域的存值与取值。

关于out与response.getWriter的问题:

image.png
代码举例:
9.jsp

  1. <%@ page language="java" contentType="text/html; charset=UTF-8"
  2. pageEncoding="UTF-8"%>
  3. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  4. <html>
  5. <head>
  6. <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  7. <title>练习9大内置对象</title>
  8. </head>
  9. <body>
  10. <%
  11. //9个内置对象,除了exception之外,都可以直接使用
  12. request.setAttribute("username","杰克");
  13. ////向session中存值
  14. session.setAttribute("age",18);
  15. //转发
  16. request.getRequestDispatcher("/9nei/9_2.jsp").forward(request, response);
  17. %>
  18. </body>
  19. </html>

9_2.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>转发后的页面</title>
</head>
<body>
    <%= request.getAttribute("username") %>
    <%
        //使用out对象输出信息
        out.write("你好吗?");
        //自己获取输出流,输出信息   由于设计的时候,将response的数据输出缓冲区放在了out对象缓冲区的前面,因此无论代码怎么写,都是response响应的数据
        //优先展示;
        response.getWriter().print("我很好,and you?");

    %>
    <br>
    <%= session.getAttribute("age") %>
    <%
        //人为模拟一个错误
        //int i=1/0;
    %>
</body>
</html>

web.xml中添加一段代码
表示出现500错误的时候往error.jsp页面跳

  <error-page>
    <error-code>500</error-code>
    <location>/error.jsp</location>
  </error-page>

error.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isErrorPage="true"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>错误信息展示页面</title>
</head>
<body>
    亲,服务器正在维护,请稍后重试...

    <br>
    具体异常信息如下:
    <br>
    <%=
        exception.printStackTrace()
    %>
</body>
</html>

访问地址:http://localhost/day34/9nei/9.jsp
输出结果:
我很好,and you? 杰克 你好吗?
18
结果分析:
“我很好,and you?”在”你好吗?”前面的原因:自己获取输出流,输出信息 由于设计的时候,将response的数据输出缓冲区放在了out对象缓冲区的前面,因此无论代码怎么写,都是response响应的数据优先展示。

1.4.5 四大域对象(记住)(面试常问)

Jsp的四大域对象实质上就是上面9个内置对象中的其中4个而已,这4个内置对象也可以称为域对象(容器对象),可以保存数据和获取数据。
4个域对象,按照生命周期从短到长的顺序是:
Page 页面域(仅当前jsp页面生效,即使转发也会失效)
Request 请求域(一次请求范围内有效,可以转发)
Session 会话域(浏览器一个打开到另一次关闭有效,相当于可以发多次请求)
Application 工程域(整个工程范围内一直生效,直到服务器关闭或重启)
使用pageContext对象操作4个域中的值的方式:(了解)
pageContext.setAttribite(“属性名”,属性值,指定域的一个代号);
pageContext.getAttribite(“属性名”,指定域的一个代号),找不到就返回null。
上面的两个方法仅操作指定的域,如果不指定域,默认操作page域。
注意:
4个域的代号,已经在PageContext类中被定义成了常量(api里能找到),直接使用即可。
Page 对应的代号 Page_Scope
Request 对应的代号 Request_Scope
Session 对应的代号 Session_Scope
Application 对应的代号 PApplication_Scope
偷懒的方法:
pageContext.findAttribute(“属性名”); 从最小域,逐次向上查找,找到为止,如果找了一圈都没找到就不找了就返回null。

1.4.6 动作标签(了解,面试可能问有啥区别)

动态包含:
所谓的动态包含就是各自编译各自的jsp文件,仅仅是将其他的jsp文件的运行结果拿过来而已,相当于使用多个jsp共同处理浏览器的一次请求。
格式:

静态包含与动态包含的区别:
image.png
注意:
开发中一般使用静态包含,因为效率高一些,但是要注意变量冲突的问题。

2 案例—展示商品信息列表

2.1 需求

当访问工程的时候,从数据库中查询所有的商品信息,并展示在jsp页面上。

2.2 技术分析

使用servlet用于处理用户的请求,使用Dbutils查询数据库,使用jsp展示数据信息。

2.3 流程分析

商品列表查询功能的流程分析.png

2.4 环境搭建

1:创建数据库与表;
2:复制jar包,工具类,静态页面,及图片等;
3:在src下创建3层包结构;
4:按照上述流程图编写代码;

2.4.1 数据库准备:

create database day34;
use day34;
create table `product` (
    `pid` varchar (96),
    `pname` varchar (150),
    `market_price` double ,
    `shop_price` double ,
    `pimage` varchar (600),
    `pdate` date ,
    `pdesc` varchar (765)
); 
INSERT INTO `product` VALUES('1','小米 4c 标准版','1399','1299','products/1/c_0001.jpg','2015-11-02','小米 4c 标准版 全网通 白色 移动联通电信4G手机 双卡双待');
INSERT INTO `product` VALUES('10','华为 Ascend Mate7','2699','2599','products/1/c_0010.jpg','2015-11-02','华为 Ascend Mate7 月光银 移动4G手机 双卡双待双通6英寸高清大屏,纤薄机身,智能超八核,按压式指纹识别!!选择下方“移动老用户4G飞享合约”,无需换号,还有话费每月返还!');
INSERT INTO `product`  VALUES('11','vivo X5Pro','2399','2298','products/1/c_0014.jpg','2015-11-02','移动联通双4G手机 3G运存版 极光白【购机送蓝牙耳机+蓝牙自拍杆】新升级3G运行内存·双2.5D弧面玻璃·眼球识别技术');
INSERT INTO `product`  VALUES('12','努比亚(nubia)My 布拉格','1899','1799','products/1/c_0013.jpg','2015-11-02','努比亚(nubia)My 布拉格 银白 移动联通4G手机 双卡双待【嗨11,下单立减100】金属机身,快速充电!布拉格相机全新体验!');
INSERT INTO `product`  VALUES('13','华为 麦芒4','2599','2499','products/1/c_0012.jpg','2015-11-02','华为 麦芒4 晨曦金 全网通版4G手机 双卡双待金属机身 2.5D弧面屏 指纹解锁 光学防抖');
INSERT INTO `product`  VALUES('14','vivo X5M','1899','1799','products/1/c_0011.jpg','2015-11-02','vivo X5M 移动4G手机 双卡双待 香槟金【购机送蓝牙耳机+蓝牙自拍杆】5.0英寸大屏显示·八核双卡双待·Hi-Fi移动KTV');
INSERT INTO `product`  VALUES('15','Apple iPhone 6 (A1586)','4399','4288','products/1/c_0015.jpg','2015-11-02','Apple iPhone 6 (A1586) 16GB 金色 移动联通电信4G手机长期省才是真的省!点击购机送费版,月月送话费,月月享优惠,畅享4G网络,就在联通4G!');

2.4.2 jar包和图片准备

image.png
image.png

2.4.3 完成后目录结构

image.png

2.4.4 部分参考代码

Product.java

package com.itheima.anli04_domain;

import java.util.Date;

public class Product {
    private String pid;
    private String pname;
    private double market_price;
    private double shop_price;
    private String pimage;
    private Date pdate;
    private String pdesc;
    public String getPid() {
        return pid;
    }
    public void setPid(String pid) {
        this.pid = pid;
    }
    public String getPname() {
        return pname;
    }
    public void setPname(String pname) {
        this.pname = pname;
    }
    public double getMarket_price() {
        return market_price;
    }
    public void setMarket_price(double market_price) {
        this.market_price = market_price;
    }
    public double getShop_price() {
        return shop_price;
    }
    public void setShop_price(double shop_price) {
        this.shop_price = shop_price;
    }
    public String getPimage() {
        return pimage;
    }
    public void setPimage(String pimage) {
        this.pimage = pimage;
    }
    public Date getPdate() {
        return pdate;
    }
    public void setPdate(Date pdate) {
        this.pdate = pdate;
    }
    public String getPdesc() {
        return pdesc;
    }
    public void setPdesc(String pdesc) {
        this.pdesc = pdesc;
    }
    public Product(String pid, String pname, double market_price, double shop_price, String pimage, Date pdate,
            String pdesc) {
        super();
        this.pid = pid;
        this.pname = pname;
        this.market_price = market_price;
        this.shop_price = shop_price;
        this.pimage = pimage;
        this.pdate = pdate;
        this.pdesc = pdesc;
    }
    public Product() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public String toString() {
        return "Product [pid=" + pid + ", pname=" + pname + ", market_price=" + market_price + ", shop_price="
                + shop_price + ", pimage=" + pimage + ", pdate=" + pdate + ", pdesc=" + pdesc + "]";
    }
}

MyC3P0Utils.java

package com.itheima.anli05_utils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/*
 * c3p0的工具类
 */
public class MyC3P0Utils {
    //直接创建了一个成员变量,且直接对成员变量初始化
    private  static ComboPooledDataSource ds = new ComboPooledDataSource();

    //自定义常用方法
    public static Connection getConnection() throws SQLException{
        return ds.getConnection();
    }
    //自定义一个,获取连接池的方法
    public static DataSource getDataSource(){
        return ds;
    }
    //关闭资源
    public static void close(ResultSet set,Statement st,Connection conn){
        try {
            if(set!=null){
                set.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            if(st!=null){
                st.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

ProductServlet.java

package com.itheima.anli01_web;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.itheima.anli02_service.ProductService;
import com.itheima.anli04_domain.Product;

/**
 * 查询商品列表的servlet
 */
public class ProductServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        /*
         * 套路: 参  调  存  转
            1:参,本案例无参
            2:调,调用业务层,查询出数据库中所有的商品对象;(会得到list集合)
            3:存,将list集合保存到request域中;
            4:转,转发到一个list.jsp页面,在list.jsp页面使用for循环遍历集合,并将集合中的对象中的数据取出来,添加到表格的单元格中
         */
        //2:调,调用业务层,查询出数据库中所有的商品对象;(会得到list集合)
        ProductService ps = new ProductService();
        List<Product> li = ps.findAllProducts();
        //3:存,将list集合保存到request域中;
        request.setAttribute("li",li);
        //4:转,转发到一个list.jsp页面,在list.jsp页面使用for循环遍历集合,并将集合中的对象中的数据取出来,添加到表格的单元格中
        request.getRequestDispatcher("/WEB-INF/list.jsp").forward(request, response);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

ProductService.java

package com.itheima.anli02_service;

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

import com.itheima.anli03_dao.ProductDao;
import com.itheima.anli04_domain.Product;

public class ProductService {
    //1:查询所有商品列表的方法
    public List<Product> findAllProducts() {
        try {
            return new ProductDao().findAllProducts();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }
    }

}

ProductDao.java

package com.itheima.anli03_dao;

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

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import com.itheima.anli04_domain.Product;
import com.itheima.anli05_utils.MyC3P0Utils;

public class ProductDao {
    //1:查询所有商品列表的方法
    public List<Product> findAllProducts() throws SQLException {
        /*
         * 1:创建sql执行者;
        2:编写sql语句;
        3:准备参数与结果集;
        4:执行sql处理结果
         */
        //1:创建sql执行者;
        QueryRunner q = new QueryRunner(MyC3P0Utils.getDataSource());
        //2:编写sql语句;
        String sql = "select * from product order by shop_price desc";
        //3:准备参数与结果集;
        BeanListHandler rsh = new BeanListHandler(Product.class);
        //4:执行sql处理结果
        return q.query(sql, rsh);
    }

}

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    import="java.util.*,com.itheima.anli04_domain.Product"
    %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>商品列表页面</title>
</head>
<body>
    <table border="1px" width="100%">
        <tr>
            <th>编号</th>
            <th>名称</th>
            <th>市场价</th>
            <th>商城价</th>
            <th>图片</th>
            <th>上架日期</th>
            <th>描述</th>
        </tr>
        <%
            //获取集合
            List<Product> li = (List<Product>)request.getAttribute("li");
            //迭代集合
            for(Product p:li){
                out.write("<tr><td>"+p.getPid()+"</td><td>"+p.getPname()+"</td><td>"+p.getMarket_price()+"</td><td>"+p.getShop_price()+"</td><td><img src='http://localhost/day34/"+p.getPimage()+"'  width='50px' height='50px'></td><td>"+p.getPdate()+"</td><td>"+p.getPdesc()+"</td></tr>");
            }
        %>

    </table>
</body>
</html>