Java web實現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄(踢人效果)
實現(xiàn)了Java web開發(fā)賬號單一登錄的功能,防止同一賬號重復(fù)登錄,后面登錄的踢掉前面登錄的,使用過濾器Filter實現(xiàn)的??梢韵认螺d項目下來測試下效果。
有博客寫的是沒個一段時間(比如500ms)讀取后臺的session進(jìn)行驗證,這種方法除了會占用資源,還會出現(xiàn)訪問session(請求1)的返回值和自己提交請求(請求2)的返回值發(fā)生沖突。比如請求1先提交,此時請求1的返回值還未返回到前端,請求2提交,實際上我們想要的是請求1的返回值先返回,然后再返回請求2的返回值,但是這不是肯定會發(fā)生的,ajax的機(jī)制所導(dǎo)致的,具體什么原因沒查到。總之出現(xiàn)了請求2先返回了返回值,這時候請求1接收到了請求2的返回值,妥妥的前端出現(xiàn)錯誤,但是后臺卻是成功的。
下面進(jìn)入主題
工程下載鏈接:鏈接: https://pan.baidu.com/s/1Rp09wv7hTJLqx9DiQ_KSeA 提取碼: xyym
其中:jquery-1.11.3.js是網(wǎng)上的工具

建立兩個簡單的界面
登錄界面:為了簡單沒有設(shè)置密碼,直接輸入賬號點擊登錄就行

// index.jsp <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>" rel="external nofollow" rel="external nofollow" > <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css" rel="external nofollow" rel="external nofollow" > --> </head> <body> <input id="username" name="username" type="text"> <!-- <a href="singlecount.jsp" rel="external nofollow" target="_self"> --> <button id="btnlogin" name="btnlogin">登錄</button><!-- </a> --> <!-- 引入jQuery --> <script type="text/javascript" src="js/jquery-1.11.3.js"></script> <script type="text/javascript" src="js/jsSubmit.js"></script> </body> </html>
主頁面:簡單的一個提交按鈕

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>" rel="external nofollow" rel="external nofollow" > <title>My JSP 'SingleCount.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css" rel="external nofollow" rel="external nofollow" > --> </head> <body> 已登錄. <br> <button id="btnsubmit" name="submit">提交</button> <!-- 引入jQuery --> <script type="text/javascript" src="js/jquery-1.11.3.js"></script> <script type="text/javascript" src="js/jsSubmit.js"></script> </body> </html>
寫ajax,向后臺提交請求
// jsSubmit.js
$(document).ready(function() {
// 登錄按鈕
$("#btnlogin").click(function() {
//data,dataType,type,url
$.ajax({
url: 'LoginServlet?method=login',
type: 'post',
data: {username: $("input[name='username']").val()}, // 將用戶名傳給servlet
//dataType:'json',
success: function(msg) { // msg為從servlet接收到的返回值
if (msg == 1) { // 接收到后臺數(shù)據(jù)為1,正常登錄
window.location.href = "singlecount.jsp";
}
},
error:function(){
window.alert("錯誤!");
}
});
});
// 提交按鈕
$("#btnsubmit").click(function() {
//data,dataType,type,url
$.ajax({
url: 'SubmitServlet?method=submit',
type: 'post',
//dataType:'json',
success: function(msg) { // msg為從servlet接收到的返回值
if (msg >= 1) { // 正常
window.alert("提交總數(shù)" + msg);
}
},
error:function(jqXHR){
if(jqXHR.status == 900){ // 900狀態(tài)碼
window.alert("登錄狀態(tài)失效,請重新登錄!");
window.location.href = "/OneLogin";
}
}
});
});
});
servlet
這部分有點長,其實主要內(nèi)容直接看doPost方法就可以了。
// LoginServlet
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletConfig;
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;
@SuppressWarnings("serial")
//注解表明什么樣的情況下可以訪問該內(nèi)容
@WebServlet(urlPatterns={"/LoginServlet"})
public class LoginServlet extends HttpServlet {
private PrintWriter out; // 輸出流
private String user;
private String method;
private HttpSession session;
// 建立一個Map存儲session信息,key-用戶名,value-session
public static Map<String, HttpSession> user_Session = new HashMap<String, HttpSession>();
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
// 在這里實現(xiàn)方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/html");
//語言編碼
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
out = resp.getWriter();
user = req.getParameter("username"); // 獲取index界面username的內(nèi)容
method = req.getParameter("method"); // 獲取方法名
session = req.getSession(); // 獲取session
switch (method) {
case "login":
mLogin();
break;
default:
break;
}
out.flush();
out.close();
}
private void mLogin() { // 按登錄按鈕調(diào)用的方法
// TODO Auto-generated method stub
removeUser(user);
session.setAttribute("name", user);
user_Session.put(user, session); // 新增或覆蓋session
System.out.println(user_Session);
out.println(1); // 返回值1,隨意選個值,和前端對應(yīng)就可以
}
/**
* 判斷是否有重復(fù)用戶,
* 若出現(xiàn)重復(fù)用戶,踢掉前面登錄的用戶,即刪除其session
*/
private void removeUser(String user) {
if(user_Session.containsKey(user))
user_Session.get(user).invalidate();
}
}
// SubmitServlet
package servlet;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@SuppressWarnings("serial")
//注解表明什么樣的情況下可以訪問該內(nèi)容 會在js和web.xml中使用
@WebServlet(urlPatterns={"/SubmitServlet"})
public class SubmitServlet extends HttpServlet {
private PrintWriter out; // 輸出流
private String method;
private int number = 0; // 計數(shù)
@Override
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
super.init(config);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
super.doDelete(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
doPost(req, resp);
}
@Override
// 在這里實現(xiàn)方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// TODO Auto-generated method stub
resp.setContentType("text/html");
//語言編碼
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
out = resp.getWriter();
method = req.getParameter("method"); // 獲取方法名
switch (method) {
case "submit":
mSubmit();
break;
default:
break;
}
out.flush();
out.close();
}
private void mSubmit() { // 按提交按鈕調(diào)用的方法
// TODO Auto-generated method stub
number++;
out.println(number);
}
}
過濾器
過濾器的原理這里就不說了,簡單來說就是請求要先經(jīng)過過濾器才能到達(dá)servlet,也就是說如果請求不滿足要求就無法通過過濾器,這里的要求是要有session。
package filter;
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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebFilter("/SessionFilter")
public class SessionFilter implements Filter {
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) arg0;
HttpServletResponse response = (HttpServletResponse) arg1;
String strURL = request.getRequestURL().toString(); // 獲取請求路徑
// System.out.println(strURL);
// 只過濾來自SubmitServlet請求和singlecount.jsp的加載,可以設(shè)置成自己想過濾的
// 需要在web.xml中添加<filter>
if(strURL.indexOf("SubmitServlet") != -1 || strURL.indexOf("singlecount.jsp") != -1){
if(request.getSession().getAttribute("name") == null){
request.getSession().invalidate();
response.sendError(900, "登錄失效,請重新登錄!"); // 自定義狀態(tài)碼,session失效
// 900 到ajax的error中處理
return;
}
else {
arg2.doFilter(arg0, arg1);
}
}
else {
arg2.doFilter(arg0, arg1);
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
配置web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1"> <display-name>OneLogin</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> <filter> <filter-name>filter.SessionFilter</filter-name> <filter-class>filter.SessionFilter</filter-class> </filter> <filter-mapping> <filter-name>filter.SessionFilter</filter-name> <url-pattern>/singlecount.jsp</url-pattern> <!-- 給界面添加過濾器 --> </filter-mapping> <filter-mapping> <filter-name>filter.SessionFilter</filter-name> <url-pattern>/SubmitServlet</url-pattern> <!-- 給servlet添加過濾器 --> </filter-mapping> </web-app>
實現(xiàn)效果
可以使用兩個不同的瀏覽器當(dāng)兩個客戶端,或者電腦多就用多臺電腦。
相同賬號登錄時,前面賬號再點提交請求就會給出提示,跳轉(zhuǎn)到登錄界面

未登錄直接進(jìn)入:http://localhost:8080/OneLogin/singlecount.jsp

如果也想實現(xiàn)跳轉(zhuǎn)效果,在jsSubmit.js的$(document).ready(function() {…}); 前面加入是否有session的判斷,沒有就給出提示,跳轉(zhuǎn)到登錄界面。
總結(jié)
以上所述是小編給大家介紹的Java web實現(xiàn)賬號單一登錄,防止同一賬號重復(fù)登錄,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
相關(guān)文章
Java使用pdfbox實現(xiàn)給pdf文件加圖片水印
有時候需要給pdf加水印,市面上工具都是收費的要會員,還是自食其力吧;嘗試過 spire.pdf.free 那個超過10頁就不行了!所以本文還是使用了pdfbox,感興趣的可以了解一下2022-11-11
java socket大數(shù)據(jù)傳輸丟失問題及解決
這篇文章主要介紹了java socket大數(shù)據(jù)傳輸丟失問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08
布隆過濾器(Bloom Filter)的Java實現(xiàn)方法
下面小編就為大家?guī)硪黄悸∵^濾器(Bloom Filter)的Java實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
java獲取request中的參數(shù)以及java解析URL問號后的參數(shù)
這篇文章主要介紹了java獲取request中的參數(shù)以及java解析URL問號后的參數(shù)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-12-12
Java實現(xiàn)根據(jù)前端所要格式返回樹形3級層級數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了Java如何實現(xiàn)根據(jù)前端所要格式返回樹形3級層級數(shù)據(jù),文中的示例代碼講解詳細(xì),有需要的小伙伴可以了解下2024-02-02

