前言

项目发布于半年前(2023年9月),这次是复习~来考古 =_=
点击前往 GitHub 项目页
通过该项目,可以加深对 JavaBean 使用以及对 JavaWeb 开发的理解
技术:

  • JavaWeb(Servlet + JSP)
  • MySQL
  • JDBC

1. 关于 JavaBean

JavaBean 其实就是 Java 中的实体类,负责数据的封装。我们可以创建 bean 包存储 JavaBean

  • 可以理解为符合某种规范的 Java 类
    比如:
    • 无参数构造方法
    • 属性私有化
    • 对外公开提供 get 和 set 方法
    • 实现 java.io.Serializable 接口
    • 重写 toString
    • 重写 hashCode + equals

2. 学生管理系统分析

职责分析

  • 数据库
    一个数据库,两张表
    • 学生信息(学号、姓名、性别、联系方式)
    • 管理员信息(id、username、password)
  • 前端,提供一套页面
    • 登录页面
    • 管理页面:列表页、详情页、修改页、新增页
  • 后端
    连接数据库,查询学生信息,实现与前端相关的一系列功能

功能分析

  • 管理员登录功能
    成功则跳转到学生列表页面,失败则跳转到失败页面
    可以从失败页面返回登录页面
  • 查看学生列表,列表中有以下功能
    • 查看学生详情
    • 修改学生信息
    • 删除学生信息
    • 新增学生信息
    • 退出系统

3. 项目实现

目录结构

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
src
|--- com.xxx.student_manage
|--- bean
|--- Student
|--- filter
|--- LoginCheckFilter
|--- utils
|--- DBUtil
|--- web.action
|--- StudentServlet
|--- UserServlet
|--- WelcomeServlet
|--- resources
|--- jdbc.properties

web
|--- WEB-INF
|--- lib
|--- jakarta.servlet.jsp.jstl-2.0.0.jar
|--- jakarta.servlet.jsp.jstl-api-2.0.0.jar
|--- mysql-connector-j-8.0.33.jar
|--- web.xml
|--- add.jsp
|--- detail.jsp
|--- edit.jsp
|--- index.jsp
|--- list.jsp
|--- login_error.jsp

3.1 数据库:MySQL

准备一个数据库,数据库中创建学生表和管理员用户表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 学生表
set character_set_client = 'utf8';
drop table if exists t_student;
create table t_student(
sno int primary key,
sname varchar(255) not null,
ssex varchar(255) not null,
telephone varchar(255) not null
);
insert into t_student(sno, sname, ssex, telephone)
values (001, 'tom', '男', '1111111');
insert into t_student(sno, sname, ssex, telephone)
values (002, 'jack', '男', '1112222');
insert into t_student(sno, sname, ssex, telephone)
values (003, '张三', '男', '1113333');
commit;
select *
from t_student;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 管理员用户表
set character_set_client = 'utf8';
drop table if exists t_user;
create table t_user(
id int primary key,
username varchar(255) not null,
password varchar(255) not null
);
insert into t_user (id, username, password)
values (01, 'admin', '123');
insert into t_user(id, username, password)
values (02, 'tom', '123321');
commit;
select * from t_user;

3.2 前端:JSP

登录页

index.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<title>欢迎使用学生管理系统</title>
<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
</head>
<body>
<h1>您好,请登录</h1>
<hr>
<form action="user/login" method="post">
用户名:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
<input type="submit" value="登录">
<input type="checkbox" name="f" value="1"/>十天内免登录<br>
</form>
</body>
</html>

登录失败页

login_error.jsp

1
2
3
4
5
6
7
8
9
10
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>error</title>
</head>
<body>
<h1>登录失败,<a href="${pageContext.request.contextPath}">请重新登录</a></h1>
</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
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<head>
<title>学生列表页面</title>
<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
</head>
<body>
<script>
function del(sno) {
if (window.confirm("确定删除该同学的信息吗???")) {
document.location.href = "${pageContext.request.contextPath}/student/delete?sno=" + sno;
}
}
</script>
<h1>学生列表</h1>
<hr>
<table>
<tr>
<td>序号</td>
<td>学号</td>
<td>姓名</td>
<td>操作</td>
</tr>
<c:forEach items="${stuList}" varStatus="stuStatus" var="student">
<tr>
<td>${stuStatus.count}</td>
<td>${student.sno}</td>
<td>${student.sname}</td>
<td>
<a href="student/detail?f=detail&sno=${student.sno}">详情</a>
<a href="student/detail?f=edit&sno=${student.sno}">修改</a>
<a href="javascript:void(0)" onclick="del(${student.sno})">删除</a>
</td>
</tr>
</c:forEach>
</table>
<a href="add.jsp">新增学生</a>
<br>
<a href="user/exit">退出系统</a>
</body>
</html>

学生详情页

detail.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>学生详细信息</title>
</head>
<body>
<h1>学生详细信息</h1>
<hr>
学号:${student.sno}<br>
姓名:${student.sname}<br>
性别:${student.ssex}<br>
联系电话:${student.telephone}<br>
<input type="button" value="后退" onclick="window.history.back()">
</body>
</html>

学生修改页

edit.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改学生信息</title>
<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
</head>
<body>
<h1>修改学生信息</h1>
<hr>
<form action="student/modify" method="post">
学号:<input type="text" name="sno" value="${student.sno}" readonly><br>
姓名:<input type="text" name="sname" value="${student.sname}"><br>
性别:${student.ssex}<br>
联系电话:<input type="text" name="telephone" value="${student.telephone}"><br>
<input type="submit" value="保存">
</form>
</body>
</html>

新增学生页

add.jsp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>新增学生</title>
<base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">
</head>
<body>
<h1>新增学生</h1>
<hr>
<form action="student/add" method="post">
学号:<input type="text" name="sno"><br>
姓名:<input type="text" name="sname"><br>
性别:男<input type="radio" name="ssex" value="男"> 女<input type="radio" name="ssex" value="女"><br>
联系电话:<input type="text" name="telephone"><br>
<input type="submit" value="保存">
</form>
</body>
</html>

3.3 后端

JavaBean

bean 包下新建 Student 类,用来封装学生信息

代码如下:

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
/**
* @author ShameYang
* @date 2023/9/10 16:45
* @description 学生类
*/
public class Student {
private String sno;
private String sname;
private String ssex;
private String telephone;

public String getSno() {
return sno;
}

public void setSno(String sno) {
this.sno = sno;
}

public String getSname() {
return sname;
}

public void setSname(String sname) {
this.sname = sname;
}

public String getSsex() {
return ssex;
}

public void setSsex(String ssex) {
this.ssex = ssex;
}

public String getTelephone() {
return telephone;
}

public void setTelephone(String telephone) {
this.telephone = telephone;
}

public Student() {
}

public Student(String sno, String sname, String ssex, String telephone) {
this.sno = sno;
this.sname = sname;
this.ssex = ssex;
this.telephone = telephone;
}


@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(sno, student.sno) && Objects.equals(sname, student.sname) && Objects.equals(ssex, student.ssex) && Objects.equals(telephone, student.telephone);
}

@Override
public int hashCode() {
return Objects.hash(sno, sname, ssex, telephone);
}
}

封装 DBUtil

Java 访问数据库,JDBC 是必不可少的。我们在 utils 包下封装一个 DBUtil,专门用来完成 JDBC 操作

具体代码如下:

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
/**
* @author ShameYang
* @date 2023/9/10 15:37
* @description JDBC 工具类
*/
public class DBUtil {
private static ResourceBundle bundle = ResourceBundle.getBundle("resources.jdbc");
private static String driver = bundle.getString("driver");
private static String url = bundle.getString("url");
private static String user = bundle.getString("user");
private static String password = bundle.getString("password");

static {
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

/**
* 获取数据库连接对象
* @return conn 连接对象
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}

/**
* 释放资源
* @param conn 连接对象
* @param ps 数据库操作对象
* @param rs 结果集对象
*/
public static void close(Connection conn, Statement ps, ResultSet rs) {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}

我们可以发现 ResourceBundle.getBundle("resources.jdbc"); 使用了 ResourceBundle 类,用来加载 JDBC 的配置文件
所以,我们还需要在 resources 包下,新建一个 jdbc.properties 配置文件用来存放连接数据库的一些配置

1
2
3
4
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/数据库名
user=你的用户
password=你的密码

Servlet 类

管理学生信息
StudentServlet:

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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/**
* @author ShameYang
* @date 2023/9/10 16:36
* @description 学生列表
*/
@WebServlet({"/student/list", "/student/detail", "/student/delete",
"/student/add", "/student/modify"})
public class StudentServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String servletPath = request.getServletPath();
switch (servletPath) {
case "/student/list" -> doList(request, response);
case "/student/detail" -> doDetail(request, response);
case "/student/delete" -> doDel(request, response);
case "/student/add" -> doAdd(request, response);
case "/student/modify" -> doModify(request, response);
}
}

/**
* 连接数据库,查询所有学生信息,将信息收集好后跳转到 JSP 页面展示
* @param request 请求
* @param response 响应
* @throws ServletException 异常
* @throws IOException 异常
*/
private void doList(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<Student> stus = new ArrayList<>();

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
String sql = "select sno, sname, ssex, telephone from t_student";
ps = conn.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
String sno = rs.getString("sno");
String sname = rs.getString("sname");
String ssex = rs.getString("ssex");
String telephone = rs.getString("telephone");
// 将以上数据封装为 java 对象
Student student = new Student();
student.setSno(sno);
student.setSname(sname);
student.setSsex(ssex);
student.setTelephone(telephone);
// 将学生对象放到 list 集合中
stus.add(student);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, rs);
}
// 将集合放到请求域中
request.setAttribute("stuList", stus);
// 转发到 JSP 页面
request.getRequestDispatcher("/list.jsp").forward(request, response);
}

/**
* 详情功能
* @param request 请求
* @param response 响应
* @throws ServletException 异常
* @throws IOException 异常
*/
private void doDetail(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sno = request.getParameter("sno");
Student student = new Student();
student.setSno(sno);
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = DBUtil.getConnection();
String sql = "select sno, sname, ssex, telephone from t_student where sno=?";
ps = conn.prepareStatement(sql);
ps.setString(1, sno);
rs = ps.executeQuery();
if (rs.next()) {
String sname = rs.getString("sname");
String ssex = rs.getString("ssex");
String telephone = rs.getString("telephone");

student.setSname(sname);
student.setSsex(ssex);
student.setTelephone(telephone);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, rs);
}

request.setAttribute("student", student);

// 这样写可以转发给修改功能使用
request.getRequestDispatcher("/" + request.getParameter("f") + ".jsp").forward(request, response);
}

/**
* 删除功能
* @param request 请求
* @param response 响应
* @throws ServletException 异常
* @throws IOException 异常
*/
private void doDel(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sno = request.getParameter("sno");
Connection conn = null;
PreparedStatement ps = null;
// 记录是否执行
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "delete from t_student where sno=?";
ps = conn.prepareStatement(sql);
ps.setString(1, sno);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, null);
}

// 删除成功,重定向至学生列表页面
if (count == 1) {
response.sendRedirect(request.getContextPath() + "/student/list");
}
}

/**
* 新增学生
* @param request 请求
* @param response 响应
* @throws ServletException 异常
* @throws IOException 异常
*/
private void doAdd(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sno = request.getParameter("sno");
String sname = request.getParameter("sname");
String ssex = request.getParameter("ssex");
String telephone = request.getParameter("telephone");
Connection conn = null;
PreparedStatement ps = null;
int count = 0;

try {
conn = DBUtil.getConnection();
String sql = "insert into t_student(sno, sname, ssex, telephone) " +
"VALUES (?, ?, ?, ?)";
ps = conn.prepareStatement(sql);
ps.setString(1, sno);
ps.setString(2, sname);
ps.setString(3, ssex);
ps.setString(4, telephone);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, null);
}

if (count == 1) {
response.sendRedirect(request.getContextPath() + "/student/list");
}
}

/**
* 修改学生信息
* @param request 请求
* @param response 响应
* @throws ServletException 异常
* @throws IOException 异常
*/
private void doModify(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String sno = request.getParameter("sno");
String sname = request.getParameter("sname");
String telephone = request.getParameter("telephone");

Connection conn = null;
PreparedStatement ps = null;
int count = 0;
try {
conn = DBUtil.getConnection();
String sql = "update t_student set sname=?, telephone=? where sno=?";
ps = conn.prepareStatement(sql);
ps.setString(1, sname);
ps.setString(2, telephone);
ps.setString(3, sno);
count = ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, null);
}

if (count == 1) {
response.sendRedirect(request.getContextPath() + "/student/list");
}
}
}

管理员登录(Session&Cookie)
UserServlet:

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
/**
* @author ShameYang
* @date 2023/9/11 08:17
* @description 用户登录
*/
@WebServlet({"/user/login", "/user/exit"})
public class UserServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String servletPath = request.getServletPath();
switch (servletPath) {
case "/user/login" -> doLogin(request, response);
case "/user/exit" -> doExit(request, response);
}
}

private void doExit(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
HttpSession session = request.getSession(false);
if (session != null) {
// 手动销毁 session
session.invalidate();
// 清除 cookie
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
cookie.setMaxAge(0);
// 这里的关联路径要与之前的一致
cookie.setPath(request.getContextPath());
response.addCookie(cookie);
}
}
response.sendRedirect(request.getContextPath());
}
}

private void doLogin(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");

Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Boolean success = false;
try {
conn = DBUtil.getConnection();
String sql = "select id, username, password from t_user where username=? and password=?";
ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
rs = ps.executeQuery();
if (rs.next()) {
success = true;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, rs);
}

// 登陆成功,重定向至学生列表
if (success) {
// session
HttpSession session = request.getSession();
session.setAttribute("username", username);
// cookie
String f = request.getParameter("f");
if ("1".equals(f)) {
Cookie cookie1 = new Cookie("username", username);
Cookie cookie2 = new Cookie("password", password);
// 设置关联路径
cookie1.setPath(request.getContextPath());
cookie2.setPath(request.getContextPath());
// 设置有效期十天
cookie1.setMaxAge(60 * 60 * 24 * 10);
cookie2.setMaxAge(60 * 60 * 24 * 10);
// 发送到服务器
response.addCookie(cookie1);
response.addCookie(cookie2);
}
response.sendRedirect(request.getContextPath() + "/student/list");
} else {
response.sendRedirect(request.getContextPath() + "/login_error.jsp");
}
}
}

登录过滤
WelcomeServlet:

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
/**
* @author ShameYang
* @date 2023/9/11 09:31
* @description 欢迎页实现 cookie
*/
@WebServlet("/welcome")
public class WelcomeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 获取 cookie
Cookie[] cookies = request.getCookies();
String username = null;
String password = null;
if (cookies != null) {
for (Cookie cookie : cookies) {
String name = cookie.getName();
if ("username".equals(name)) {
username = cookie.getValue();
} else if ("password".equals(name)) {
password = cookie.getValue();
}
}
}

if (username != null && password != null) {
// 连接数据库,验证用户名密码
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Boolean success = false;
try {
conn = DBUtil.getConnection();
String sql = "select * from t_user where username=? and password=?";
ps = conn.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, password);
rs = ps.executeQuery();
if (rs.next()) {
success = true;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.close(conn, ps, rs);
}

if (success) {
HttpSession session = request.getSession();
session.setAttribute("username", username);

response.sendRedirect(request.getContextPath() + "/student/list");
} else {
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
} else {
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}
}

filter 包下 LoginCheckFilter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* @author ShameYang
* @date 2023/9/13 15:13
* @description 登录检查过滤器
*/
public class LoginCheckFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;

HttpSession session = request.getSession(false);
if (session != null && session.getAttribute("username") != null) {
filterChain.doFilter(request, response);
} else {
response.sendRedirect(request.getContextPath() + "/index.jsp");
}
}
}

web.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<welcome-file-list>
<welcome-file>welcome</welcome-file>
</welcome-file-list>

<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.shameyang.student_manage.filter.LoginCheckFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/student/*</url-pattern>
</filter-mapping>
</web-app>

4. 总结

  • JSP:我们使用 base 标签 + EL 表达式,这样简化了地址的编写和属性的访问
    示例:

    1
    2
    3
    4
    5
    <base href="${pageContext.request.scheme}://${pageContext.request.serverName}:${pageContext.request.serverPort}${pageContext.request.contextPath}/">

    登录失败,<a href="${pageContext.request.contextPath}">请重新登录</a>

    <form action="student/add" method="post">...</form>
  • Servlet:根据请求路径,执行相应的方法
    访问数据时,我们要将数据封装到集合或对象中,然后把集合或对象放到请求域中,转发到相应页面

    1
    2
    3
    request.setAttribute("name", 集合或对象);

    request.getRequestDispatcher("/xxx").forward(request, response);

    使用或修改数据时,使用请求获取对应参数,然后通过数据库进行修改,操作成功则通过响应重定向到主页面

    1
    2
    3
    request.getParameter("xxx");

    response.sendRedirect(request.getContextPath() + "/xxx");
  • Session&Cookie 实现的逻辑

    1. 我们配置了欢迎页,优先级要高于 index.jsp,所以先走 WelcomeServlet
    2. WelcomeServlet 中只进行登录状态验证,设置 Session 和 Cookie 要到 UserServlet 中,即用户登录并选择免登录才设置
    3. 添加了过滤器 LoginCheckFilter,在直接请求学生管理相关路径时,会判断登陆状态