jsp:javaBean
一、javaBean简介
javaBean是使用java语言开发的一个人可重用的组件,在jsp开发中可以使用javaBean减少重复的代码,是一种特殊的java类,使用java语言编写,遵循javaBean API规范
优点
- 将html和java代码分离,这主要是为了日后的维护方便
- 减少代码重复
在jsp中如果要应用jsp提供的javaBean的标签来操作简单类,则此类要满足以下要求:
- 所有类都要在一个包中,在web项目中没有包的类时不存在的。
- 所有类必须是public修饰,这样才能被外界访问。
- 提供一个默认的无参构造函数。
- 需要被序列化并且实现了 Serializable 接口。
- 可能有一系列可读写属性。(可能的意思就是除了private修饰的字段,也可以有其他修饰符修饰的字段,但是必须至少要有一个private修饰的字段)
- 可能有一系列的 getter 或 setter 方法。
二、在jsp中使用javaBean
一个javaBean编写结束后,需要进行打包编译,那么存放到哪里呢?
classes目录保存所有的javaBean,如果不存在则可以手动创建(WEBAPP/WEB-INFO/classes)
引入useBean
- 打包编译
直接使用javac -d.类名,根据该类的路径的定义来打包编译变为class文件,在web开发中,tomcat安装目录的lib文件夹、WEB-INFO\classes和WEB-INFO\lib文件夹实际上都表示了classpath,所以直接将类或者jar包复制到这些文件夹中就可以直接使用了。
- 使用jsp:useBean指令,语法:
<jsp:useBean id="实例化对象名称(自己命名)" scope="作用范围" class="包.类名">
- 使用jsp中的page指令导入所需要的javaBean
<%@ page import=""%>
三、javaBean属性
1. 一个 JavaBean 对象的属性应该是可访问的。这个属性可以是任意合法的 Java 数据类型,包括自定义 Java 类。
2. 一个 JavaBean 对象的属性可以是可读写,或只读,或只写。JavaBean 对象的属性通过 JavaBean 实现类中提供的两个方法来访问:
方法 | 描述 |
---|---|
getPropertyName() | 举例来说,如果属性的名称为 myName,那么这个方法的名字就要写成 getMyName() 来读取这个属性。这个方法也称为访问器。 |
setPropertyName() | 举例来说,如果属性的名称为 myName,那么这个方法的名字就要写成 setMyName()来写入这个属性。这个方法也称为写入器。 |
一个只读的属性只提供 getPropertyName() 方法,一个只写的属性只提供 setPropertyName() 方法。
四 、jvaBean实例程序
package taeyeon.com.jsp.javaBean;
import java.io.Serializable;
public class JavaBean_1 implements Serializable {
private String firstName;
private String lastName;
private Integer age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
五、访问javaBean
接下来给出的是 jsp:useBean 标签的一个简单的用法:
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>javaBean的测试</title>
</head>
<body>
<jsp:useBean id="date" scope="page" class="java.util.Date" />
<%
String date1=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
%>
<p>日期为<%=date1%>
</body>
</html>
输出
日期为2019-11-07 23:14:59
六、javaBean的保存范围
scope 的值可以是 page,request,session 或 application。id值可任意只要不和同一 JSP 文件中其它 jsp:useBean 中 id 值一样就行了。
七、访问javaBean对象的属性
在 jsp:useBean 标签主体中使用 jsp:getProperty/ 标签来调用 getter 方法,使用 jsp:setProperty/ 标签来调用 setter 方法,语法格式如下:
<jsp:useBean id="id" class="bean 编译的类" scope="bean 作用域">
<jsp:setProperty name="bean 的 id" property="属性名"
value="value"/>
<jsp:getProperty name="bean 的 id" property="属性名"/>
...........
</jsp:useBean>
name属性指的是Bean的id属性。property属性指的是想要调用的getter或setter方法。
接下来给出使用以上语法进行属性访问的一个简单例子:
<%--
Created by IntelliJ IDEA.
User: YOONA
Date: 2019/11/7/007
Time: 23:00
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>javaBean的Property </title>
</head>
<body>
<jsp:useBean id="student" scope="page" class="taeyeon.com.jsp.javaBean.JavaBean_1">
<jsp:setProperty name="student" property="firstName" value="teayeon"/>
<jsp:setProperty name="student" property="lastName" value="西西"/>
<jsp:setProperty name="student" property="age" value="19"/>
</jsp:useBean>
<p>学生名字:
<jsp:getProperty name="student" property="firstName"/>
</p>
<p>学生姓氏:
<jsp:getProperty name="student" property="lastName"/>
</p>
<p>学生年龄:
<jsp:getProperty name="student" property="age"/>
</p>
</body>
</html>
输出
学生名字: teayeon
学生姓氏: 西西
学生年龄: 19
八、javaBean的删除
当不再使用javaBean的时候,我们可以使用4种属性范围的removeAttribute()方法进行删除。
- 删除page域:pageContext.removeAttribute(javaBean名称id);
- 删除request域:request.removeAttribute(javaBean名称id);
- 删除session域:session.removeAttribute(javaBean名称id);
- 删除application域:application.removeAttribute(javaBean名称id);
删除session范围的javaBean
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>通过removeAttribute()方法进行删除javaBean</title>
</head>
<body>
<jsp:useBean id="sessionScope" scope="session" class="taeyeon.com.jsp.javaBean.JavaBean_1">
<jsp:setProperty name="sessionScope" property="age" value="21"/>
</jsp:useBean>
<p>年龄1:<jsp:getProperty name="sessionScope" property="age"/></p>
<%
session.removeAttribute("sessionScope");
%>
<p>年龄2:<jsp:getProperty name="sessionScope" property="age"/></p>
</body>
</html>
输出
当我们不使用session.removeAttribute("sessionScope");
这行语句时系统运行正常,但是当我们使用时,就会报错在<p>年龄2:<jsp:getProperty name="sessionScope" property="age"/></p>
报错,因为运行到这一行时该id的javaBean已经被删除了,所以会报错500:java.lang.NullPointerException
年龄1:21
九、dao设计模式
1. DAO设计模式简介
DAO的主要功能就是数据操作,在程序的标准开发构架中属于数据层的操作,程序的标准开发构架如下:
客户层 -->显示层(servlet、jsp)-->业务层(BO)-->数据层(DAO)-->(资源层)DataBase
- 客户层:因为现在都采用B/S开发构架,所以一般都是用浏览器进行访问。
- 显示层:使用jsp、Servlet进行页面效果的显示。
- 业务层:会将多个原生的DAO操作进行组合,组合成一个完整的业务逻辑。
- 数据层:提供多个原子性的DAO操作,如增删改,都属于原子性操作。
在整个DAO中实际上是以接口为操作标准的,即客户端依靠DAO实现的接口进行操作,而服务器端将接口进行具体的实现。DAO由以下几部分组成。
-
DatabaseConnection:专门负责数据库打开与关闭操作的类;
-
VO:主要由属性,setter,getter方法组成,VO类中的属性与表中的字段相对应,每一个VO类的对象都表示表中的每一条记录;
-
DAO:主要定义操作的接口,定义一系列数据库的原子性操作,例如增删改查等;
-
Impl: DAO接口的真实实现类,主要完成具体数据库操作,但不负责数据库的打开和关闭;
-
Proxy:代理实现类,主要完成数据库的打开和关闭并且调用真实实现类对象的操作;
-
Factory: 工厂类,通过工厂类取得一个DAO的实例化对象。
对于包的命名:
一个好的程序必须要有严格的命名要求,在使用DAO定义操作时一定要注意包的命名很严格,使用如下方式命名:
- 数据库连接: xxx.dbc.DatabaseConnection
- DAO接口: xxx.dao.IXxxDAO
- DAO接口真实实现类:xxx.dao.impl.XxxDAOImpl
- DAO接口代理实现类:xxx.dao.proxy.XxxDAOProxy
- VO类:xxx.vo.Xxx, VO命名要与表的命名一致
- 工厂类:xxx.factory.DAOFactory.
2. DAO开发
- 用户注册信息表user
create table user
(
ID int auto_increment comment '序列号',
NAME varchar(50) not null, -- 姓名
USERNAME varchar(100) primary key not null, -- 用户名(登陆名)
PASSWORD varchar(30) null, -- 密码
SEX char(5) null, --性别
TEL varchar(20) null, -- 电话
PWDTROUBLE1 varchar(100) null, -- 密保问题1
ANSWER1 varchar(100) null,-- 答案1
PWBTROUBLE2 varchar(100) null, -- 密保问题2
ANSWER2 varchar(100) null, --答案2
constraint user_ID_uindex --索引
unique (ID)
)
comment '用户信息表';
- 下面按照DAO的方式完成后端代码的开发,首先定义VO类,VO类的名称与表的名称一致,类的首字母大写,该类表示当前用户,可以存储一些该用户的属性。
package taeyeon.com.dao_1;
import java.io.Serializable;
/**
* 定义用户信息类,保存用户个人信息
*/
public class User implements Serializable {
private String name;//用户姓名
private String username;//登陆名
private String password;//密码
private String tel;//电话
private String sex;//性别
private String pwdtrouble1;//密保问题
private String answer1;//答案
private String pwbtrouble2;
private String answer2;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public String getPwdtrouble1() {
return pwdtrouble1;
}
public void setPwdtrouble1(String pwdtrouble1) {
this.pwdtrouble1 = pwdtrouble1;
}
public String getAnswer1() {
return answer1;
}
public void setAnswer1(String answer1) {
this.answer1 = answer1;
}
public String getPwbtrouble2() {
return pwbtrouble2;
}
public void setPwbtrouble2(String pwbtrouble2) {
this.pwbtrouble2 = pwbtrouble2;
}
public String getAnswer2() {
return answer2;
}
public void setAnswer2(String answer2) {
this.answer2 = answer2;
}
}
- 定义数据库连接和关闭的操作接口
package taeyeon.com.dao_1;
import java.sql.Connection;
/**
* 定义数据库的链接与关闭接口
*/
public interface DatabaseConnection {
public Connection getConnection();
public void close();
}
- 定义一个用于打开关闭数据库操作的类,实现DatabaseConnection接口
package taeyeon.com.dao_1;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
@SuppressWarnings("ALL")
/**
* 实现数据库的链接与关闭接口
* @param URL:mysql链接的url
* @param NAME:用户名
* @param PASSWORD:链接密码
* @param DRIVER:mysql链接的jdbc驱动
*/
public class UserDatabaseConnection implements DatabaseConnection {
private static final String URL = "jdbc:mysql://localhost:3306/student";
private static final String NAME = "lining";
private static final String PASSWORD = "123456";
private static final String DRIVER = "com.mysql.jdbc.Driver";
private Connection connection;
public UserDatabaseConnection() {
try {
Class.forName(DRIVER);
this.connection = DriverManager.getConnection(URL, NAME, PASSWORD);
} catch (Exception e) {
e.printStackTrace();
}
}
//取得当前对象数据库链接
@Override
public Connection getConnection() {
return this.connection;
}
//关闭当前对象数据链接
@Override
public void close() {
if (this.connection != null) {
try {
this.connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
- 创建实现数据库连接关闭类UserDatabaseConnection的工厂类,该类可以直接获取其他类的实例。
package taeyeon.com.dao_1;
/**
* 创建链接类的工厂<br/>
* 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。<br/>
* 通过专门定义一个类来负责创建其它类的实例,被创建的实例通常<br/>
* 都具有共同的父类。
*/
public class UserDatabaseConnectionFactory {
public static DatabaseConnection getDatabaseConnection(){
return new UserDatabaseConnection();
}
}
- 定义DAO接口,用于实现用户具体对数据库的操作,比如对数据的增删改查。
package taeyeon.com.dao_1;
import java.util.List;
import java.util.Map;
/**
*定义操作数据库的方法
*/
public interface IUserDAO {
/**
* 修改数据(增加,跟新)
*/
public boolean doModify(String state, String username, Map<String,String> map,User userMsg);
/**
* 修改密码
*/
public boolean doModifyPWD(String username,String pwd);
/**
* 查询数据(按照登陆名来查询信息)
*/
public List<User> doSelect(String username);
}
- 创建用于实现IUserDAO接口的类
package taeyeon.com.dao_1;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
@SuppressWarnings("ALL")
public class UserDaoImpl implements IUserDAO {
private Connection conn;
private PreparedStatement pst;
//当创建该类的对象时获得链接
public UserDaoImpl(Connection conn) {
this.conn = conn;
}
/**
* 判断是否修改数据成功(增加,更新)
*
* @param state=(I,U) I代表新增注册信息,U代表用户修改基本数据
* @param username:表示当前登录的用户名
* @param map:用于当前用户更新数据。除掉密码修改,密码修改有单另的方法和界面
* @param userMsg:用于新增数据的对象
* @return
*/
@Override
public boolean doModify(String state, String username, Map<String, String> map, User userMsg) {
boolean flag = false;
if ("I" == state) {
//新增用户数据时,用的是注册的信息,所以可以使用getXXX来获取User类的数据
String sql = "INSERT INTO USER ( NAME , USERNAME ,PASSWORD , SEX , TEL , PWDTROUBLE1 ," +
" ANSWER1 , PWBTROUBLE2 , ANSWER2,LOGINDATE ) VALUES (?,?,?,?,?,?,?,?,?,sysdate)";
try {
this.pst = this.conn.prepareStatement(sql);
this.pst.setString(1, userMsg.getName());
this.pst.setString(2, userMsg.getUsername());
this.pst.setString(3, userMsg.getPassword());
this.pst.setString(4, userMsg.getSex());
this.pst.setString(5, userMsg.getTel());
this.pst.setString(6, userMsg.getPwdtrouble1());
this.pst.setString(7, userMsg.getAnswer1());
this.pst.setString(8, userMsg.getPwbtrouble2());
this.pst.setString(9, userMsg.getAnswer2());
if (this.pst.executeUpdate() > 0) {//判断该链接对象运行的sql语句返回受影响行数是否大于0
flag = true;
}
this.pst.close();
} catch (Exception e) {
e.printStackTrace();
}
} else {
//更新数据是使用登录后的用户this,将修改界面的数据更新到该用户名的数据中
if (map.size() != 0) {
String name = map.get("NAME");
String username1 = map.get("USERNAME");//修改的用户名
String sex = map.get("SEX");
String tel = map.get("TEL");
String pwdtrouble1 = map.get("PWDTROUBLE1");
String answer1 = map.get("ANSWER1");
String pwbtrouble2 = map.get("PWBTROUBLE2");
String answer2 = map.get("ANSWER2");
String sql = "UPDATE USER SET NAME=" + name + " , USERNAME=" + username1 + " , SEX =" + sex + " , " +
"TEL=" + tel + " , PWDTROUBLE1 =" + pwdtrouble1 + " ," +
" ANSWER1 =" + answer1 + ", PWBTROUBLE2=" + pwbtrouble2 + " , ANSWER2 =" + answer2 + ") " +
"WHERE USERNAME= ? ";
try {
this.pst = this.conn.prepareStatement(sql);
this.pst.setString(1, username);
if (this.pst.executeUpdate() > 0) {
flag = true;
}
this.pst.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
return flag;
}
/**
* 修改密码
* 利用当前用户的用户名来查找该密码,进行更改登录密码
*
* @param username:当前用户的用户名
* @return
*/
@Override
public boolean doModifyPWD(String username, String pwd) {
boolean flag = false;
String sql = "UPDATE USER SET PASSWORD=? WHERE USERNAME =?";
try {
this.pst = this.conn.prepareStatement(sql);
this.pst.setString(1, pwd);
this.pst.setString(2, username);
if (this.pst.executeUpdate() > 0) {
flag = true;
}
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* @param username:根据用户登录名来查询客户基本信息然后返回到信息页面上
* @return 将用户信息保存在list集合中
*/
@Override
public List<User> doSelect(String username) {
String sql = "SELECT NAME , USERNAME , SEX , TEL , PWDTROUBLE1 ,ANSWER1, PWBTROUBLE2, " +
"ANSWER2 FROM USER WHERE USERNAME=?";
List<User> userList = null;
try {
this.pst = this.conn.prepareStatement(sql);
ResultSet rs = this.pst.executeQuery();
if (this.pst.execute()) {//如果返回的有结果集
while (rs.next()) {
User user = new User();
user.setName(rs.getString(1));
user.setUsername(rs.getString(2));
user.setSex(rs.getString(3));
user.setTel(rs.getString(4));
user.setPwdtrouble1(rs.getString(5));
user.setAnswer1(rs.getString(6));
user.setPwbtrouble2(rs.getString(7));
user.setAnswer2(rs.getString(8));
userList.add(user);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return userList;
}
}
- 创建用于具体操作用户数据的代理类,用于连接操作关闭数据库。
package taeyeon.com.dao_1;
import java.util.List;
import java.util.Map;
/**
* 用来实行数据库连接,数据库操作,关闭数据库
*/
public class IUserDAOProxy implements IUserDAO {
private DatabaseConnection dbc = null;
private IUserDAO dao = null;
public IUserDAOProxy() {
this.dbc = UserDatabaseConnectionFactory.getDatabaseConnection();
this.dao = new UserDaoImpl(this.dbc.getConnection());//获得数据库连接
}
@Override
public boolean doModify(String state, String username, Map<String, String> map, User userMsg) {
boolean flag = false;
flag = this.dao.doModify(state, username, map, userMsg);
return flag;
}
@Override
public boolean doModifyPWD(String username, String pwd) {
boolean flag = false;
flag = this.dao.doModifyPWD(username, pwd);
return flag;
}
@Override
public List<User> doSelect(String username) {
List<User> list = null;
list = this.dao.doSelect(username);
return list;
}
}
- 创建该代理类的工厂类
package taeyeon.com.dao_1;
public class IUserDAOProxyFactory {
public static IUserDAOProxy getIUserDAOInstance() {
return new IUserDAOProxy();
}
}
在书写dao设计模式的开发时,要做到低耦合,这样才能减少每个类之间的依赖性,降低后期维护的难度
八、总结
- 使用javaBean可以减少jsp中的代码重复,以达到程序的重用功能。
- 在jsp中定义了jsp:useBean,jsp:setProperty,jsp:getProperty3个标签支持javaBean操作
- javaBean存在page,request,session,application四种操作域,可以用removeAttribute()删除这四种属性范围中设置的属性。
- DAO设计模式可以完成数据层的开发,首先使用DAO定义数据表的操作标准,即具体对数据的操作,然后通过代理类和真实实现类实现接口的具体操作,真实实现类只操作数据,代理类实现对数据库的连接,数据库的关闭,调用具体实现类实现对数据的操作,所有DAO接口的实例要通过工厂类取得。