Extjs springmvc session 超時 處理


若是你的項目使用ExtJS做爲表現層,你會發現,SESSION超時控制將是一個問題。
本文將就本身的經驗,來解決這一問題,固然,解決問題並不是只有一種方法,我只是提出個人方法。
首先,作超時控制,必需使用過濾器,而咱們既然使用了Spring MVC,那就用攔截器取代吧,寫一個攔截器,用來攔截用戶請求,固然,這個攔截器還須要能夠配置哪些請求是不須要攔截的。
[java] view plaincopy
/**
*
*/
package net.bioslink.business.intercepter;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.bioslink.common.util.ConfigureUtil;
import net.bioslink.common.vo.Constants;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
* @author leoly
*
*/
@Repository
public class SystemAccessInterceper extends HandlerInterceptorAdapter {
private final Logger logger = Logger.getLogger(getClass());

@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
String[] noFilters = ConfigureUtil.getStringArray("no_filter_setting");
boolean isFilter = true;
if (!ArrayUtils.isEmpty(noFilters)) {
for (String u : noFilters) {
if (uri.contains(u)) {
isFilter = false;
break;
}
}
}

if (isFilter) {
// Session
Object obj = request.getSession()
.getAttribute(Constants.SESSION_ID);
if (null == obj) {
logger.info("登陸超時!!");
PrintWriter writer = response.getWriter();
writer.print("<script>top.location='http://127.0.0.1:8080/VkDesktop/login/loginSystem.do';</script>SESSION_TIMEOUT_ERROR");
IOUtils.closeQuietly(writer);
return false;
} else {
request.setAttribute("LOG_ACCESS_TIME",
System.currentTimeMillis());
logger.info(obj + "訪問了" + uri);
}
}
return super.preHandle(request, response, handler);
}

@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
super.afterCompletion(request, response, handler, ex);
Object obj = request.getAttribute("LOG_ACCESS_TIME");
if (null != obj) {
long accessTime = (long) obj;
logger.info("處理請求" + request.getRequestURI() + "耗時"
+ (System.currentTimeMillis() - accessTime) + "毫秒!");
}
}
} javascript

而後,將這個攔截器註冊到Spring MVC中,在xxx-servlet.xml文件中添加註冊代碼:
[html] view plaincopy
<mvc:interceptors>
<bean class="net.bioslink.business.intercepter.SystemAccessInterceper" />
</mvc:interceptors> html

OK,如今這個攔截器已經開始工做了,它會攔截用戶請求,判斷SESSION中是否存在登陸信息,若是不存在,則說明已經超時,攔截器向客戶問寫一段代碼
[java] view plaincopy
writer.print("<script>top.location='http://127.0.0.1:8080/VkDesktop/login/loginSystem.do';</script>SESSION_TIMEOUT_ERROR");
這樣,若是客戶端是網頁,它就會自動跳到登陸頁面,若是不是網頁(如AJAX請求),咱們須要在客戶端中判斷返回的字符串中是否包含「SESSION_TIMEOUT_ERROR」,若是有的話就作出跳到首頁的處理。java

那麼,如今輪到客戶端了,由於使用的是ExtJS,幾乎全部的請求都是AJAX請求,因此判斷SESSION_TIMEOUT_ERROR是關鍵。那總不能全部的AJAX請求都加上這些判斷吧??OMG,殺了我吧,可憐的碼農……
其實,咱們能夠寫一個TimeoutControl類,封裝一些咱們須要修改和添加的東西,來實現超時跳轉功能!誰叫ExtJS提供了這麼多類功能(繼承,重寫,覆蓋)呢?
咱們知道,ExtJS的請求雖然都是AJAX請求,可是卻能夠區分爲Store請求和通常的AJAX請求,那麼咱們的TimeoutControl類就須要從新構造這些請求方式,而且,之後寫的全部請求都須要使用這個類來完成。
[javascript] view plaincopy
Ext.define('Ext.ux.TimeoutControl', {
extend : 'Ext.data.Store',
alias : 'widget.timeoutstore',
constructor : function(config) {
Ext.apply(config.proxy, {
listeners : {
exception : function(self, response) {
var responseText = response.responseText;
if (responseText
&& responseText.indexOf("SESSION_TIMEOUT_ERROR") > 0) {
top.location = '../login/loginSystem.do';
}
}
}
});
this.callParent([config]);
},

statics : {
request : function(config) {
var f = config.success;
config.success = Ext.Function.createInterceptor(f, function(
response) {
var txt = response.responseText;
// alert(txt);
if (txt && txt.indexOf("SESSION_TIMEOUT_ERROR") > 0) {
top.location = '../login/loginSystem.do';
return false;
}

return true;
});
Ext.Ajax.request(config);
}
}
}); ios


這個類中,咱們繼承了Ext.data.Store,而且在構造器中動態加入了一個proxy的exception處理函數,也就是說,只要使用此類,不管Store的proxy中寫沒寫exception函數,都會在這裏添加上,而這個函數就是處理超時控制的。而後,這個類還提供了一個靜態方法request,這個request方法會調用Ext.Ajax.request(config),可是在調用以前,咱們給配置的success函數添加了一段判斷超時的代碼,使用的是ExtJS的函數攔截方法,效果槓槓的。
最後,只要咱們在使用到Store的地方中使用Ext.ux.TimeoutControl類,在使用Ext.Ajax.request的地方中使用Ext.ux.TimeoutControl.request取代,那麼,超時控制就完成了。
使用Store的例子:
[javascript] view plaincopy
var store = Ext.create('Ext.ux.<span style="font-size:18px; white-space: pre; background-color: rgb(240, 240, 240);">TimeoutControl</span>', {
model : 'MyDesktop.data.WorkOrderModule',
remoteSort : true,
remoteFilter : true,
sorters : [new Ext.util.Sorter({
property : 'reportId',
direction : 'ASC'
})],
proxy : {
type : 'ajax',
actionMethods : {
read : 'POST'
},
extraParams : {
projectCode : "44190008",
orderMonth : 2,
id : 0
},
pageParam : 'pageNo',
limitParam : 'pageSize',
url : '../lebang/workOrder/queryWorkorderList.do',
reader : {
type : 'json',
root : 'orders',
totalProperty : 'totalCount'
}
}
}); web

使用AJAX請求的例子:
[javascript] view plaincopy
Ext.ux.TimeoutControl.request({
url : "../user/logout.do",
timeout : 60000,
method : 'POST',
disableCaching : false,
params : {},
success : function(response) {
window.location = '../login/loginSystem.do';
},
failure : function() {
Ext.Msg.alert("系統提示", "註銷異常,請聯繫管理人員!!");
}
}); ajax