一、学习目标
- 会使用include指令
- 掌握application对象的原理和应用
- 掌握对象的作用域
- 会使用JSP访问数据库
- 掌握JavaBean的概念和应用
二、include指令
问题:
同一项目中多个页面中含有大量相同代码。重复内容:页面头部、页面尾部、权限验证、…;存在问题:代码冗余、修改不便、开发工作量大
分析:
提取相同部分内容,统一维护
在原页面中加载==提取出的公共代码==
JSP提供了include指令,可以静态加载其他JSP页面
在翻译JSP文件时,插入一个包含文本或代码的文件
语法:
<%@ include file="应用文件路径" %>
使用include指令减少重复代码示例:
- 创建公共代码页面(
authentication.jsp
) - 提取登录权限验证的公共代码,放入其中
- 在首页( index.jsp )中引入公共代码页面
创建公共代码页面(
authentication.jsp
)提取登录权限验证的公共代码,放入其中
<%@ page import="com.aiden.entity.User" %>
<%@ page import="com.aiden.utils.Constants" %>
<%@ page import="com.aiden.utils.CookieUtils" %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
//验证用户访问权限
User user = (User) session.getAttribute(Constants.SESSION_USER);
if (user == null) {
//检查Cookie
String loginPwd = CookieUtils.getCookieValue(request, "loginPwd");
String loginName = CookieUtils.getCookieValue(request, "loginName");
//判断非空与用户名密码验证
if (loginName != null && loginPwd != null && "yunGe".equals(loginName) && "123456".equals(loginPwd)) {
User userInfo = new User(10001, loginName, loginPwd, "男", new Date());
session.setAttribute(Constants.SESSION_USER, userInfo);
session.setMaxInactiveInterval(60);//设置失效时间为60秒
} else {
response.sendRedirect("login.jsp");
return;
}
}
%>
在首页( index.jsp )中引入公共代码页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首页</title>
</head>
<body>
<%@include file="authentication.jsp" %>
<h1>欢迎【<%=user.getUserName()%>】登录后台首页</h1>
</body>
</html>
二、application内置对象
需求:
在微博系统的用户登录页面,统计并显示网站访问人数
分析:
在application对象中添加一个数字类型属性用于统计登录人数,有用户登录时,属性值+1
使用application对象统计登录人数示例代码:
Integer count = (Integer) application.getAttribute("visitorCount");
if(count != null) {
count = count + 1;
} else {
count = 1;
}
application.setAttribute("visitorCount",count);
【您是本网站第<%= (Integer)application.getAttribute("visitorCount")%>位到访用户】
小结:
application 对象可将信息保存在服务器中,直到服务器关闭,否则application对象中保存的信息会在整个应用中都有效。与session对象相比,application对象生命周期更长,类似于系统的“全局变量”。
存储数据类型:Object
作用域:整个网站
销毁时间:关闭服务器
获取值:application.getAttribute(“key”)
存储值:application.setAttribute(“key”,value);
三、JSP对象作用域
JSP中包含四大作用域
1、page作用域: 当前页面
2、request作用域: 当前请求
3、session作用域: 当前会话
4、application作用域: 当前Web应用
作用域从小到大范围排序:
page < request < session < application
3.1page作用域
page作用域
作用域范围:当前页面
作用域对象:pageContext 对象
本页面读取pageContext对象中的数据
<%
//pageA.jsp
String pageName = "This is pageA";
pageContext.setAttribute("pageName",pageName);
System.out.println("控制台输出pageName:"+ pageContext.getAttribute("pageName"));
//转发跳转pageB.jsp
request.getRequestDispatcher("pageB.jsp").forward(request,response);
%>
其他页面读取pageContext对象中的数据
<!--pageB.jsp-->
pageName: <%= pageContext.getAttribute("pageName")%>
观察pageB.jsp页面发现 pageName:Null
控制台运行结果正常输出 “控制台输出pageName:This is pageA”
结论: page作用域范围只在当前页有效
3.2request作用域
request作用域
作用域范围:当前请求
作用域对象: request对象
观察请求转发过程中,request对象中的数据
创建
count.jsp
页面,设置countPage属性并赋值
Integer countPage= (Integer)request.getAttribute("countPage");
if(countPage==null){
countPage = 1;
}else{
countPage++;
}
request.setAttribute("countPage",countPage);
在
one.jsp
页面通过include指令引入count.jsp
页面,并转发至two.jsp
<%@ include file="count.jsp" %>
<%
request.getRequestDispatcher("two.jsp").forward(request,response);
%>
在
two.jsp
页面通过include指令引入count.jsp
页面,并输出request对象中的countPage属性
<%@ include file="count.jsp" %>
<h3>count in request: <%= request.getAttribute("countPage")%></h3>
运行结果:
3.2session作用域
session作用域
作用域范围:当前会话
作用域对象: session对象
观察请求过程中, session对象中的数据
修改count.jsp页面,在request对象和session对象中分别设置不同属性
Integer countInRequest = (Integer)request.getAttribute("countInRequest");
Integer countInSession = (Integer)session.getAttribute("countInSession");
countInRequest = (countInRequest==null)?1:countInRequest+1;
countInSession = (countInSession==null)?1:countInSession+1;
request.setAttribute("countInRequest",countInRequest);
session.setAttribute("countInSession",countInSession);
在
one.jsp
页面通过include指令引入count.jsp
页面,并重定向至two.jsp
页面
<%@ include file="count.jsp" %>
<%
response.sendRedirect("two.jsp");
%>
在
two.jsp
页面通过include指令引入count.jsp
页面,并输出request对象和session对象中的属性
<%@ include file="count.jsp" %>
<h3>count in request: <%= request.getAttribute("countInRequest")%></h3>
<h3>count in session: <%= session.getAttribute("countInSession")%></h3>
运行结果
3.2application作用域
application作用域
作用域范围:当前Web应用
作用域对象: application对象
观察请求过程中, application对象中的数据
修改
count.jsp
页面,在session对象和application对象中分别设置不同属性
Integer countInSession = (Integer) session.getAttribute("countInSession");
Integer countInApplication = (Integer) application.getAttribute("countInApplication");
countInSession = (countInSession == null) ? 1 : countInSession + 1;
countInApplication = (countInApplication == null) ? 1 : countInApplication + 1;
session.setAttribute("countInSession", countInSession);
application.setAttribute("countInApplication", countInApplication);
在
one.jsp
页面通过include指令引入count.jsp
页面,并重定向至two.jsp
<%@ include file="count.jsp" %>
<%
response.sendRedirect("two.jsp");
%>
在
two.jsp
页面通过include指令引入count.jsp
页面,并输出session对象和application对象中的属性
<%@ include file="count.jsp" %>
<h3>count in session: <%= session.getAttribute("countInSession")%></h3>
<h3>count in application: <%= application.getAttribute("countInApplication")%></h3>
运行结果
四、JavaBean
将基础模块组件化,通过简单的组装,可以快速组成成品
JavaBean是可以跨平台的重用组件,本质是一个特殊的Java类
4.1JavaBean的特点
JavaBean的功能分类
- 封装数据
- 封装业务
JavaBean的规范
- 提供无参的公有构造方法
- 实现Serializable接口
- 属性私有
- 属性的getter、setter方法公有
JavaBean的优势
- 解决代码重复编写,减少代码冗余
- 功能区分明确
- 提高了代码的维护性
4.2使用JavaBean封装数据
在JSP中使用JavaBean : 按照JavaBean的规范修改User实体类
getter 、 setter方法命名规范
属性首字母大写,名为xxx的属性对应setXxx()
方法
特殊属性的getter、setter方法命名规范
属性第二个字母大写,该属性名直接用作getter、setter方法的后半部分
属性名:uName,方法:getuName
、setuName
属性前两个字母大写,该属性名直接用作getter 、setter方法的后半部分
属性名:URL ;方法:getURL
、setURL
属性首字母大写;该属性名直接用作getter 、setter方法的后半部分
属性名:Name;方法:getName
、setName
public class User implements Serializable {//1.实现序列化接口
private static final long serialVersionUID = -6890038231098895941L;
//2.属性私有化
private int id;
private String userId;//账户
//省略其他属性
public int getId() { //3.提供公有的getter、setter方法
return id;
}
public void setId(int id) {
this.id = id;
}
//省略其他属性的getter和setter方法
}
五、在JSP中访问数据库
在JSP中可以借助JSP小脚本实现数据库连接
Java部分
- 数据控制、业务处理
- DAO接口:把对数据库的所有操作定义成抽象方法
- DAO实现类:给出DAO接口中定义方法的具体实现
- 实体类:用于存放、传输对象数据
- 工具类:配置文件读取类
JSP部分
数据展示
5.1JDBC回顾
第一步:加载JDBC驱动
使用Class.forName( )方法加载JDBC驱动类到Java虚拟机中
第二步:与数据库建立连接
调用DriverManager 类的getConnection()方法,获取数据库连接
第三步:发送SQL语句,得到返回结果
第四步:处理返回结果
第五步:数据库访问结束后,进行资源释放
JDBC编程模板
5.2DAO模式与业务层回顾
回顾数据访问层与业务层
- 数据库工具类 BaseDao =>位于
dao
包下 - 实体类 =>位于
entity
包下 - DAO接口 =>位于
dao
包下 - DAO实现类 =>位于
dao.impl
包下 - 业务接口 =>位于
service
包下 - 业务接口实现类 =>位于
service.impl
包下
5.3搭建三层架构
需求: 实现第三波书店首页图书类型导航菜单数据动态加载。
5.3.1添加maven依赖和database.properties
maven中添加依赖包
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
resources根资源文件夹下添加database.properties配置文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/bookshopplus?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
user=root
password=root
5.3.2添加工具类BaseDao与ConfigManager
BaseDao
package com.bookshop.dao;
import com.bookshop.utils.ConfigManager;
import java.sql.*;
/**
* 操作数据库的基类--静态类
* @author Aiden
*/
public class BaseDao {
//构造函数私有化
private BaseDao() { }
//在该类的内部提供一个静态的实例对象
private static BaseDao baseDao = new BaseDao();//饿汉模式
//提供一个对外获取实例对象的静态方法
public static BaseDao getInstance() {
return baseDao;
}
/**
* 获取数据库连接对象
*
* @return
*/
public static Connection getConnection() {
Connection connection = null;
String driver = ConfigManager.getInstance().getProperty("driver");
String url = ConfigManager.getInstance().getProperty("url");
String user = ConfigManager.getInstance().getProperty("user");
String password = ConfigManager.getInstance().getProperty("password");
try {
Class.forName(driver);//加载驱动
connection = DriverManager.getConnection(url, user, password);//建立连接
} catch (Exception e) {
e.printStackTrace();
}
return connection;
}
/**
* 查询操作
*/
public static ResultSet execute(Connection connection, PreparedStatement stmt, ResultSet rs,String sql, Object... params) throws SQLException {
stmt = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
}
rs = stmt.executeQuery();
return rs;
}
/**
* 更新操作
*/
public static int execute(Connection connection, PreparedStatement stmt,String sql, Object... params) throws SQLException {
int updateRows = 0;
stmt = connection.prepareStatement(sql);
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
}
updateRows = stmt.executeUpdate();
return updateRows;
}
/**
* 释放资源
*/
public static boolean closeResource(Connection connection, PreparedStatement stmt, ResultSet rs) {
boolean flag = true;
if (rs != null) {
try {
rs.close();
rs = null;//GC回收
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (stmt != null) {
try {
stmt.close();
stmt = null;//GC回收
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
if (connection != null) {
try {
connection.close();
connection = null;//GC回收
} catch (SQLException e) {
e.printStackTrace();
flag = false;
}
}
return flag;
}
}
ConfigManager
package com.bookshop.utils;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @author Aiden
* 读取配置文件的工具类-单例模式
*/
public class ConfigManager {
//1.定义静态的实例属性
private static ConfigManager configManager;
//Properties操作配置文件的实例属性
private static Properties properties;
//2.将构造函数私有化
private ConfigManager() {
String configFile = "database.properties";
InputStream is = null;
properties = new Properties();
try {
is = ConfigManager.class.getClassLoader().getResourceAsStream(configFile);
properties.load(is);
is.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
//3.静态内部类
public static class ConfigManagerHelper {
//final修饰
private static final ConfigManager CONFIG_MANAGER = new ConfigManager();
}
//4.对外提供的获取ConfigManager实例的方法
public static ConfigManager getInstance() {
configManager = ConfigManagerHelper.CONFIG_MANAGER;
return configManager;
}
//5.提供根据key获取对应value值的方法
public static String getProperty(String key) {
return properties.getProperty(key);
}
}
5.3.3添加实体类
package com.bookshop.entity;
import java.io.Serializable;
/**
* 图书类型实体类
* @author Aiden
*/
public class Categorie implements Serializable {
private static final long serialVersionUID = 3646156839950581681L;
private Integer id;
private String name;
public Categorie() {}
public Categorie(Integer id, String name) {
this.id = id;
this.name = name;
}
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;
}
}
5.3.4添加DAO接口
package com.bookshop.dao;
import com.bookshop.entity.Categorie;
import java.sql.SQLException;
import java.util.List;
/**
* @author Aiden
*/
public interface CategorieDao {
/**
* 查询所有图书分类
*/
List<Categorie> findAll() throws SQLException;
}
5.3.5添加DAO实现
package com.bookshop.dao.impl;
import com.bookshop.dao.BaseDao;
import com.bookshop.dao.CategorieDao;
import com.bookshop.entity.Categorie;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* 图书分类DAO实现
*
* @author Aiden
*/
public class CategorieDaoImpl implements CategorieDao {
private Connection connection;
public CategorieDaoImpl(Connection connection) {
this.connection = connection;
}
@Override
public List<Categorie> findAll() throws SQLException {
List<Categorie> list = new ArrayList<>();
String sql = "SELECT id,name FROM `categorie`";
PreparedStatement stmt = null;//执行对象
ResultSet rs = null;//结果集
rs = BaseDao.execute(connection, stmt, rs, sql);//调用查询方法
while (rs.next()) {
Categorie categorie = new Categorie(rs.getInt("id"), rs.getString("name"));
list.add(categorie);
}
BaseDao.closeResource(null, stmt, rs);
//释放资源
return list;
}
}
5.3.6添加业务接口
package com.bookshop.service;
import com.bookshop.entity.Categorie;
import java.util.List;
/**
* 图书分类业务接口
*
* @author Aiden
*/
public interface CategorieService {
/**
* 查询所有图书分类
*/
List<Categorie> findAll();
}
5.3.7添加业务实现
package com.bookshop.service.impl;
import com.bookshop.dao.BaseDao;
import com.bookshop.dao.CategorieDao;
import com.bookshop.dao.impl.CategorieDaoImpl;
import com.bookshop.entity.Categorie;
import com.bookshop.service.CategorieService;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* 图书类型业务实现类
* @author Aiden
*/
public class CategorieServiceImpl implements CategorieService {
@Override
public List<Categorie> findAll() {
List<Categorie> list = null;
Connection connection = BaseDao.getConnection();
CategorieDao dao = new CategorieDaoImpl(connection);
try {
list = dao.findAll();
} catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭连接对象
BaseDao.closeResource(connection, null, null);
}
return list;
}
}
5.3.8在JSP页面显示加载数据
<%@ page import="com.bookshop.entity.Categorie" %>
<%@ page import="com.bookshop.service.CategorieService" %>
<%@ page import="com.bookshop.service.impl.CategorieServiceImpl" %>
<%@ page import="java.util.List" %>
<%@ page language="java" pageEncoding="UTF-8" %>
<div id="basket"><a href="#">目前您的购物篮是空的</a></div>
<div id="search">
<form action="" method="post" target="_blank">
<input type="text" class="search_key"/>
<input type="submit" class="search_sub" value=""/>
</form>
</div>
<div id="alltype">
<h1 class="all_type black"><a href="#">查看所有分类>></a></h1>
<div id="subnav">
<ul class="black">
<%
//实例化图书类型业务对象
CategorieService categorieService = new CategorieServiceImpl();
//查询所有图书类型列表
List<Categorie> list = categorieService.findAll();
if (list != null) {
for (Categorie categorie : list) {
%>
<li>
<a href="#"><%=categorie.getName()%></a>
</li>
<%
}
}
%>
</ul>
</div>
<!--subnav end-->
</div>
<!--link start-->
<div id="choice_pub">
<select name="publishs" id="publishs" class="n_select">
<option>>>根据出版社选择图书</option>
<option>北京师范大学出版社</option>
<option>电子工业出版社</option>
</select>
<select name="publishs" id="special" class="n_select">
<option>>>根据专题选择图书</option>
<option>国庆出游专题</option>
<option>新年计划专题</option>
</select>
</div>
<div id="s_b_03"><a href="#">赖世雄美语从头学</a><br/><a href="#">沪江团购 ,价格更优惠</a></div>
5.3.9运行结果
六、总结
思维导图
学习讨论群: 617530501