将jsp,servelt,jstl,EL一起使用,写一个小demo学生管理系统。
在学生管理系统中,我们要定义三层架构,首先,
什么是三层?
1.数据展示层:主要是指与用户交互的页面,用于接用户输入的数据和显示处理用户需要的数据
2.业务逻辑层:数据展示和数据访问之间的桥梁,实现业务逻辑。
3.数据访问层:与数据库打交道,主要实现对数据的更新(增删改)和查询。将存储在数据库中的数据提交给业务层,或将业务层处理的数据存储到数据库中。
其次,为什么要使用三层
简单来说就是为了实现"高内聚低耦合"。
当项目中有变化,只需要改变相应的层,不需要对整个项目进行整改。层次清晰,分工明确,每层之间耦合度低,提高效率,可维护性高,可扩展性高。
三层架构的优势:
1.结构清晰,耦合度低
2.可维护性高,可扩展性高
3.利于开发任务同步进行,适应需求变化
三层架构的劣势:
1.降低了系统性能。
2.增加了代码量。
3.增加新的方法会变得麻烦。
那么三层架构表现形式
- entity--实体类,
- dao层--定义规范,不关心实现
- dao层实现
- service--业务逻辑,定义规范
- service实现
- servlet--存放servlet
- utils--工具类
entity实体类实现面向对象中的封装。
在我们的学生表中
那么对应的entity中的实体类即为:
package com.stu_clss.entity;
/**
* 与stu表产生映射
* @author ljf
*
*/
public class Stu {
//封装属性
private Integer id;
private String sname;
private String sex;
private String age;
private String hobby;
private Integer cid;
/**
提供对应的set/get方法
*/
}
实体类中属性对应表字段。
在dao层中定义方法规范
public int add(Stu stu); //添加方法
那么就需要实现类来实现这些方法
dao.impl中
@Override
public int add(Stu stu) {
编写sql并执行
将执行结果返回
}
由此我们不难发现,对于每一个方法就需要编写一个执行sql语句的方法,如果有多张表,就会有大量的重复代码,因此我们可以将重复代码,封装到工具类utils.BaseDao中。
/**
在BaseDao中,首先将四大参数driver,url,username,password设置
并声明连接池,注意声明为静态
*/
static{
//创建连接池
cmp = new ComboPooledDataSource();
//绑定四大参数
try {
cmp.setDriverClass(driver);
} catch (PropertyVetoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cmp.setJdbcUrl(url);
cmp.setUser(user);
cmp.setPassword(password);
}
在jdbc我们知道,增删改执行的一个方法,那么在工具类中
//定义方法
//增删改执行一个方法
public int update(String sql,Object... params ){
//创建queryrunner对象 传入连接池
QueryRunner qr = new QueryRunner(cmp);
//接收受影响行数
int row = -1;
try {
//执行sql;
row = qr.update(sql, params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return row;
}
而查询方法,需要知道查询到的类型,需要我们传入一个泛型,谁调用就返回谁
//单个查询
//引入泛型 谁调用就返回谁
public T getone(String sql,Class<T> cls,Object... params ){
//创建queryrunner对象 传入连接池
QueryRunner qr = new QueryRunner(cmp);
//执行sql
/*
* 第二个参数
* beanhandler
* 结果集-->实体类
*/
T t=null;
try {
t = qr.query(sql, new BeanHandler<T>(cls), params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return t;
}
//多个查询
public List<T> getall(String sql,Class<T> cls,Object... params){
//创建queryrunner对象 传入连接池
QueryRunner qr = new QueryRunner(cmp);
//执行sql
/*
* 第二个参数
* beanhandler
* 结果集-->实体类
*/
List<T> list=null;
try {
list = qr.query(sql, new BeanListHandler<T>(cls), params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
}
到此,我们的BaseDao工具类编写完毕,在dao层实现中继承我们的工具类即可
那么对应的方法实现就会变得非常简单
@Override
public int add(Stu stu) {
String sql = "insert into stu values(0,?,?,?,?,?)";
int row = update(sql, stu.getSname(),stu.getSex(),stu.getAge(),
stu.getHobby(),stu.getCid());
return row;
}
在service接口中也是定义逻辑规范,在实现类中创建dao层对象,并编写逻辑处理
/**
* 定义逻辑规范
* @author ljf
*
*/
public interface Stu_service {
public int add(Stu stu);
}
public class Stu_service_impl implements Stu_service {
//封装Stu_dao 对象
private Stu_dao sd = new Stu_dao_impl();
@Override
public int add(Stu stu) {
int row = sd.add(stu);
return row;
}
}