目录
5.listener层 -------- 用于监听登录次数 、 时间
b.过滤登录 --- 未登录状态 --- 点击后重定向到登录界面
要求:
使用maven的方式,创建web项目完成如下功能:
1 编辑登陆页面
2 模拟登陆功能(可以使用数据库 也可以不用,模拟即可)
3 登陆成功之后将 用户登陆成功的状态保存在session中
4 使用其他浏览器再次登陆,登陆成功之后,将其他地方登陆该用户强制下线
5 编辑主页
6 添加过滤器 ,控制如果用户未登录则无法访问主页,必须登陆之后才能访问
7 添加监听器, 记录用户登陆信息 例如:时间 次数等等
一.图片展示
1.登录界面
2.注册界面
3.查询用户登录信息界面
二.主要的jsp代码
1.登录---login.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录界面</title>
</head>
<body>
<a href="index.jsp">返回测试♥网页界面</a>
<form action="login" method="post">
<p>用户名:<input type="text" name="username" placeholder="请输入用户名"></p>
<p>密    码:<input type="text" name="password" placeholder="请输入密码"></p>
<p>
<input type="submit" value="登录">
<span style="color: red">
${empty error ? "" : error}
</span>
</p>
</form>
<p>没有账户?<a href="register.jsp">点此注册</a></p>
</body>
</html>
2.注册--register.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>注册♥界面</title>
</head>
<body>
<a href="index.jsp">返回测试♥网页界面</a>
<form action="register" method="post">
<p>
用户名:<input type="text" name="username">
<span style="color: red">
${empty error? "" : error}
</span>
</p>
<p> 密★码:<input type="text" name="password"></p>
<p> 生★日:<input type="date" name="birthday"></p>
<p> 电★话:<input type="text" name="telephone"></p>
<p>
<input type="reset" value="重置">
<input type="submit" value="注册">
</p>
</form>
</body>
</html>
3.用户登录信息查询---userLoginMsg.jsp
<%@ page import="java.util.Map" %>
<%@ page import="com.ak.entity.UserLoginMsg" %>
<%@ page import="java.util.Set" %>
<%@ page import="java.util.Iterator" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>统计所有用户的登录信息</title>
</head>
<body>
<%
Map<String, UserLoginMsg> userLoginMsgMap = (Map<String, UserLoginMsg>) application.getAttribute("userLoginMsgMap");
Set<Map.Entry<String, UserLoginMsg>> entries = userLoginMsgMap.entrySet();
Iterator<Map.Entry<String, UserLoginMsg>> iterator = entries.iterator();
out.println("<table border='1' width='500px'><caption>统计所有用户的登录信息如下:</caption><tr><th>用户名</th><th>登录时间 </th><th>登录次数</th></tr>");
while (iterator.hasNext()) {
Map.Entry<String, UserLoginMsg> next = iterator.next();
UserLoginMsg userLoginMsgValue = next.getValue();
String username = userLoginMsgValue.getUsername();
String loginTime = userLoginMsgValue.getLoginTime();
int loginCount = userLoginMsgValue.getLoginCount();
out.println("<tr style=\"text-align: center\"><td>" + username + "</td><td>" + loginTime + "</td><td>" + loginCount + "</td></tr>");
}
out.println("</table>");
out.flush();
out.close();
%>
</body>
</html>
三.主要的java代码
1.工具类 Utils 层
a.Druid工具类的封装
package com.ak.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class DruidUtils {
//定义成员变量 数据源
private static DataSource dataSource;
//使用静态代码块 读取配置文件信息
static {
try {
//创建Properties 对象
Properties p = new Properties();
//基于反射技术 获取类加载器
InputStream inputStream = DruidUtils.class.getClassLoader().getResourceAsStream("druid.properties");
p.load(inputStream);
dataSource = DruidDataSourceFactory.createDataSource(p);
} catch (Exception e) {
e.printStackTrace();
}
}
public static DataSource getDataSource() {
return dataSource;
}
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
public void close(Connection connection, Statement statement){
if (connection != null && statement != null){
try {
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public void close(Connection connection, Statement statement, ResultSet resultSet){
if (connection != null && statement != null && resultSet != null){
try {
resultSet.close();
statement.close();
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
b. UUID工具的封装
package com.ak.utils;
import java.util.UUID;
public class UUIDUtils {
public static String getUUID(){
return UUID.randomUUID().toString().replace("-","");
}
}
2. dao层
package com.ak.dao;
import com.ak.entity.User;
import com.ak.utils.DruidUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.sql.SQLException;
public class UserDao {
private QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//注册用户 即添加用户
public void registerUser(User user) {
try {
String sql = "insert into user values (?,?,?,?,?)";
qr.update(sql, user.getId(), user.getUsername(), user.getPassword(), user.getBirthday(), user.getTelephone());
} catch (SQLException e) {
e.printStackTrace();
}
}
//定义登录功能
public User loginUser(User user) {
User loginUser = null;
try {
String sql = "select * from user where username = ? and password = ?";
loginUser = qr.query(sql, new BeanHandler<>(User.class), user.getUsername(), user.getPassword());
} catch (SQLException e) {
e.printStackTrace();
}
return loginUser;
}
public User findUserByName(String username) {
try {
String sql = "select*from user where username=?";
User user = qr.query(sql, new BeanHandler<>(User.class), username);
return user;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
3.servlet层
a. 登录
package com.ak.filter;
import com.ak.entity.User;
import com.ak.service.UserService;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@WebFilter(filterName = "loginFilter", urlPatterns = "/login")
public class LoginFilter implements Filter {
//声明成员变量
private ServletContext servletContext = null;
/**
* 构造方法执行后 执行初始化
*
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//获取servletContext对象
servletContext = filterConfig.getServletContext();
//准备一个map 用于保存 用户名和sessionID 并将map绑定在servletContext
Map<String, String> userLoginMap = new HashMap<>();
servletContext.setAttribute("userLoginMap", userLoginMap);
}
/**
* 定义拦截到请求后 具体执行逻辑
*
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1.获取用户名
servletRequest.setCharacterEncoding("utf-8");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String username = request.getParameter("username");
String password = request.getParameter("password");
//使用UserService 验证用户名和密码的正确性
UserService userService = new UserService();
User user = userService.loginUser(username, password);
if (user != null) {
//2.检查userLoginMap 中是否存在key = username
Map<String, String> userLoginMap = (Map<String, String>) servletContext.getAttribute("userLoginMap");
if (userLoginMap.containsKey(username)) {
//3.如果存在 已登录userLoginMap
// a.获取userLoginMap 中 username 对应的sessionID sid01
String sid01 = userLoginMap.get(username);
System.out.println("sid01=" + sid01);
// b.获取当前的sessionID sid02
String sid02 = request.getSession().getId();
System.out.println("sid02=" + sid02);
// c.如果sid01 != sid02 异地登陆 则 将userLoginMap.put(username,sid02)
if (!sid01.equals(sid02)) {
userLoginMap.put(username, sid02);
}
} else {
//4.如果不存在 则第一次登陆 获取sessionID 与 username 存在 userLoginMap
userLoginMap.put(username, request.getSession().getId());
}
}
//5.放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("Filter销毁执行了......");
}
}
b.注册
package com.ak.servlet;
import com.ak.entity.User;
import com.ak.service.UserService;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "registerServlet",urlPatterns = "/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
User user = new User();
String username = req.getParameter("username");
user.setUsername(username);
String password = req.getParameter("password");
user.setPassword(password);
String birthday = req.getParameter("birthday");
user.setBirthday(birthday);
String telephone = req.getParameter("telephone");
user.setTelephone(telephone);
UserService userService = new UserService();
String str = userService.registerUser(user);
if (str.equals("success")){
System.out.println("servlet层,提示:"+"Registered successfully");
//重定向到登录界面
resp.sendRedirect("login.jsp");
} else if (str.equals("msg")){
req.setCharacterEncoding("utf-8");
//返回提示信息
req.setAttribute("error","用户名已存在!");
//获取转发器 并指定转发路径
RequestDispatcher requestDispatcher = req.getRequestDispatcher("register.jsp");
//执行转发
requestDispatcher.forward(req,resp);
} else {
req.setCharacterEncoding("utf-8");
//返回提示信息
req.setAttribute("error","用户名和密码不能为空!");
//获取转发器 并指定转发路径
RequestDispatcher requestDispatcher = req.getRequestDispatcher("register.jsp");
//执行转发
requestDispatcher.forward(req,resp);
}
}
}
4.service层
package com.ak.service;
import com.ak.dao.UserDao;
import com.ak.entity.User;
import com.ak.utils.UUIDUtils;
/**
* 负责业务逻辑处理
*/
public class UserService {
private UserDao userDao = new UserDao();
//登录
public User loginUser(String username, String password) {
//将username 和 password 封装成一个user对象
//调用UserDao 中的 longingUser 方法
User user = new User();
user.setUsername(username);
user.setPassword(password);
System.out.println("service层,User:" + user);
User loginUser = userDao.loginUser(user);
return loginUser;
}
//注册
public String registerUser(User user) {
if (!user.getUsername().equals("") && !user.getPassword().equals("")) {
User userByName = userDao.findUserByName(user.getUsername());
if (userByName == null) {
user.setId(UUIDUtils.getUUID());
userDao.registerUser(user);
return "success";
} else {
return "msg";
}
} else {
return "error";
}
}
}
5.listener层 -------- 用于监听登录次数 、 时间
package com.ak.listener;
import com.ak.entity.UserLoginMsg;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@WebListener
public class UserLoginListener implements HttpSessionAttributeListener, ServletContextListener {
/**
* 1.在ServletContext中,绑定一个userLoginMsgMap 用于记录所有用户的登录
* userLoginMsgMap key:username
* value : 登录时间 + 登录次数 封装一个javaBean
* 2.监听session中属性为username的变化,有变化,将其放入userLoginMsgMap
*
*/
//声明servletContext的引用
private ServletContext servletContext = null;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//在项目启动的时候 初始化 servletContext
servletContext = servletContextEvent.getServletContext();
//用于记录用户登录信息的Map
Map<String, UserLoginMsg> userLoginMsgMap = new HashMap<>();
//绑定到servletContext
servletContext.setAttribute("userLoginMsgMap",userLoginMsgMap);
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//销毁
servletContext = null;
}
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("session新增了属性:"+event.getName()+"="+event.getValue());
addOrReplaceAction(event);
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("session修改了属性:"+event.getName());
addOrReplaceAction(event);
}
//封装 属性 新增和修改的逻辑
public void addOrReplaceAction(HttpSessionBindingEvent event){
String date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
//1.判断新增属性名 是否是username
if (event.getName().equals("username")){
//获取用户名
String username = (String) event.getSession().getAttribute("username");
Map<String, UserLoginMsg> userLoginMsgMap = (Map<String, UserLoginMsg>)servletContext.getAttribute("userLoginMsgMap");
//检测userLoginMsgMap中是否包含 key 为username的元素
if (userLoginMsgMap.containsKey(username)){
//如果包含 证明 不是第一次登录 获取UserLoginMsg 并修改登录时间
UserLoginMsg userLoginMsg = userLoginMsgMap.get(username);
//登录次数+1
userLoginMsg.setLoginCount(userLoginMsg.getLoginCount()+1);
//修改登录时间
userLoginMsg.setLoginTime(date);
} else {
//不包含 证明 第一次登录
UserLoginMsg userLoginMsg = new UserLoginMsg(username, date, 1);
userLoginMsgMap.put(username,userLoginMsg);
}
}
}
}
6.filter层 ----用于过滤
a.过滤 异地登录 强制下线
package com.ak.filter;
import com.ak.entity.User;
import com.ak.service.UserService;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@WebFilter(filterName = "loginFilter", urlPatterns = "/login")
public class LoginFilter implements Filter {
//声明成员变量
private ServletContext servletContext = null;
/**
* 构造方法执行后 执行初始化
*
* @param filterConfig
* @throws ServletException
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//获取servletContext对象
servletContext = filterConfig.getServletContext();
//准备一个map 用于保存 用户名和sessionID 并将map绑定在servletContext
Map<String, String> userLoginMap = new HashMap<>();
servletContext.setAttribute("userLoginMap", userLoginMap);
}
/**
* 定义拦截到请求后 具体执行逻辑
*
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1.获取用户名
servletRequest.setCharacterEncoding("utf-8");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String username = request.getParameter("username");
String password = request.getParameter("password");
//使用UserService 验证用户名和密码的正确性
UserService userService = new UserService();
User user = userService.loginUser(username, password);
if (user != null) {
//2.检查userLoginMap 中是否存在key = username
Map<String, String> userLoginMap = (Map<String, String>) servletContext.getAttribute("userLoginMap");
if (userLoginMap.containsKey(username)) {
//3.如果存在 已登录userLoginMap
// a.获取userLoginMap 中 username 对应的sessionID sid01
String sid01 = userLoginMap.get(username);
System.out.println("sid01=" + sid01);
// b.获取当前的sessionID sid02
String sid02 = request.getSession().getId();
System.out.println("sid02=" + sid02);
// c.如果sid01 != sid02 异地登陆 则 将userLoginMap.put(username,sid02)
if (!sid01.equals(sid02)) {
userLoginMap.put(username, sid02);
}
} else {
//4.如果不存在 则第一次登陆 获取sessionID 与 username 存在 userLoginMap
userLoginMap.put(username, request.getSession().getId());
}
}
//5.放行
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
System.out.println("Filter销毁执行了......");
}
}
b.过滤登录 --- 未登录状态 --- 点击后重定向到登录界面
package com.ak.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
@WebFilter(filterName = "loginFilter2",urlPatterns = "/*")
public class LoginFilter2 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filter初始化执行了......");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//1.判断请求路径是否 是 index.jsp
HttpServletRequest request = (HttpServletRequest) servletRequest;
//获取请求路径
String servletPath = request.getServletPath();
if (servletPath.contains("index")){
//2.是 访问index.jsp 再判断登录状态
HttpSession session = request.getSession();
String username = (String) session.getAttribute("username");
ServletContext servletContext = request.getServletContext();
Map<String,String> userLoginMap = (Map<String,String>)servletContext.getAttribute("userLoginMap");
//获取登录成功之后,保存的sessionID
String sid01 = userLoginMap.get(username);
//获取本次登录的sessionID
String sid02 = session.getId();
if (username != null && sid02.equals(sid01)){
//b. 已登录 放行
filterChain.doFilter(request,servletResponse);
} else {
//a. 未登录 重定向到登录界面
((HttpServletResponse)servletResponse).sendRedirect("login.jsp");
}
} else {
//3.不是 访问index.jsp 放行即可
filterChain.doFilter(request,servletResponse);
}
}
@Override
public void destroy() {
System.out.println("Filter销毁执行了......");
}
}
7.entity层
a.封装用户登录信息 类
package com.ak.entity;
public class UserLoginMsg {
private String username;
private String loginTime;
private int loginCount;
public UserLoginMsg() {
}
public UserLoginMsg(String username, String loginTime, int loginCount) {
this.username = username;
this.loginTime = loginTime;
this.loginCount = loginCount;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getLoginTime() {
return loginTime;
}
public void setLoginTime(String loginTime) {
this.loginTime = loginTime;
}
public int getLoginCount() {
return loginCount;
}
public void setLoginCount(int loginCount) {
this.loginCount = loginCount;
}
@Override
public String toString() {
return "UserLoginMsg{" +
"username='" + username + '\'' +
", loginTime='" + loginTime + '\'' +
", loginCount=" + loginCount +
'}';
}
}
b. 用户 类
package com.ak.entity;
public class User {
private String id;
private String username;
private String password;
private String birthday;
private String telephone;
public User() {
}
public User(String id, String username, String password, String birthday, String telephone) {
this.id = id;
this.username = username;
this.password = password;
this.birthday = birthday;
this.telephone = telephone;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", birthday='" + birthday + '\'' +
", telephone='" + telephone + '\'' +
'}';
}
}