【发布时间】:2013-12-24 19:25:51
【问题描述】:
我正在处理的一个项目从母版页实现了三个 JAVA 脚本“计时器”,以跟踪会话超时并进行“心跳”检查。如果在会话超时发生前超时计数达到 1 分半钟,“setTimerout”计时器会将用户重定向到警告页面。实现了两个“setInterval”计时器来跟踪用户的浏览器是否在站点上处于活动状态。以下是几个实现“定时器”和“心跳”和“心跳检查”处理程序的代码 sn-ps。
激活计时器的母版页代码:
Dim BaseAccountTimeout As Single = CType((CType(CurrentSessionTimeout, Single) - 1.5), Single)
If Session.Item("UseSessionTimeout") Then
Dim TimeoutAcount As String = CType(((BaseAccountTimeout * 60) * 1000), Integer).ToString
Page.ClientScript.RegisterStartupScript(Me.GetType, "TimeoutScript", "setTimeout(""top.location.href = '" & GotoTimeoutPage & "'""," & TimeoutAcount & ");", True)
End If
If Session.Item("UseHeartBeat") Then
Dim BaseHeartBeatTimeout As Single = CType(CurrentHeartBeatTimeout, Single)
Dim BaseHeartBeatCheckTimeout As Single = CType((BaseHeartBeatTimeout + 1.5), Single)
Dim TimeoutHeartBeat As String = CType(((BaseHeartBeatTimeout * 60) * 1000), Integer).ToString
Dim TimeoutHeartBeatCheck As String = CType(((BaseHeartBeatCheckTimeout * 60) * 1000), Integer).ToString
Page.ClientScript.RegisterStartupScript(Me.GetType, "HeartBeatScript", "setInterval(""ajax.post('/pages/heartbeat.ashx', {id: '" + Session.SessionID + "'}, function() {})""," & TimeoutHeartBeat & ");", True)
Page.ClientScript.RegisterStartupScript(Me.GetType, "HeartBeatCheckScript", "setInterval(""ajax.post('/pages/heartbeatcheck.ashx', {id: '" + Session.SessionID + "'}, function() {})""," & TimeoutHeartBeatCheck & ");", True)
End If
心跳处理程序代码:
<%@ webhandler language="VB" class="HeartbeatHandler" %>
Imports System
Imports System.Web
Imports System.Data
Imports System.Data.SqlClient
Public Class HeartbeatHandler
Implements IHttpHandler
Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
Public Sub ProcessRequest(ByVal ctx As HttpContext) Implements IHttpHandler.ProcessRequest
Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim dreader As System.Data.SqlClient.SqlDataReader
Dim GotOne As Boolean = False
Dim ValuesString As String = ""
Dim FieldsString As String = ""
Dim id As String = ""
id = ctx.Request.Params.Item("id")
If IsNothing(id) Then id = ""
If id = "" Then GoTo EXITHEARTBEAT
cmd.Connection = sqlConnection1
cmd.CommandType = System.Data.CommandType.Text
If cmd.Parameters.Count = 0 Then
cmd.Parameters.Add("@uID", System.Data.SqlDbType.NVarChar)
cmd.Parameters.Add("@Date", System.Data.SqlDbType.DateTime)
cmd.Parameters.Add("@IP", System.Data.SqlDbType.NVarChar)
End If
cmd.Parameters("@uID").Value = id
cmd.Parameters("@Date").Value = CType(Now, DateTime)
cmd.Parameters("@IP").Value = HttpContext.Current.Request.UserHostAddress
Try
cmd.CommandText = "SELECT SessionID FROM aspnet_Sessions WHERE SessionID = @uID"
sqlConnection1.Open()
dreader = cmd.ExecuteReader()
If dreader.Read() Then GotOne = True
dreader.Close()
Catch ex As Exception
' do nothing here
Finally
sqlConnection1.Close()
End Try
If GotOne Then
Try
ValuesString = "LastRequest = @Date"
cmd.CommandText = "UPDATE aspnet_Sessions SET " + ValuesString + " WHERE SessionID = @uID"
sqlConnection1.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
' do nothing here
Finally
sqlConnection1.Close()
End Try
Else
Try
FieldsString = "(Record, LiveDate, SessionID, LastRequest, IPAddress)"
ValuesString = "(NEWID(), @Date, @uID, @Date, @IP)"
cmd.CommandText = "INSERT aspnet_Sessions " + FieldsString + " VALUES " + ValuesString
sqlConnection1.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
' do nothing here
Finally
sqlConnection1.Close()
End Try
End If
EXITHEARTBEAT:
End Sub
End Class
心跳检查处理程序代码:
<%@ webhandler language="VB" class="HeartbeatCheckHandler" %>
Imports System
Imports System.Web
Imports System.Data
Imports System.Data.SqlClient
Public Class HeartbeatCheckHandler
Implements IHttpHandler
Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable
Get
Return True
End Get
End Property
Public Sub ProcessRequest(ByVal ctx As HttpContext) Implements IHttpHandler.ProcessRequest
Dim sqlConnection1 As New System.Data.SqlClient.SqlConnection(ConfigurationManager.ConnectionStrings("ApplicationServices").ConnectionString)
Dim cmd As New System.Data.SqlClient.SqlCommand
Dim dreader As System.Data.SqlClient.SqlDataReader
Dim GotOne As Boolean = Nothing
Dim ValuesString As String = ""
Dim FieldsString As String = ""
Dim LastRequest As DateTime = Nothing
Dim TimeDifference As Long = 0
Dim HeartBeatTimeout As Single = CommonCode.Common.DefaultHeartBeatTimeout
Dim MissedHeartBeats As Single = CommonCode.Common.DefaultMissedHeartBeats
Dim id As String = ""
id = ctx.Request.Params.Item("id")
If IsNothing(id) Then id = ""
If id = "" Then GoTo EXITHEARTBEATCHECK
cmd.Connection = sqlConnection1
cmd.CommandType = System.Data.CommandType.Text
Try
cmd.CommandText = "SELECT HeartBeatTimeout, MaximumMissedHeartBeats FROM aspnet_WebSiteSettings"
cmd.CommandType = System.Data.CommandType.Text
sqlConnection1.Open()
dreader = cmd.ExecuteReader()
If dreader.Read() Then
HeartBeatTimeout = dreader("HeartBeatTimeout")
MissedHeartBeats = dreader("MaximumMissedHeartBeats")
End If
dreader.Close()
Catch ex As Exception
' do nothing here
Finally
sqlConnection1.Close()
End Try
Dim MaximumDifference As Single = (HeartBeatTimeout * MissedHeartBeats) + 0.5
If cmd.Parameters.Count = 0 Then cmd.Parameters.Add("@uID", System.Data.SqlDbType.NVarChar)
cmd.Parameters("@uID").Value = id
Try
cmd.CommandText = "SELECT SessionID, LastRequest FROM aspnet_Sessions WHERE SessionID = @uID"
cmd.CommandType = System.Data.CommandType.Text
sqlConnection1.Open()
dreader = cmd.ExecuteReader()
If dreader.Read() Then
If Not IsDBNull(dreader("LastRequest")) Then
If dreader("LastRequest").ToString.Trim <> "" Then
LastRequest = dreader("LastRequest")
TimeDifference = DateDiff(DateInterval.Minute, LastRequest, CType(Now, DateTime))
If TimeDifference > MaximumDifference Then GotOne = True
Else
GotOne = False
End If
Else
GotOne = False
End If
Else
GotOne = False
End If
dreader.Close()
Catch ex As Exception
' do nothing here
Finally
sqlConnection1.Close()
End Try
If GotOne Then
Try
cmd.CommandText = "DELETE aspnet_Sessions WHERE SessionID = @uID"
cmd.CommandType = System.Data.CommandType.Text
sqlConnection1.Open()
cmd.ExecuteNonQuery()
Catch ex As Exception
' do nothing here
Finally
sqlConnection1.Close()
End Try
CommonCode.Common.DeleteFromSessionIDCollection(id)
CommonCode.Common.SessionData(CommonCode.Common.DeleteSessionData, id)
CommonCode.Common.DisposeSession()
End If
EXITHEARTBEATCHECK:
End Sub
End Class
以下是母版页上的代码:
var ajax = {};
ajax.x = function () {
try {
return new ActiveXObject('Msxml2.XMLHTTP')
} catch (e1) {
try {
return new ActiveXObject('Microsoft.XMLHTTP')
} catch (e2) {
return new XMLHttpRequest()
}
}
};
ajax.send = function (url, callback, method, data, sync) {
var x = ajax.x();
x.open(method, url, sync);
x.onreadystatechange = function () {
if (x.readyState == 4) {
callback(x.responseText)
}
};
if (method == 'POST') {
x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
}
x.send(data)
};
ajax.get = function (url, data, callback, sync) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
}
ajax.send(url + '?' + query.join('&'), callback, 'GET', null, sync)
};
ajax.post = function (url, data, callback, sync) {
var query = [];
for (var key in data) {
query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]));
}
ajax.send(url, callback, 'POST', query.join('&'), sync)
};
我发现 JAVA 脚本计时器仅在浏览器在站点上时才会继续触发。一旦用户关闭浏览器或导航离开站点,即使 Web 应用程序仍在运行,文件的唯一事件是会话超时时 Global.asax 中的 ASP.NET“Session_End”事件。我假设没有一个“计时器”会触发,这是由于母版页不再加载,因此主页面上的脚本不会触发。
我并不真正关心“setTimeout”计时器,因为如果浏览器在站点上不再处于活动状态,则无需重定向到超时页面,这样脚本就可以留在母版页上。但是,两个“setInterval”计时器是我试图继续运行的,因此应用程序可以检测用户是否离开了站点,然后应用程序可以删除该会话的会话数据和临时目录。
我的问题是:有谁知道从服务运行这两个脚本的方法或其他实现它们的方法,这样即使浏览器关闭或转到另一个站点,它们也会继续触发?
谢谢! 大卫
附言。一点背景知识:当应用程序从存储在 SQL 数据库中的值启动时,会设置四个全局变量“CurrentSessionTimeout”、“CurrentHeartBeatTimeout”、“DefaultHeartBeatTimeout”和“DefaultMissedHeartBeats”以及两个会话变量“UseSessionTimeout”和“UseHeartBeat”。但是,两个处理程序都不使用会话变量,而是直接从全局变量或数据库中获取它们需要的任何值,因为会话可能在处理程序触发之前结束,也就是说,如果仍然加载页面,则返回原始这篇文章的原因。 :)
【问题讨论】:
-
我在这里看不到任何 Java 代码。请注意,Java 和 Javascript 不是一回事。
-
他正在尝试动态评估 JavaScript。问题是应用程序需要浏览器的解释器才能做到这一点。因此,如果浏览器不在页面上,它就不会发生。
-
通过脚本管理器调用java代码...
-
@rescuecreative,没错!这就是为什么我正在寻找一种独立于浏览器页面运行 JavaScript 的方法。
-
正确,它是使用我添加到上面原始帖子末尾的页面上的代码的脚本
标签: java javascript asp.net timer handler