当前位置: 代码迷 >> Ajax >> 怎么判断一个请求是否为AJAX请求
  详细解决方案

怎么判断一个请求是否为AJAX请求

热度:409   发布时间:2012-11-13 10:00:50.0
如何判断一个请求是否为AJAX请求
   在一次做非常复杂的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
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头不同,来返回不同的结果
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判断,然后分开处理。一劳永逸。

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">&amp;lt;?php
/**
* 日志系统抽象类
*
*/
abstract class LogWriterAbstract {

    /**
     * 是否启用日志记录
     *
     * @var boolean
     */
    protected $_enabled = true;
   
    /**
     * 日志记录的错误级别
     *
     * @var array
     */
    protected $_errorLevel = array(
    'notice' =&amp;gt; false,
    'debug' =&amp;gt; false,
    'warning' =&amp;gt; false,
    'error' =&amp;gt; false,
    'exception' =&amp;gt; false,
    'info' =&amp;gt; false,
    );
   
    abstract function append($msg, $title = '', $level = 'info');
}

/**
* LogFirePHPWriter 类提供对 FirePHP 的支持
*/
class LogFirePHPWriter extends LogWriterAbstract {
       
    function __construct(){
    $this-&amp;gt;_enabled = App::ini('_log/enabled',true);
    if (!$this-&amp;gt;_enabled) return;
   
    $errorLevel = normalize(strtolower(App::ini('_log/levels','exception,error')),',');
           
        if (!empty($errorLevel))
            foreach ($errorLevel as $e)
               $this-&amp;gt;_errorLevel[$e] = true;
    }
   
    function append($msg, $title = '', $level = 'info'){
    $level = strtolower(trim($level));
    if ($this-&amp;gt;_enabled &amp;amp;&amp;amp; isset($this-&amp;gt;_errorLevel[$level])){
    switch($level){
    case 'info':
    case 'debug':
    FirePhpHelper::getInstance()-&amp;gt;info($msg, $title);
    break;
    case 'notice':
    FirePhpHelper::getInstance()-&amp;gt;log($msg, $title);
    break;
    case 'exception':
    FirePhpHelper::getInstance()-&amp;gt;warn($msg, $title);
    break;
    case 'error':
    FirePhpHelper::getInstance()-&amp;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-&amp;gt;_enabled = App::ini('_log/enabled',true);
    if (!$this-&amp;gt;_enabled) return;
   
        $dir = App::ini('_log/file_dir',null);
        if (empty($dir)){
        $this-&amp;gt;_enabled = false;
        return;
        }
       
        $dir = realpath($dir);
        if (substr($dir, -1) != DS) {
            $dir .= DS;
        }
        if (!is_dir($dir) || !is_writable($dir)) {
            $this-&amp;gt;_enabled = false;
        } else {
            $this-&amp;gt;_logFileDir = $dir;
            $this-&amp;gt;_logFilename = $this-&amp;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-&amp;gt;_errorLevel[$e]))
            $this-&amp;gt;_errorLevel[$e] = true;
            }
            }
           
            global $___sfw_loaded_time;
            $sec = (int) $___sfw_loaded_time;
        $usec = $___sfw_loaded_time - $sec;
           
            $this-&amp;gt;_startTag = sprintf("[%s %s] ======= SFW Loaded =======\n",
                date($this-&amp;gt;dateFormat, $sec), $usec);

            if (isset($_SERVER['REQUEST_URI'])) {
                $this-&amp;gt;_startTag .= sprintf("[%s] REQUEST_URI: %s\n",
                        date($this-&amp;gt;dateFormat),
                        $_SERVER['REQUEST_URI']);
            }

            // 注册脚本结束时要运行的方法,将缓存的日志内容写入文件
            ShutdownCallback::getInstance()-&amp;gt;add(array($this, '__writeLog'));
           
            // 检查文件是否已经超过指定大小
            if (file_exists($this-&amp;gt;_logFilename)) {
                $filesize = filesize($this-&amp;gt;_logFilename);
            } else {
                $filesize = 0;
            }
            $maxsize = (int)App::ini('_log/file_maxsize',512);
            if ($maxsize &amp;gt;= 512) {
                $maxsize = $maxsize * 1024;
                if ($filesize &amp;gt;= $maxsize) {
                    // 使用新的日志文件名
                    $pathinfo = pathinfo($this-&amp;gt;_logFilename);
                    $newFilename = $pathinfo['dirname'] . DS .
                        basename($pathinfo['basename'], '.' . $pathinfo['extension']) .
                        date('-Ymd-His') . '.' . $pathinfo['extension'];
                    rename($this-&amp;gt;_logFilename, $newFilename);
                }
            }
        }
    }

    /**
     * 追加日志信息
     *
     * @param string $msg
     * @param string $title
     * @param string $level
     */
    function append($msg, $title = '', $level = 'info')
    {
    if ($this-&amp;gt;_enabled &amp;amp;&amp;amp; isset($this-&amp;gt;_errorLevel[strtolower($level)])){
        $this-&amp;gt;_log .= sprintf("[%s] [%s] %s:%s\n", date($this-&amp;gt;dateFormat), $level, $title, print_r($msg, true));
    }
    }

/**
     * 将缓存的日志信息写入实际存储,并清空缓存
     * 此方法由系统自动调用
     *
     */
    function __writeLog(){
   
if (!$this-&amp;gt;_enabled) return;

if (empty($this-&amp;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-&amp;gt;_startTag . $this-&amp;gt;_log . sprintf("[%s %s] ======= SFW End (elapsed: %f seconds) =======\n\n",date($this-&amp;gt;dateFormat, $sec), $usec, $elapsedTime);

        $fp = fopen($this-&amp;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)处理,返回页面那就是登录页面了, 当然如果权限模型比较复杂的话,可能只能区别不同类型的请求的思路来处理了。
  相关解决方案