效果:同一个账号,最后一个登录的用户会把前一个登录后的用户顶掉,被迫下线!
登录的后台逻辑
session
,并重定向到首页。而实现上述效果只需要稍加修改即可。
sessionId
的值。sessionId
字段。(不同浏览器的sessionId
都是唯一的)session
之前,把当前账号对应的sessionId
字段值置Null
。sessionId
到账户信息表查询是否可以查到,如果查得到,说明账号状态正常,如果没有查到,只能是该账号被另一个浏览器进行访问登录了(会覆盖掉原来的sessionId
,改为登录人本机浏览器的sessionId
)登录请求方法
/**
* todo 登录请求
*/
@PostMapping("/loginSubmit")
public String loginSubmit(String username, String password, HttpSession session, Model model){
List<Map> accountByPassword = busineService.getAccountByPassword(username, password);
if(accountByPassword.size()>0){
//用户存在
session.setAttribute("account",username);
model.addAttribute("account",username);
//############## 重点 #########################
String sessionid = session.getId();
int i = busineMapper.updateSessionIdByUsername(sessionid, username);
//############## 重点 #########################
return "redirect:/business/index";
}else{
//用户不存在
model.addAttribute("msg","用户名或密码错误");
return "login";
}
}
退出登录方法
/**
* todo 退出系统
*/
@RequestMapping("/logout")
public String logout(HttpSession session){
String username=(String) session.getAttribute("account");
//############## 重点 #########################
int i = busineMapper.updateSessionIdByUsername(null, username);
//############## 重点 #########################
session.removeAttribute("account");
return "forward:/business/login";
}
/**
* todo 退出系统[通知下线时点击确定跳转此方法,不可以清空sessionId的值,因为后来登录的人要正常使用系统]
*/
@RequestMapping("/logout1")
public String logout1(HttpSession session){
session.removeAttribute("account");
return "forward:/business/login";
}
登录sql实现
// todo 登录
@Select(value = "select * from activiti_account where username=#{username} and password=#{password} and yxbz=1")
List<Map> getAccountByPassword(@Param("username") String username, @Param("password") String password);
//登录时更新账号表的sessionid字段
@Update(value = "update activiti_account set sessionid=#{sessionid} where username=#{username}")
int updateSessionIdByUsername(@Param("sessionid") String sessionid,@Param("username") String username);
//轮询检查sessionid是否存在或是否被替换
@Select(value = "select * from activiti_account where sessionid=#{sessionid}")
Map checkSessionId(String sessionid);
js
写一个定时器,定时刷新账号登录状态
$(function () {
var is=true;
setInterval(function () {
if(is){
$.ajax({
url:"/business/checkSessionId",
type:"post",
dataType:"json",
success:function (data) {
if(data==0){
is=false;
layer.confirm('您的账号已在异地登录,请重新登录', {
btn: ['确定'] //按钮
}, function(){
//退出并跳转登录页面
window.location.href = "/business/logout1";
}, function(){
//退出并跳转登录页面
window.location.href = "/business/logout1";
});
}
}
});
}
},5000);
轮询方法
//轮询检查sesiosnid是否被替换,如果被替换,说明该账号已在异地登录
@RequestMapping("/checkSessionId")
@ResponseBody
public int checkSessionId(HttpSession session){
Map map = busineMapper.checkSessionId(session.getId());
if(map!=null){
//没有被替换,账号状态正常
return 1;
}else{
//账号已在异地登录,掉线通知
return 0;
}
}
效果:在A平台上复制一段某商品分享的吱口令,然后打开B平台,然后B平台会自动识别用户复制的吱口令,并打开该口令对应商品的详情页。
步骤分析:
JS
定时器请求后台方法,该方法到剪切板中查看吱口令内容】,如果有吱口令信息,则解密吱口令并打开该口令对应商品的详情页。这里没有具体实现,只给出实现思路,不过实现起来挺简单的!
剪切板如何操作?
Java 操作剪贴板的类在 java.awt.* 包(及其子包)下,获取系统剪贴板代码
下面代码实现用 Java
代码获取系统剪贴板对象,实现 复制 和 粘贴 文本的例子。
package com.xiets.clipboard;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
public class Main {
public static void main(String[] args) throws InterruptedException {
// 把文本设置到剪贴板(复制)
setClipboardString("Hello System Clipboard!");
// 从剪贴板中获取文本(粘贴)
String text = getClipboardString();
System.out.println("text: " + text);
}
/**
* 把文本设置到剪贴板(复制)
*/
public static void setClipboardString(String text) {
// 获取系统剪贴板
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
// 封装文本内容
Transferable trans = new StringSelection(text);
// 把文本内容设置到系统剪贴板
clipboard.setContents(trans, null);
}
/**
* 从剪贴板中获取文本(粘贴)
*/
public static String getClipboardString() {
// 获取系统剪贴板
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
// 获取剪贴板中的内容
Transferable trans = clipboard.getContents(null);
if (trans != null) {
// 判断剪贴板中的内容是否支持文本
if (trans.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
// 获取剪贴板中的文本内容
String text = (String) trans.getTransferData(DataFlavor.stringFlavor);
return text;
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
}
控制台输出
参考文章:https://blog.csdn.net/xietansheng/article/details/70478266