我在 JSF+Primefaces 上有一个应用程序,它实现了授权机制。通过 servlet.Filter,我查看所有传入的请求,如果没有授权,则重定向到授权页面(如果请求是针对不存在的页面,则重定向到 404 页面)。
一切正常。我想这样做,如果用户从其中一个页面退出(注销),其他打开的页面也会自动退出。从理论上讲,您可以向服务器发出定期重复的请求,但这种方法在我看来并不正确(来自用户的持续流量,而不是立即退出)。
我决定实现 COMET 架构,为此,在页面加载时,我打开一个 js 套接字并向服务器发出请求。
JS:
function loginControl() {
var xhr = new XMLHttpRequest();
xhr.open('GET', 'myURL/'+uuidv4(),true);
xhr.send("");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
if (xhr.response == 'logout') {
window.location.replace('login.xhtml');
}
}
}
}
}
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
(uuidv4——这是一个实验,让每一个新的请求都会有一个新的URL,我以为可以解决“等待socket”的问题)。
public class SecurityFilterr implements Filter {
@Inject
private Access access;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
//...
if((resource != null) && (resource.length()> 6) && (resource.substring(0,6).equals("myURL/"))) {
try {
PrintWriter printWriter = response.getWriter();
AccessEntity ae = new AccessEntity();
access.addToListPage(ae);
ae.logoutControl(false);
printWriter.write("logout");
printWriter.close();
} catch (InterruptedException ex ){
System.err.println(ex);
}
return;
}
//...
}
}
AccessEntity - 我“睡眠”线程的类
public class AccessEntity {
synchronized public void logoutControl(boolean logout) throws InterruptedException {
if(logout){
this.notifyAll();
} else {
this.wait();
}
}
}
使用权
@Named
@SessionScoped
public class Access implements Serializable {
private List<AccessEntity> listPage;
@PostConstruct
public void init(){
//..
listPage = new ArrayList();
}
public String logout() {
//..
try {
for (AccessEntity obj : listPage){
obj.logoutControl(true);
}
listPage = new ArrayList<>();
} catch (InterruptedException ex){
System.err.println(ex);
}
return "logout";
}
}
重点是我通过js向服务器发出请求,服务器并没有立即响应,而是睡着了。它仅在发生注销时才返回响应。响应后,js会重定向到授权页面。
当打开 2-3 页时,一切正常,但当打开 6-7 页时,第 7 页甚至没有加载,而是挂起。此时浏览器会写入“等待空闲套接字”。单击其他选项卡上的按钮根本没有任何作用。
我用野蝇。
为什么会发生这种情况,我是否正确实施 COMET 架构?
实际上,浏览器对打开的 XMLHttpRequest 套接字的数量有限制(5-10 个,具体取决于浏览器)。正如评论中所建议的,您可以使用 WebSocket,它消除了这个限制