`
achun
  • 浏览: 306304 次
  • 性别: Icon_minigender_1
  • 来自: 河南郑州
社区版块
存档分类
最新评论

降低前后台业务逻辑上的耦合度,前后台细粒度数据通讯的方法

    博客分类:
  • jCT
阅读更多

题的提出 :

jCT模板属于前后台分离的设计.

对于前后台分离的设计.

S根据B提出的请求,发送原始数据,S不需要对表现层有任何控制,降低了B,S的耦合度.

这种降低了B,S的耦合度方法,本质上是降低了 数据内容 上的 耦合度 ,仅仅把表现层的控制数据分离出去了.

由于请求和数据直接影响到表现,表现 业务逻辑 的最直接体现,但是 这两个词不能画等号.因此我们用表现逻辑 这个词.暗示表现和业务逻辑是关联比较密切的.

表现逻辑 变化的时候,势必要 改变 后台数据内容 的组合结构,我们的问题就是

如何降低前后台 表现逻辑( 业务逻辑) 上的耦合度


附加举例 说明问题:

常见的页面上有多种访问(按日,月,年或分类)排名,如果我们要增加或减少一个排名规则的话,表现 是要改的,后台 数据内容 也要同期改,这就是耦合度高的问题.

当然,对于新增的表现,采取多次和后台通讯也是一种解决方法,不过这增加了通讯的次数.

我们要达到只需要 表现,不用改 后台 ,并且不增加通讯次数的目标.


问题分析 :

表现逻辑 最终体现在原始数据的变化上.

业务逻辑对数据的细粒度化是比较容易实现的,就是把数据的请求最小化,然后把多个请求 获得的数据组合输出就行了.这在设计中是常见的.最简单的就是按请求的次序 请求队列 ,输出关联数组结构 的数据就行了.

那要解决的问题就是,前台如何在一次通讯中发出 请求队列 ,后台如何正确解析 请求队列 的问题.


解决方案 :

这里我直接给出我的方案,

利用POST方法和GET参数的配合.

在实际使用POST和GET方法的时候我们通常是用参数名=值 ,这种值对 的形式提交,事实上http协议并没有限定死这种形式,我们这种形式对http协议来说只不过是一串字符串罢了.用ajax 方法提交数据的时候是可以直接传送以JSON形式 的数据的,这就是纯字符串了.JSON 对数据的表现能力是毋庸置疑的.经后台解析后才对象化的.

我们可以把 请求队列 JSON 形式与后台通讯,后台完成 请求队列 解析.当然对于ajax 来说使用POST 方法

无疑是很好的,因为POST 方法其实是兼容GET 的,ajax 请求中的url 参数就是GET 方法的实现.那GET参数 在这里有什么用途呢?共用参数 的传递(这个语言描述就到这里,做个应用的朋友应该已经明白了).

ajax POST的数据是JSON字符串格式,比如:

写道
{"login":{"name":"youname","pw":"123456"},"onlineusers":true}
 

我一直用PHP编程,php获得POST过来的JSON数据是很容易的

写道
$json=file_get_contents('php://input');
$json=json_decode($json,true);

 

到此 请求队列 的数据通信解决了,后台获取解决了,解析呢?这恐怕要和你的应用有关了.解决起来类似于如下结构

 

写道
$OUT=array();
foreach($requireQueue as $Q){
  switch($Q['REQUIRE']){
    case 'login':
      $OUT['login']=login();break;
    case 'onlineusers':
      $OUT['onlineusers']=onlineusers();break;
  }
}

 

 

switch..case 就是细粒度的实现了.可以看出,在业务逻辑确定的情况下,表现只需要改变请求的队列的组合 就可以一次通讯获取 数据 了.

 

==========ps============

很遗憾,由于人事变动,我不再参与www.91mh.net这个项目了,项目负责人又回到了古老的编程方法,这个网站已经不采用我的技术了,回头有新的站我再给出新的地址吧。

分享到:
评论
28 楼 zbm2001 2008-06-11  
chanawudi 写道
关于mvc。。就不用讨论了吧,功过之由后来人来评论。。一般普遍应用的mvc框架确实有时候是运行效率和开发效率的障碍,但是我自己开发符合我自己style的框架我一直在用,用的很好。。

楼主继续努力,你的jct我一直会关注下去。。。



你的情形我觉得已经算是MVC在心中了,不在于什么形式
27 楼 chanawudi 2008-06-10  
关于mvc。。就不用讨论了吧,功过之由后来人来评论。。一般普遍应用的mvc框架确实有时候是运行效率和开发效率的障碍,但是我自己开发符合我自己style的框架我一直在用,用的很好。。

楼主继续努力,你的jct我一直会关注下去。。。
26 楼 zbm2001 2008-06-10  
所以我认为web开发:
M一定要灵动
V不一定受后台约束,甚至在某些条件下可完全抛开
C不光是枷锁了,有时还存在效率问题

MVC在心中啊
25 楼 achun 2008-06-10  
<p>继续谈对MVC的认识</p>
<p>MVC这个概念是来自编程活动,是对程序逻辑的理论研究结果,</p>
<p>不管有没有提出MVC,事实上代码总是以某种形式隐含着MVC的概念,</p>
<p>问题是人们一旦用理论去指导实践就会犯一个错误.</p>
<p>教条主义</p>
<p>M一定要非常明确,固定吗?灵动些不行么?可以做到随时加入新的元素吗?</p>
<p>V一定要在后台完成吗?一定要受后台的约束吗?</p>
<p>C一定要用class,oo之类的技术手段封装起来吗?分散嵌入在整个实现代码里不行吗?</p>
<p> </p>
<p><br/>所以我一看到把</p>
<p>M明确成什么REST,SOA(我认为,rest,soa也是一种modul),就奇怪,modul到底是用来解决应用的还是用来解决程序逻辑(数据逻辑)的.</p>
<p>V,表现数据和业务数据紧密结合在后台,就要问个性化的表现怎么办,客户随时的变动怎么办,还增大了服务器压力.</p>
<p>C实例成一个对象的时候,我就摇头了.这是自己给自己套枷锁.</p>
<p> </p>
24 楼 achun 2008-06-10  
chanawudi 写道
另外,如果谁想了解我的框架,可以到下面看看:

http://www.blogjava.net/kingyaoo/

对于MVC框架这种解决方案来说,我也有自己的看法,
我认为在业务代码中流动的就是数据,请求的数据,返回的数据,
只要在必要的环节里调入相应的代码,处理该处理的事情就性了,
我一般根本就不用框架的方法,而是用流程。数据到了什么流程就写什么样的代码就行了。
比如我现在方案的流程:(多域名,单入口,前台模板,业务请求队列)
1.判断客户端传递过来的参数,判断域名入口,和是否对SE进行输出支持
2.进入域名相关的入口
3.数据合法性验证,通过继续,否则输出错误信息
4.进入业务请求队列处理阶段
5.输出数据
也想有朋友会说,如果有上百上千个不同的业务请求,还要处理权限,没有一个控制器你怎么办?
可用的方法多了,仅仅用一些小的技巧就可以完成这些功能了。
我把数据里可以利用的东西列出来,
1.权限和登陆有关,这个就是SESSSION了,SESSION中本来就可以存放权限判断的参数
2.客户段的参数可以附加的
3.域名本身也可以利用,比如2级域名如此空闲,不用白不用
4.每个请求的KEY,是可以区分大小写的,就算仅仅利用前2,3位对大小写的区分,也可以做出很多变化
有这么多可以利用的元素,随便组合一下就可以完成控制器所做的工作了,(我已经实践了)
关键是不用控制器的好处就是成本问题,整体的考虑问题成本很高的,如果可以利用参数,分环节,自由的代码来处理问题,反而修改起来更安逸。
另外如果按MVC的世界观来看我的方案的话
M:就是一个前台模板工具,一个求队列通讯规则,一个单入口多域名支持规则
V:前台模板工具,后台原始业务数据
C:隐含在M的两个规则里了。主要是靠技巧实现的,不存在独立完整的控制器
而且是前后台完全分离的。
但是回头看看,这个方案其实只真正给出了什么呢?
模板工具--------有代码。
通讯规则--------只是规则。
单入口多域名支持规则---而且这个还是我的应用里的特殊规则,一般的应用里面根本就没有这个。
也就是说我给出的主要是一种策略(模式)。代码要靠使用者自己完成。
一个没有框架代码实现的策略(模式),当然仅仅只有认识上的学习成本。
实做的成本呢?如果你做的话就会发现,比写独立的控制器成本更低。因为就是控制器不用写配置,
可是最后的处理SQL,处理UPFILE的代码还是要写,数据验证代码还是要写,而我的这个策略要写的也就是这些了.
23 楼 achun 2008-06-09  
chanawudi 写道
achun 写道
xzs 写道
引用
我最近在开发一个java 的MVC框架(类似struts),其中有一种View可以在直接返回任何对象的json


可以做到吗?我的对象存在继承,关联,聚合,组成几种关系, 这样的对象也可以转换为json?

你理解错误了。
我的方法是基于数据通讯接口的,不是基于对象状态的。
所以对象存在继承,关联,聚合,组成几种关系对于我的方法来说是无关的,因为在通讯接口上根本就不考虑他们.
换句话就是,方法背景是不同的,不能用转换这种说法,方法根本就不同。


其实他的理解也没错,我现在就可以实现通过一个统一的接口返回任何的对象的json,把所有对象统一转换为json,包括数组嵌套什么的,有一个JSONObject 开源包。。你可以去看看

另。今天把我的框架做了你上次说的 多action执行,通过一个请求,指定多个action执行,然后返回结果,比如
http://xxx.com/ajaxChain.x?id=|one?name=one,two?name=two|
后台 通过配置把one注册到 one.x这个action,把two注册到 two.x
假如 one.x本来返回的是 {"name":"one"} two.x本来返回的是 {"name":"two"}
那么现在应该返回
{"one?name=one":{"name":"one"},"two?name=two":{"name":"two"}}

这个就不争了吧,我们的应用背景不同,对名词的解释和理解也不同,还是解决问题是关键,理论就不要争论了,只是口水。
22 楼 achun 2008-06-09  
chanawudi 写道
话说回来,其实可以通过做一个统一页面网站地图 来实现搜索引擎爬到数据。。。
关键是他爬到数据,然后保存到搜索引擎数据库后,用户搜索后直接返回的是哪里?是模板文件?还是本来应该的那个页面?如果是模板文件,就算数据可以正常的现实,但是也和网站的整个结构脱节。。。如果要实现返回的是正常的网站结构。。。就有点难了。。

站点地图不是和我的应用,
因为我的应用里,一台服务器是挂多个不同的DOMAIN的。而所有的DOMAIN都指向同一个入口文件,
也就是多域名单入口的设计,这种设计站点地图无能为力的。
还记得我前面php文件里的函数名se_xxx吗?se 就是单入口的缩写。
21 楼 achun 2008-06-09  
chanawudi 写道
看了
http://www.91mh.net/

有点意思。。不过搜索引擎也只能搜索到  一些分类什么的,对于列表中分页的内容,好像无能为力吧。。

首先这个实现不是我写的,是我们团队的一个成员写的。
他对搜索引擎有自己的看法,我不便干涉,如果我做的话,看上去会更离谱。因为那不是让人看的。
而且你所说的,什么分页之类的问题.
你再想想,这个页面不是让人看的是让机器看的,什么分页之类的想法对机器的意义到底是什么呢?
用了这个方法,多搜索引擎的优化表现形式都要重新定义了。
20 楼 chanawudi 2008-06-09  
看了
http://www.91mh.net/

有点意思。。不过搜索引擎也只能搜索到  一些分类什么的,对于列表中分页的内容,好像无能为力吧。。
19 楼 chanawudi 2008-06-09  
另外,如果谁想了解我的框架,可以到下面看看:

http://www.blogjava.net/kingyaoo/
18 楼 chanawudi 2008-06-09  
话说回来,其实可以通过做一个统一页面网站地图 来实现搜索引擎爬到数据。。。
关键是他爬到数据,然后保存到搜索引擎数据库后,用户搜索后直接返回的是哪里?是模板文件?还是本来应该的那个页面?如果是模板文件,就算数据可以正常的现实,但是也和网站的整个结构脱节。。。如果要实现返回的是正常的网站结构。。。就有点难了。。
17 楼 chanawudi 2008-06-09  
achun 写道
xzs 写道
引用
我最近在开发一个java 的MVC框架(类似struts),其中有一种View可以在直接返回任何对象的json


可以做到吗?我的对象存在继承,关联,聚合,组成几种关系, 这样的对象也可以转换为json?

你理解错误了。
我的方法是基于数据通讯接口的,不是基于对象状态的。
所以对象存在继承,关联,聚合,组成几种关系对于我的方法来说是无关的,因为在通讯接口上根本就不考虑他们.
换句话就是,方法背景是不同的,不能用转换这种说法,方法根本就不同。


其实他的理解也没错,我现在就可以实现通过一个统一的接口返回任何的对象的json,把所有对象统一转换为json,包括数组嵌套什么的,有一个JSONObject 开源包。。你可以去看看

另。今天把我的框架做了你上次说的 多action执行,通过一个请求,指定多个action执行,然后返回结果,比如
http://xxx.com/ajaxChain.x?id=|one?name=one,two?name=two|
后台 通过配置把one注册到 one.x这个action,把two注册到 two.x
假如 one.x本来返回的是 {"name":"one"} two.x本来返回的是 {"name":"two"}
那么现在应该返回
{"one?name=one":{"name":"one"},"two?name=two":{"name":"two"}}
16 楼 chanawudi 2008-06-09  
achun 写道
chanawudi 写道
还是忍不住偷空上来看了看。。整个模式有点明白了。。

对于你说的搜索引擎支持,还是不太明白,因为在首页上根本没有链接到/16lo/index.html,在这个页面中的数据怎么给搜索引擎,这个页面在首页上是不暴露url的,根据搜索引擎算法是找不到的,就算搜索引擎爬首页的js,爬到了entry,他也不知道怎么去/16lo/index.html。。。对这里不是很理解。。。

看看这个先
http://www.iteye.com/topic/191661
首先这个问题分两部分
1.搜索引擎可以爬
2.通过搜索引擎搜索结果如何指向正确的结果
我现在解决的是第一个问题
具体的站点是:http://www.91mh.net
你搜一下,已经可以被搜索引擎支持了。
关掉前台的javascript查看一下页面你就明白了(注意body被display:none了,需要firebug处理一下)
这个站就是jCT的实做站之一,不过总体上说还不成熟,所以才想在做一个,等成熟了,再重写91mh


好的,我再看看。。。
15 楼 achun 2008-06-09  
xzs 写道
引用
我最近在开发一个java 的MVC框架(类似struts),其中有一种View可以在直接返回任何对象的json


可以做到吗?我的对象存在继承,关联,聚合,组成几种关系, 这样的对象也可以转换为json?

你理解错误了。
我的方法是基于数据通讯接口的,不是基于对象状态的。
所以对象存在继承,关联,聚合,组成几种关系对于我的方法来说是无关的,因为在通讯接口上根本就不考虑他们.
换句话就是,方法背景是不同的,不能用转换这种说法,方法根本就不同。
14 楼 xzs 2008-06-09  
引用
我最近在开发一个java 的MVC框架(类似struts),其中有一种View可以在直接返回任何对象的json


可以做到吗?我的对象存在继承,关联,聚合,组成几种关系, 这样的对象也可以转换为json?
13 楼 achun 2008-06-09  
chanawudi 写道
还是忍不住偷空上来看了看。。整个模式有点明白了。。

对于你说的搜索引擎支持,还是不太明白,因为在首页上根本没有链接到/16lo/index.html,在这个页面中的数据怎么给搜索引擎,这个页面在首页上是不暴露url的,根据搜索引擎算法是找不到的,就算搜索引擎爬首页的js,爬到了entry,他也不知道怎么去/16lo/index.html。。。对这里不是很理解。。。

看看这个先
http://www.iteye.com/topic/191661
首先这个问题分两部分
1.搜索引擎可以爬
2.通过搜索引擎搜索结果如何指向正确的结果
我现在解决的是第一个问题
具体的站点是:http://www.91mh.net
你搜一下,已经可以被搜索引擎支持了。
关掉前台的javascript查看一下页面你就明白了(注意body被display:none了,需要firebug处理一下)
这个站就是jCT的实做站之一,不过总体上说还不成熟,所以才想在做一个,等成熟了,再重写91mh
12 楼 chanawudi 2008-06-09  
还是忍不住偷空上来看了看。。整个模式有点明白了。。

对于你说的搜索引擎支持,还是不太明白,因为在首页上根本没有链接到/16lo/index.html,在这个页面中的数据怎么给搜索引擎,这个页面在首页上是不暴露url的,根据搜索引擎算法是找不到的,就算搜索引擎爬首页的js,爬到了entry,他也不知道怎么去/16lo/index.html。。。对这里不是很理解。。。
11 楼 chanawudi 2008-06-09  
很详细,很详细,谢谢啦,今天上午没空,下午或晚上具体来研究研究!!
10 楼 achun 2008-06-08  
<p>可恨,hack的方法safari不支持,没有关系我换个方法</p>
<pre name='code' class='js'>$HTTP["querystring"] =~ "_MIME=(xml)" {
    mimetype.assign = ( "" =&gt; "application/xml" )
}
</pre>
 
<pre name='code' class='js'>url:R(a['entry']+'?_MIME=xml')</pre>
<p> 这下都ok了.</p>
9 楼 achun 2008-06-08  
<div class='quote_title'>chanawudi 写道</div>
<div class='quote_div'>。。。。。好像没看懂。。。我js实在不行啊。。。</div>
<p><br/>在firefox下用firebug配合查看<br/><br/>涉及的js文件</p>
<p style='padding-left: 30px;'><br/>jquery-1.2.6.js ------- 这里面有一些hack 用 //achun 表明了,具体作用先抛开不讲<br/>jquery-ajax-queue.js----ajax 队列插件<br/>json.js-----------------JSON支持了<br/>jct.js------------------我的jCT模板工具<br/>lib.js------------------自己写的几个小函数里面有注释,注意一下几个方法</p>
<p style='padding-left: 60px;'><br/>   R<br/>   urlPath<br/>   processXDOC<br/>   serializeXML</p>
<p style='padding-left: 30px;'><br/>app.js------------------自己写的适合具体应用的函数模块,注意一下几个方法<br/>   jsonQueue------------队列化的 ajax 请求,当然返回数据类型为JSON,</p>
<p style='padding-left: 60px;'><br/>        要注意的是这个使用options.callback作为处理接口的</p>
<p style='padding-left: 30px;'><br/>   $().ready------------这里就是开始了</p>
<p style='padding-left: 60px;'><br/>        这里面有一个契约编程,我一直在说分离,那么应该是前台主动向后台要数据,那么第一个POST数据就是</p>
<pre name='code' class='js'>{entry:true}</pre>
 
<p style='padding-left: 60px;'>也就是entry了,(我采用的队列使用值对里的KEY作为请求指示,用值做参数的,你不一定要这样),<br/>        后台看到entry的请求就知道了前台要程序的入口模板,所以返回了</p>
<pre name='code' class='js'>{"entry":"/16lo/index.html"}</pre>
 
<p style='padding-left: 60px;'>(KEY的一致性是我采取的方式,你不一定要这样)<br/>        前台就去调用/16lo/index.html文件,并用jCT解析执行.注意window.jct();这一句没有参数,看看<br/>        /16lo/index.html的内容就知道了(我把注释也加进去)</p>
<p style='padding-left: 60px;'>首先这是一个完整的html,这也就是jCT的特性 <strong>一致性</strong> 如果直接在浏览器地址栏输入 <a href='http://www.16lo.com/16lo/index.html'>http://www.16lo.com/16lo/index.html</a> 就会得到和结果一直的表现样式(当然我这个例子没有使用样式,不过很快你就会看到样式的)</p>
<p style='padding-left: 30px;'> </p>
<pre name='code' class='html'>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"  xml:lang="zh-CN"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;
&lt;meta http-equiv="Content-Language" content="zh-CN" /&gt;
&lt;title&gt;快乐的春天&lt;/title&gt;&lt;!--head段的title,link,style,script会被processXDOC正确的处理--&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;!--entry function(D){
if(undefined==D) return jsonQueue({init:true},{callback:this});
with(D)
--&gt;
&lt;!--outlet
$('body').html(__CTV__.join(""));
--&gt;
&lt;!--上面这两句就是jCT的entry和outlet语法了,说白了就是在模板里对页面上的数据获取和装配提供了支持,
里面的
if(undefined==D) jsonQueue({init:true},{callback:this});
是个小技巧,可以看出这个jCT实例其实被调用了两次,第一次是由$().ready里的window.jct();调用的,第一次由于没有数据所以不能正确表现,
所以利用if判断和{callback:this}参数在得到数据后进行第二次调用,也就是表现了。{init:true}当然就是向后台提出的请求了。
至于,$('body').html(__CTV__.join(""));就简单了,__CTV__是jCT实例执行后的结果,这里面就是把结果显示于body了
--&gt;
+-init-+&lt;!--这个简单就是后台打出的数据了--&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
 
<p>现在配合后台的php代码</p>
<pre name='code' class='cpp'>foreach ($AQ as $Q=&gt;$P){//$AQ是 $json=file_get_contents('php://input'); $AQ=json_decode($json,true);处理的来的。
switch ($Q){
case 'entry':
se_Msg(se_webPath(dirname(__FILE__).'/index.html'));//entry入口模板文件
break;
case 'init':
se_Msg('hello anmouse');//init的数据
break;
}
}</pre>
<p> se_Msg,se_webPath是我写的库函数,功能就简单了,</p>
<p>se_Msg--------负责输出JSON格式的数据</p>
<p>se_webPath--通过后台路径计算对应前台的路径</p>
<p>当然还有一些辅助性的处理没有给出,不过那不是重点,随应用的不同那些处理会不同的,关键的就都在这里了。</p>
<p>还有就是最初后台给出的html代码</p>
<pre name='code' class='html'>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict

.dtd"&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"  xml:lang="zh-CN"&gt;

&lt;head&gt;

&lt;meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /&gt;

&lt;meta http-equiv="Content-Language" content="zh-CN" /&gt;

&lt;style type="text/css"&gt;

body{display:none}

&lt;/style&gt;

&lt;script type="text/javascript" src="/js/jquery-1.2.6.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="/js/jquery/jquery-ajax-queue.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="/js/json.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="/js/jct.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="/js/lib.js"&gt;&lt;/script&gt;

&lt;script type="text/javascript" src="/js/app.js"&gt;&lt;/script&gt;&lt;title&gt;&lt;/title&gt;

&lt;/head&gt;

&lt;body&gt;&lt;p&gt;搜索引擎支持&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</pre>
<p> 呵呵就是这样,主意里面默认body是display:none的,因为里面的</p>
<pre name='code' class='html'>&lt;p&gt;搜索引擎支持&lt;/p&gt;</pre>
<p>
不是让浏览器看的是专门对搜索引擎输出的数据(当然站建成后这些数据就具体了),也就是说通过在通讯的时候判断一些特殊的变量来区分浏览器和搜索引擎,php判断代码如下:</p>
<p>(说来失望,我这个前台模板的方案向很多朋友解释过,可是一听是对纯ajax支持才能发挥特点时就动摇了,因为ajax对搜索引擎支持的不好,我就奇怪了,程序员遇到困难就退缩,这.........,一怒之下,用了2个小时我就想到了解决方案,这不是很简单么!)</p>
<pre name='code' class='cpp'>$JSON=count($_FILES)&gt;0 || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) and $_SERVER['HTTP_X_REQUESTED_WITH'] =='XMLHttpRequest') || isset($_GET['_']);</pre>
<p> $JSON为true就是浏览器,为false就是SE了,当然第一次不管是不是浏览器或者SE都要输出一次,</p>
<pre name='code' class='html'>&lt;p&gt;搜索引擎支持&lt;/p&gt;</pre>
<p>
这样的数据</p>
<p> </p>
<p>最后就是由于我是利用XMLHttpRequest对象对模板进行解析的,但是可恨的IE有BUG必须要求Content-Type为application/xml,不支持application/xhtml+xml而且还不能在浏览器上直接渲染xhtml文件,只能用html文件(因为xhtml文件Content-Type为application/xhtml+xml),没有办法就hack了jQuery 的 ajax方法,</p>
<pre name='code' class='js'> if (s.dataType =='xml') {
xhr.setRequestHeader("User-Agent", 'application/xml');
}</pre>
<p> 利用</p>
<pre name='code' class='js'>User-Agent</pre>
<p>
告诉后台,我要返回Content-Type 为 application/xml,而不是text/html</p>
<p>我的web server用的是lighttpd,配套设置为</p>
<pre name='code' class='js'>$HTTP["useragent"] =="application/xml" {
        setenv.add-response-header  = ( "Content-Type" =&gt; "application/xml" )
}</pre>
<p> 当然用了mod_setenv</p>
<p> </p>
<p>所有的要点都在这里了。</p>

相关推荐

Global site tag (gtag.js) - Google Analytics