宿舍管理系统

1月7日 18:00前

  1. 项目源码

  2. sql

  3. 实验报告

  4. 2014-学号-姓名.zip

  5. chendikai1314@163.com

项目结构

数据库连接

1
2
3
4
driverClassName =com.mysql.cj.jdbc.Driver
url =jdbc:mysql://localhost:3306/dorm-management-system?serverTimezone=GMT&useSSL=false&characterEncoding=utf-8
username =root
password =123456
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
public class JDBCUtil {
// 获取配置文件
static ResourceBundle bundle;
static String driverClass;
static String url;
static String username;
static String password;

static {
bundle = ResourceBundle.getBundle("jdbc"); // 无文件后缀
driverClass = bundle.getString("driverClassName");
url = bundle.getString("url");
username = bundle.getString("username");
password = bundle.getString("password");
try {
Class.forName(driverClass);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}

public static Connection getConnection() {
try {
return DriverManager.getConnection(url, username, password);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}

public static void close(ResultSet rs, Statement st, Connection co){
try {
if(rs!=null) rs.close();
if(st!=null) st.close();
if(co!=null) co.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

DAO层

查询#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Override
public User findUserById(String id) {
Connection con = JDBCUtil.getConnection();
PreparedStatement ps = null;
ResultSet rs = null;
String sql = "select * from tb_user where id = ?";
try {
ps = con.prepareStatement(sql);
ps.setString(1, id);
rs = ps.executeQuery();
// 处理结果
return rs.next() ? ResultSetUtil.ResultSetToUser(rs) : null;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtil.close(rs, ps, con);
}
}

处理结果#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static User ResultSetToUser(ResultSet rs) throws SQLException {
return new User(rs.getInt(1),
rs.getString(2),
rs.getString(3),
rs.getString(4),
rs.getString(5),
rs.getString(6),
rs.getString(7),
rs.getInt(8),
rs.getInt(9),
rs.getInt(10),
rs.getInt(11),
null,
null);
}

修改#

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
@Override
public int updateUserDisabled(int disabled, String id) {
Connection con = JDBCUtil.getConnection();
PreparedStatement ps = null;
String sql = "update tb_user set disabled = ? where id = ?";
int rows = 0;
try {
// 关闭自动提交事物
con.setAutoCommit(false);
ps = con.prepareStatement(sql);
ps.setInt(1, disabled);
ps.setString(2, id);
rows = ps.executeUpdate();
// 提交事务
con.commit();
} catch (SQLException e) {
try {
// 出现异常回滚
con.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
} finally {
JDBCUtil.close(null, ps, con);
}
return rows;
}

过滤器

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
@Slf4j
@WebFilter(urlPatterns = "*")
public class GlobalFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
HttpSession session = req.getSession();
Object user = session.getAttribute("session_user");
// 获取请求地址
String requestURI = req.getRequestURI();
log.info("拦截请求: {}", requestURI);
switch (requestURI) {
// 登录和登出请求直接放行
case "/login":
case "/loginOut.action":
break;
// 1. 请求登录页面, 有session记录, 直接跳转主页
case "/":
if (user != null) req.getRequestDispatcher("/index.action").forward(req, resp);
break;
// 2. 请求其他页面, 未session记录, 重定向到登录页面
default:
if (user == null) {
req.setAttribute("error", "登录身份过期, 请重新登录");
req.getRequestDispatcher("/loginOut.action").forward(req, resp);
}
}
filterChain.doFilter(servletRequest, servletResponse);
}

@Override
public void destroy() {
}
}

实体类

1
2
3
4
5
6
7
8
9
10
11
12
// Getter、Setter、toString、equals
@Data
// 全参构造方法
@AllArgsConstructor
// 无参构造方法
@NoArgsConstructor
public class DormBuild {
private Integer id;
private String name;
private String remark;
private Integer disabled;
}

登录Servlet

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
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String stuCode = req.getParameter("stuCode");
String password = req.getParameter("password");
String remember = req.getParameter("remember");
User user = userDao.findByStuCode(stuCode);
if (user == null) {
req.setAttribute("error", "用户名不存在");
req.getRequestDispatcher("/").forward(req, resp);
} else if (!password.equals(user.getPassword())) {
req.setAttribute("error", "密码错误");
req.getRequestDispatcher("/").forward(req, resp);
} else {
HttpSession session = req.getSession();
session.setAttribute("session_user", user);
if (remember != null) {
// 7天内自动填充密码
Cookie cookie_stuCode = new Cookie("cookie_stuCode", stuCode);
Cookie cookie_pwd = new Cookie("cookie_pwd", password);
cookie_stuCode.setMaxAge(7 * 24 * 60 * 60);
cookie_pwd.setMaxAge(7 * 24 * 60 * 60);
resp.addCookie(cookie_stuCode);
resp.addCookie(cookie_pwd);
}else{
// 未勾选 => 删除Cookie
Cookie[] cookies = req.getCookies();
List<Cookie> collect = Arrays.stream(cookies)
.filter(cookie ->
cookie.getName().equals("cookie_stuCode") ||
cookie.getName().equals("cookie_pwd"))
.collect(Collectors.toList());
collect.forEach(cookie ->{
cookie.setMaxAge(0);
resp.addCookie(cookie);
});
}
req.getRequestDispatcher("/index.action").forward(req, resp);
}
}

依赖pom.xml

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
<dependencies>
<!-- jsp依赖-->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- jstl表达式依赖-->
<dependency>
<groupId>javax.servlet.jsp.jstl</groupId>
<artifactId>jstl-api</artifactId>
<version>1.2</version>
</dependency>
<!-- taglibs 标签库依赖-->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<!--日志依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.28</version>
</dependency>
<!--mysql连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!--Servlet-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>compile</scope>
</dependency>
</dependencies>

JSP语法

jsp页面标注

1
2
3
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

引入css、js#

1
2
<link href="${pageContext.request.contextPath}/bootstrap/css/bootstrap.css" rel="stylesheet">
<script type="text/javascript" src="${pageContext.request.contextPath}/bootstrap/js/jQuery.js"></script>

表单请求#

1
2
3
4
5
6
7
8
<form name="myForm" 
class="form-signin"
action="${pageContext.request.contextPath}/login"
method="post"
onsubmit="return checkForm()">
表单体...
</form>

导航栏和主体#

  • 根据不同权限显示不同菜单

  • 右侧内容填充使用,达到复用导航栏的目的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div class="span2 bs-docs-sidebar" >
<ul class="nav nav-list bs-docs-sidenav">
<!-- 超级管理员-->
<c:if test="${session_user.roleId == 0}">
导航栏菜单....
</c:if>

<!--宿舍管理员 -->
<c:if test="${session_user.roleId == 1}">
</c:if>

<!-- 学生 -->
<c:if test="${session_user.roleId == 2}">
</c:if>
</ul>
</div>
<div class="span10">
<!--右侧内容-->
<jsp:include page="${mainRight==null? 'blank.jsp':mainRight}"></jsp:include>
</div>

forEach#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--items:表示要循环遍历的元素   var:代表当前集合中每一个元素     varStatus代表循环状态的变量名-->
<c:forEach items="${builds}" var="build" varStatus="stat">
<tr>
<td>${stat.index+1}</td>
<td>${build.name}</td>
<td>${build.remark}</td>
<td>
<button type="button"
onclick="javascript:window.location='dormBuild.action?action=preUpdate&id=${build.id}'">
修改
</button>
</td>
</tr>
</c:forEach>

jsp自定义标签#

注意 并不完整, jsp标签处理类未写好, 没有html结构

配置文件page-taglib.tld, 在WEB-INF目录下

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
<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/j2ee/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<!--标签的版本号 -->
<tlib-version>1.0</tlib-version>
<!--jsp的版本号 -->
<jsp-version>1.2</jsp-version>
<!--标签的简称号 -->
<short-name>simple</short-name>
<!--jsp页面可通过引入该地址 与标签进行关联,并找到标签处理类 -->
<uri>wdl-page-tag</uri>
<!-- 描述信息 -->
<description>
A simple tab library for the examples
</description>

<tag>
<!-- 标签名 -->
<name>pager</name>
<!-- 标签处理类 -->
<tag-class>fit.yujing.utils.PageTag</tag-class>
<description> Display JSP sources </description>
<!-- 属性 -->
<attribute>
<!-- 属性名 -->
<name>totalNum</name>
<!-- 该属性是否必填-->
<required>true</required>
<!--是否支持el表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>

<!-- 属性 -->
<attribute>
<!-- 属性名 -->
<name>pageSize</name>
<!-- 该属性是否必填-->
<required>true</required>
<!--是否支持el表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>

<!-- 属性 -->
<attribute>
<!-- 属性名 -->
<name>pageIndex</name>
<!-- 该属性是否必填-->
<required>true</required>
<!--是否支持el表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>

<!-- 属性 -->
<attribute>
<!-- 属性名 -->
<name>submitUrl</name>
<!-- 该属性是否必填-->
<required>true</required>
<!--是否支持el表达式 -->
<rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
</taglib>

标签处理类

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
@Getter
@Setter
public class PageTag extends BodyTagSupport {
private Integer totalNum;
private Integer pageSize;
private Integer pageIndex;
private String submitUrl;

@Override
public int doStartTag() throws JspException {
// TODO Auto-generated method stub
return super.doStartTag();
}

@Override
public int doAfterBody() throws JspException {
// TODO Auto-generated method stub
return super.doAfterBody();
}

@Override
public int doEndTag() throws JspException {
// TODO Auto-generated method stub
// 将属性值写入到页面显示
PrintWriter out = null;
try {
out = pageContext.getResponse().getWriter();
// 写入值并输出
out.print(this.pageSize);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return super.doEndTag();
}
}

使用

1
2
3
4
5
6
7
8
9
10
11
<!-- jsp页面引入 -->
<%@taglib prefix="wdlPager" uri="wdl-page-tag" %>
<!-- 使用 -->
<wdlPager:pager
totalNum ="${totalNum}"
pageSize="3"
pageIndex="${pageIndex}"
submitUrl="${pageContext.request.contextPath}/record.action?action=list&searchType=${searchType}&keyword=${keyword}&dormBuildId=${dormBuildId}&startDate=${startDate}&endDate=${endDate}">
</wdlPager:pager>


日志

引入依赖

1
2
3
4
5
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.28</version>
</dependency>

配置文件log4j.properties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
### ??###
log4j.rootLogger = info,stdout,D,E

### ???????? ###
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%m%n

### ??DEBUG ????????=logs/error.log ###
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/log.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = DEBUG
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

### ??ERROR ????????=logs/error.log ###
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File =logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [ %t:%r ] - [ %p ] %m%n

使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 添加注解使用日志
@Slf4j
@WebServlet("/record.action")
public class RecordServlet extends HttpServlet {

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 防止接收的中文参数乱码, 必须在所有req使用之前
req.setCharacterEncoding("utf-8");
String action = req.getParameter("action");
log.info("接收参数action: {}", action);
try {
Date date = new SimpleDateFormat("yyyy-MM-dd").parse(date);
} catch (ParseException e) {
log.error("时间转换错误, string = {}", date);
}
}
}