最近又捡起了对Java的学习,通过对一个实例的介绍,总结下此次对Web开发中MVC三层架构的学习,以便用于日后的复习。

一、 MVC

简单的先介绍下MVC模式:

  • M(Model):JavaBean。用于完成具体的业务操作。

    JavaBeanJava中特殊的类.

    JavaBean满足条件:

    • public修饰的类,并提供public无参构造方法
    • 所有的属性都是private修饰
    • 提供gettersetter方法

    使用层面:

    • 封装业务逻辑:dao层封装对数据库的底层操作
    • 封装数据:domain层。对数据库中所要查询对象的封装
  • V(View):视图。用于数据的展示。

    • 页面的展示
    • 与用户的交互
  • C(Controller):控制器。由Servlet实现控制器。

    主要功能:

    • 获取用户的输入
    • 调用模型,将请求交给模型进行处理
    • 将数据交给视图进行展示
MVC模式

首先浏览器(通过View页面)向服务器端进行请求(可以是表单请求、超链接、AJAX请求等),Controller层获取浏览器请求的数据进行解析,调用模型;模型进行业务逻辑的操作,并将处理结果返回给Controller层;Controller层再将相应的数据交给View层,进行数据展示到客户端。

二、三层架构

三层架构:视图层View、服务层Service、与持久层Dao。

  • View:用于接收用户提交请求的代码。
  • Service:用于编写系统的业务逻辑。(最重要的一层)
  • Dao:对数据库进行最直接的操作。即:对数据库的增删改查。

三层架构

dao层中,定义了对数据库的增删改查的接口。而service层中即对数据的具体业务操作,用于组合dao层中的接口方法。web层中则用于对用户数据的接收和发送。上图很好的解释了MVC与三层架构之间的关系。

三、案例

通过servletjspMysqlJDBCTempleatDuirdBeanUtilsTomcat等技术完成用户信息列表展示的实例。此部分着重解释后端代码的实现。

1.查询所有用户信息

当点击前端页面查询按钮时,此时通过对服务器端的请求,到web层中的Controller层,触发FindUserServlet。由Controller调用Service层中的模型,继而Service层通过dao层获取全部的用户信息,封装到List<User>集合中。返回给Service层,再通过Service层将用户信息返回给Controller层。Web层中的Controller将数据进行存储转发给View,进行数据的解析展示,返回给客户端。

findAll方法:

dao层中findAll接口的实现
1
2
3
4
5
6
7
@Override
public List<User> findAll() {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "select * from user";
List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class));
return users;
}
service层中findAll接口的实现
1
2
3
4
5
6
@Override
public List<User> findAll() {
UserDao userDao = new UserDaoImpl();
List<User> users = userDao.findAll();
return users;
}
web层中UserListServlet
1
2
3
4
5
6
7
8
9
10
11
12
13
@WebServlet("/userListServlet")
public class UserListServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
UserService userService = new UserServiceImpl();
List<User> users = userService.findAll();
request.setAttribute("users", users);
request.getRequestDispatcher("/list.jsp").forward(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
2.增加用户信息

增加用户信息

当客户端点击提交按钮时,此次对服务器端的请求带着表单的数据。根据我们上面对三层架构以及Controller层的介绍可知,由其进行数据的接收。这里即为AddUserServlet对获取的数据进行处理、封装。将封装好的数据传给Service层(Model),即为UerService,进行业务逻辑的操作。再通过dao层对数据库进行相应的访问。

dao层中add接口的实现
1
2
3
4
5
6
@Override
public void addUser(User user) {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "insert into user values(null,?,?,?,?,?,?,null,null)";
template.update(sql, user.getName(), user.getGender(), user.getAge(), user.getAddress(), user.getQq(), user.getEmail());
}
Service层中add接口的实现
1
2
3
4
5
@Override
public void addUser(User user) {
UserDao userDao = new UserDaoImpl();
userDao.addUser(user);
}
web层中addServlet的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@WebServlet("/addServlet")
public class AddServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
User user = new User();
Map<String, String[]> parameterMap = request.getParameterMap(); // 将请求参数进行Map集合的封装
try {
BeanUtils.populate(user, parameterMap);//将获取到的值封装到User对象中
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
UserService service = new UserServiceImpl();
service.addUser(user);
HttpSession session = request.getSession(); // 再进行重定向之前,将需要添加的User对象设置到session中,以便后续对其的获取使用
session.setAttribute("addUser", user);
response.sendRedirect(request.getContextPath() + "/findUserByPageServlet");//重定向至View层
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}

思考:

在上一个方法查找所有的用户时,在最后,我们将获取到的数据传给view层,采用的是存储转发,而在这里,对用户的添加,我们却采用的是重定向(实际上,增、删、改都是采用的重定向)。这是为什么呢?

这里先对重定向和存储转发的几个特点进行简单的比较:

  • 存储转发:一种在服务器内部的资源跳转方式。

    特点:

    1. 浏览器地址栏不会发生变化
    2. 只能转发到当前服务器内部资源中
    3. 转发是一次请求

    最重要的一点便是转发只在当前服务器内部进行,请求也只有一次。这样做带来的一点用处便是,request域中带有的请求是可以在多次资源跳转中进行共享的。在使用时,只需要添加资源路径即可。

  • 重定向:具有多次的请求。其跳转在于客户端与服务器端之间,每次请求都是独立的,存在新的requestresponse

    特点:

    1. 重定向之后地址栏会发生变化
    2. 重定向可以访问其他站点(服务器)的资源
    3. 重定向是两次请求。故不能使用request域共享数据。

其中,重定向可避免在用户重新加载页面时,两次调用相同的动作。即,访问数据库时,增删改使用重定向。当前我的理解是:转发只有一次请求,故当重新加载页面时,会沿着之前的请求再请求一次(这句话可能比较绕),在页面进行展示全部用户数据之前,又会将数据库添加用户的操作进行一遍,所以会造成表单的重复提交;而重定向中是多次(两次)请求,所以只复用”最近一次“请求(因为每次请求是独立的,之前的请求都不在了),这里只是对页面进行全部用户的展示。

重定向:

存储转发:

存储转发

3.用户信息更改

update

思路:用户信息的更改相对前面的用户显示的展示和增加要多了一些步骤。首先,在我们需要对信息进行更改时,需要将原信息展示给我们,在原信息的基础上进行修改,即:是查询到所要修改的用户,将其信息进行回显。其次,当我们对用户信息更改完毕以后,通过对数据库的访问,将对应的数据库信息进行Update操作。最后,通过view层,对列表信息进行展示传送给客户端。这里,每个用户都有一个唯一标识符–id主键,所以当我们拿到主键id时,其实也就获得了对应的数据库中的User对象,后面的操作也就顺理成章了。

  1. FindUserServlet – 查询需要修改的用户,用于信息的回显
web层中FindUserServlet的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@WebServlet("/findUserServlet")
public class FindUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String id = request.getParameter("id"); // 获取id
UserService service = new UserServiceImpl();
User user = service.findUser(Integer.parseInt(id));// 通过id返回User对象
request.setAttribute("user", user);// 查找操作所以存储-转发,将用户信息封装传至view层
request.getRequestDispatcher("/update.jsp").forward(request,response);// 即传至update.jsp页面进行解析
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
service层中findUser的实现
1
2
3
4
5
6
@Override
public User findUser(int id) {
UserDao userDao = new UserDaoImpl();
User user = userDao.findUser(id);
return user;
}
dao层中findUser接口的实现
1
2
3
4
5
6
7
@Override
public User findUser(int id) {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "select * from user where id = ?";
User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), id);
return user;
}

以上是获取到需要修改的对象,然后对用户信息进行一个回显操作。

下面,便是对用户信息进行修改。

  1. UpdateUserServlet – 修改用户信息,对数据库数据进行修改
web层中UpdateUserServlet的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@WebServlet("/updateUserServlet")
public class UpdateUserServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
Map<String, String[]> parameterMap = request.getParameterMap();
User user = new User();
try {
BeanUtils.populate(user, parameterMap);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
int id = user.getId();
UserService service = new UserServiceImpl();
service.updateUser(id, user);// 对用户信息进行修改
response.sendRedirect(request.getContextPath()+"/findUserByPageServlet");//View层,信息的展示
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
service层中UpdateUser接口的实现
1
2
3
4
5
@Override
public void updateUser(int id, User user) {
UserDao userDao = new UserDaoImpl();
userDao.updateUser(id, user);
}
dao层中UpdateUser抽象方法的实现
1
2
3
4
5
6
@Override
public void updateUser(int id, User user) {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "update user set name = ?,age=?,gender=?,address=?,qq=?,email=? where id=?";
template.update(sql, user.getName(), user.getAge(), user.getGender(), user.getAddress(), user.getQq(), user.getEmail(), user.getId());
}
4.用户的删除

用户的删除

用户的删除同用户的更新类似,这里同样是获取用户的id,通过id查询到数据库中相应的数据,然后将数据进行删除。

dao层中deleteUser抽象方法的实现
1
2
3
4
5
6
@Override
public void deleteUser(int id) {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "delete from user where id = ?";
template.update(sql, id);
}
5.删除选中功能

删除选中

这里删除选中,是对数据进行批量删除。其中思路同单个用户的删除类似,这里是获取一个id的集合,然后通过循环遍历id删除用户即可。这里的难点在于如何通过前端获取到这些id传递到web层。

1
<a class="btn btn-primary" href="javascript:void(0);" onclick="select()">删除选中</a>

定义Javascript方法。

其中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function select() {
var uids = document.getElementsByName("uid");// 获取属性为uid的标签 -- 这里给所有用户指定的class属性值即为uid,所以是为了获取每一个用户的信息
var flag = false;
for (var i = 0; i < uids.length; ++i) {
var checked = uids[i].checked;
if (checked) {
flag = true;
break;
}
}
if (flag) { // 判断id是否为空 (前端防空的校验)
var flag = window.confirm("您确认删除么?"); // 用于确认删除
if (flag) {
document.getElementById("s_form").submit(); // 提交表单
}
}
}

首先获取被选中的uid,判断是否有用户被选中,这里是为了防止传入到后端的值为空,而报空指针异常。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<c:forEach items="${userByPages.user}" var="user" varStatus="u">
<tr>
<td><input type="checkbox" name="uid" value="${user.id}"></td>
<td>${u.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</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>&nbsp;
<a class="btn btn-default btn-sm" href="javascript:give_msg(${user.id})">删除</a>
</td>
</tr>
</c:forEach>

以上便是由前端获取需要删除的用户的id。

web层中DeleteSelectServlet的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@WebServlet("/delSelectServlet")
public class DelSelectServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String[] uids = request.getParameterValues("uid");// 获取用户id的数组
UserService service = new UserServiceImpl();
service.delByIds(uids);
response.sendRedirect(request.getContextPath()+"/findUserByPageServlet");

}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
service层中DelByIds接口的实现
1
2
3
4
5
6
7
8
9
10
11
@Override
public void delByIds(String[] ids) {
UserDao userDao = new UserDaoImpl();
int id_count;
if (ids != null && ids.length != 0) { // 删除选项的后台验证 -- 防止参数为空(后端判空的校验)
for (String id : ids) {
id_count = Integer.parseInt(id);
userDao.deleteUser(id_count);
}
}
}
dao层中DeleteUser接口的实现
1
2
3
4
5
6
@Override
public void deleteUser(int id) {
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "delete from user where id = ?";
template.update(sql, id);
}

批量删除的注意事项:

  • id获取的批量方式
  • 删除前的确认操作
  • 防止空参数时的删除操作(前后端都进行校验)
6.分页查询

页面基础信息

在客户端对用户列表进行分页展示的基本思路,即需要获取以下的信息:

  • 首先确定数据库中总的条目数 – totalCount;
  • 总的页面数量 – totalPage
  • 获取每页的数据 – List集合
  • 获取当前的页码 – currentPage
  • 每页显示的条数 – rows

totalCount:可以借鉴findAll()的思路,统计出总条目数。

1
totalCount = select count(*) frow user;

rows:有客户端进行传递到参数,即预先设定好的请求参数。

totalPage:totalCount/rows,上取。

currentPage:包含在客户端的请求参数中。

List集合:获取起始索引index以及上面的rows即可确定当前页面需要显示的条目数。

1
2
index = (currentPage - 1)*rows
list = select * from user where limit index,rows

还记得前面所说的Model中操作的是JavaBean对象么,所以这里我们将以上的信息封装成一个PageBean对象。以便我们进行业务逻辑的操作,最终将整个PageBean进行返回交给Web层的Controller,再由Controller传递给View视图,进行展示。逻辑操作见下图:

扩展:对数据的查询进行组合查询,即复杂功能的查询。

web层中FindUserByPageServlet的实现
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
//findUserByPageServlet?currentPage=2&rows=5
@WebServlet("/findUserByPageServlet")
public class FindUserByPageServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String currentPage = request.getParameter("currentPage");
String rows = request.getParameter("rows");
if (currentPage == null || "".equals(currentPage)) { // 当首次进入到列表查询页面时,用于判空操作,即给currentPage,rows赋初始值。
currentPage = "1";
}
if (rows == null || "".equals(rows)) {
rows = "5";
}

Map<String, String[]> condition = request.getParameterMap();//用于复杂条件的查询,本小结可暂时忽略

UserService service = new UserServiceImpl();
PageBean<User> userByPage = service.findUserByPage(Integer.parseInt(currentPage), Integer.parseInt(rows),condition);
request.setAttribute("userByPages", userByPage);
request.setAttribute("condition",condition);// 后续转发时,条件的回显
request.getRequestDispatcher("/list.jsp").forward(request, response);
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
Service层中findUserByPage抽象方法的实现
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
@Override
public PageBean<User> findUserByPage(int currentPage, int rows, Map<String, String[]> condition) {
PageBean<User> userPageBean = new PageBean<>();
// 页数不能小于1
if (currentPage <= 0) {
currentPage = 1;
}
// 查询总条目数
UserDao dao = new UserDaoImpl();
int totalCount = dao.findTotalCount(condition);
// 计算出总页数
int totalPageCount = (totalCount % rows == 0) ? (totalCount / rows) : (totalCount / rows + 1);
// 页数不能大于总页数
if (currentPage > totalPageCount) {
currentPage = totalPageCount;
}
// 查询的索引数
int starIndex = (currentPage - 1) * rows;
// 返回出所要查询的对象数目
List<User> users = dao.findByPage(starIndex, rows,condition);
// 设置对象的属性
userPageBean.setTotalCount(totalCount);
userPageBean.setTotalPage(totalPageCount);
userPageBean.setUser(users);
userPageBean.setCurrentPage(currentPage); // 当前页数
userPageBean.setRows(rows); // 每页展示的条目数
return userPageBean;
}
dao层中findTotalCount及findByPage抽象方法的实现
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
48
49
@Override
public int findTotalCount(Map<String, String[]> condition) { // search condition
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "select count(*) from user where 1=1 ";
List<Object> params = new ArrayList<Object>();
StringBuffer sb = new StringBuffer(sql);
Set<String> keySet = condition.keySet(); // 复杂条件的查询
for (String key : keySet) {
if ("currentPage".equals(key) || "rows".equals(key)) {
continue;
}
String value = condition.get(key)[0];
if (value != null && value != "") {
sb.append(" and " + key + " like ?");
params.add("%" + value + "%");
}

}
sql = sb.toString();
Integer count = template.queryForObject(sql, Integer.class, params.toArray());
System.out.println(sql);
System.out.println(params);
return count;
}

@Override
public List<User> findByPage(int starIndex, int rows, Map<String, String[]> condition) { // 根据索引返回的列表对象
JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
String sql = "select * from user where 1=1";
List<Object> params = new ArrayList<Object>();
StringBuffer sb = new StringBuffer(sql);
Set<String> keySet = condition.keySet();
for (String key : keySet) { // 用于复杂条件的查询
if ("currentPage".equals(key) || "rows".equals(key)) {
continue;
}
String value = condition.get(key)[0];
if (value != null && value != "") {
sb.append(" and " + key + " like ?");
params.add("%" + value + "%");
}
}
params.add(starIndex);
params.add(rows);
sb.append(" limit ?,? ");
sql = sb.toString();
List<User> users = template.query(sql, new BeanPropertyRowMapper<User>(User.class), params.toArray());
return users;
}
7.复杂条件的分页查询

组合条件的查询,在于SQL语句的编写。

  1. 定义初始化SQL语句: select count(*) from user where 1=1再将查询条件进行拼接,再拼接之前先进行判空操作。

webservicedao层的编写在上一个小节中已包含。

四、前端代码展示

add.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<%--
Created by IntelliJ IDEA.
User: liz
Date: 2020/8/9
Time: 19:17
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>添加用户</title>

<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style>
.error {
color: red;
}
</style>
<script>

window.onload = function () {


document.getElementById('form').onsubmit = function () {

return checkName() && checkAge() && checkQQ() && checkEmail();


};
document.getElementById("name").onblur = checkName;
document.getElementById("age").onblur = checkAge;
document.getElementById("qq").onblur = checkQQ;
document.getElementById("email").onblur = checkEmail;
};

function checkName() {
var name = document.getElementById("name").value;
var regExp = /(^([a-zA-Z]+\s)*[a-zA-Z]+$)|(^[\u4e00-\u9fa5]+$)/;
var flag = regExp.test(name);
var s_name = document.getElementById("s_name");
if (flag) {
s_name.innerHTML = '<img src="img/gou.png" width="35px" height="25px">';
} else {
s_name.innerHTML = "请输入正确姓名"
}
return flag;
};


function checkAge() {
var age = document.getElementById("age").value;
var s_age = document.getElementById("s_age");
var regExp = /^(([0-9]|[1-9][1-9]|1[0-7][0-9])(\\.[0-9]+)?|180)$/;
var flag = regExp.test(age);
if (flag) {
s_age.innerHTML = '<img src="img/gou.png" width="35px" height="25px">';
} else {
s_age.innerHTML = "请输入正确格式的年龄"
}
return flag;
};

function checkQQ() {
var qq = document.getElementById("qq").value;
var regExp = /^[1-9][0-9]{4,14}$/;
var flag = regExp.test(qq);
var s_qq = document.getElementById("s_qq");
if (flag) {
s_qq.innerHTML = '<img src="img/gou.png" width="35px" height="25px">';
} else {
s_qq.innerHTML = '请输入正确格式的qq号'
}

return flag;

};

function checkEmail() {
var email = document.getElementById("email").value;
var regExp = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$/;
var flag = regExp.test(email);
var s_email = document.getElementById("s_email");
if (flag) {
s_email.innerHTML = '<img src="img/gou.png" width="35px" height="25px">';
} else {
s_email.innerHTML = '请输入正确格式的email地址';
}

return flag;

};


</script>

</head>
<body>
<div class="container">
<center><h3>添加联系人页面</h3></center>
<form action="${pageContext.request.contextPath}/addServlet" method="post" id="form">
<div class="form-group">
<label for="name">姓名:</label>
<input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
<sapn id="s_name" class="error"></sapn>
</div>

<div class="form-group">
<label>性别:</label>
<input type="radio" name="gender" value="男" checked="checked"/>
<input type="radio" name="gender" value="女"/>
</div>

<div class="form-group">
<label for="age">年龄:</label>
<input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄">
<sapn id="s_age" class="error"></sapn>
</div>

<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" class="form-control" id="address">
<option value="陕西">陕西</option>
<option value="北京">北京</option>
<option value="南京">南京</option>
<option value="安徽">安徽</option>
<option value="上海">上海</option>
</select>
</div>

<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" class="form-control" id="qq" name="qq" placeholder="请输入QQ号码"/>
<sapn id="s_qq" class="error"></sapn>
</div>

<div class="form-group">
<label for="email">Email:</label>
<input type="text" class="form-control" id="email" name="email" placeholder="请输入邮箱地址"/>
<sapn id="s_email" class="error"></sapn>
</div>

<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交" id="submit"/>
<input class="btn btn-default" type="reset" value="重置"/>
<input class="btn btn-default" type="button" value="返回"/>
</div>
</form>
</div>
</body>
</html>
index.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
<%--
Created by IntelliJ IDEA.
User: liz
Date: 2020/8/9
Time: 14:20
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>首页</title>

<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript">
</script>
</head>
<body>
<div align="center">
<a
href="${pageContext.request.contextPath}/findUserByPageServlet" style="text-decoration:none;font-size:33px">查询所有用户信息

</a>
</div>
</body>
</html>
list.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<!DOCTYPE html>
<!-- 网页使用的语言 -->
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<!-- 使用Edge最新的浏览器的渲染方式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- viewport视口:网页可以根据设置的宽度自动进行适配,在浏览器的内部虚拟一个容器,容器的宽度与设备的宽度相同。
width: 默认宽度与设备的宽度相同
initial-scale: 初始的缩放比,为1:1 -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 上述3个meta标签*必须*放在最前面,任何其他内容都*必须*跟随其后! -->
<title>用户信息管理系统</title>

<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<style type="text/css">
td, th {
text-align: center;
}
</style>
<script>
function give_msg(id) {
var flag = confirm("您确定删除么?");
if (flag) {
location.href = '${pageContext.request.contextPath}/deleteServlet?id=' + id;
}
}

function select() {
var uids = document.getElementsByName("uid");
var flag = false;
for (var i = 0; i < uids.length; ++i) {
var checked = uids[i].checked;
if (checked) {
flag = true;
break;
}
}
if (flag) {
var flag = window.confirm("您确认删除么?");
if (flag) {
document.getElementById("s_form").submit();
}
}
}


window.onload = function () {

document.getElementById("selectAll").onclick = function () {
var uids = document.getElementsByName("uid");
for (var i = 0; i < uids.length; ++i) {
uids[i].checked = this.checked; // this代表 --> document.getElementById("selectAll")组件

}

}

};
</script>

</head>
<body>
<div class="container">
<h3 style="text-align: center">用户信息列表</h3>
<div>
<form class="form-inline" style="float: left" action="${pageContext.request.contextPath}/findUserByPageServlet"
method="post">
<div class="form-group">
<label for="name">姓名</label>
<input type="text" name="name" class="form-control" id="name" value="${condition.name[0]}">
</div>
<div class="form-group">
<label for="address">籍贯</label>
<input type="text" name="address" class="form-control" id="address" value="${condition.address[0]}">
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="text" name="email" class="form-control" id="email" value="${condition.email[0]}">
</div>
<button type="submit" name="submit" class="btn btn-default">查询</button>
</form>
<div style="float: right;margin: 3px">
<a class="btn btn-primary" href="${pageContext.request.contextPath}/add.jsp">添加联系人</a>
<a class="btn btn-primary" href="javascript:void(0);" onclick="select()">删除选中</a>
</div>
</div>
<form action="${pageContext.request.contextPath}/delSelectServlet" method="post" id="s_form">
<table border="1" class="table table-bordered table-hover">
<tr class="success">
<th><input type="checkbox" id="selectAll"></th>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>籍贯</th>
<th>QQ</th>
<th>邮箱</th>
<th>操作</th>
</tr>
<c:forEach items="${userByPages.user}" var="user" varStatus="u">
<tr>
<td><input type="checkbox" name="uid" value="${user.id}"></td>
<td>${u.count}</td>
<td>${user.name}</td>
<td>${user.gender}</td>
<td>${user.age}</td>
<td>${user.address}</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>&nbsp;
<a class="btn btn-default btn-sm" href="javascript:give_msg(${user.id})">删除</a>
</td>
</tr>
</c:forEach>
</table>
</form>
<div>
<nav aria-label="Page navigation">
<ul class="pagination">
<c:if test="${userByPages.currentPage - 1==0}">
<li class="disabled">
</c:if>
<c:if test="${userByPages.currentPage - 1 > 0}">
<li>
</c:if>
<a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${userByPages.currentPage - 1}&rows=${5}&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}"
aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
<c:forEach begin="1" end="${userByPages.totalPage}" var="num" step="1" varStatus="c">
<c:if test="${userByPages.currentPage==num}">
<li class="active">
<a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${num}&rows=${5}&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}">${num}</a>
</li>
</c:if>
<c:if test="${userByPages.currentPage!=num}">
<li>
<a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${num}&rows=${5}&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}">${num}</a>
</li>
</c:if>
</c:forEach>

<c:if test="${userByPages.currentPage + 1 > userByPages.totalPage}">
<li class="disabled">
</c:if>
<c:if test="${userByPages.currentPage + 1 <= userByPages.totalPage}">
<li>
</c:if>
<a href="${pageContext.request.contextPath}/findUserByPageServlet?currentPage=${userByPages.currentPage + 1}&rows=${5}&name=${condition.name[0]}&address=${condition.address[0]}&email=${condition.email[0]}"
aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
<span style="font-size: 25px;padding-left: 10px">
共${userByPages.totalCount}条记录,${userByPages.totalPage}页
</span>
</ul>
</nav>
</div>
</div>
</body>
</html>
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<%--
Created by IntelliJ IDEA.
User: liz
Date: 2020/8/9
Time: 16:35
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html lang="zh-CN">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>管理员登录</title>

<!-- 1. 导入CSS的全局样式 -->
<link href="css/bootstrap.min.css" rel="stylesheet">
<!-- 2. jQuery导入,建议使用1.9以上的版本 -->
<script src="js/jquery-2.1.0.min.js"></script>
<!-- 3. 导入bootstrap的js文件 -->
<script src="js/bootstrap.min.js"></script>
<script type="text/javascript"></script>
<script>
function refreshCode() {
var vcode = document.getElementById("vcode");
var date = new Date().getTime();
vcode.src = "${pageContext.request.contextPath}/checkCode?time=" + date;
}

</script>
</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">管理员登录</h3>
<form action="${pageContext.request.contextPath}/loginUser" method="post">
<div class="form-group">
<label for="user">用户名:</label>
<input type="text" name="username" class="form-control" id="user" placeholder="请输入用户名"/>
</div>

<div class="form-group">
<label for="password">密码:</label>
<input type="password" name="password" class="form-control" id="password" placeholder="请输入密码"/>
</div>

<div class="form-inline">
<label for="vcode">验证码:</label>
<input type="text" name="verifycode" class="form-control" id="verifycode" placeholder="请输入验证码"
style="width: 120px;"/>
<a href="javascript:refreshCode()"><img src="${pageContext.request.contextPath}/checkCode" title="看不清点击刷新"
id="vcode"/></a>
</div>
<hr/>
<div class="form-group" style="text-align: center;">
<input class="btn btn btn-primary" type="submit" value="登录">
</div>
</form>

<!-- 出错显示的信息框 -->
<div class="alert alert-warning alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert">
<span>&times;</span>
</button>
<strong>${code_error}</strong>
<strong>${adminUser_error}</strong>
</div>
</div>
</body>
</html>
update.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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<%--
Created by IntelliJ IDEA.
User: liz
Date: 2020/8/10
Time: 20:03
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html lang="zh-CN">
<head>
<!-- 指定字符集 -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>修改用户</title>

<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/jquery-2.1.0.min.js"></script>
<script src="js/bootstrap.min.js"></script>

</head>
<body>
<div class="container" style="width: 400px;">
<h3 style="text-align: center;">修改联系人</h3>
<form action="${pageContext.request.contextPath}/updateUserServlet" method="post">
<div class="form-group">
<label for="name">姓名:</label>
<input type="hidden" name="id" value="${user.id}">
<input type="text" class="form-control" id="name" name="name" readonly="readonly" placeholder="请输入姓名"
value="${requestScope.user.name}"/>
</div>

<div class="form-group">
<label>性别:</label>
<c:if test="${user.gender=='男'}">
<input type="radio" name="gender" value="男" checked/>男
<input type="radio" name="gender" value="女"/>女
</c:if>
<c:if test="${user.gender=='女'}">
<input type="radio" name="gender" value="男"/>男
<input type="radio" name="gender" value="女" checked/>女
</c:if>
</div>

<div class="form-group">
<label for="age">年龄:</label>
<input type="text" class="form-control" id="age" name="age" placeholder="请输入年龄" value="${user.age}"/>
</div>

<div class="form-group">
<label for="address">籍贯:</label>
<select name="address" id="address" class="form-control">
<c:if test="${user.address =='陕西'}">
<option value="陕西" selected>陕西</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="南京">南京</option>
<option value="安徽">安徽</option>
<option value="苏州">苏州</option>
</c:if>
<c:if test="${user.address =='北京'}">
<option value="陕西">陕西</option>
<option value="北京" selected>北京</option>
<option value="上海">上海</option>
<option value="南京">南京</option>
<option value="安徽">安徽</option>
<option value="苏州">苏州</option>
</c:if>
<c:if test="${user.address =='上海'}">
<option value="陕西">陕西</option>
<option value="北京">北京</option>
<option value="上海" selected>上海</option>
<option value="南京">南京</option>
<option value="安徽">安徽</option>
<option value="苏州">苏州</option>
</c:if>
<c:if test="${user.address =='南京'}">
<option value="陕西">陕西</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="南京" selected>南京</option>
<option value="安徽">安徽</option>
<option value="苏州">苏州</option>
</c:if>
<c:if test="${user.address =='安徽'}">
<option value="陕西">陕西</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="南京">南京</option>
<option value="安徽" selected>安徽</option>
<option value="苏州">苏州</option>
</c:if>
<c:if test="${user.address =='苏州'}">
<option value="陕西">陕西</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="南京">南京</option>
<option value="安徽">安徽</option>
<option value="苏州" selected>苏州</option>
</c:if>
</select>
</div>

<div class="form-group">
<label for="qq">QQ:</label>
<input type="text" id="qq" class="form-control" name="qq" placeholder="请输入QQ号码" value="${user.qq}"/>
</div>

<div class="form-group">
<label for="email">Email:</label>
<input type="text" id="email" class="form-control" name="email" placeholder="请输入邮箱地址"
value="${user.email}"/>
</div>

<div class="form-group" style="text-align: center">
<input class="btn btn-primary" type="submit" value="提交"/>
<input class="btn btn-default" type="reset" value="重置"/>
<input class="btn btn-default" type="button" value="返回"/>
</div>
</form>
</div>
</body>
</html>

Comment