# javaweb案例
# 数据库创建
CREATE table `user` (
id int(3) PRIMARY key auto_increment,
username varchar(10) not null,
password VARCHAR(10) not null,
age int(3) DEFAULT(22),
sex VARCHAR(1) DEFAULT('男'),
city VARCHAR(2) DEFAULT('云南'),
qq int(17) DEFAULT(2291308006),
email VARCHAR(15) DEFAULT('2291308006@qq.com')
)
2
3
4
5
6
7
8
9
10
# 三层结构


# 创建包
domain 存放具体的实现类 User
# 开始
# 查询所有用户信息
原则:尽量让每一个类,只完成一个操作
# web层
点击查询标签,应该让这个页面去UserListServlet
文件中去执行查询结果,这个文件的service方法中只完成查询所有信息的操作,只管这一个
定义这个类在web
包中执行,因为后期可能还有其他的,比如过滤
,可以重新在web包中,建一个包,用于处理所有的servlet文件请求
web包是表现层,用于处理数据,并将结果数据返回给jsp页面进行展示
# service层
service用于执行业务逻辑
创建一个接口,此接口中定义的方法用于返回查询数据库的返回的结果
每一种查询对应一个方法
package com.chu.service.impl;
import com.chu.dao.UserDao;
import com.chu.dao.impl.UserDaoImpl;
import com.chu.domain.User;
import com.chu.service.UserService;
import java.util.List;
public class UserServiceImpl implements UserService {
//可以理解为 每一个用户服务类,都是用于操作数据库,所以has a返回数据库的类
private UserDao userDao = new UserDaoImpl();
/**
* @description: 返回DAO层中查询所有用户信息
* @param
* @return java.util.List<com.chu.domain.User>
*/
public List<User> findAll () {
//调用dao的findAll()方法
return userDao.findAll();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# dao层
dao层用于执行查询操作
所有的sql语句的查询都在这个类中进行
最好定义一个接口,并重新建一个包,创建一个类,实现这个dao的接口,这样做的好处就是使用多态
package com.chu.dao.impl;
import com.chu.dao.UserDao;
import com.chu.domain.User;
import com.chu.utils.DruidUtil;
import org.junit.Test;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
import java.util.Random;
public class UserDaoImpl implements UserDao {
private JdbcTemplate template = new JdbcTemplate(DruidUtil.getDs());
@Override
public List<User> findAll () {
//使用JDBC操作数据库,完成查询所有的信息
//编写sql语句
String sql = "select * from user";
//执行sql语句
List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
return users;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# util
这个包用于存放工具类
# UserListServlet
此类是执行查询所有的servlet文件
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//此类用于执行查询所有的用户信息
UserService userService = new UserServiceImpl();
//返回所有的用户信息
List<User> users = userService.findAll();
//存储用户信息,使用请求转发 转发到list.jsp页面
request.setAttribute("users",users);
request.getRequestDispatcher("/list.jsp").forward(request,response);
}
2
3
4
5
6
7
8
9
10
# list.jsp
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<c:forEach items="${users}" var="user" varStatus="s">
<tr>
<td>${s.count}</td>
<td>${user.username}</td>
<td>${user.sex}</td>
<td>${user.age}</td>
<td>${user.city}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td><a class="btn btn-default btn-sm" href="update.html">修改</a> <a class="btn btn-default btn-sm" href="">删除</a></td>
</tr>
</c:forEach>
<tr>
<td colspan="8" align="center"><a class="btn btn-primary" href="add.html">添加联系人</a></td>
</tr>
</table>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<c:forEach items="${users}" var="user" varStatus="s">
varStatus="s"定义的主要作用就是展示编号
# 封装User对象
获取请求的usermap集合
Map<String, String[]> map = request.getParameterMap();
BeanUtils.populate(user,map);
调用BeanUtils的方法,可以将获取的map集合,自动存入user对象中验证码正确,进行用户密码的验证
@Override protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("utf-8"); //用户登录验证 //1.获取用户输入验证码 String verifycode = request.getParameter("verifycode"); //2.获取生成的验证码 HttpSession session = request.getSession(); String checkcode_server = (String)session.getAttribute("CHECKCODE_SERVER"); //3.验证码进行比对 if (!verifycode.equalsIgnoreCase(checkcode_server)) { //验证码不正确 //错误提示信息 request.setAttribute("login_err","验证码错误!!"); //请求转发到失败页面 request.getRequestDispatcher("/login.jsp").forward(request,response); return; } //4.user对象的封装 Map<String, String[]> map = request.getParameterMap(); User user = new User(); try { BeanUtils.populate(user,map); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } //调用service层返回查询的user对象 UserService service = new UserServiceImpl(); User login_User = service.findLoginUsernameAndPassword(user); //判断 if (login_User != null) { //用户名正确 //请求转发到查询所有界面 request.getRequestDispatcher("/userListServlet").forward(request,response); //移除保存的验证码 session.removeAttribute("CHECKCODE_SERVER"); return; } //用户名或者密码错误 //提示信息 session.setAttribute("Username_err","用户名或者密码错误!!!"); //重定向到登录界面 response.sendRedirect(request.getContextPath()+"/login.jsp"); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
注意:因为请求中会存在中文用户名,所以需要设置请求头的编码格式,否则就会出现乱码情况
,并且使用乱码的数据进行用户密码的验证,也会失败,
request.setCharacterEncoding("utf-8");
请求编码
# 删除操作
删除操作应该根据唯一键进行删除,这样更简单,因为可能用户名会存在相同
在jsp中为了让用户的体验更好,因为设置一个提示,只有点击确定之后,才能进行删除
function deleteUser(id) {
if (confirm("确定删除id为'"+id+"'的记录?")) {
location.href = "${pageContext.request.contextPath}/deletUserServlet?id="+id+"";
}
}
2
3
4
5
confirm()
返回的是一个Boolean值,
# 修改操作

点击修改按钮,进入修改页面,应该把需要修改记录的信息回显在修改框中,

因为性别还有籍贯是使用选择,所以这里使用jsvascript
进行,根据请求转发过来的性别还有籍贯
//性别还有籍贯的选择
var sex = "${requestScope.user.sex}";
var choice_sex = document.querySelector(".div_sex");
for (let i = 0; i < choice_sex.children.length; i++) {
if (sex == choice_sex.children[i].value) {
choice_sex.children[i].checked="checked";
}
}
//籍贯的选择
var select_c = document.querySelector(".select_c");
var city = "${user.city}";
for (let i = 0; i < select_c.children.length; i++) {
if (city == select_c.children[i].value) {
select_c.children[i].selected="selected";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
因为修改操作,最好使用唯一键进行修改,而修改页面中没有
id
,所以解决的办法就是,新加一个input
并设置为隐藏,用来存储id的信息<input type="hidden" name="id" value="${user.id}">
1
# 删除选中
获取选中的id,获取选中的id可以有很多种方式,就比如说,使用JavaScript进行,利用点击事件
比如,爱好复选框进行提交,默认就会把我们选中的提交,所以最简单的方式就是在让form套住复选框
<a class="btn btn-primary select_all" href="javascript:void(0);">删除选中</a> <form class="form_submit" action="${pageContext.request.contextPath}/deleteSelectServlet" method="post"> <table border="1" class="table table-bordered table-hover"> <tr class="success"> <th></th> <th>编号</th> <th>姓名</th> <th>性别</th> <th>年龄</th> <th>籍贯</th> <th>QQ</th> <th>邮箱</th> <th>操作</th> </tr> <c:forEach items="${users}" var="user" varStatus="s"> <tr class="tr"> <td><input type="checkbox" name="uid" value="${user.id}"></td> <td>${s.count}</td> <td>${user.username}</td> <td>${user.sex}</td> <td>${user.age}</td> <td>${user.city}</td> <td>${user.qq}</td> <td>${user.email}</td> <td> <a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a> <a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a> </td> </tr> </c:forEach> </table> </form> //js代码 //删除选中 var selAll = document.querySelector(".select_all"); selAll.onclick = function () { if (confirm("确定删除选中?")) { //提交 document.querySelector(".form_submit").submit(); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
因为之前就写了一个,根据id进行删除,所以我们可以直接在service层遍历调用dao层的delete()
进行删除
# 分页查询
浏览器和服务器的输入和输出问题:
输出指的是:服务器向浏览器输出
输入是:浏览器向服务器进行输入
解决分页查询的主要思想就是先确定浏览器和服务器的输入的输出,需要展示的数据有哪些,如要如何进行这些的数据的封装
步骤
获取
传入的某页的参数,默认每一页的展示的行数不变,
进行参数的判断,因为传入的参数可能为空,就会使服务器发生
500
所以要进行传入参数的判断调用service方法,在这个方法中,需要将在dao层获取的数据存入
PageBean
中,进行对象的封装,前端数据展示需要使用获取
PageBean
对象请求转发,数据存储
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletEx //此类用于返回从数据库中查询出的总页面,条目数等 //设置编码格式 request.setCharacterEncoding("utf-8"); //获取参数 当前页面 查询的条数 String currentPage = request.getParameter("currentPage"); String rows = request.getParameter("rows"); if (currentPage == null || currentPage.equals("")) { currentPage = "1"; } if (rows == null || rows.equals("")) { rows = "5"; } //调用service层方法 UserService service = new UserServiceImpl(); //方法返回的是一个PageBean对象 PageBean<User> pb = service.findUserPageBean(currentPage,rows); //返回UserList集合 //请求转发 并将pb对象存入 request.setAttribute("pb",pb); request.getRequestDispatcher("list.jsp").forward(request,response); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
service
层方法
public PageBean<User> findUserPageBean (String _currentPage, String _rows) {
int currentPage = Integer.parseInt(_currentPage);
int rows = Integer.parseInt(_rows);
//此方法应该将查询到的结果,都存入PageBean对象中
PageBean<User> pb = new PageBean<>();
pb.setCurrentPage(currentPage);
pb.setRows(rows);
//获取总的条目数
int totalCount = userDao.findCount();
pb.setTotalCount(totalCount);
//获取总的页码数
int totalPage = (totalCount % rows) == 0 ? (totalCount / rows) : (totalCount / rows) +1;
pb.setTotalPage(totalPage);
//根据当前页面,查询出User集合
List<User> users = userDao.findUserList(currentPage,rows);
pb.setList(users);
return pb;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
PageBean
类中属性字段
private int totalCount;//总的条目数
private int totalPage;//总的页码数
private int currentPage;//当前的页码数
private int rows;//每页显示的条数
private List<T> list;
2
3
4
5
dao
层查询所有条目返回值
public int findCount () {
String sql = "select count(*) from user";
return template.queryForObject(sql, Integer.class);
}
//主要注意template.queryForObject(sql, Integer.class);
2
3
4
5
# 前台字段的展示
遍历每一页中的所有数据
<c:forEach items="${requestScope.pb.list}" var="user" varStatus="s">
<tr class="tr">
<td><input type="checkbox" name="uid" value="${user.id}"></td>
<td>${s.count}</td>
<td>${user.username}</td>
<td>${user.sex}</td>
<td>${user.age}</td>
<td>${user.city}</td>
<td>${user.qq}</td>
<td>${user.email}</td>
<td>
<a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/findUserServlet?id=${user.id}">修改</a>
<a class="btn btn-default btn-sm" href="javascript:deleteUser(${user.id});">删除</a>
</td>
</tr>
</c:forEach>
//items="${requestScope.pb.list}"注意
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
根据返回所有页数,进行页数的遍历
<c:forEach begin="1" end="${pb.totalPage}" var="i" step="1" varStatus="s">
<li class="li_need"><a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${i}&rows=5">${i}</a></li>
<script>
//获取所有的
var li_need = document.querySelectorAll(".li_need");
if (${pb.currentPage} == ${i}) {
li_need[${i}-1].className = "active li_need";
}
</script>
</c:forEach>
//js部分是进行当前页面,按钮为激活状态的设置
2
3
4
5
6
7
8
9
10
11
设置前一页和后一页
<script>
//前后页的选择
var previous = document.querySelector(".previous_page");
var next = document.querySelector(".next_page");
previous.onclick = function () {
var currentPage = ${pb.currentPage} - 1;
if (currentPage <= 0) {
currentPage = ${pb.totalPage};
}
location.href = "${pageContext.request.contextPath}/findUserByPageServlet?currentPage="+currentPage+"&rows=5";
}
next.onclick = function () {
var currentPage = ${pb.currentPage} + 1;
if (currentPage >= ${pb.totalPage} + 1) {
currentPage = 1;
}
location.href = "${pageContext.request.contextPath}/findUserByPageServlet?currentPage="+currentPage+"&rows=5";
}
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
如果当前页数为1,那么继续点前一页,就会到最后一页,最后一页也是同理
# 复杂条件查询
结构图
对于复杂的条件查询,为了让我们的操作更容易,模糊查询时使用 select * from user where 1=1 and....
拼接模糊查询的语句就直接在where后面
,使用and
进行连接,因为where 1=1
并不影响
程序代码
protected void doPost (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("user..."+request.getSession().getAttribute("login_user"));
//此类用于返回从数据库中查询出的总页面,条目数等
//设置编码格式
request.setCharacterEncoding("utf-8");
//获取参数 当前页面 查询的条数
String currentPage = request.getParameter("currentPage");
String rows = request.getParameter("rows");
if (currentPage == null || currentPage.equals("")) {
currentPage = "1";
}
if (rows == null || rows.equals("")) {
rows = "5";
}
//获取模糊查询的参数 获取到的包括了currentPage rows 需要在进行sql拼接时 跳过这两个
//如果是点击查询进行表单的提交 那么当前页面还有行数的参数不会被提交
Map<String, String[]> condition = request.getParameterMap();
//调用service层方法
UserService service = new UserServiceImpl();
//方法返回的是一个PageBean对象
PageBean<User> pb = service.findUserPageBean(currentPage,rows,condition);
//返回UserList集合
//请求转发 并将pb对象存入
request.setAttribute("pb",pb);
request.getRequestDispatcher("list.jsp").forward(request,response);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//service层
public PageBean<User> findUserPageBean (String _currentPage, String _rows, Map<String, String[]> condition) {
int currentPage = Integer.parseInt(_currentPage);
int rows = Integer.parseInt(_rows);
//此方法应该将查询到的结果,都存入PageBean对象中
PageBean<User> pb = new PageBean<>();
pb.setCurrentPage(currentPage);
pb.setRows(rows);
//获取总的条目数
int totalCount = userDao.findCount(condition);
pb.setTotalCount(totalCount);
//获取总的页码数
int totalPage = (totalCount % rows) == 0 ? (totalCount / rows) : (totalCount / rows) +1;
pb.setTotalPage(totalPage);
//根据当前页面,查询出User集合
List<User> users = userDao.findUserList(currentPage,rows,condition);
pb.setList(users);
return pb;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//dao层
@Override
public int findCount (Map<String, String[]> condition) {
String sql = "select count(*) from user where 1=1";//这是一个拼接的模板
//只有当condition的size大于0时 才进行遍历
if (condition.size()>=3) {
//进行稽核的遍历
Set<String> keys = condition.keySet();
StringBuilder builder = new StringBuilder(sql);
List<String> list = new ArrayList();
for (String key : keys) {
//判断参数是否是currentPage or rows 如果是 进行return;
if ("currentPage".equals(key) || "rows".equals(key)) {
continue;
}
//每一个key对应多个值 因为Map<String, String[]> value值为数组
//通过key获取值
String value = condition.get(key)[0];//但是这里的情况 value就只有一个值 所以可以直接取出
//进行模糊查询的拼接 不用管传递的是一个空值 因为
builder.append(" and " + key + " like ? ");
//将value保存至数组中
list.add("%"+value+"%");
}
sql = builder.toString();
String username = list.get(0);
String city = list.get(1);
String email = list.get(2);
return template.queryForObject(sql, Integer.class,username,city,email);
}
return template.queryForObject(sql, Integer.class);
}
@Override
public List<User> findUserList (int start_row, int rows, Map<String, String[]> condition) {
//只有当condition的size大于3时 才进行遍历
if (condition.size()>=3) {
String sql = "select * from user where 1=1 ";//下标从0开始
//进行稽核的遍历
Set<String> keys = condition.keySet();
StringBuilder builder = new StringBuilder(sql);
List<String> list = new ArrayList();
for (String key : keys) {
//判断参数是否是currentPage or rows 如果是 进行return;
if ("currentPage".equals(key) || "rows".equals(key)) {
continue;
}
//每一个key对应多个值 因为Map<String, String[]> value值为数组
//通过key获取值
String value = condition.get(key)[0];//但是这里的情况 value就只有一个值 所以可以直接取出
//进行模糊查询的拼接 不用管传递的是一个空值 因为
builder.append(" and " + key + " like ? ");
//将value保存至数组中
list.add("%"+value+"%");
}
builder.append(" limit ?,?");
sql = builder.toString();
String username = list.get(0);
String city = list.get(1);
String email = list.get(2);
return template.query(sql, new BeanPropertyRowMapper<User>(User.class),username,city,email,start_row,rows);
}
String sql = "select * from user where 1=1 limit ?, ? ";//下标从0开始
return template.query(sql,new BeanPropertyRowMapper<User>(User.class), start_row, rows);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67





