JSP开发模式
模式一:JSP+JavaBean
模式二:JSP+JavaBean+Servlet
两种模式利用图片的方式展示如下。
三层架构与MVC的联系如图所示。
学生管理系统
- 数据库搭建
建立一个stus数据库,由于整个学生管理系统只涉及学生,因此建立一个stu表。
CREATE DATABASE stus;
USE stus;
CREATE TABLE stu (
id INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR (20),
gender VARCHAR (5),
phone VARCHAR (20),
birthday DATE,
hobby VARCHAR(50),
info VARCHAR(200)
);
- 环境搭建
系统主要包括dao包、domain包、service包、servlet包、util包。其中dao包用于数据的封装处理;domain包用于定义Bean;service包用于调用dao包中的函数;servlet包用于控制请求、数据调用与反馈;util包用于存储一些必要的工具函数。整个结构如下图所示。
如下图所示显示数据在各个包中传输方向,并阐述了为什么有service包。
3. 查询
1)写一个JSP页面,里面放一个超链接
<a href="StudentListServlet"> 学生列表显示</a>
2)写servlet,接收请求——>调用service——>service调用dao
3)先写dao,再写daoImpl
/**
* 查询所有学生
* @return List<Student>
*/
public interface StudentDao {
List<Student> findAll() throws SQLException ;
}
/**
* daoImpl包中findAll()的实现
* @return List<Student>
*/
public class StudentDaoImpl implements StudentDao {
public List<Student> findAll() throws SQLException {
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
return runner.query("select * from stu", new BeanListHandler<Student>(Student.class));
}
}
4)写service,再写serviceImpl
public interface StudentService {
/**
* 查询所有学生
* @return List<Student>
*/
List<Student> findAll() throws SQLException ;
}
/**
* 这是学生业务实现
* @author sj
*/
public class StudentServiceImpl implements StudentService{
@Override
public List<Student> findAll() throws SQLException {
StudentDao dao = new StudentDaoImpl();
return dao.findAll();
}
}
5)在servlet中 存储数据,并且做出页面响应
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//1. 查询出来所有的学生
StudentService service = new StudentServiceImpl();
List<Student> list = service.findAll();
//2. 先把数据存储到作用域中
request.setAttribute("list", list);
//3. 跳转页面
request.getRequestDispatcher("list.jsp").forward(request, response);
} catch (SQLException e) {
e.printStackTrace();
}
6)在显示层显示数据
<table border="1" width="1200" >
<tr>
<td colspan="8">
<a href="add.jsp">添加</a>
</td>
</tr>
<tr align="center">
<td>编号</td>
<td>姓名</td>
<td>性别</td>
<td>电话</td>
<td>生日</td>
<td>爱好</td>
<td>操作</td>
</tr>
<c:forEach var="stu" items="${requestScope.list}">
<tr align="center">
<td>${stu.id }</td>
<td>${stu.sname }</td>
<td>${stu.gender }</td>
<td>${stu.phone }</td>
<td>${stu.birthday }</td>
<td>${stu.hobby }</td>
<td>${stu.info }</td>
<td><a href="#" >更新</a> <a href="#" >删除</a></td>
</tr>
</c:forEach>
</table>
- 添加
1)先跳转到添加的页面
<form action="AddStudentServlet" method="post">
<table border="1" width="600">
<tr>
<td>姓名</td>
<td><input type="text" name="sname"></td>
</tr>
<tr>
<td>性别</td>
<td>
<input type="radio" name="gender" value="男" checkd>男
<input type="radio" name="gender" value="女">女
</td>
</tr>
<tr>
<td>电话</td>
<td><input type="text" name="phone"></td>
</tr>
<tr>
<td>生日</td>
<td><input type="text" name="birthday"></td>
</tr>
<tr>
<td>爱好</td>
<td>
<input type="checkbox" name="hobby" value="游泳">游泳
<input type="checkbox" name="hobby" value="篮球">篮球
<input type="checkbox" name="hobby" value="乒乓球">乒乓球
<input type="checkbox" name="hobby" value="看书">看书
<input type="checkbox" name="hobby" value="写字">写字
</td>
</tr>
<tr>
<td>简介</td>
<td><textarea name="info" rows="3" cols="20"></textarea></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="添加"></td>
</tr>
</table>
</form>
2)点击添加——>提交数据到AddServlet,servlet处理数据
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
try {
//1. 获取客户端提交上来的数据
String sname = request.getParameter("sname"); //sname:sj
String gender = request.getParameter("gender");
String phone = request.getParameter("phone");
String birthday = request.getParameter("birthday"); // 1998-12-18
String info = request.getParameter("info");
//String hobby = request.getParameter("hobby");//hobby有多个值(: 游泳,写字, 足球),因此无法使用getParameter取值
String [] h = request.getParameterValues("hobby");
// 爱好的value值有多少个。
String hobby = Arrays.toString(h); //这里将数组转化为字符串
hobby = hobby.substring(1, hobby.length()-1); //去掉[]
//2. 添加到数据库
//string --> date
Date date= new SimpleDateFormat("yyyy-MM-dd").parse(birthday);
Student student = new Student(sname, gender, phone, hobby, info, date);
StudentService service = new StudentServiceImpl();
service.insert(student);
//3. 跳转到列表页
//再查一次数据库,然后再装到作用域中 ,然后再跳转。
//这里是直接跳转到页面上, 那么这个页面会重新翻译一次,上面的那个request的请求存放的数据是没有了。
//完成了这些存储工作后,需要跳转到列表页面。这里不能直接跳转到列表页面,否则没有什么内容显示。应该先跳转到查询到所有学生信息的那个Servlet,由StudentListServlet再去跳转到列表页面。
//request.getRequestDispatcher("list.jsp").forward(request, response);
//servlet除了能跳jsp之外。 还能跳servlet
request.getRequestDispatcher("StudentListServlet").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
3)生成service对象,并使用serviceImpl
/**
* 添加学生
* @param student 需要添加到数据库的学生对象
* @throws SQLException
*/
void insert(Student student) throws SQLException ;
/**
serviceImpl包
*/
public void insert(Student student) throws SQLException {
StudentDao dao = new StudentDaoImpl();
dao.insert(student);
}
``
4)调用dao,完成数据库持久化
```java
public void insert(Student student) throws SQLException {
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
runner.update("insert into stu values(null , ?,?,?,?,?,?)" ,
student.getSname(),
student.getGender(),
student.getPhone(),
student.getBirthday(),
student.getHobby(),
student.getInfo()
);
}
- 删除
1)点击超链接,弹出一个确定是否删除的询问对话框,如果点击确定,直接删除。
<a href="#" onclick="doDelete(${stu.sid})">删除</a>
<!--让超链接,执行一个js方法-->
<script type="text/javascript">
function doDelete(id) {
/* 如果这里弹出的对话框,用户点击的是确定,就马上去请求Servlet。 */
var flag = confirm("是否确定删除?");
if(flag){
//表明点了确定。 访问servlet。 在当前标签页上打开 超链接,
//window.location.href="DeleteServlet?sid="+sid; 该方法也可以使用
location.href="DeleteServlet?id="+id;
}
}
</script>
- 在js访问里面判断点击的选项,然后跳转到DeleteServlet。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//1. 接收id
int id = Integer.parseInt(request.getParameter("id"));
//2. 执行删除
StudentService service = new StudentServiceImpl();
service.delete(id);
//3. 跳转到列表页。
request.getRequestDispatcher("StudentListServlet").forward(request, response);
} catch (SQLException e) {
e.printStackTrace();
}
}
- 使用service ——> service去调用dao
/**
调用daoimpl中的delete
*/
public void delete(int id) throws SQLException {
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
runner.update("delete from stu where id=?" ,id);
}
- 更新
1) 点击列表上的更新, 先跳转到一个EditServlet
在这个servlet里面,先根据ID 去查询这个学生的所有信息,并显示在页面中。
<td><a href="EditStudentServlet?id=${stu.id }" >更新</a> <a href="#" onclick="doDelete(${stu.id})">删除</a></td>
/**
EditServlet,更新数据
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//1. 接收id
int id = Integer.parseInt(request.getParameter("id"));
//2. 查询学生数据
StudentService service = new StudentServiceImpl();
Student stu = service.findStudentById(id);
//3. 显示数据
//存数据
request.setAttribute("stu", stu);
//跳转
request.getRequestDispatcher("edit.jsp").forward(request, response);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
ServiceImpl中
*/
public Student findStudentById(int id) throws SQLException {
StudentDao dao = new StudentDaoImpl();
return dao.findStudentById(sid);
}
/**
DaoImpl中
*/
public Student findStudentById(int id) throws SQLException {
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
return runner.query("select * from stu where id = ?", new BeanHandler<Student>(Student.class) ,sid);
}
2)由list.jsp(展示)页面跳转到edit.jsp(更新)页面,然后在页面上显示要编辑学生的数据
<form method="post" action="UpdateServlet">
<!--提交上来的数据是没有带id的,所以我们要手动创建一个隐藏的输入框, 在这里面给定id的值, 以便提交表单,带上id。 -->
<input type="hidden" name="sid" value="${stu.sid }">
<table border="1" width="600">
<tr>
<td>姓名</td>
<td><input type="text" name="sname" value="${stu.sname }"></td>
</tr>
<tr>
<td>性别</td>
<td>
<!-- 如果性别是男的, 可以在男的性别 input标签里面, 出现checked ,
如果性别是男的, 可以在女的性别 input标签里面,出现checked -->
<input type="radio" name="gender" value="男" <c:if test="${stu.gender == '男'}">checked</c:if>>男
<input type="radio" name="gender" value="女" <c:if test="${stu.gender == '女'}">checked</c:if>>女
</td>
</tr>
<tr>
<td>电话</td>
<td><input type="text" name="phone" value="${stu.phone }"></td>
</tr>
<tr>
<td>生日</td>
<td><input type="text" name="birthday" value="${stu.birthday }"></td>
</tr>
<tr>
<td>爱好</td>
<td>
<!-- 爱好: 篮球 , 足球 , 看书
因为爱好有很多个, 里面存在包含的关系 -->
<input type="checkbox" name="hobby" value="游泳" <c:if test="${fn:contains(stu.hobby,'游泳') }">checked</c:if>>游泳
<input type="checkbox" name="hobby" value="篮球" <c:if test="${fn:contains(stu.hobby,'篮球') }">checked</c:if>>篮球
<input type="checkbox" name="hobby" value="足球" <c:if test="${fn:contains(stu.hobby,'足球') }">checked</c:if>>足球
<input type="checkbox" name="hobby" value="看书" <c:if test="${fn:contains(stu.hobby,'看书') }">checked</c:if>>看书
<input type="checkbox" name="hobby" value="写字" <c:if test="${fn:contains(stu.hobby,'写字') }">checked</c:if>>写字
</td>
</tr>
<tr>
<td>简介</td>
<td><textarea name="info" rows="3" cols="20">${stu.info }</textarea></td>
</tr>
<tr>
<td colspan="2"> <input type="submit" value="提交"> </td>
</tr>
</table>
</form>
3)修改完毕后,点击提交,将数据传送到UpdateServlet,获取数据——>使用service——> 调用dao.
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
try {
//1. 获取客户端提交上来的数据
int id = Integer.parseInt(request.getParameter("id"));
String sname = request.getParameter("sname"); //sname:zhangsan
String gender = request.getParameter("gender");
String phone = request.getParameter("phone");
String birthday = request.getParameter("birthday"); // 1989-10-18
String info = request.getParameter("info");
//String hobby = request.getParameter("hobby");//hobby : 游泳,写字, 足球。
String[] h = request.getParameterValues("hobby");
// [篮球,足球,写字] --- 篮球,足球,写字
String hobby = Arrays.toString(h);
hobby = hobby.substring(1, hobby.length() - 1);
//2. 添加到数据库
//string -->date
Date date = new SimpleDateFormat("yyyy-MM-dd").parse(birthday);
Student student = new Student(id ,sname, gender, phone, hobby, info, date);
//2. 更新数据库数据
StudentService service = new StudentServiceImpl();
service.update(student);
//3. 跳转界面
request.getRequestDispatcher("StudentListServlet").forward(request, response);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
serviceImpl包中
*/
public void update(Student student) throws SQLException {
StudentDao dao = new StudentDaoImpl();
dao.update(student);
}
/**
daoImpl包中
*/
public void update(Student student) throws SQLException {
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
runner.update("update stu set sname=? , gender=? , phone=? , birthday=? , hobby=? , info=? where sid = ?",
student.getSname(),
student.getGender(),
student.getPhone(),
student.getBirthday(),
student.getHobby(),
student.getInfo(),
student.getId());
}
- 模糊查询
1)编写模糊查询入口
<body>
<form action="SearchStudentServlet" method="post">
<table border="1" width="700">
<tr >
<td colspan="8">
按姓名查询:<input type="text" name="sname"/>
按性别查询:<select name="gender">
<option value="">--请选择--
<option value="男">男
<option value="女">女
</select>
<input type="submit" value="查询">
<a href="add.jsp">添加</a>
</td>
</tr>
</table>
</form>
</body>
2)跳转到servlet并调用service,并调用dao。
/**
模糊查询
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
try {
//1. 取到了要查询的关键数据 姓名 , 性别。
String sname= request.getParameter("sname");
String sgender= request.getParameter("sgender");
//2. 找service去查询
StudentService service = new StudentServiceImpl();
List<Student> list = service.searchStudent(sname, sgender);
System.out.println("list的大小是:"+list.size());
for (Student student : list) {
System.out.println("stu="+student);
}
request.setAttribute("list", list);
//3. 跳转界面。列表界面
request.getRequestDispatcher("list.jsp").forward(request, response);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
在serviceImpl包中
*/
public List<Student> searchStudent(String sname, String sgender) throws SQLException {
return new StudentDaoImpl().searchStudent(sname, sgender);
}
/**
在daoImpl包中
*/
public List<Student> searchStudent(String sname, String sgender) throws SQLException {
System.out.println("现在要执行模糊查询了,收到的name ="+sname + "==genser=="+sgender);
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
//String sql = "select * from stu where sname=? or sgender=?";
/*
* 这里要分析一下:
* 如果只有姓名 ,select * from stu where sname like ? ;
* 如果只有性别 , select * from stu where gender = ?
*
* 如果两个都有 select * from stu where sname like ? and gender=?
*
* 如果两个都没有就查询所有。
*
*/
String sql = "select * from stu where 1=1 ";
List<String> list = new ArrayList<String> ();
//判断有没有姓名, 如果有,就组拼到sql语句里面
if(!TextUtils.isEmpty(sname)){
sql = sql + " and sname like ?";
list.add("%"+sname+"%");
}
//判断有没有性别,有的话,就组拼到sql语句里面。
if(!TextUtils.isEmpty(sgender)){
sql = sql + " and gender = ?";
list.add(sgender);
}
return runner.query(sql , new BeanListHandler<Student>(Student.class) ,list.toArray() );
}
/**
判断传入的字符是否为空
*/
public class TextUtils {
/**
* 判断某一个字符串是否为空。
* @param s
* @return
*/
public static boolean isEmpty(CharSequence s){
return s==null || s.length() == 0;
}
}
3)跳转list.jsp页面,展示模糊查询的结果
8. 分页
1)构建一个分页页面
<tr>
<td colspan="8">
第 ${pageBean.currentPage } / ${pageBean.totalPage }
每页显示${pageBean.pageSize }条
总的记录数${pageBean.totalSize }
<!--如果当前的页面不为1,那么就显示首页和上一页-->
<c:if test="${pageBean.currentPage !=1 }">
<a href="StudentListPageServlet?currentPage=1">首页</a>
| <a href="StudentListPageServlet?currentPage=${pageBean.currentPage-1 }">上一页</a>
</c:if>
<!-- 显示当前页面并不显示链接,其他页面显示为链接-->
<c:forEach begin="1" end="${pageBean.totalPage }" var="i">
<c:if test="${pageBean.currentPage == i }">
${i }
</c:if>
<c:if test="${pageBean.currentPage != i }">
<a href="StudentListPageServlet?currentPage=${i }">${i }</a>
</c:if>
</c:forEach>
<!--如果当前的页面不为1,那么就显示下一页和尾页-->
<c:if test="${pageBean.currentPage !=pageBean.totalPage }">
<a href="StudentListPageServlet?currentPage=${pageBean.currentPage+1 }">下一页</a> |
<a href="StudentListPageServlet?currentPage=${pageBean.totalPage }">尾页</a>
</c:if>
</td>
</tr>
2)跳转到servlet,并使用service,调用dao——>分页页面
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//1. 获取需要显示的页码数
int currentPage =Integer.parseInt( request.getParameter("currentPage"));
//2. 根据指定的页数,去获取该页的数据回来
//List<Student> --- list.jsp
StudentService service = new StudentServiceImpl();
PageBean pageBean= service.findStudentByPage(currentPage);
request.setAttribute("pageBean", pageBean);
//3. 跳转界面。
request.getRequestDispatcher("list_page.jsp").forward(request, response);
} catch (SQLException e) {
e.printStackTrace();
}
}
public List<Student> findStudentByPage(int currentPage) throws SQLException {
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
//第一个问号,代表一页返回多少条记录 , 第二个问号, 跳过前面的多少条记录。
//5 0 --- 第一页 (1-1)*5
//5 5 --- 第二页 (2-1)*5
//5 10 --- 第三页
return runner.query("select * from stu limit ? offset ?",
new BeanListHandler<Student>(Student.class) , PAGE_SIZE , (currentPage-1)*PAGE_SIZE);
}
public int findCount() throws SQLException {
QueryRunner runner = new QueryRunner(JDBCUtil02.getDataSource());
//用于处理 平均值 、 总的个数。
Long result = (Long) runner.query("SELECT COUNT(*) FROM stu" , new ScalarHandler() );
return result.intValue();
}
public PageBean findStudentByPage(int currentPage) throws SQLException {
//封装分页的该页数据
PageBean<Student> pageBean = new PageBean<Student>();
int pageSize = StudentDao.PAGE_SIZE ;
pageBean.setCurrentPage(currentPage); //设置当前页
pageBean.setPageSize(pageSize); //设置每页显示多少记录
StudentDao dao = new StudentDaoImpl() ;
List<Student> list =dao .findStudentByPage(currentPage);
pageBean.setList(list); //设置这一页的学生数据
//总的记录数, 总的页数。
int count = dao.findCount();
pageBean.setTotalSize(count); //设置总的记录数
//200 , 10 ==20 201 , 10 = 21 201 % 10 == 0 ?201 / 10 :201 % 10 + 1
pageBean.setTotalPage(count % pageSize==0 ? count / pageSize : (count / pageSize) + 1); //总页数
return pageBean;
}