在一次做非常复杂的ajax应用时,如果一个会话已经超时,但是此时再通过ajax请求,那么ajax返回的则是一个登陆页面的html,那这下就惨了,页面上而已就乱了,那么,能否在java端,如拦截器里判断客户的的请求是否是ajax请求呢,经过查询,能.
普通请求与ajax请求的报文头不一样,通过如下
String requestType = request.getHeader("X-Requested-With");
如果requestType能拿到值,并且值为XMLHttpRequest,表示客户端的请求为异步请求,那自然是ajax请求了,反之如果为null,则是普通的请求
19 楼
Cindy_Lee
2011-06-07
其实你想要的就是多视图配置,spring mvc和struts2都有类似的解决方案
20 楼
jbm3072
2011-06-07
会话过期的话,可以在跳转页面上设置http状态码为500,ajax处理错误码为500的错误即可.同时,添加页面的javascript,使其跳转到登陆页面.
21 楼
wenzhui5
2011-06-07
还有木有其他的思路哈!
22 楼
int08h
2011-06-07
X-Request-With不是XMLHttpRequest自己的特性,只是各个库比较统一地都用了这个头,jquery/ext/kissy/tangram/yui等都会自己给加上而已,如果是自己来实现ajax函数的话,就要注意下了
23 楼
pujia12345
2011-06-07
一切都是浮云。
HTTP 请求就是字符串请求,随你组合了,比如,在你想“超时返回页面“的ajax请求增加参数:ret=index,“返回注册页面”的加参数:ret=regedit,“返回出错页面”的家参数:ret=error
HTTP 请求就是字符串请求,随你组合了,比如,在你想“超时返回页面“的ajax请求增加参数:ret=index,“返回注册页面”的加参数:ret=regedit,“返回出错页面”的家参数:ret=error
24 楼
BearRui
2011-06-07
我们的做法是,配置strust可以处理.do和.rmi2个后缀的请求,所有的ajax请求都请求rmi后缀,其他的请求使用.do后缀,这样来区分。
25 楼
Simon.Wang
2011-06-07
还是用不同的URL来做比较容易控制
26 楼
sky_dream
2011-06-07
设置head是一种方法,另外,在方法中添加请求类型参数,就可以区分开了。
27 楼
xiaoxiaoniao11
2011-06-07
redish 写道
fflame 写道
呃,从安全角度说,会话过期以后,返回登录页面是应该的吧?换句话说,处理应该是前台分析一下返回值,并相应的处理吧?
个人意见。。。。
个人意见。。。。
我也是这么处理的,会话过期返回相应的值,前台取到值并处理。
+1
28 楼
edokeh
2011-06-07
用REST的思路来做
根据http的accept头不同,来返回不同的结果
根据http的accept头不同,来返回不同的结果
29 楼
airpeng
2011-06-07
zwllxs 写道
能否在java端,如拦截器里判断客户的的请求是否是ajax请求呢
判断出来了你想怎么样?
我之前的处理是在前台里弄的,判断返回的是登陆页面就让他整个跳到登陆页面去
30 楼
zwllxs
2011-06-07
airpeng 写道
zwllxs 写道
能否在java端,如拦截器里判断客户的的请求是否是ajax请求呢
判断出来了你想怎么样?
我之前的处理是在前台里弄的,判断返回的是登陆页面就让他整个跳到登陆页面去
你这样的话,项目中所有的ajax请求所在的页面,都要去单独判断单独处理,并且如果新加了ajax请求模块,你又要去格外处理,如果项目中的ajax请求多了,开发和维护就麻烦了,
所以如果能在拦截器中一次性处理那就更好,目前我就是在拦截器中返回一个逻辑视图,然后在全局配置中,通过这个逻辑视图去指向一个页面。然后你可以在这个页面上任意发挥了,你可以将这个页面做成div弹框,你也可以直接简单写几个字,直接提醒用户去重新登陆,但是,在这里不能写js,因为异步响应返回的js,是不会被识别的
31 楼
ltj
2011-06-08
AJAX请求和普通请求后缀分开。
filter判断,然后分开处理。一劳永逸。
filter判断,然后分开处理。一劳永逸。
32 楼
sebatinsky
2011-06-08
呵呵,这个的确是一个问题
33 楼
airpeng
2011-06-08
zwllxs 写道
airpeng 写道
zwllxs 写道
能否在java端,如拦截器里判断客户的的请求是否是ajax请求呢
判断出来了你想怎么样?
我之前的处理是在前台里弄的,判断返回的是登陆页面就让他整个跳到登陆页面去
你这样的话,项目中所有的ajax请求所在的页面,都要去单独判断单独处理,并且如果新加了ajax请求模块,你又要去格外处理,如果项目中的ajax请求多了,开发和维护就麻烦了,
所以如果能在拦截器中一次性处理那就更好,目前我就是在拦截器中返回一个逻辑视图,然后在全局配置中,通过这个逻辑视图去指向一个页面。然后你可以在这个页面上任意发挥了,你可以将这个页面做成div弹框,你也可以直接简单写几个字,直接提醒用户去重新登陆,但是,在这里不能写js,因为异步响应返回的js,是不会被识别的
我对你的做法的理解是:如果是ajax请求,那么超时了就不跳转到登陆页面,而是跳到指定的页面,对吗?
如果要象我说的那样弄的话,可以把你的ajax封装成一个方法,以为每次调用的时候只需要传下相应的参数就行了,不知道可以否,另:像jquery这类的js框架不太熟,不知道它们的封装的ajax有没有可以借鉴的
34 楼
songdewu
2011-06-08
<pre name="code" class="php">&lt;?php
/**
* 日志系统抽象类
*
*/
abstract class LogWriterAbstract {
/**
* 是否启用日志记录
*
* @var boolean
*/
protected $_enabled = true;
/**
* 日志记录的错误级别
*
* @var array
*/
protected $_errorLevel = array(
'notice' =&gt; false,
'debug' =&gt; false,
'warning' =&gt; false,
'error' =&gt; false,
'exception' =&gt; false,
'info' =&gt; false,
);
abstract function append($msg, $title = '', $level = 'info');
}
/**
* LogFirePHPWriter 类提供对 FirePHP 的支持
*/
class LogFirePHPWriter extends LogWriterAbstract {
function __construct(){
$this-&gt;_enabled = App::ini('_log/enabled',true);
if (!$this-&gt;_enabled) return;
$errorLevel = normalize(strtolower(App::ini('_log/levels','exception,error')),',');
if (!empty($errorLevel))
foreach ($errorLevel as $e)
$this-&gt;_errorLevel[$e] = true;
}
function append($msg, $title = '', $level = 'info'){
$level = strtolower(trim($level));
if ($this-&gt;_enabled &amp;&amp; isset($this-&gt;_errorLevel[$level])){
switch($level){
case 'info':
case 'debug':
FirePhpHelper::getInstance()-&gt;info($msg, $title);
break;
case 'notice':
FirePhpHelper::getInstance()-&gt;log($msg, $title);
break;
case 'exception':
FirePhpHelper::getInstance()-&gt;warn($msg, $title);
break;
case 'error':
FirePhpHelper::getInstance()-&gt;error($msg, $title);
break;
}
}
}
}
/**
* LogFile 类提供基本的文件日志服务
*/
class LogFileWriter extends LogWriterAbstract {
/**
* 保存运行期间的日志
*
* @var string
*/
private $_log = '';
/**
* 日期格式
*
* @var string
*/
private $dateFormat = 'Y-m-d H:i:s';
/**
* 保存日志文件的目录
*
* @var string
*/
private $_logFileDir;
/**
* 保存日志的文件名
*
* @var string
*/
private $_logFilename;
/**
* 构造函数
*/
function __construct()
{
$this-&gt;_enabled = App::ini('_log/enabled',true);
if (!$this-&gt;_enabled) return;
$dir = App::ini('_log/file_dir',null);
if (empty($dir)){
$this-&gt;_enabled = false;
return;
}
$dir = realpath($dir);
if (substr($dir, -1) != DS) {
$dir .= DS;
}
if (!is_dir($dir) || !is_writable($dir)) {
$this-&gt;_enabled = false;
} else {
$this-&gt;_logFileDir = $dir;
$this-&gt;_logFilename = $this-&gt;_logFileDir . App::ini('_log/filename','access.log');
$errorLevel = normalize(strtolower(App::ini('_log/levels','exception,error')),',');
if (!empty($errorLevel)){
foreach ($errorLevel as $e){
if (isset($this-&gt;_errorLevel[$e]))
$this-&gt;_errorLevel[$e] = true;
}
}
global $___sfw_loaded_time;
$sec = (int) $___sfw_loaded_time;
$usec = $___sfw_loaded_time - $sec;
$this-&gt;_startTag = sprintf("[%s %s] ======= SFW Loaded =======\n",
date($this-&gt;dateFormat, $sec), $usec);
if (isset($_SERVER['REQUEST_URI'])) {
$this-&gt;_startTag .= sprintf("[%s] REQUEST_URI: %s\n",
date($this-&gt;dateFormat),
$_SERVER['REQUEST_URI']);
}
// 注册脚本结束时要运行的方法,将缓存的日志内容写入文件
ShutdownCallback::getInstance()-&gt;add(array($this, '__writeLog'));
// 检查文件是否已经超过指定大小
if (file_exists($this-&gt;_logFilename)) {
$filesize = filesize($this-&gt;_logFilename);
} else {
$filesize = 0;
}
$maxsize = (int)App::ini('_log/file_maxsize',512);
if ($maxsize &gt;= 512) {
$maxsize = $maxsize * 1024;
if ($filesize &gt;= $maxsize) {
// 使用新的日志文件名
$pathinfo = pathinfo($this-&gt;_logFilename);
$newFilename = $pathinfo['dirname'] . DS .
basename($pathinfo['basename'], '.' . $pathinfo['extension']) .
date('-Ymd-His') . '.' . $pathinfo['extension'];
rename($this-&gt;_logFilename, $newFilename);
}
}
}
}
/**
* 追加日志信息
*
* @param string $msg
* @param string $title
* @param string $level
*/
function append($msg, $title = '', $level = 'info')
{
if ($this-&gt;_enabled &amp;&amp; isset($this-&gt;_errorLevel[strtolower($level)])){
$this-&gt;_log .= sprintf("[%s] [%s] %s:%s\n", date($this-&gt;dateFormat), $level, $title, print_r($msg, true));
}
}
/**
* 将缓存的日志信息写入实际存储,并清空缓存
* 此方法由系统自动调用
*
*/
function __writeLog(){
if (!$this-&gt;_enabled) return;
if (empty($this-&gt;_log)) return;
global $___sfw_loaded_time;
$shutdown_time = microtime(true);
$sec = (int) $shutdown_time;
$usec = $shutdown_time - $sec;
$elapsedTime = $shutdown_time - $___sfw_loaded_time;
$content = $this-&gt;_startTag . $this-&gt;_log . sprintf("[%s %s] ======= SFW End (elapsed: %f seconds) =======\n\n",date($this-&gt;dateFormat, $sec), $usec, $elapsedTime);
$fp = fopen($this-&gt;_logFilename, 'a');
if (!$fp) { return; }
flock($fp, LOCK_EX);
fwrite($fp, str_replace("\r", '', $content));
flock($fp, LOCK_UN);
fclose($fp);
}
}
</pre>
<p>?</p>
/**
* 日志系统抽象类
*
*/
abstract class LogWriterAbstract {
/**
* 是否启用日志记录
*
* @var boolean
*/
protected $_enabled = true;
/**
* 日志记录的错误级别
*
* @var array
*/
protected $_errorLevel = array(
'notice' =&gt; false,
'debug' =&gt; false,
'warning' =&gt; false,
'error' =&gt; false,
'exception' =&gt; false,
'info' =&gt; false,
);
abstract function append($msg, $title = '', $level = 'info');
}
/**
* LogFirePHPWriter 类提供对 FirePHP 的支持
*/
class LogFirePHPWriter extends LogWriterAbstract {
function __construct(){
$this-&gt;_enabled = App::ini('_log/enabled',true);
if (!$this-&gt;_enabled) return;
$errorLevel = normalize(strtolower(App::ini('_log/levels','exception,error')),',');
if (!empty($errorLevel))
foreach ($errorLevel as $e)
$this-&gt;_errorLevel[$e] = true;
}
function append($msg, $title = '', $level = 'info'){
$level = strtolower(trim($level));
if ($this-&gt;_enabled &amp;&amp; isset($this-&gt;_errorLevel[$level])){
switch($level){
case 'info':
case 'debug':
FirePhpHelper::getInstance()-&gt;info($msg, $title);
break;
case 'notice':
FirePhpHelper::getInstance()-&gt;log($msg, $title);
break;
case 'exception':
FirePhpHelper::getInstance()-&gt;warn($msg, $title);
break;
case 'error':
FirePhpHelper::getInstance()-&gt;error($msg, $title);
break;
}
}
}
}
/**
* LogFile 类提供基本的文件日志服务
*/
class LogFileWriter extends LogWriterAbstract {
/**
* 保存运行期间的日志
*
* @var string
*/
private $_log = '';
/**
* 日期格式
*
* @var string
*/
private $dateFormat = 'Y-m-d H:i:s';
/**
* 保存日志文件的目录
*
* @var string
*/
private $_logFileDir;
/**
* 保存日志的文件名
*
* @var string
*/
private $_logFilename;
/**
* 构造函数
*/
function __construct()
{
$this-&gt;_enabled = App::ini('_log/enabled',true);
if (!$this-&gt;_enabled) return;
$dir = App::ini('_log/file_dir',null);
if (empty($dir)){
$this-&gt;_enabled = false;
return;
}
$dir = realpath($dir);
if (substr($dir, -1) != DS) {
$dir .= DS;
}
if (!is_dir($dir) || !is_writable($dir)) {
$this-&gt;_enabled = false;
} else {
$this-&gt;_logFileDir = $dir;
$this-&gt;_logFilename = $this-&gt;_logFileDir . App::ini('_log/filename','access.log');
$errorLevel = normalize(strtolower(App::ini('_log/levels','exception,error')),',');
if (!empty($errorLevel)){
foreach ($errorLevel as $e){
if (isset($this-&gt;_errorLevel[$e]))
$this-&gt;_errorLevel[$e] = true;
}
}
global $___sfw_loaded_time;
$sec = (int) $___sfw_loaded_time;
$usec = $___sfw_loaded_time - $sec;
$this-&gt;_startTag = sprintf("[%s %s] ======= SFW Loaded =======\n",
date($this-&gt;dateFormat, $sec), $usec);
if (isset($_SERVER['REQUEST_URI'])) {
$this-&gt;_startTag .= sprintf("[%s] REQUEST_URI: %s\n",
date($this-&gt;dateFormat),
$_SERVER['REQUEST_URI']);
}
// 注册脚本结束时要运行的方法,将缓存的日志内容写入文件
ShutdownCallback::getInstance()-&gt;add(array($this, '__writeLog'));
// 检查文件是否已经超过指定大小
if (file_exists($this-&gt;_logFilename)) {
$filesize = filesize($this-&gt;_logFilename);
} else {
$filesize = 0;
}
$maxsize = (int)App::ini('_log/file_maxsize',512);
if ($maxsize &gt;= 512) {
$maxsize = $maxsize * 1024;
if ($filesize &gt;= $maxsize) {
// 使用新的日志文件名
$pathinfo = pathinfo($this-&gt;_logFilename);
$newFilename = $pathinfo['dirname'] . DS .
basename($pathinfo['basename'], '.' . $pathinfo['extension']) .
date('-Ymd-His') . '.' . $pathinfo['extension'];
rename($this-&gt;_logFilename, $newFilename);
}
}
}
}
/**
* 追加日志信息
*
* @param string $msg
* @param string $title
* @param string $level
*/
function append($msg, $title = '', $level = 'info')
{
if ($this-&gt;_enabled &amp;&amp; isset($this-&gt;_errorLevel[strtolower($level)])){
$this-&gt;_log .= sprintf("[%s] [%s] %s:%s\n", date($this-&gt;dateFormat), $level, $title, print_r($msg, true));
}
}
/**
* 将缓存的日志信息写入实际存储,并清空缓存
* 此方法由系统自动调用
*
*/
function __writeLog(){
if (!$this-&gt;_enabled) return;
if (empty($this-&gt;_log)) return;
global $___sfw_loaded_time;
$shutdown_time = microtime(true);
$sec = (int) $shutdown_time;
$usec = $shutdown_time - $sec;
$elapsedTime = $shutdown_time - $___sfw_loaded_time;
$content = $this-&gt;_startTag . $this-&gt;_log . sprintf("[%s %s] ======= SFW End (elapsed: %f seconds) =======\n\n",date($this-&gt;dateFormat, $sec), $usec, $elapsedTime);
$fp = fopen($this-&gt;_logFilename, 'a');
if (!$fp) { return; }
flock($fp, LOCK_EX);
fwrite($fp, str_replace("\r", '', $content));
flock($fp, LOCK_UN);
fclose($fp);
}
}
</pre>
<p>?</p>
35 楼
defty
2011-06-09
其实不用判断啊,会话既然已经过期,就直接返回登录页面,你管它是从哪里来的
36 楼
chansman
2011-06-20
写2个方法
37 楼
抛出异常的爱
2011-06-20
kimmking 写道
报文头可以自己设置的。
严格的说,木有办法。
严格的说,木有办法。
从收的地方想办法
你发送返回的如果是html
总有预期吧
目有达到预期的html
都是错的不加到到dom树上
38 楼
grandboy
2011-06-21
使用URL来区分是最理想的设计方案。另外判断是不是已经SESSION过期可以在返回页面之前用切面(+少量js)处理,返回页面那就是登录页面了, 当然如果权限模型比较复杂的话,可能只能区别不同类型的请求的思路来处理了。