整体项目创建的包与类
1.依赖导入pom.xml
<dependencies>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>5.0.0</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>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.0.33</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.28</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
<!--bootstrap-->
<dependency>
<groupId>org.webjars</groupId>
<artifactId>bootstrap</artifactId>
<version>5.2.3</version>
</dependency>
</dependencies>
2.程序启动页面跳转至tologin
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body onload="location='tologin'">
</body>
</html>
3.pojo包下创建Person属性类
package com.example.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person implements Serializable {
private Integer id;
private String username;
private String password;
private Integer sex;
private Date birthday;
private String mobile;
private String address;
}
4.dao包下创建DBUtils工具类
package com.example.dao;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sql.DataSource;
import java.io.IOException;
import java.sql.SQLException;
import java.util.List;
import java.util.Properties;
public class DButils {
//创建日志
private static final Logger LOGGER= LoggerFactory.getLogger(DButils.class);
//创建数据源
private static DataSource ds;
static {
Properties properties=new Properties();
try {
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
} catch (IOException e) {
LOGGER.debug("未找到资源文件!");
}
try {
ds= DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
LOGGER.debug("创建数据源失败!");
}
}
/**
* 通用的增、删、改方法
* @param sql
* @param args
* @return
*/
public static int exectueComm(String sql,Object...args){
QueryRunner runner=new QueryRunner(ds);
int m=0;
try {
m= runner.update(sql,args);
} catch (SQLException e) {
LOGGER.debug("执行增,删,改异常,请检查sql语句和参数");
}
return m;
}
/**
* 查询所有的方法
* @param sql
* @param clazz
* @param args
* @return
* @param <T>
*/
public static <T>List<T> findAll(String sql,Class<T> clazz,Object...args){
QueryRunner runner=new QueryRunner(ds);
List<T> list=null;
try {
list=runner.query(sql,new BeanListHandler<>(clazz),args);
} catch (SQLException e) {
LOGGER.debug("执行查询所有异常,请检查sql语句");
}
return list;
}
/**
* 查询单条数据方法
* @param sql
* @param clazz
* @param args
* @return
* @param <T>
*/
public static <T> T findOne(String sql,Class<T> clazz,Object...args){
QueryRunner runner=new QueryRunner(ds);
T t=null;
try {
t=runner.query(sql,new BeanHandler<>(clazz),args);
} catch (SQLException e) {
LOGGER.debug("执行查询单条数据异常,请检查sql语句");
}
return t;
}
}
5.dao包下创建person接口
(存放sql语句以及执行方法)
package com.example.dao;
import com.example.pojo.Person;
import java.util.List;
public interface IPersonDao {
String SEL_ALL="SELECT * FROM person";
String SEL_BYID="SELECT * FROM person WHERE id=?";
String LOGIN="SELECT * FROM person WHERE username=? AND password=?";
String INSERT="INSERT INTO person(username,password,sex,birthday,mobile,address) VALUES(?,?,?,?,?,?)";
String UPDATE="UPDATE person SET username=?,password=?,sex=?,birthday=?,mobile=?,address=? WHERE id=?";
String DELETE="DELETE FROM person WHERE id=?";
List<Person> selectAll();
Person selectByID(int id);
List<Person> selectLike(String mohu);
int insert(Person person);
int update(Person person);
int delete(int id);
Person login(String username,String password);
}
6.impl包下创建person接口实现类
(实现接口,重写接口方法)
package com.example.dao.impl;
import com.example.dao.IPersonDao;
import com.example.pojo.Person;
import com.example.dao.DButils;
import java.util.List;
public class PersonDaoImpl implements IPersonDao {
@Override
public List<Person> selectAll() {
return DButils.findAll(SEL_ALL, Person.class);
}
@Override
public Person selectByID(int id) {
return DButils.findOne(SEL_BYID, Person.class,id);
}
@Override
public List<Person> selectLike(String mohu) {
mohu=mohu==null? "":mohu;
return DButils.findAll("SELECT * FROM person WHERE username like '%"+mohu+"%'", Person.class);
}
@Override
public int insert(Person person) {
return DButils.exectueComm(INSERT,person.getUsername(),
person.getPassword(),
person.getSex(),
person.getBirthday(),
person.getMobile(),
person.getAddress());
}
@Override
public int update(Person person) {
return DButils.exectueComm(UPDATE,person.getUsername(),
person.getPassword(),
person.getSex(),
person.getBirthday(),
person.getMobile(),
person.getAddress(),
person.getId());
}
@Override
public int delete(int id) {
return DButils.exectueComm(DELETE,id);
}
@Override
public Person login(String username, String password) {
return DButils.findOne(LOGIN, Person.class,username,password);
}
}
7.util包下导入工具类
8.Servlet包下创建服务类继承HttpServlet类
package com.example.servlet;
import com.example.dao.IPersonDao;
import com.example.dao.impl.PersonDaoImpl;
import com.example.pojo.Person;
import com.example.util.ThUtils;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.*;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thymeleaf.context.Context;
import org.thymeleaf.context.WebContext;
import org.thymeleaf.web.IWebExchange;
import org.thymeleaf.web.servlet.JakartaServletWebApplication;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.Map;
@WebServlet(urlPatterns = {"/tologin","/login","/findAll","/toadd","/find","/delete","/baocun","/logout","/mess"})
public class HelloServlet extends HttpServlet {
private static final Logger LOGGER= LoggerFactory.getLogger(HelloServlet.class);
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//创建接口实例化对象
IPersonDao personDao=new PersonDaoImpl();
//获取执行路径在控制台输出
String servletPath = req.getServletPath();
//创建session
HttpSession session=req.getSession();
//创建传值对象(request作用域)
Context context=new Context();
IWebExchange webExchange= JakartaServletWebApplication.buildApplication(getServletContext()).buildExchange(req, resp);
//session作用域
WebContext webContext=new WebContext(webExchange);
//switch判断路径执行语句
switch (servletPath){
case "/mess"->{
ThUtils.print("/view/mess.html",webContext,resp);
}
case "/logout"->{
//清空所有session
if (session.getAttribute("logUser")!=null){
session.removeAttribute("logUser");
}
resp.sendRedirect("tologin");
}
case "/tologin"->{
Cookie[] cookies = req.getCookies();
String uname=null;
if (cookies!=null){
for (Cookie c:cookies){
//判断cookie获取名字与用户名是否相同,并且session是否为空
if (c.getName().equals("username") && session.getAttribute("logUser")!=null){
uname=c.getValue();
break;
}
}
if(uname!=null){
resp.sendRedirect("findAll");
}else{
ThUtils.print("/view/login.html",webContext,resp);
}
}
}
case "/login"->{
String username = req.getParameter("username");
String password = req.getParameter("password");
String autologin = req.getParameter("autologin");
String code = req.getParameter("code");
Person person=personDao.login(username,password);
if (!code.equals(session.getAttribute("session_code"))){
webContext.setVariable("err","<font color='red'>验证码错误</font>");
ThUtils.print("view/login.html",webContext,resp);
}
//判断是否获取到对象
if (person!=null){
//判断用户是否选择自动登录
if (autologin!=null){
//创建一个cookie对象保存用户名:键值对
Cookie cookie=new Cookie("username",username);
//保存记忆时间
cookie.setMaxAge(60);
//添加cookie对象
resp.addCookie(cookie);
}
//存储用户名到session
session.setAttribute("logUser",username);
resp.sendRedirect("findAll");
}else{
webContext.setVariable("mess","<font color='red'>对不起,登录失败</font>");
ThUtils.print("view/login.html",webContext,resp);
}
}
case "/findAll"->{
String mohu = req.getParameter("mohu");
webContext.setVariable("ps",personDao.selectLike(mohu));
ThUtils.print("/view/findAll.html",webContext,resp);
}
case "/toadd"->{
ThUtils.print("/view/add.html",context,resp);
}
case "/delete"->{
String pid = req.getParameter("pid");
Integer id=Integer.parseInt(pid);
int m = personDao.delete(id);
if (m==1){
resp.sendRedirect("findAll");
}
}
case "/find"->{
String pid = req.getParameter("pid");
Integer id=Integer.parseInt(pid);
Person person=personDao.selectByID(id);
webContext.setVariable("person",person);
ThUtils.print("/view/update.html",webContext,resp);
}
case "/baocun"->{
//设置一个日期转换器
DateConverter dateConverter = new DateConverter();
//设置格式
dateConverter.setPatterns(new String[]{"yyyy-MM-dd"});
//注册格式
ConvertUtils.register(dateConverter, Date.class);
Map map=req.getParameterMap();
Person person=new Person();
try {
BeanUtils.populate(person,map);
} catch (IllegalAccessException e) {
LOGGER.debug("参数异常!");
} catch (InvocationTargetException e) {
LOGGER.debug("运行时异常1");
}
int m=0;
System.out.println(person);
if (person.getId()==null || person.getId()==0){
m=personDao.insert(person);
}else{
m=personDao.update(person);
}
if (m==1){
resp.sendRedirect("findAll");
}
}
}
}
}
9.resources下创建view目录
导入需要的资源文件
创建需要用到的html页面
(1)登录页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录</title>
<link rel="stylesheet" href="webjars/bootstrap/5.2.3/css/bootstrap.min.css">
<script>
function show(){
document.getElementById("pic")
.setAttribute("src","code.jpg?="+Math.random());
}
</script>
</head>
<body>
<form action="login" method="post">
账号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
验证码:<input type="text" name="code">
<img src="code.jpg" title="看不清,换一张" onclick="show()" id="pic"><br>
<span th:utext="${err}"></span>
<input type="checkbox" name="autologin">自动登录<br>
<button class="btn btn-success">登录</button>
</form>
<span th:utext="${mess}"></span>
</body>
</html>
(2)列表页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表</title>
<link rel="stylesheet" href="webjars/bootstrap/5.2.3/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h4>欢迎【[[${session.logUser}]]】登录,<a href="logout">退出</a></h4>
<form action="findAll" method="post">
<input type="text" name="mohu">
<button class="btn btn-success">搜索</button>
</form>
<table class="table table-bordered table-hover">
<tr>
<th>序号</th>
<th>编号</th>
<th>账号</th>
<th>密码</th>
<th>性别</th>
<th>生日</th>
<th>手机</th>
<th>地址</th>
<th>
<button class="btn btn-success" onclick="location='toadd'">新增</button>
</th>
</tr>
<tr th:each="person:${ps}" th:object="${person}">
<td th:text="${personStat.count}"></td>
<td th:text="*{id}"></td>
<td th:text="*{username}"></td>
<td th:text="*{password}"></td>
<td th:text="*{sex==0 ? '男':'女'}"></td>
<td th:text="*{birthday}"></td>
<td th:text="*{mobile}"></td>
<td th:text="*{address}"></td>
<td >
<a th:href="@{delete(pid=*{id})}">删除</a>
<a th:href="@{find(pid=*{id})}">修改</a>
</td>
</tr>
</table>
</div>
</body>
</html>
(3)添加页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>新增</title>
<link rel="stylesheet" href="webjars/bootstrap/5.2.3/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<form action="baocun" method="post">
账号:<input type="text" name="username"><br>
密码:<input type="password" name="password"><br>
性别:<input type="radio" name="sex" value="0">男
<input type="radio" name="sex" value="1">女<br>
生日:<input type="text" name="birthday"><br>
手机:<input type="text" name="mobile"><br>
地址:<input type="text" name="address"><br>
<button class="btn btn-success">提交</button>
</form>
</div>
</body>
</html>
(4)修改页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>修改</title>
<link rel="stylesheet" href="webjars/bootstrap/5.2.3/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<form action="baocun" method="post" th:object="${person}">
<input type="hidden" name="id" th:value="*{id}" readonly>
账号:<input type="text" name="username" th:value="*{username}"><br>
密码:<input type="password" name="password" th:value="*{password}"><br>
性别:<input type="radio" name="sex" value="0" th:checked="*{sex==0}">男
<input type="radio" name="sex" value="1" th:checked="*{sex==1}">女<br>
生日:<input type="text" name="birthday" th:value="*{birthday}"><br>
手机:<input type="text" name="mobile" th:value="*{mobile}"><br>
地址:<input type="text" name="address" th:value="*{address}"><br>
<button class="btn btn-success">提交</button>
</form>
</div>
</body>
</html>
(5)要求登录提示页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
let m=5;
function show(){
if(m==0){
location.href='tologin';
}else{
document.getElementById("sp1").innerHTML="<font>"+m+"</font>";
}
m--;
setTimeout("show()",1000);
}
</script>
</head>
<body onload="show()">
<h2>对不起,您还没有登录</h2>
<h4>本页将在<font color="blue"><span id="sp1"></span></font>秒后自动跳转,您也可以点击<a href="tologin">这里</a>跳转页面</h4>
</body>
</html>
10.filter包下创建过滤器类
package com.example.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;
import java.util.ArrayList;
import java.util.List;
@WebFilter("/*")
public class LoginFilter implements Filter {
//创建静态的常量集合
private static final List<String> PASS=new ArrayList<>(10);
//在静态块中将需要放过的路径添加到集合中
static {
PASS.add("code.jpg");
PASS.add("login");
PASS.add("tologin");
PASS.add("logout");
PASS.add("message");
PASS.add(".js");
PASS.add(".css");
PASS.add("mess");//强制登录提示
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//转换为http的请求与响应
HttpServletRequest request=(HttpServletRequest) servletRequest;
HttpServletResponse response=(HttpServletResponse) servletResponse;
//设置请求与响应的编码格式
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//获取请求的uri
String uri = request.getRequestURI();
HttpSession session = request.getSession();
boolean flag=false;
//循环判断该路径是否存在放过路径集合中
for (String s:PASS){
if (uri.endsWith(s)){
flag=true;
break;
}
}
if (session.getAttribute("logUser")!=null || flag){
filterChain.doFilter(request,response);
}else{
response.sendRedirect("mess");
}
}
}
11.pojo包下创建login属性类
package com.example.pojo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class Login implements Serializable {
Integer id;
String username;
Date logtime;
String loginfo;
}
12.dao包下创建login接口
package com.example.dao;
import java.util.Date;
public interface LoginDao {
String LOGINTNS="insert into t_log(username,logtime,loginfo) VALUES(?,?,?)";
int Listener(String username, Date logtime, String loginfo);
}
13.impl包下创建接口实习实现类实现login接口
package com.example.dao.impl;
import com.example.dao.LoginDao;
import com.example.dao.DButils;
import java.util.Date;
public class LoginDaoIpml implements LoginDao {
@Override
public int Listener(String username, Date logtime, String loginfo) {
return DButils.exectueComm(LOGINTNS,username,logtime,loginfo);
}
}
14.lisenter包下创建监听类
package com.example.listener;
import com.example.dao.LoginDao;
import com.example.dao.impl.LoginDaoIpml;
import jakarta.servlet.annotation.WebListener;
import jakarta.servlet.http.HttpSessionAttributeListener;
import jakarta.servlet.http.HttpSessionBindingEvent;
import java.util.Date;
@WebListener
public class LoginListener implements HttpSessionAttributeListener {
private static final LoginDao LOGINDAO=new LoginDaoIpml();
private String name=null;//获取session中存储的用户名
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("登录!!");
name=(String) event.getSession().getAttribute("logUser");
LOGINDAO.Listener(name,new Date(),"登录操作");
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("退出!!");
LOGINDAO.Listener(name,new Date(),"注销操作");
}
}