1、效果展示
上一次未勾选十天免登录之后,打开浏览器访问欢迎页面的效果(跳转到登录页面)
勾选了十天免登录完成登录之后,在下一次打开浏览器访问欢迎页面时的效果(直接访问到部门列表页面)
在本地清除cookie之后重新打开浏览器访问欢迎页面的效果(跳转到登录页面)
2、流程展示
2.1、流程图
2.2、模块介绍
2.2.1、IndexServlet
该模块用于用户浏览的时候的一次判断,主要判断是否本地存储有携带账号密码的cookie,如果有就取出携带的的账号密码,然后进行判断是否正确,正确则跳过登录页面,直接访问部门列表,不正确或者没有携带,则进行登录操作
2.2.2、LoginServlet
该模块就是一个对登录页面信息的判断,首先获取用户提供的账号密码和免登录信息的标志,通过连接数据库查询user表中是否存在该账号密码,如果正确则进行免登录的判断,若用户实点击了免登录按钮,就生成cookie保存账号密码并响应给浏览器,若没有则只生成session用于保存会话状态,最后跳转到DeptList.jsp,显示部门信息。
2.2.3、DeptFilter
该模块用于判断会话状态信息,在执行DeptServlet的时候,里边所有的路径都会经过过滤器DeptFilter(过滤路径为/dept/*),用来判断是否当前路径下存在会话对象session,如果没有则表示未登录过,直接访问页面,无法连接数据库,对其进行修改。
2.2.4、DeptServlet
该模块用于处理部门列表对应的各种操作,例如增加部门,删除部门,部门详情,修改部门等。
3、工程分析
3.1、工程结构目录
该工程我使用的是idea工具,采用了maven中的webapp模板,并进行了一些小的修改,其中:
- filter包用于存放编写的过滤器
- mapper包用于存放sql语句的操作
- pojo包用于存放表中数据的实体类
- servlet包中存放具体的操作功能
- util包中放编写的工具类。
- webapp下是各种jsp前端页面
3.2、工程代码
3.2.1、filter:
该包下是我编写了一个过滤器,用来判断当前访问的会话状态,作用是在没有登录的时候禁止进行连接数据库的增上改查功能,达到想要对部门列表进行查看和增删改必须要先完成登录的这种效果。
DeptFIlter具体代码如下:
package com.peng.filter;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
@WebFilter("/dept/*")
public class DeptFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
HttpServletResponse response1 = (HttpServletResponse) response;
HttpSession session = request1.getSession(false);
System.out.println(request1.getServletPath());
System.out.println(request1.getRequestURI());
if (session != null && session.getAttribute("user") != null){
chain.doFilter(request1,response1);
}else {
response1.sendRedirect(request1.getContextPath()+"/welcome");
}
}
@Override
public void destroy() {
}
}
3.2.2、mapper:
该包下共有四个文件,分别是DeptMapper.java、UserMapper.java和DeptMapper.xml、UserMapper.xml,分别用于实现对部门和用户信息的查询修改
具体代码如下:
DeptMapper
package com.peng.mapper;
import com.peng.pojo.Dept;
import java.util.List;
public interface DeptMapper {
List<Dept> getAll();
void insertColumn(Dept dept);
void deleteById(Integer deptno);
void updateColumn(Dept dept);
Dept getById(Integer deptno);
}
DeptMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.peng.mapper.DeptMapper">
<sql id="allColumn" >
deptno,dname,loc
</sql>
<select id="getAll" resultType="dept">
select <include refid="allColumn"/> from dept
</select>
<insert id="insertColumn" parameterType="dept">
insert into dept(<include refid="allColumn"/>) values(#{deptno},#{dname},#{loc})
</insert>
<delete id="deleteById" parameterType="Integer">
delete from dept where deptno=#{deptno}
</delete>
<update id="updateColumn" parameterType="dept">
update dept set DNAME = #{dname},LOC = #{loc} where DEPTNO = #{deptno}
</update>
<select id="getById" parameterType="Integer" resultType="dept">
select <include refid="allColumn"/> from dept where DEPTNO = #{deptno}
</select>
</mapper>
UserMapper
package com.peng.mapper;
import com.peng.pojo.User;
public interface UserMapper {
User getAll(User user);
}
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.peng.mapper.UserMapper">
<sql id="allColumn">
username,userpassword
</sql>
<select id="getAll" parameterType="User" resultType="user">
select <include refid="allColumn"/> from m_user
<where>
<if test="username != null and username != ''">
and username = #{username}
</if>
<if test="userpassword != null">
and userpassword = #{userpassword}
</if>
</where>
</select>
</mapper>
3.2.3、pojo:
该包下存放了dept部门和user用户表中数据的实体类,用于sql查询接收返回值和传参。
具体代码如下:
User
package com.peng.pojo;
import java.util.Objects;
public class User {
private String username;
private Integer userpassword;
public User() {
}
public User(String username, Integer userpassword) {
this.username = username;
this.userpassword = userpassword;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", userpassword=" + userpassword +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
return Objects.equals(getUsername(), user.getUsername()) && Objects.equals(getUserpassword(), user.getUserpassword());
}
@Override
public int hashCode() {
return Objects.hash(getUsername(), getUserpassword());
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Integer getUserpassword() {
return userpassword;
}
public void setUserpassword(Integer userpassword) {
this.userpassword = userpassword;
}
}
Dept
package com.peng.pojo;
import java.util.Objects;
public class Dept {
private Integer deptno;
private String dname;
private String loc;
public Dept() {
}
public Dept(Integer deptno, String dname, String loc) {
this.deptno = deptno;
this.dname = dname;
this.loc = loc;
}
@Override
public String toString() {
return "Dept{" +
"deptno=" + deptno +
", dname='" + dname + '\'' +
", loc='" + loc + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Dept)) return false;
Dept dept = (Dept) o;
return Objects.equals(getDeptno(), dept.getDeptno()) && Objects.equals(getDname(), dept.getDname()) && Objects.equals(getLoc(), dept.getLoc());
}
@Override
public int hashCode() {
return Objects.hash(getDeptno(), getDname(), getLoc());
}
public Integer getDeptno() {
return deptno;
}
public void setDeptno(Integer deptno) {
this.deptno = deptno;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}
3.2.4、servlet:
该包下共三个文件,分别是DeptServlet.java、IndexServlet.java、LoginServlet.java,用于对部门列表的各种操作、对欢迎页面跳转的判断和对登录页面信息的判断。
具体代码如下:
DeptServlet:
package com.peng.servlet.deptServelt;
import com.peng.mapper.DeptMapper;
import com.peng.pojo.Dept;
import com.peng.util.SqlSessionUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
import java.util.List;
@WebServlet({"/dept/list","/dept/add","/dept/update","/dept/delete","/dept/out","/dept/detail"})
public class DeptServlet extends HttpServlet {
// SqlSession sqlSession;
// DeptMapper mapper;
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String path = request.getServletPath();
System.out.println(path);
if ("/dept/list".equals(path)){
listDept(request, response);
}else if("/dept/add".equals(path)){
addDept(request, response);
}else if ("/dept/update".equals(path)){
updateDept(request, response);
}else if ("/dept/delete".equals(path)){
deleteDept(request, response);
}else if ("/dept/detail".equals(path)){
detailDept(request,response);
} else if("/dept/out".equals(path)){
outDept(request,response);
}
}
private void detailDept(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String deptno = request.getParameter("deptno");
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
Dept dept = mapper.getById(Integer.valueOf(deptno));
request.setAttribute("d",dept);
request.getRequestDispatcher("/DeptDetail.jsp").forward(request,response);
}
private void outDept(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession();
session.invalidate();
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
private void addDept(HttpServletRequest request,HttpServletResponse response) throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
String deptno = request.getParameter("deptno");
String dname = request.getParameter("dname");
String loc = request.getParameter("loc");
Dept dept = new Dept(Integer.valueOf(deptno),dname,loc);
mapper.insertColumn(dept);
sqlSession.commit();
sqlSession.close();
response.sendRedirect(request.getContextPath()+"/dept/list");
}
private void deleteDept(HttpServletRequest request,HttpServletResponse response) throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
String deptno = request.getParameter("deptno");
mapper.deleteById(Integer.valueOf(deptno));
sqlSession.commit();
sqlSession.close();
response.sendRedirect(request.getContextPath()+"/dept/list");
}
private void updateDept(HttpServletRequest request,HttpServletResponse response) throws IOException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
String deptno = request.getParameter("deptno");
String dname = request.getParameter("dname");
String loc = request.getParameter("loc");
Dept dept = new Dept(Integer.valueOf(deptno),dname,loc);
mapper.updateColumn(dept);
sqlSession.commit();
sqlSession.close();
response.sendRedirect(request.getContextPath()+"/dept/list");
}
private void listDept(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
List<Dept> deptList = mapper.getAll();
sqlSession.close();
request.setAttribute("deptList",deptList);
request.getRequestDispatcher("/DeptList.jsp").forward(request,response);
}
}
IndexServlet:
package com.peng.servlet.deptServelt;
import com.peng.mapper.UserMapper;
import com.peng.pojo.User;
import com.peng.util.SqlSessionUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
@WebServlet("/welcome")
public class IndexServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
String username = null;
String password = null;
if (cookies != null) {
for (Cookie data : cookies) {
if ("username".equals(data.getName())) {
username = data.getValue();
} else if ("password".equals(data.getName())) {
password = data.getValue();
}
}
if (username == null || password == null) {
response.sendRedirect(request.getContextPath() + "/login.jsp");
} else {
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getAll(new User(username, Integer.valueOf(password)));
if (user.getUsername() != null) {
HttpSession session = request.getSession();
session.setAttribute("user", user);
session.setMaxInactiveInterval(60 * 30);
response.sendRedirect(request.getContextPath() + "/dept/list");
} else {
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
}
}else{
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
}
}
LoginServlet
package com.peng.servlet.deptServelt;
import com.mysql.cj.Session;
import com.peng.mapper.UserMapper;
import com.peng.pojo.User;
import com.peng.util.SqlSessionUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
String without = request.getParameter("without");
System.out.println(request.getServletPath());
//判断密码
SqlSession sqlSession = SqlSessionUtil.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getAll(new User(username,Integer.valueOf(password)));
sqlSession.close();
if (user != null ){
if(without != null){
Cookie cookie1 = new Cookie("username",username);
Cookie cookie2 = new Cookie("password",password);
cookie1.setMaxAge(60*60*24*10);
cookie2.setMaxAge(60*60*24*10);
response.addCookie(cookie1);
response.addCookie(cookie2);
}
HttpSession session = request.getSession();
session.setAttribute("user",user);
session.setMaxInactiveInterval(60*30);
response.sendRedirect(request.getContextPath()+"/dept/list");
}else{
response.sendRedirect(request.getContextPath()+"/login.jsp");
}
}
}
3.2.5、util:
该包下只有一个文件,SqlSessionUtil,用于创建SqlSession对象,减少代码的重复编写,实现代码复用。
具体代码如下:
package com.peng.util;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class SqlSessionUtil {
public static SqlSession getSqlSession() throws IOException {
InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
return factory.openSession();
}
}
3.2.6、resources
该包下核心的就是SqlMapConfig.xml这个配置文件,他是mybatis的核心配置文件,jdbc.properties根据自己数据库进行配置。
具体代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="jdbc.properties"/>
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
</settings>
<typeAliases>
<package name="com/peng/pojo"/>
</typeAliases>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<package name="com.peng.mapper"/>
</mappers>
</configuration>
3.2.7、jsp文件
这些文件用于前端页面的展示
具体代码:
DeptAdd
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Add</title>
</head>
<body>
<h1 align="center">添加部门</h1>
<hr>
<form action="${pageContext.request.contextPath}/dept/add" method="post">
部门编号:<input type="text" name="deptno" />
<br>
部门名称:<input type="text" name="dname" />
<br>
所在地:<input type="text" name="loc"/>
<br>
<input type="submit" name="sub" value="确认添加">
</form>
<input type="button" value="返回" onclick="window.history.back()"/>
</body>
</html>
DeptDetail
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>detail</title>
</head>
<body>
<h1 align="center">部门详情</h1>
<hr>
<table border="1" align="center">
<tr>
<th>部门编号</th>
<th>部门名称</th>
<th>所在地</th>
</tr>
<tr>
<td>${d.deptno}</td>
<td>${d.dname}</td>
<td>${d.loc}</td>
</tr>
</table>
<input type="button" value="返回" onclick="window.history.back()"/>
</body>
</html>
DeptList
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>部门列表</title>
</head>
<body>
<script type="text/javascript">
function dele(deptno){
if (window.confirm("确认删除")){
document.location.href="${pageContext.request.contextPath}/dept/delete?deptno="+deptno
}
}
</script>
<table border="1px" align="center">
<tr>
<th>序号</th>
<th>部门编号</th>
<th>部门名称</th>
<th>所在地</th>
<th>操作</th>
</tr>
<c:forEach items="${deptList}" var="list" varStatus="sta">
<tr>
<td>${sta.count}</td>
<td>${list.deptno}</td>
<td>${list.dname}</td>
<td>${list.loc}</td>
<td>
<a href="${pageContext.request.contextPath}/dept/detail?deptno=${list.deptno}">详情</a>
<a href="${pageContext.request.contextPath}/DeptUpdate.jsp?deptno=${list.deptno}">修改</a>
<a href="javascript:void(0)" onclick="dele(${list.deptno})">删除</a>
</td>
</tr>
</c:forEach>
</table>
<br>
<a href="${pageContext.request.contextPath}/DeptAdd.jsp"><input type="button" value="添加"></a>
<a href="${pageContext.request.contextPath}/dept/out" ><input type="button"value="安全退出"></a>
</body>
</html>
DeptUpdate
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>update</title>
</head>
<body>
<h1 align="center">修改部门</h1>
<hr>
<form action="${pageContext.request.contextPath}/dept/update" method="post">
部门编号:<input type="text" name="deptno" value="<%=request.getParameter("deptno")%>" readonly />
<br/>
部门名称:<input type="text" name="dname" />
<br/>
所在地:<input type="text" name="loc" />
<br/>
<input type="submit" name="sub" value="修改"/>
</form>
<input type="button" value="返回" onclick="window.history.back()"/>
</body>
</html>
Login
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<title>welcome</title>
</head>
<body>
<h1 align="center">欢迎登录系统</h1>
<hr/>
<form action="${pageContext.request.contextPath}/login" method="post" >
账号:<input type="text" name="username"/>
<br>
密码:<input type="password" name="password"/>
<br>
十天免登录:<input type="checkbox" name="without" value="tendays" />
<br>
<input type="submit" value="login"/>
</form>
</body>
</html>
4、小结
该工程是我完成的第一个小工程,其中包含了Java基础、MySQL数据库、jdbc、html、javascri、Javaweb、maven、mybatis框架,算是我对自己掌握知识的一次融合使用,期间遇到了各种各样的bug,最多的就是某处的空指针异常,然而最令我头大的是idea生成的模板中,pom.xml版本太低,导致后面的EL表达式解析不出来,这一点是我没想到的,也是找的时间最长的地方,以后也会多加注意这点,再其次遇到的bug还有关于SqlMapConfig.xml的,这里我已经犯过两次错了
这里的name是固定的,value也要和自己jdbc写的一摸一样,一摸一样,千万不要写错了(为了懒省事不想复制粘贴,手打的下场)。不过总体来说,虽然debug的时候很煎熬,但是真正做出来的时候还是很有成就感的,最主要的收获颇丰,让我找到了很多掌握不足的地方,发现了很多忽略的地方。