经过对业务逻辑的完善,解决了一部分问题,但还是有一部分问题没有解决
在解决问题的过程中,也意识到了一些细节的重要性。在网页每次向服务端发出请求时,doget方法中的实例对象是(比如集合对象,用户信息对象)都会被重新创建吗?因为每次发出新的请求的时候,doget方法中都是在执行集合对象为空的代码。后面我直接将集合对象loginList创建在用户信息类LoginMessage类中,对象也在servlet全局中声明,解决了这一问题(如下)
未解决的问题(如下):
已经判断出了用户新登入的账户已登录,但是remove方法还是没有执行,是调用的remove方法不对还是?
2. 在踢掉之前登录的账户,我的思路大概是这样的,LoginMessage对象保存用户的账户以及密码,把LoginMessage对象存入List集合中,然后通过遍历List集合,判断新传入的用户账户是否已存在,如果已存在,则把list集合已存在的用户账户调用remove方法,再到监听器remove方法中循环遍历,找出与之对应的sessionID,在将其删除。 在返回到LoginServlet类中,将新传入的用户信息加入。整体是这样的一样思路。
相关代码:servlet业务逻辑实现类
package com.roan.login;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
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 javax.servlet.http.HttpSession;
/**
* Servlet implementation class LoginServlet
*/
@WebServlet("/servlet/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 声明用户信息对象loginMessage
private LoginMessage loginM=null;
// 创建用户会话对象,存储用户信息
private HttpSession session =null;
/**
* @see HttpServlet#HttpServlet()
*/
public LoginServlet() {
super();
loginM=new LoginMessage();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
* response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
boolean flag=false;
session=request.getSession();
// 获取login界面传来的用户名密码参数
String name = request.getParameter("userName");
String pwd = request.getParameter("pwd");
if(name!=null&&pwd!=null) {
// 用户信息对象为空时,用户信息直接添加,用户会话属性直接赋值
if(!loginM.getLoginList().isEmpty()) {
// 用户信息对象不为空时,则先判断用户信息是否已存在?如不存在则添加,如存在则删除上一个用户会话对象
for(LoginMessage l:loginM.getLoginList()) {
if(l.getUserName().equals(name)) {
System.out.println("该用户账户已经登录");
// 调用remove方法,将之前的用户信息传值
session.removeAttribute(l.getUserName());
// 将新登入的用户信息传入,赋予新的用户会话ID
session.setAttribute("name", name);
flag=true;
break;
}else {
System.out.println("新用户持续登录中");
session.setAttribute("name", name);
loginM.setPwd(pwd);
loginM.setUserName(name);
loginM.getLoginList().add(loginM);
flag=true;
}
}
}else {
session.setAttribute("name", name);
loginM.setPwd(pwd);
loginM.setUserName(name);
loginM.getLoginList().add(loginM);
System.out.println("用户第一次登录成功");
flag=true;
}
}
// 发送请求,将该请求下发到登录成功页面
if(flag){
request.setAttribute("name", name);
response.sendRedirect("/user-login-project/jsp/login-success.jsp");
}
}
}
相关代码:监听器实现类
package com.roan.login;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
public class SessionAttributeListener implements HttpSessionAttributeListener{
// 声明用户会话ID和用户账户Map集合
private Map<String,String> loginMap=null;
public SessionAttributeListener() {
super();
loginMap=new HashMap<>();
}
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
System.out.println("新增属性:");
System.out.println(event.getSession().getId()+":"+event.getValue().toString());
loginMap.put(event.getSession().getId(), event.getValue().toString());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
System.out.println("删除属性"+event.getValue());
// 遍历集合loginMap,找出用户账户与之对应的用户会话ID并删除
Set<Entry<String,String>> entrySet=loginMap.entrySet();
for(Entry<String,String> entry:entrySet) {
if(entry.getValue().equals(event.getValue())){
event.getSession().removeAttribute(entry.getKey());
}
}
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
System.out.println("修改属性属性");
System.out.println(event.getSession().getId()+":"+event.getValue());
loginMap.put(event.getSession().getId(), event.getValue().toString());
}
}
相关代码:用户信息实体类
package com.roan.login;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class LoginMessage {
private String userName;//用户账户
private String pwd;//用户密码
private List<LoginMessage> loginList;
public LoginMessage() {
loginList=new ArrayList<>();
}
public LoginMessage(String userName, String pwd) {
super();
this.userName = userName;
this.pwd = pwd;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public List<LoginMessage> getLoginList() {
return loginList;
}
public void setLoginList(List<LoginMessage> loginList) {
this.loginList = loginList;
}
}
相关代码:过滤器实现类
package com.roan.login;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class isFilter implements Filter{
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain arg2)
throws IOException, ServletException {
HttpServletRequest re=(HttpServletRequest)request;
// 拦截当前浏览网页的URL
String url=re.getRequestURI().toString();
// 判断用户是否登录
if(url.startsWith("/user-login-project/jsp/login-success")){
System.out.println("用户已登录 url="+url);
}else if(url.startsWith("/user-login-project/user-login")){
System.out.println("用户未登录 url="+url);
}
arg2.doFilter(request, response);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("初始化");
}
}
相关代码:登录界面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>用户登录</title>
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
</head>
<body>
<div id="login_h">
<div id="login_h_title">
<h1>系统登录</h1>
</div>
<div id="login_body">
<form id="body_form" action="http://localhost:8080/user-login-project/servlet/login" method="get" >
<p>用户名:
</p>
<input type="text" id="userName" name="userName" placeholder="请输入中文/字母/数字的用户名【4-7位】"
/>
<p>密码:
</p>
<input type="password" id="pwd" name="pwd" placeholder="字母开头,数字字母6-10位组成"/ ><br>
<input type="submit" id="sub" name="sub" value="登录">
</form>
</div>
</div>
<script type="text/javascript">
$.ajax({
"url":"http://localhost:8080/user-login-project/servlet/login",
"type":"get",
"dataType":"json",
"success":function(json){
}
})
/* 给表单添加提交事件 */
/* 给相应的输入框添加正则表达式,限制输入内容 */
document.getElementById("body_form").onsubmit=function(){
var regexUserName=/^[\u4e00-\u9fa5A-Za-z1-9]{1}[\u4e00-\u9fa5A-Za-z0-9]{3,6}$/;
var regexPwd=/^[A-Za-z]{1}[0-9A-Za-z]{5,9}$/;
var userName=document.getElementById("userName").value;
var pwd=document.getElementById("pwd").value;
if(regexUserName.test(userName)==false){
alert("用户名不符合当前格式!");
return false;
}else if(regexPwd.test(pwd)==false){
alert("密码不不符合格式");
return false;
}else{
alert("校验成功!");
}
}
</script>
</body>
</html>
相关代码:登录成功页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
<head>
<script type="text/javascript">
</script>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1 style="color:red;">您好,${sessionScope.name},您已登录!</h1>
</body>
</html>
正在回答 回答被采纳积分+1
同学你好,需要删除上一个用户账户对应的session ID值,新登录的用户账户需要重新调用监听器中的新增方法。同学可以参考如下代码:
LoginMessage类:该类是单例,有存储用户登录sessionID和用户登录session的Map集合,有通过用户名查询和设置sessionID的方法,以及通过sessionID查找和设置session的方法。
public class LoginMessage {
private static LoginMessage instance = new LoginMessage();
private Map<String,String> loginUserSession = new HashMap<String,String>();// key值:登录用户登录名,value值:登录用户sessionId
private Map<String, HttpSession> loginSession = new HashMap<String,HttpSession>();//key值:登录用户sessionId,value值:登录用户session对象
private LoginMessage(){
}
public static LoginMessage getInstance(){
return instance;
}
public String getSessionIdByUsername(String username){
return loginUserSession.get(username);
}
public HttpSession getSessionBySessionId(String sessionId){
return loginSession.get(sessionId);
}
public void setSessionIdByUserName(String username,String sessionId){
loginUserSession.put(username, sessionId);
}
public void setSessionBySessionId(String sessionId,HttpSession session){
loginSession.put(sessionId, session);
}
}
LoginServlet类:
该类中只需要获取登录用户信息,将其存入session,转发到主界面的代码,如:
@WebServlet("/servlet/login")
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 发送请求,将该请求下发到登录成功页面
String username = request.getParameter("userName");
String password = request.getParameter("password");
HttpSession session = request.getSession();
session.setAttribute("loginUser", username);//登录完成,将登录用户名存储至session对象
response.sendRedirect("/success.jsp");
}
}
isFilter类(类命名不规范,首字母应该大写)
该类中只用来判断是否登录,如果登录,则跳转到主界面,没有登录则跳转到登录页面:
public class isFilter implements Filter{
@Override
public void destroy() {
System.out.println("过滤器销毁");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain arg2)
throws IOException, ServletException {
HttpServletRequest hrequest = (HttpServletRequest)request;
HttpServletResponse hresponse = (HttpServletResponse)response;
String loginUser = (String)hrequest.getSession().getAttribute("loginUser");
// 判断用户是否登录
if(loginUser==null){
hresponse.sendRedirect(hrequest.getContextPath()+"/login.jsp?flag=1");
return;
}else{
arg2.doFilter(request, response);
return;
}
}
LoginSessionListener监听器类:
该类的attributeAdded方法中获取监听到的属性名,如果是登录操作,则获取登录的名称,判断登录名称是否之前登录过,如果登录过,则清理前次会话信息,将本次登录信息存入LoginMessage。如:
public class SessionAttributeListener implements HttpSessionAttributeListener{
private static final String LOGIN_USER="loginUser";
public SessionAttributeListener() {
super();
}
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
String attrName = event.getName();
if(LOGIN_USER.equals(attrName)){//若属性名为登录属性名,判定为用户登录操作
String attrVal = (String)event.getValue();//获取添加的属性值,即用户登录名
HttpSession session = event.getSession();//该次操作的session对象
String sessionId = session.getId();//该次操作的session对象ID
String sessionId2 = LoginMessage.getInstance().getSessionIdByUsername(attrVal);//从缓存对象里面,获得该用户登录名对应的sessionID值
if(null == sessionId2){//未获得结果,不需要清理前次登录用户会话信息
}else{
HttpSession session2 = LoginMessage.getInstance().getSessionBySessionId(sessionId2);//获取前次该用户登录对应的session对象
session2.invalidate();//清理前次登录用户会话存储信息,使得前次登录失效
}
//完成该次登录用户登录名、sessionID,session对象的缓存对象存储
LoginMessage.getInstance().setSessionIdByUserName(attrVal, sessionId);
LoginMessage.getInstance().setSessionBySessionId(sessionId, session);
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
}
}
同学可以参考如上代码进行理解。
祝学习愉快~
- 参与学习 人
- 提交作业 9393 份
- 解答问题 16556 个
综合就业常年第一,编程排行常年霸榜,无需脱产即可学习,北上广深月薪过万 无论你是未就业的学生还是想转行的在职人员,不需要基础,只要你有梦想,想高薪
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星