﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-xiaoguozi's Blog-随笔分类-框架</title><link>http://cppblog.com/guojingjia2006/category/11424.html</link><description>Pay it forword - 我并不觉的自豪，我所尝试的事情都失败了······习惯原本生活的人不容易改变，就算现状很糟，他们也很难改变，在过程中，他们还是放弃了······他们一放弃，大家就都是输家······让爱传出去，很困难，也无法预料，人们需要更细心的观察别人，要随时注意才能保护别人，因为他们未必知道自己要什么·····</description><language>zh-cn</language><lastBuildDate>Wed, 14 May 2014 14:21:39 GMT</lastBuildDate><pubDate>Wed, 14 May 2014 14:21:39 GMT</pubDate><ttl>60</ttl><item><title> shrio 权限管理filterChainDefinitions过滤器配置 </title><link>http://www.cppblog.com/guojingjia2006/archive/2014/05/14/206956.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 14 May 2014 03:57:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2014/05/14/206956.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/206956.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2014/05/14/206956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/206956.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/206956.html</trackback:ping><description><![CDATA[<div><p><span>/** </span></p> <p><span>* Shiro-1.2.2内置的FilterChain </span></p> <p><span><span>* @see  =============================================================================================================================</span> </span></p> <p><span>* @see 1)Shiro验证URL时,URL匹配成功便不再继续匹配查找(所以要注意配置文件中的URL顺序,尤其在使用通配符时) </span></p> <p><span>* @see&nbsp;&nbsp; 故filterChainDefinitions的配置顺序为自上而下,以最上面的为准 </span></p> <p><span>* @see 2)当运行一个Web应用程序时,Shiro将会创建一些有用的默认Filter实例,并自动地在[main]项中将它们置为可用 </span></p> <p><span>* @see&nbsp;&nbsp; 自动地可用的默认的Filter实例是被DefaultFilter枚举类定义的,枚举的名称字段就是可供配置的名称 </span></p> <p><span>* @see&nbsp;&nbsp; anon---------------org.apache.shiro.web.filter.authc.AnonymousFilter </span></p> <p><span>* @see&nbsp;&nbsp; authc--------------org.apache.shiro.web.filter.authc.FormAuthenticationFilter </span></p> <p><span>* @see&nbsp;&nbsp; authcBasic---------org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter </span></p> <p><span>* @see&nbsp;&nbsp; logout-------------org.apache.shiro.web.filter.authc.LogoutFilter </span></p> <p><span>* @see&nbsp;&nbsp; noSessionCreation--org.apache.shiro.web.filter.session.NoSessionCreationFilter </span></p> <p><span>* @see&nbsp;&nbsp; perms--------------org.apache.shiro.web.filter.authz.PermissionAuthorizationFilter </span></p> <p><span>* @see&nbsp;&nbsp; port---------------org.apache.shiro.web.filter.authz.PortFilter </span></p> <p><span>* @see&nbsp;&nbsp; rest---------------org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter </span></p> <p><span>* @see&nbsp;&nbsp; roles--------------org.apache.shiro.web.filter.authz.RolesAuthorizationFilter </span></p> <p><span>*&nbsp;@see&nbsp;&nbsp; ssl----------------org.apache.shiro.web.filter.authz.SslFilter </span></p> <p><span>&nbsp;<a target="_blank" href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#42;&#64;&#115;&#101;&#101;">*@see</a>&nbsp;&nbsp; user---------------org.apache.shiro.web.filter.authz.UserFilter </span></p> <p><span><span>* @see  =============================================================================================================================</span> </span></p> <p><span>* @see 3)通常可将这些过滤器分为两组 </span></p> <p><span>* @see&nbsp;&nbsp; anon,authc,authcBasic,user是第一组认证过滤器 </span></p> <p><span>* @see&nbsp;&nbsp; perms,port,rest,roles,ssl是第二组授权过滤器 </span></p> <p><span>* @see&nbsp;&nbsp; 注意user和authc不同：当应用开启了rememberMe时,用户下次访问时可以是一个user,但绝不会是authc,因为authc是需要重新认证的 </span></p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; user表示用户不一定已通过认证,只要曾被Shiro记住过登录状态的用户就可以正常发起请求,比如rememberMe </span></p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说白了,以前的一个用户登录时开启了rememberMe,然后他关闭浏览器,下次再访问时他就是一个user,而不会authc </span></p> <p><span><span>* @see  =============================================================================================================================</span> </span></p> <p><span>* @see 4)举几个例子 </span></p> <p><span>* @see&nbsp;&nbsp; /admin=authc,roles[admin]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表示用户必需已通过认证,并拥有admin角色才可以正常发起'/admin'请求 </span></p> <p><span>* @see&nbsp;&nbsp; /edit=authc,perms[admin:edit]&nbsp; 表示用户必需已通过认证,并拥有admin:edit权限才可以正常发起'/edit'请求 </span></p> <p><span>* @see&nbsp;&nbsp; /home=user&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 表示用户不一定需要已经通过认证,只需要曾经被Shiro记住过登录状态就可以正常发起'/home'请求 </span></p> <p><span><span>* @see  =============================================================================================================================</span> </span></p> <p><span>* @see 5)各默认过滤器常用如下(注意URL Pattern里用到的是两颗星,这样才能实现任意层次的全匹配) </span></p> <p><span>* @see&nbsp;&nbsp; /admins/**=anon&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无参,表示可匿名使用,可以理解为匿名用户或游客 </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=authc&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无参,表示需认证才能使用 </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=authcBasic&nbsp; 无参,表示httpBasic认证 </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=user&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无参,表示必须存在用户,当登入操作时不做检查 </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=ssl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 无参,表示安全的URL请求,协议为https </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=perms[user:add:*] </span> </p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参数可写多个,多参时必须加上引号,且参数之间用逗号分割,如/admins/user/**=perms["user:add:*,user:modify:*"] </span></p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当有多个参数时必须每个参数都通过才算通过,相当于isPermitedAll()方法 </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=port[8081] </span></p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当请求的URL端口不是8081时,跳转到schemal://serverName:8081?queryString </span></p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其中schmal是协议http或https等,serverName是你访问的Host,8081是Port端口,queryString是你访问的URL里的?后面的参数 </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=rest[user] </span> </p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据请求的方法,相当于/admins/user/**=perms[user:method],其中method为post,get,delete等 </span></p> <p><span>* @see&nbsp;&nbsp; /admins/user/**=roles[admin] </span> </p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 参数可写多个,多个时必须加上引号,且参数之间用逗号分割,如/admins/user/**=roles["admin,guest"] </span></p> <p><span>* @see&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当有多个参数时必须每个参数都通过才算通过,相当于hasAllRoles()方法 </span></p> <span>* @see<br /><br /><div>http://liureying.blog.163.com/blog/static/61513520136205574873/</div><br /><div>spring中 shiro logout 配置方式<br />     有两种方式实现logout<br />1. 普通的action中 实现自己的logout方法，取到Subject，然后logout<br />这种需要在ShiroFilterFactoryBean 中配置 filterChainDefinitions <br />对应的action的url为anon<br />&lt;property name="filterChainDefinitions"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # some example chain definitions:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /index.htm = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /logout = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /unauthed = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /console/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /css/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /js/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /lib/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /admin/** = authc, roles[admin]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /docs/** = authc, perms[document:read]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** = authc<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # more URL-to-FilterChain definitions here<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/value&gt;<br /><br />2. 使用shiro提供的logout filter<br />需要定义 相应的bean<br />&lt;bean id="logout" class="org.apache.shiro.web.filter.authc.LogoutFilter"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="redirectUrl" value="/loginform" /&gt;<br />&nbsp;&nbsp;&nbsp; &lt;/bean&gt;<br /><br />然后将相应的url filter配置为logout如下<br />&lt;property name="filterChainDefinitions"&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;value&gt;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # some example chain definitions:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /index.htm = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>/logout = logout</strong><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /unauthed = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /console/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /css/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /js/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /lib/** = anon<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /admin/** = authc, roles[admin]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /docs/** = authc, perms[document:read]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /** = authc<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # more URL-to-FilterChain definitions here<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/value&gt;  </div><br /><div>http://kdboy.iteye.com/blog/1154652</div><div>http://blog.csdn.net/peterwanghao/article/details/8084126</div><div>http://www.oschina.net/question/593111_62454</div><div>http://blog.csdn.net/shadowsick/article/details/17265625</div><br /></span></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/206956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2014-05-14 11:57 <a href="http://www.cppblog.com/guojingjia2006/archive/2014/05/14/206956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CentOS 6下安装nodejs 0.9.0</title><link>http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 20 Jan 2014 02:11:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/205486.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/205486.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/205486.html</trackback:ping><description><![CDATA[<div><div id="cnblogs_post_body"><p>确保安装了python，大部分安装失败都是由于python版本过低导致。安装之前，升级python版本，升级步骤 <a href="http://www.tomtalk.net/wiki/Python">http://www.tomtalk.net/wiki/Python</a>。</p>  <p>[root@SNDA-192-168-15-161 ~]# python -V   <br />Python 2.7.3    <br />开始安装：</p>  <p>1).下载nodejs到本地并解压缩   <br />[root@SNDA-192-168-15-161 node]# wget http://nodejs.org/dist/v0.9.0/node-v0.9.0.tar.gz    <br />[root@SNDA-192-168-15-161 node]# tar zxvf node-v0.9.0.tar.gz    <br />2).进入到该目录编译和安装    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# cd node-v0.9.0    <br />[root@SNDA-192-168-15-161&nbsp; node-v0.9.0]# ./configure --prefix=/usr/local/node/0.9.0    <br />这里安装在了/usr/local/node/0.9.0目录下    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# make    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# make install    <br />3).配置NODE_HOME    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# vi /etc/profile    <br />在export PATH USER 。。。一行的上面添加如下内容，并将NODE_HOME/bin设置到系统path中    <br />#set for nodejs    <br />export NODE_HOME=/usr/local/node/0.9.0    <br />export PATH=$NODE_HOME/bin:$PATH    <br />保存退出后执行如下命令，使刚才的配置生效    <br />[root@SNDA-192-168-15-161 node-v0.9.0]# source /etc/profile</p>  <p>执行node -h命令验证设置成功</p>  <p>[root@SNDA-192-168-15-161 ~]# node -h   <br />Usage: node [options] [ -e script | script.js ] [arguments]    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node debug script.js [arguments] </p>  <p>Options:   <br />&nbsp; -v, --version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print node's version    <br />&nbsp; -e, --eval script&nbsp;&nbsp;&nbsp; evaluate script    <br />&nbsp; -p, --print&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print result of --eval    <br />&nbsp; -i, --interactive&nbsp;&nbsp;&nbsp; always enter the REPL even if stdin    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; does not appear to be a terminal    <br />&nbsp; --no-deprecation&nbsp;&nbsp;&nbsp;&nbsp; silence deprecation warnings    <br />&nbsp; --trace-deprecation&nbsp; show stack traces on deprecations    <br />&nbsp; --v8-options&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; print v8 command line options    <br />&nbsp; --max-stack-size=val set max v8 stack size (bytes) </p>  <p>Environment variables:   <br />NODE_PATH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ':'-separated list of directories    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prefixed to the module search path.    <br />NODE_MODULE_CONTEXTS&nbsp;&nbsp; Set to 1 to load modules in their own    <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; global contexts.    <br />NODE_DISABLE_COLORS&nbsp;&nbsp;&nbsp; Set to 1 to disable colors in the REPL </p>  <p>Documentation can be found at <a href="http://nodejs.org/">http://nodejs.org/</a>    <br />至此安装设置完毕。</p>  <p>运行一个简单的node应用程序 + socket.io，首先需要安装socket.io模块</p>  <p>[root@SNDA-192-168-15-161 ~]# npm install socket.io</p>  <p>[root@SNDA-192-168-15-161 ~]# vi app.js</p>  <p>var http=require('http');   <br />var io =require('socket.io');    <br />var server = http.createServer(function(req,res){ </p>  <p>&nbsp;&nbsp;&nbsp; res.writeHead(200,{'Content-Type':'text/plain'});   <br />&nbsp;&nbsp;&nbsp; res.end('Hello world');    <br />}); </p>  <p>server.listen(process.argv[2]); </p>  <p>var socket = io.listen(server);   <br />socket.on('connection',function(client){    <br />&nbsp;&nbsp;&nbsp; console.log('client has connected');    <br />&nbsp;&nbsp;&nbsp; client.on('message',function(){ });    <br />});    <br />&nbsp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8001 &amp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8002 &amp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8003 &amp;</p>  <p>[root@SNDA-192-168-15-161 ~]# nodejs ./app.js 8004 &amp;</p>  <p>更详细的参照<a href="http://socket.io/#how-to-use">socket.io的官网</a>的例子。 </p>  <p><a href="http://cnodejs.org/topic/4f16442ccae1f4aa27001139" target="_blank">websocket与node.js的完美结合</a></p>  <p><a title="http://wanshuiqianshan.iteye.com/blog/1618498" href="http://wanshuiqianshan.iteye.com/blog/1618498">http://wanshuiqianshan.iteye.com/blog/1618498</a></p></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/205486.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2014-01-20 10:11 <a href="http://www.cppblog.com/guojingjia2006/archive/2014/01/20/205486.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Meteor：让实时Web App成为主流</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Mar 2013 01:41:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/198709.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/198709.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/198709.html</trackback:ping><description><![CDATA[<div><p>     <a href="http://www.meteor.com/" target="_blank">Meteor</a>是一个新鲜出炉的现代网站开发平台，目前发布的是开发<a href="http://www.meteor.com/faq/preview" target="_blank">预览版</a><a href="http://www.meteor.com/faq/preview" target="_blank">0.5.8</a>，代码以GPL协议开源。大家可以去     <a href="https://github.com/meteor/meteor" target="_blank">GitHub</a>上关注它。Meteor本质上是Node.JS应用的开发，继承了Ruby on Rails、Node.JS、MongoDB     API等框架的基础特性，模糊了服务器端和客户端，弱化网络连接质量造成的影响。</p> <p>如果简单定义&#8220;现代网站&#8221;是一个实时交互、超高性能、具备非凡体验的网站，那么  Meteor就是一个可为开发者以简单高效而且充满乐趣的方式进行现代网站开发的平台，以往开发周期需要几周到几个月的项目，现在可能只需要几个小时或者 一个周末的时间就可以完成。Meteor构建的应用体验，会让人觉得浏览器的刷新按钮和地址栏是多余的。</p> <p>Meteor在2012年4月首次发布，该消息一经发布，便迅速占据了Haceker News头条宝座，并且成为Hacker News上最热门的文章之一。本文是作者Sacha     Greif使用Meteor开发的心得体会，他认为Meteor会让实时Web App在未来成为主流。     <br /> </p> <p>下面是对原文的翻译：</p> <p>在过去6个月里，我使用Meteor做了点东西（     <a href="http://telesc.pe/" target="_blank">Telescope</a>，Meteor开源的主要应用程序之一），我觉得有必要分享一下我的感受。</p> <p style="text-align: center; ">     <a href="http://cms.csdnimg.cn/article/201303/14/514120de6fe3f.jpg" target="_blank">         <img src="http://cms.csdnimg.cn/article/201303/14/514120de6fe3f.jpg" border="0"  alt="" />     </a>     <br /> </p> <p>首先声明：在和Meteor代码打交道的每一天里，我的大部分时间都在使Telescope变更加可用，而不是去深入挖掘Meteor，所以我不敢 自称是Meteor方面的专家，而之所以能很快上手，很大一部分原因是因为它是一个非常好用且高效的框架，即使在你不精通的情况下也能开发出非常出色的应 用。</p> <p><strong>简单 智能</strong> </p> <p>Meteor的一大特色就是可以轻松构建高品质的实时Web应用程序，相信很多程序员都是因为这一特性而熟知Meteor的。当开始使用Meteor时，会让你的生活变得很简单。</p> <p>     <a href="http://docs.meteor.com/#quickstart" target="_blank">安装Meteor</a>也非常简单，只需一行命令即可。随即便创建第一个应用程序，就连部署也都非常简单，由于Meteor提供免费的托管，因此你可以在线部署，供世界各地的人来浏览。</p> <p style="text-align: center; ">     <a href="http://cms.csdnimg.cn/article/201303/14/5141220800ca2.jpg" target="_blank">         <img src="http://cms.csdnimg.cn/article/201303/14/5141220800ca2.jpg" border="0"  alt="" />     </a>     <br />     </p>     <p>此外，使用Meteor编写的应用程序运行速度也非常快。例如，当你的项目引用JS或CSS文件时，这些文件将会被自动加载，而Meteor也提供了内置的用户管理，自动完成UI部件的加载。</p>     <p><strong>Meteor九大特性</strong>     </p>          <ol><li>纯JavaScript</li><li>实时页面更新</li><li>干净、强大的数据同步</li><li>&nbsp;延迟补偿</li><li>代码热推送</li><li>敏感代码运行于受限环境中</li><li>&nbsp;完全独立的应用包</li><li>互操作</li><li>智能的包</li></ol>          <p><strong>实时的未来</strong>     </p>     <p>说实话，实时框架是Meteor的最大卖点，实时Web应用程序会让人联想到多人游戏和实时在线文档编辑，但在使用Meteor时，我快速发现实时也可以编写出更加实用且非常好的应用程序，而这种实时很有可能会成为未来几年内Web应用程序的默认编写方式。</p>     <p>在桌面应用系统中，如果一个目录被两个窗口同时打开，那么当你在其中一个窗口删除一个文件后，你必须刷新另一个窗口，那个文件才会&#8220;消失&#8221;。因此，这就缺乏了实时性，而Meteor框架就可弥补这方面的不足。</p>     <p>此外，实时也影响到我们的编码风格。你无需刷新页面或使用特定的回调逻辑来使应用程序做出响应：每一个块数据都会自动监测、任何与UI元素有关的数据也会自动更新。</p>     <p>下面提供一个案例，一旦有人投票，就响应upvote按钮的&#8220;disable&#8221;类，模板代码（Meteor使用         <a href="http://thechangelog.com/handlebars-js/" target="_blank">Handlebars</a>）：</p>     <div><div id="highlighter_973470"  html"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div style="height: 24px !important;" number1="" index0=""  alt2"="">1</div><div style="height: 24px !important;" number2="" index1=""  alt1"="">2</div><div style="height: 24px !important;" number3="" index2=""  alt2"="">3</div><div style="height: 24px !important;" number4="" index3=""  alt1"="">4</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">&lt;</code><code keyword"="">div</code> <code color1"="">class</code><code plain"="">=</code><code string"="">"post"</code><code plain"="">&gt;</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">&lt;</code><code keyword"="">a</code> <code color1"="">href</code><code plain"="">=</code><code string"="">"#"</code> <code color1"="">class</code><code plain"="">=</code><code string"="">"upvote btn {{upvotedClass}}"</code><code plain"="">&gt;⬆&lt;</code><code keyword"="">a</code> <code plain"="">/&gt;</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">&lt;</code><code keyword"="">h3</code><code plain"="">&gt;&lt;</code><code keyword"="">a</code> <code color1"="">href</code><code plain"="">=</code><code string"="">"{{url}}"</code><code plain"="">&gt;{{title}}&lt;/</code><code keyword"="">a</code><code plain"="">&gt;&lt;/</code><code keyword"="">h3</code><code plain"="">&gt;</code></div><div number4="" index3=""  alt1"=""><code plain"="">&lt;/</code><code keyword"="">div</code><code plain"="">&gt;</code></div></div></td></tr></tbody></table></div></div>          <p>下面是与之匹配的控制器代码：</p>     <div><div id="highlighter_392042"  js"=""><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div style="height: 24px !important;" number1="" index0=""  alt2"="">1</div><div style="height: 24px !important;" number2="" index1=""  alt1"="">2</div><div style="height: 48px !important;" number3="" index2=""  alt2"="">3</div><div style="height: 48px !important;" number4="" index3=""  alt1"="">4</div><div style="height: 24px !important;" number5="" index4=""  alt2"="">5</div><div style="height: 24px !important;" number6="" index5=""  alt1"="">6</div><div style="height: 24px !important;" number7="" index6=""  alt2"="">7</div><div style="height: 24px !important;" number8="" index7=""  alt1"="">8</div><div style="height: 24px !important;" number9="" index8=""  alt2"="">9</div><div style="height: 24px !important;" number10="" index9=""  alt1"="">10</div><div style="height: 24px !important;" number11="" index10=""  alt2"="">11</div><div style="height: 24px !important;" number12="" index11=""  alt1"="">12</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">Template.post.helpers({</code></div><div number2="" index1=""  alt1"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">upvotedClass: </code><code keyword"="">function</code><code plain"="">() {</code></div><div number3="" index2=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code comments"="">// test if user is logged in, and if their userId </code></div><div number4="" index3=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code comments"="">// is included in the 'upvoters' array</code></div><div number5="" index4=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">var</code> <code plain"="">userId = Meteor.userId();</code></div><div number6="" index5=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">if</code> <code plain"="">(userId &amp;&amp; !_.include(</code><code keyword"="">this</code><code plain"="">.upvoters, userId)) {</code></div><div number7="" index6=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">return</code> <code string"="">'upvoteable'</code><code plain"="">;</code></div><div number8="" index7=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">} </code><code keyword"="">else</code> <code plain"="">{</code></div><div number9="" index8=""  alt2"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code keyword"="">return</code> <code string"="">'disabled'</code></div><div number10="" index9=""  alt1"=""><code spaces"="">&nbsp;&nbsp;&nbsp;&nbsp;</code><code plain"="">}</code></div><div number11="" index10=""  alt2"=""><code spaces"="">&nbsp;&nbsp;</code><code plain"="">}</code></div><div number12="" index11=""  alt1"=""><code plain"="">});</code></div></div></td></tr></tbody></table></div></div>          <p>这段代码妙在何处呢？如果用户的userid从upvoters数组中删除（例如，实现一个&#8220;cancel upvote&#8221;操作），这会自动在UI上反应出来，无需编写额外的代码。</p>     <p><strong>一切就绪了吗？</strong>     </p>     <p>现在，你可能会随着这一行行代码思考些东西：&#8220;好，它看起来很棒，但是它真的就可以作为现实应用（&nbsp;real-world apps）吗？&#8221;</p>     <p>答案肯定是依情况而定。Meteor当然可以作为现实应用使用。Telescope和Sidebar（基于Telescope）就是非常完美的例子。</p>     <p>但并不是说Meteor就可以完全作为现实应用使用。Meteor没有服务端渲染功能，有些网站对加载速度要求特别高，比如电子商务网站，而有些则需要在旧的/老的设备上运行，比如过时的手机。</p>     <p><strong>Meteor Book</strong>     </p>     <p>目前，我和         <a href="http://tom.thesnail.org/" target="_blank">Tom Coleman</a>（Meteor开源生态系统的主要贡献者之一，创建Meteor包管理器         <a href="https://github.com/oortcloud/meteorite" target="_blank">Meteorite</a>）正在专注于         <a href="http://themeteorbook.com/" target="_blank">The Meteor Book</a>，教你如何使用Meteor编写基本的应用程序。</p>     <p>更多精彩内容，大家可以来到Hacker News上和我一起         <a href="https://news.ycombinator.com/item?id=5362370" target="_blank">探讨</a>。（编译/张红月 责编/付江）</p> <hr />     <p><strong>学习资料：</strong>     </p>     <p>官方提供的3个示例：</p>          <ul><li>             <a href="http://meteor.com/examples/leaderboard">http://meteor.com/examples/leaderboard</a>         </li><li>             <a href="http://meteor.com/examples/todos">http://meteor.com/examples/todos</a>         </li><li>             <a href="http://meteor.com/examples/wordplay">http://meteor.com/examples/wordplay</a>         </li></ul>          <p>GitHub项目页：</p>          <ul><li>             <a href="http://github.com/meteor/meteor">http://github.com/meteor/meteor</a>         </li></ul>          <p>Meteor@StackOverflow</p>          <ul><li>             <a href="http://stackoverflow.com/questions/tagged/meteor?sort=newest&amp;pagesize=15">http://stackoverflow.com/questions/tagged/meteor?sort=newest&amp;pagesize=15</a>         </li></ul>          <p>文档：</p>          <ul><li>             <a href="http://docs.meteor.com/">http://docs.meteor.com/</a>         </li></ul>          <p>FAQ：</p>          <ul><li>             <a href="http://meteor.com/faq">http://meteor.com/faq</a>         </li></ul></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/198709.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-03-22 09:41 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/03/22/198709.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eclipse 4.2 aptana</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Feb 2013 02:25:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197992.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197992.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197992.html</trackback:ping><description><![CDATA[<div> 	<div id="cnblogs_post_body"><p>1、使用软件更新的方式：</p> <p>打开Eclipse -&gt; Help -&gt; Install New Software 然后在弹出对话框的 Work with 框中输入如下的地址，回车。</p> <p>http://update.aptana.com/update/studio/3.2/</p> <p>然后就会一步步选择需要安装的组件即可。</p> <p>2、在Eclipse 4.2 上安装 Aptana 3.2遇到的错误，提示找不到&nbsp;org.eclipse.update.ui 0.0.0</p> <p>通过google（这种时候记得别使用百度），看到有同样的问题：</p> <p>http://boards.developerforce.com/t5/General-Development/Trouble-with-Force-com-IDE-installation-in-Eclipse-4-2/m-p/480891#M73687</p> <p>&nbsp;</p> <p>其中的有人回答：</p> <div lia-quilt-row-main"=""> <div lia-quilt-column-20="" lia-quilt-column-right=""  lia-quilt-column-main-right"=""> <div lia-quilt-column-alley-right"=""> <div id="messagebodydisplay_4"  lia-component-body"=""> <div>Hi, After i am downloadinng  org.eclipse.update.ui_3.2.300.v20100512.jar and  org.eclipse.update.ui.source_3.2.300.v20100512.jar files from the below  site and placed it under eclipse/plugins directory and it worked for me.<a href="http://grepcode.com/snapshot/repository.grepcode.com/java/eclipse.org/3.6/org.eclipse.update/ui/3.2...." rel="nofollow" target="_blank">http://grepcode.com/snapshot/repository.grepcode.com/java/eclipse.org/3.6/org.eclipse.update/ui/3.2....</a>&nbsp;thanks, Ravi</div> </div> </div> </div> </div> <div lia-quilt-row-footer"="">&nbsp;</div> <div lia-quilt-row-footer"="">按照提示的这个网址，去下载 ui组件，放置到eclipse目录的 plugins 之中，重启eclipse，再次安装即可成功。</div> <div lia-quilt-row-footer"="">&nbsp;</div> <div lia-quilt-row-footer"="">注：Eclipse 4.2的update  ui，在这里：http://grepcode.com/search /?r=repository.grepcode.com$java$eclipse.org$4.2&amp;start=20&amp;query=org.eclipse.update+ui+3.2....&amp;entity=project</div> <div lia-quilt-row-footer"="">&nbsp;</div> <div lia-quilt-row-footer"=""><strong>另外如果要安装Aptana直接输入：http://download.aptana.com/studio3/plugin/install 进行更新即可。</strong></div></div></div><br /><div><div lia-component-message-header"=""> 					<div lia-quilt-row-standard"=""> 	 						<div lia-quilt-column-20=""  lia-quilt-column-left"=""> 	<div lia-quilt-column-alley-left"=""> 		 							 		<div> 			<img title="Solution!" id="display_5" src="http://sforce.i.lithium.com/skins/images/AB7BE5A46312549054BBC94CA9D2261C/base/images/message_type_solution.png" alt="" /> 			 			 			 			 			<h1>Re: Trouble with Force.com IDE installati<wbr>on in Eclipse 4.2</h1> 			<span> 				 				 			</span> 		</div> 	 						 	</div> </div> 						<div lia-quilt-column-04=""  lia-quilt-column-right"=""> 	<div lia-quilt-column-alley-right"=""> 		 							 		<div> 			<div lia-menu-action=""  message-menu"="" id="actionMenuDropDown_3">	 	<div> 		<div><a default-menu-option="" lia-js-click-menu=""  lia-link-navigation"="" id="dropDownLink_3" href="http://boards.developerforce.com/t5/General-Development/Trouble-with-Force-com-IDE-installation-in-Eclipse-4-2/td-p/477651#">Options</a> 			<div> 				<div> 					 	  				</div> 			</div> 		</div> 	</div> </div> 		</div> 	 						 	</div> </div> 					 </div> 				</div> 			  	 				<p lia-message-post-date=""  lia-component-post-date-last-edited"=""> 					 		 <span lia-message-posted-on=""  lia-component-common-widget-date"="">  	 		 		 		&#8206;08-09-2012 	 		 		10:06 AM 	 	  	 	 	 	 	 	 	 	 	 	 	 	 </span> 	 				</p> 			  	 				<div id="messagebodydisplay_2"> 	 		<div> 			 				<p>Update:</p><p>&nbsp;</p><p>In the post I linked above:&nbsp;<a href="http://boards.developerforce.com/t5/General-Development/Install-Eclipse-Juno-4-2-with-Force-com-IDE/m-p/480771#M73674" target="_blank">http://boards.developerforce.com/t5/General-Develo<wbr>pment/Install-Eclipse-Juno-4-2-with-Force-com-IDE/<wbr>...</a>, there's been a solution that worked for me.</p><p>&nbsp;</p><p>To Quote Zokito:</p><p>&nbsp;</p><div lia-component-message-header"=""><div lia-quilt-row-standard"=""><div lia-quilt-column-20=""  lia-quilt-column-left"=""><div lia-quilt-column-alley-left"=""><div><em>08-09-2012&nbsp;09:04 AM</em></div></div></div></div></div><div lia-component-body"=""><div><p><em>Hi,</em></p><p><em>&nbsp;</em></p><p><em>cause of the problem lies here:</em></p><p><em>&nbsp;</em></p><p><em><a href="http://www.eclipse.org/eclipse/development/porting/4.2/incompatibilities.html" target="_blank" rel="nofollow">http://www.eclipse.org/eclipse/development/porting<wbr>/4.2/incompatibilities.html</a></em></p><p><em>(search for&nbsp;org.eclipse.update.ui)</em></p><p><em>&nbsp;</em></p><p><em>It  should be possible to fetch the deependency automatically through the  marketplace but for me it's not working.... so what would you need to do  is install the&nbsp;<strong>org.eclipse.update.ui&nbsp;</strong>manually from e.g.</em></p><p><em><a href="http://www.java2s.com/Code/Jar/o/Downloadorgeclipseupdateui32300v20100512jar.htm" target="_blank" rel="nofollow">http://www.java2s.com/Code/Jar/o/Downloadorgeclips<wbr>eupdateui32300v20100512jar.htm</a></em></p><p><em>&nbsp;</em></p><p><em>&nbsp;</em></p><p><em>extract it and than copy the jar file to your eclipse/plugins/ directory.&nbsp;</em></p><p><em>Start Eclipse again and then try to install the Force IDE plugin.</em></p><p><em>&nbsp;</em></p><p><em>&nbsp;</em></p><p><em>this solved the issue for me</em></p><p>&nbsp;</p><p>Hope this is helpful!</p><p>&nbsp;</p><p>Kelly</p></div></div> 			 			 				 			 		</div> 		 		 		 		 		 		 		 	 </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-22 10:25 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yii RBAC(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 15 Jan 2013 11:38:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197298.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197298.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197298.html</trackback:ping><description><![CDATA[<div><h2>写在前面</h2> <ul><li>以下内容适合Yii 1.0.x，其他版本可能有略微的差别。 </li><li>根据您的评论和反馈，本文会不断进行修改和补充，以方便新学习者。 </li></ul> <h2><a name="t1"></a>开始准备</h2> <p>Yii提供了强大的配置机制和很多现成的类库。在Yii中使用RBAC是很简单的，完全不需要再写RBAC代码。所以准备工作就是，打开编辑器，跟我来。</p> <h2><a name="t2"></a>设置参数、建立数据库</h2> <p>在配置数组中，增加以下内容：</p> <div style="line-height: 12px; font-family: courier new; font-size: 12px;"> <table style="width: 100%; border-width: 0px; padding: 0px;" border="0" cellspacing="0"> <tbody> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">components</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <strong><span style="color: #00008b;">array</span></strong><span style="color: #000000;">(</span></td> </tr> <tr> <td><span style="color: #008000;">//</span><span style="color: #008000;">&#8230;&#8230;</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">authManager</span><span style="color: #4682b4;">&#8216;</span><span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span><span style="color: #000000;">array</span><span style="color: #000000;">(</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">class</span><span style="color: #4682b4;">&#8216;</span><span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">CDbAuthManager</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证类名称</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">defaultRoles</span><span style="color: #4682b4;">&#8216;</span><span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span><span style="color: #000000;">array</span><span style="color: #000000;">(</span><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">guest</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">)</span><span style="color: #000000;">,</span><span style="color: #008000;">//默认角色</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">itemTable</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">pre_auth_item</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证项表名称</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">itemChildTable</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">pre_auth_item_child</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证项父子关系</span></td> </tr> <tr> <td><span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">assignmentTable</span><span style="color: #4682b4;">&#8216;</span> <span style="color: #ff0000;">=</span><span style="color: #ff0000;">&gt;</span> <span style="color: #4682b4;">&#8216;</span><span style="color: #4682b4;">pre_auth_assignment</span><span style="color: #4682b4;">&#8216;</span><span style="color: #000000;">,</span><span style="color: #008000;">//认证项赋权关系</span></td> </tr> <tr> <td><span style="color: #000000;">)</span><span style="color: #000000;">,</span></td> </tr> <tr> <td><span style="color: #008000;">//</span><span style="color: #008000;">&#8230;&#8230;</span></td> </tr> </tbody> </table> </div> <p>那这三个数据表怎么建立呢？很简单，去看framework/web/auth/schema.sql。注意要和你的自定义的表名称对应起来。比如SQL文件中的AuthItem你要修改为pre_auth_item。然后在数据库中运行这个SQL文件中的语句。</p> <h2><a name="t3"></a>了解概念</h2> <p>你可能要问，剩下的代码呢？我告诉你，没有啦。RBAC系统就这样建立起来了。但是为了使用它，你需要了解它的运行机制。我会尽量讲的啰嗦一点&#8230;&#8230;（官方的RBAC文档在<a href="http://www.yiiframework.com/doc/guide/zh_cn/topics.auth" target="_blank">这里</a>，但是我曾经看了4-5遍才明白。）</p> <h3><a name="t4"></a>三个概念</h3> <p>你需要了解的是，授权项目可分为<em>operations</em>（行动）,<em>tasks</em>（任务）和 <em>roles</em>（角色）。</p> <p>一个用户拥有一个或者多个角色，比如，我们这里有三个角色：<strong>银行行长</strong>、<strong>银行职员</strong>、<strong>顾客</strong>。我们假设：</p> <ul><li><strong>张行长 </strong>有角色：银行行长、银行职员、顾客（人家自己可以存钱嘛）。 </li><li><strong>王职员 </strong>有角色：银行职员、顾客。 </li><li><strong>小李 </strong>有角色：顾客。 </li></ul> <p>那么，相应的，只要顾客可以做的事情，小李就可以做，王职员和张行长也可以。银行职员可以做的事情，王职员和张行长都可以做，小李就不可以了。</p> <p>比如，一个&#8220;顾客&#8221;可以存钱，那么拥有&#8220;顾客&#8221;角色的张行长、王职员、小李都可以存钱。&#8220;银行职员&#8221;可以打印顾客的交易记录，那么有&#8220;银行职员&#8221;角 色的张行长和王职员都可以，而小李不行，必须找一个有&#8220;银行职员&#8221;角色的人才可以打印详细的交易记录。一个&#8220;银行行长&#8221;才可以进入银行钱库提钱，那么只有 张行长可以，因为它才有&#8220;银行行长&#8221;的角色。</p> <p>这就是基于角色的认证体系，简称RBAC。</p> <h3><a name="t5"></a>角色的继承</h3> <p>角色是可以继承的，比如我们规定如下：</p> <ul><li>凡是&#8220;银行行长&#8221;都是&#8220;银行职员&#8221;，也就是说，只要银行职员可以做的事情，银行行长都可以做。 </li><li>凡是&#8220;银行职员&#8221;都是顾客，同上，顾客可以做的事情银行职员也可以做。 </li></ul> <p>那么角色关系就变成了：</p> <ul><li><strong>张行长 </strong>有角色：银行行长。 </li><li><strong>王职员 </strong>有角色：银行职员。 </li><li><strong>小李 </strong>有角色：顾客。 </li></ul> <p>这样更简单了，这就是角色的继承。</p> <h3><a name="t6"></a>任务的继承</h3> <p>一个任务（task）是可以包含另外一个任务的，我们举个例子，比如&#8220;进入银行&#8221;。</p> <p>我们设定&#8220;顾客&#8221;这个角色有&#8220;进入银行&#8221;的权限。也就是说，&#8220;顾客&#8221;可以执行&#8220;进入银行&#8221;的任务。接下来，我们假设&#8220;进入柜台&#8221;是进入银行的父权 限，也就是说，&#8220;进入柜台&#8221;包含&#8220;进入银行&#8221;。只要能&#8220;进入柜台&#8221;的人都可以&#8220;进入银行&#8221;。我们把&#8220;进入柜台&#8221;这个任务权限给&#8220;银行职员&#8221;。</p> <p>那么从角色上来说，王职员可以进入银行，因为王职员的角色是&#8220;银行职员&#8221;，而&#8220;银行职员&#8221;包含了&#8220;顾客&#8221;的角色。那么&#8220;顾客&#8221;可以进行的&#8220;任务&#8221;对于&#8220;银行职员&#8221;来说也是可以进行的。而&#8220;顾客&#8221;可以&#8220;进入银行&#8221;，那么王职员也可以&#8220;进入银行&#8221;。这是角色的继承带来的。</p> <p>我们再假设有个<strong>赵领导</strong>，是上级领导，可以进入柜台进行视察。那么，我们的任务关系是：</p> <ul><li><strong>赵领导</strong> 有任务：进入柜台。 </li></ul> <p>那么，赵领导就可以&#8220;进入银行&#8221;。因为&#8220;进入银行&#8221;是被&#8220;进入柜台&#8221;包含的任务。只要可以执行&#8220;进入柜台&#8221;的人都可以执行&#8220;进入银行&#8221;。这就是任务的继承。</p> <h3><a name="t7"></a>关于行动</h3> <p>行动是不可划分的一级。也就是说。而一个行动是不能包含其他行动的。假设我们有个行动叫&#8220;从银行仓库中提钱&#8221;。我们把这个行动作包含&#8220;进入柜台&#8221;。那么只要可以执行&#8220;从银行仓库中提钱&#8221;的角色都可以执行&#8220;进入柜台&#8221;这个任务。</p> <h3><a name="t8"></a>三者关系</h3> <ul><li>一个角色可以包含另外一个或者几个角色。 </li><li>一个角色可以包含另外一个或者几个任务。 </li><li>一个角色可以包含另外一个或者几个行动。 </li><li>一个任务可以包含另外一个或者几个任务。 </li><li>一个任务可以包含另外一个或者几个行动。 </li><li>一个行动只能被角色或者任务包含，行动是不可以包含其他，也不可再分。 </li></ul> <p>这样，就形成了一个权限管理体系。关于&#8220;任务&#8221;和&#8220;行动&#8221;，你不必思考其字面上的意义。这两者就是形成两层权限。</p> <h2><a name="t9"></a>进行赋权</h2> <p>我们建立了RBAC权限管理，就需要进行对权限的WEB管理。这些就需要你自己写代码了。</p> <p>根据不同种类的项目调用下列方法之一定义授权项目：</p> <ul><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#createRole">CAuthManager::createRole</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#createTask">CAuthManager::createTask</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#createOperation">CAuthManager::createOperation</a> </li></ul> <p>一旦我们拥有一套授权项目，我们可以调用以下方法建立授权项目关系：</p> <ul><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#addItemChild">CAuthManager::addItemChild</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#removeItemChild">CAuthManager::removeItemChild</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthItem#addChild">CAuthItem::addChild</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthItem#removeChild">CAuthItem::removeChild</a> </li></ul> <p>最后，我们调用下列方法来分配角色项目给各个用户：</p> <ul><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#assign">CAuthManager::assign</a> </li><li><a href="http://www.yiiframework.com/doc/api/CAuthManager#revoke">CAuthManager::revoke</a> </li></ul> <p>下面我们将展示一个例子是关于用所提供的API建立一个授权等级：</p> <blockquote> <pre>$auth=Yii::app()-&gt;authManager;  <br />$auth-&gt;createOperation('createPost','create a post'); <br />$auth-&gt;createOperation('readPost','read a post'); <br />$auth-&gt;createOperation('updatePost','update a post'); <br />$auth-&gt;createOperation('deletePost','delete a post');  <br /><br />$bizRule='return Yii::app()-&gt;user-&gt;id==$params["post"]-&gt;authID;'; <br />$task=$auth-&gt;createTask('updateOwnPost','update a post by author himself',$bizRule); <br />$task-&gt;addChild('updatePost');  <br /><br />$role=$auth-&gt;createRole('reader'); <br />$role-&gt;addChild('readPost');  <br /><br />$role=$auth-&gt;createRole('author'); <br />$role-&gt;addChild('reader'); <br />$role-&gt;addChild('createPost'); <br />$role-&gt;addChild('updateOwnPost'); <br /><br />$role=$auth-&gt;createRole('editor'); <br />$role-&gt;addChild('reader'); <br />$role-&gt;addChild('updatePost');  <br /><br />$role=$auth-&gt;createRole('admin'); <br />$role-&gt;addChild('editor'); <br />$role-&gt;addChild('author');<br />$role-&gt;addChild('deletePost');  <br /><br />$auth-&gt;assign('reader','readerA'); <br />$auth-&gt;assign('author','authorB'); <br />$auth-&gt;assign('editor','editorC'); <br />$auth-&gt;assign('admin','adminD');</pre> </blockquote> <pre>也就是说，你需要自己写一个管理界面，来列出你的角色、任务、行动，然后可以在这个界面上进行管理。比如增加、删除、修改。</pre> <h2><a name="t10"></a>权限检查</h2> <p>假设你在你的管理界面进行了赋权，那么可以在程序里面进行权限检查：</p> <pre>if(  Yii::app()-&gt;user-&gt;checkAccess('createPost')  )</pre> <pre>{</pre> <blockquote> <pre>// 这里可以显示表单等操作</pre> </blockquote> <pre>} else　{</pre> <blockquote> <pre>// 检查没有通过的可以跳转或者显示警告</pre> </blockquote> <pre>}</pre> <pre>上面的代码就检查了用户是否可以执行&#8220;createPost&#8221;，这createPost可能是一个任务，也可以是一个行动。</pre> <h2><a name="t11"></a>其他的</h2> <p>对于很多说Yii权限体系RBAC不好用的人其实都没有看懂文档。综合我的体验，我感觉Yii框架的RBAC是我用过的框架里面最好用的。而且是需要自己写代码最少的。</p> <p>Yii的RBAC有更加高级的用法，比如&#8220;业务规则&#8221;，&#8220;默认角色&#8221;。你可以去参考官方文档。</p> <p>我知道，会有部分人仍旧不理解RBAC，或者不会用Yii的RBAC。没有关系，你可以在下方的评论框里提问。</p> <p>happy Yii ！</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-15 19:38 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/15/197298.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>yii 源码调试笔记(1)---theme - module - controller about layout</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/11/197181.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 10 Jan 2013 16:03:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/11/197181.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197181.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/11/197181.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197181.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197181.html</trackback:ping><description><![CDATA[<div>string(79) "D:\Program Files\Apach\htdocs\novemweb\themes\classic\views/admin/default\index" string(81) "D:\Program Files\Apach\htdocs\novemweb\themes\classic\views/admin/layouts/column1" string(78) "D:\Program Files\Apach\htdocs\novemweb\themes\classic\views/admin/layouts/main" string(81) "D:\Program Files\Apach\htdocs\novemweb\protected\modules\admin\views/layouts/main"  <div id="content"> 	<h1>admin/default/index</h1>  <p> This is the view content for action "index". The action belongs to the controller "DefaultController" in the "admin" module. </p> <p> You may customize this page by editing <tt>D:\Program Files\Apach\htdocs\novemweb\themes\classic\views\admin\default\index.php</tt> </p>test--------------</div></div><br /><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197181.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-11 00:03 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/11/197181.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>centos 上安装gearman</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 07 Jan 2013 08:39:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197076.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197076.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197076.html</trackback:ping><description><![CDATA[<div><div>官网：http://gearman.org/</div><br />跨多种环境部署 Gearman<br /> http://www.ibm.com/developerworks/cn/opensource/os-gearman/index.html<br /> 利用开源的Gearman框架构建分布式图片处理平台－张宴<br /> http://blog.s135.com/dips/<br /> 监控：<br /> https://github.com/yugene/Gearman-Monitor <br /> <br /> 一、简介<br /> Gearman是一个分发任务的程序架构，由三部分组成：<br /> Gearman client：提供gearman client API给应用程序调用。API可以使用C,PHP,PERL,MYSQL UDF等待呢个语言，它是请求的发起者。<br /> Gearman job server：将客户端的请求分发到各个gearman worker的调度者，相当于中央控制器，但它不处理具体业务逻辑。<br /> Gearman worker：提供gearman worker API给应用程序调用，具体负责客户端的请求，并将处理结果返回给客户端。<br /> Mogilefs的分布式文件系统的核心就是用gearman实现的。<br /> 这个软件的应用场景很多，比如视频网站的视频处理，分布式日志处理，电子邮件处理，文件同步处理，图片处理等等，只要是可以放开，不影响体验和响应的场 景，需要并行进行大量计算和处理的程序都是可以的。Yahoo在60或更多的服务器上使用gearman每天处理600万个作业。新闻聚合器digg构建 了一个相同规模的gearman网络，每天可处理400000个作业。<br /> Gearman不但可以做为任务分发，还可以做为应用方面的负载均衡。可以让worker放在不同的一堆服务器上，也可以启动放在同一个cpu的多个核 上。比如，应用视频转换程序，不希望web服务器来处理视频格式转换，这时，可以在这一堆服务器上进行任务分发，在上面加载worker处理视频格式，对 外的web服务器就不会被视频转换过程影响。而且扩展方便，加一台服务器到任务调度中心，注册成worker即可，这时job  server会在请求到来的时候，将请求发送给空闲的worker。还可以运行多个job server，组成ha架构，如果一个job  server当掉了，client和worker会自动迁移到另一台job server上。<br /> <br /> 二、安装<br /> [Job Server (gearmand) -- 172.16.1.183]<br /> 1.首先安装libdrizzle<br /> &nbsp;&nbsp;&nbsp; #yum install libdrizzle libdrizzle-devel<br /> 2.安装gearman（两种方法1.yum2.源码包）。（c版的server）<br /> &nbsp;&nbsp;&nbsp; 1）yum安装<br /> &nbsp;&nbsp;&nbsp; #rpm -ivh http://dl.iuscommunity.org/pub/ius/stable/Redhat/6/x86_64/epel-release-6-5.noarch.rpm<br /> &nbsp;&nbsp;&nbsp; #yum install -y gearmand<br /> &nbsp;&nbsp;&nbsp; 2）源码包安装<br /> &nbsp;&nbsp;&nbsp; #cd /opt/build/<br /> &nbsp;&nbsp;&nbsp; #wget https://launchpad.net/gearmand/trunk/0.34/+download/gearmand-0.34.tar.gz<br /> &nbsp;&nbsp;&nbsp; #tar zxf gearmand-0.34.tar.gz<br /> &nbsp;&nbsp;&nbsp; #cd gearmand-0.34<br /> &nbsp;&nbsp;&nbsp; #./configure<br /> &nbsp;&nbsp;&nbsp; #make &amp;&amp; make install<br /> 3.启动gearman服务<br /> &nbsp;&nbsp;&nbsp; 1）yum安装方式<br /> &nbsp;&nbsp;&nbsp; #/etc/init.d/gearmand start<br /> &nbsp;&nbsp;&nbsp; 2）源码包安装方式<br /> &nbsp;&nbsp;&nbsp; #/opt/build/gearmand-0.34/sbin/gearmand -d<br /> <br /> &nbsp;&nbsp;&nbsp; #gearmand -vvv -u root <br /> &nbsp;&nbsp;&nbsp; INFO Starting up<br /> &nbsp;&nbsp;&nbsp; INFO Listening on :::4730 (6)<br /> &nbsp;&nbsp;&nbsp; INFO Creating wakeup pipe<br /> &nbsp;&nbsp;&nbsp; INFO Creating IO thread wakeup pipe<br /> &nbsp;&nbsp;&nbsp; INFO Adding event for listening socket (6)<br /> &nbsp;&nbsp;&nbsp; INFO Adding event for wakeup pipe<br /> &nbsp;&nbsp;&nbsp; INFO Entering main event loop<br /> <br /> worker&amp;&amp;client以php方式<br /> [worker --&nbsp; 172.16.1.180]<br /> 安装gearmand如上所示<br /> <br /> 安装 Gearman PHP extension<br /> 1.下载gearman-0.8.0.tgz并安装<br /> &nbsp;&nbsp;&nbsp; #cd /opt/build/<br /> &nbsp;&nbsp;&nbsp; #wget http://pecl.php.net/get/gearman-0.8.0.tgz<br /> &nbsp;&nbsp;&nbsp; # yum install -y libgearman-devel.x86_64<br /> &nbsp;&nbsp;&nbsp; # yum install -y re2c <br /> &nbsp;&nbsp;&nbsp; #tar zxf gearman-0.8.0.tgz <br /> &nbsp;&nbsp;&nbsp; #cd gearman-0.8.0.tgz<br /> &nbsp;&nbsp;&nbsp; #phpize<br /> &nbsp;&nbsp;&nbsp; # ./configure<br /> &nbsp;&nbsp;&nbsp; # make &amp;&amp; make install<br /> 2.编辑php.ini配置文件加载相应模块并使之生效<br /> &nbsp;&nbsp;&nbsp; # vim /etc/php.ini<br /> &nbsp;&nbsp;&nbsp; extension = "gearman.so"<br /> 3.查看gearman.so模块是否加载<br /> &nbsp;&nbsp;&nbsp; # php --info | grep gearman<br /> &nbsp;&nbsp;&nbsp; gearman<br /> &nbsp;&nbsp;&nbsp; gearman support =&gt; enabled<br /> &nbsp;&nbsp;&nbsp; libgearman version =&gt; 0.14<br /> &nbsp;&nbsp;&nbsp; PWD =&gt; /opt/build/gearman-0.8.0<br /> &nbsp;&nbsp;&nbsp; _SERVER["PWD"] =&gt; /opt/build/gearman-0.8.0<br /> &nbsp;&nbsp;&nbsp; # php -m | grep gearman<br /> &nbsp;&nbsp;&nbsp; gearman<br /> 4.启动job<br /> gearmand -d<br /> 如果当前用户是 root 的话，则需要这样操作：<br /> gearmand -d -u root<br /> 缺省会使用 4730 端口，下面会用到。<br /> &nbsp;&nbsp;&nbsp; 注意：如果找不到 gearmand 命令的路径，别忘了用 whereis gearmand 确认<br /> <br /> [client -- 172.16.1.181]<br /> &nbsp;&nbsp;&nbsp; 安装如work同。如上所示。<br /> <br /> 三、测试：<br /> [Job Server (gearmand) -- 172.16.1.183]<br /> 启动gearmand<br /> <br /> 以命令行工具来验证gearman的功能<br /> 启动 Worker：gearman -h 172.16.1.183 -w -f wc -- wc -l &amp;<br /> 运行Client：gearman -h 172.16.1.183 -f wc &lt; /etc/passwd<br /> 42<br /> 可以看到验证成功。<br /> <br /> 以php验证gearman的功能<br /> 编写 Worker<br /> worker.php 文件内容如下：<br /> &lt;?php<br /> $worker= new GearmanWorker();<br /> $worker-&gt;addServer('172.16.1.183', 4730);<br /> $worker-&gt;addFunction('reverse', 'my_reverse_function');<br /> while ($worker-&gt;work());<br /> function my_reverse_function($job) {<br /> return strrev($job-&gt;workload());<br /> }<br /> ?&gt;<br /> 设置后台运行 work<br /> php worker.php &amp;<br /> 编写 Client<br /> client.php 文件内容如下：<br /> &lt;?php<br /> $client= new GearmanClient();<br /> $client-&gt;addServer('172.16.1.183', 4730);<br /> echo $client-&gt;do('reverse', 'Hello World!'), "\n";<br /> ?&gt;<br /> 运行 client<br /> php client.php<br /> 输出：!dlroW olleH<br /><br />Q:<br /><div><div itemprop="description">         <p>I've been trying to get Gearman compiled on CentOS 5.8 all  afternoon. Unfortunately I am restricted to this version of CentOS by my  CTO and how he has our entire network configured. I think it's simply  because we don't have enough resources to upgrade our network... But  anyways, the problem at hand.</p>  <p>I have searched through Server Fault, Stack Overflow, Google, and am  unable to locate a working solution. What I have below is stuff I have  pieced together from my searching.</p>  <p>Searches have told said to install the following via <code>yum</code>:</p>  <pre><code>yum -y install --enablerepo=remi boost141-devel libgearman-devel e2fsprogs-devel e2fsprogs gcc44 gcc-c++ </code></pre>  <p>To get the Boost headers working correctly I did this:</p>  <pre>cp -f /usr/lib/boost141/* /usr/lib/ cp -f /usr/lib64/boost141/* /usr/lib64/ rm -f /usr/include/boost ln -s /usr/include/boost141/boost /usr/include/boost </pre>  <p>With all of the dependancies installed and paths setup I then download and compile <code>gearmand-1.1.2</code> just fine.</p>  <pre>wget -O /tmp/gearmand-1.1.2.tar.gz https://launchpad.net/gearmand/1.2/1.1.2/+download/gearmand-1.1.2.tar.gz cd /tmp &amp;&amp; tar zxvf gearmand-1.1.2.tar.gz ./configure &amp;&amp; make -j8 &amp;&amp; make install </pre>  <p>That works correctly. So now I need to install the Gearman library  for PHP. I have attempted through PECL and downloading the source  directly, both result in the same error:</p>  <pre>checking whether to enable gearman support... yes, shared not found configure: error: Please install libgearman </pre>  <p>What I don't understand is I installed the <code>libgearman-devel</code> package which also installed the core <code>libgearman</code>. The installation installs <code>libgearman-devel-0.14-3.el5.x86_64</code>, <code>libgearman-devel-0.14-3.el5.i386</code>, <code>libgearman-0.14-3.el5.x86_64</code>, and <code>libgearman-0.14-3.el5.i386</code>.</p>  <p>Is it possible the package version is lower than what is required?  I'm still poking around with this, but figured I'd throw this up to see  if anyone has a solution while I continue to research a fix.</p>  <p>Thanks!</p>      </div></div><br />A:<br /><div><div><p>This should do the trick:</p>  <pre><code>export GEARMAN_LIB_DIR=/usr/include/libgearman <br />export GEARMAN_INC_DIR=/usr/include/libgearman </code></pre>  <p>That should work, if not you'll have to do some minor edits to config.m4.</p><p><br /></p><p>other:</p><p><div>http://gearman.org/gearman_php_extension</div><div>http://blog.csdn.net/aidenliu/article/details/7406390</div><div>http://www.php.net/manual/en/gearmanclient.dobackground.php</div><div>http://www.wenzizone.com/2012/09/27/how_to_fix_rpm_filedigests_payloadisxz_is_needed.html</div><div>http://www.2cto.com/os/201206/136785.html</div><div>http://blog.s135.com/dips</div><div>http://blog.csdn.net/hfahe/article/details/5519582</div><div>http://hi.baidu.com/sunjiujiu/item/4406281c952cf47a7b5f2594</div><br /></p> </div></div><div></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197076.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-01-07 16:39 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/01/07/197076.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Gearman简单介绍</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/12/27/196738.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 27 Dec 2012 12:19:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/12/27/196738.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196738.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/12/27/196738.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196738.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196738.html</trackback:ping><description><![CDATA[<div><p style="line-height:30px;text-indent:2em;text-align:left">Gearman是一个分布式的任务调度框架，它包括 a client，a worker ，a job server这三部分组成。</p><p style="line-height:30px;text-indent:2em;text-align:left">Gearman的执行过程：客户端通过客户端API（PHP，C，Perl等）创建一个任务发送到job server上，Job Server 通过客户端的function name 查找合适的worker，并分到该worker上，worker接收到任务后根据worker的规则执行，并返回数据到job Server，而Job Server则把数据返回给客户端，这样Gearman的执行过程就结束了。</p><p style="line-height:30px;text-indent:2em;text-align:left">用户可以根据不同的需求制定不同的worker来处理不同的任务，将这些worker存放到不同的服务器上，Job Server会根据不同的客户端发送来的任务的function name寻找worker来执行，从而达到为业务服务器减轻压力；</p><p style="line-height:30px;text-indent:2em;text-align:left">Gearman的安装：</p><p style="line-height:30px;text-indent:2em;text-align:left">下载http://launchpad.net/gearmand/trunk/0.12/+download/gearmand-0.12.tar.gz</p><br /> <br /> [falcon@www-001&nbsp;&nbsp;~/src/]$ wget <a href="http://launchpad.net/gearmand/trunk/0.12/+download/gearmand-0.12.tar.gz" target="_blank">http://launchpad.net/gearmand/tr ... earmand-0.12.tar.gz</a><br /> [falcon@www-001&nbsp;&nbsp;~/src/]$ cd gearmand-0.12<br /> <br /> [falcon@www-001&nbsp;&nbsp;~/src/gearmand-0.12]$ ./configure --prefix=/home/falcon/gearmand<br /> <br /> [falcon@www-001&nbsp;&nbsp;~/src/gearmand-0.12]$ make &amp;&amp; make instal<br /><br /><p style="line-height:30px;text-indent:2em;text-align:left">运行gearman 的job Server</p><br /> [falcon@www-001&nbsp;&nbsp;~/src/gearmand-0.12]$ cd ~/gearmand<br /> <br /> [falcon@www-001&nbsp;&nbsp;~/gearmand]$ ls<br /> bin&nbsp;&nbsp;include&nbsp;&nbsp;lib&nbsp;&nbsp;sbin&nbsp;&nbsp;share<br /> [falcon@www-001&nbsp;&nbsp;~/gearmand]$ sbin/gearmand --help<br /> gearmand 0.12 - <a href="https://launchpad.net/gearmand" target="_blank">https://launchpad.net/gearmand</a><br /> usage: sbin/gearmand <br /> [OPTIONS]Main Options:<br />  -b, --backlog=BACKLOG&nbsp; &nbsp;&nbsp; &nbsp; Number of backlog connections for listen. <br /> -d, --daemon&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; Daemon, detach and run in the background. <br /> -f, --file-descriptors=FDS&nbsp;&nbsp;Number of file descriptors to allow for the process&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;<br /> (total connections will be slightly less). Default&nbsp; &nbsp;&nbsp;&nbsp;is max allowed for user. <br /> -h, --help&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;Print this help menu. <br /> -j, --job-retries=RETRIES&nbsp; &nbsp;Number of attempts to run the job before the  job&nbsp;&nbsp;server removes it. Thisis helpful to ensure a bad&nbsp;&nbsp;job does not  crash all available workers. Default&nbsp;&nbsp;is no limit. <br /> -l, --log-file=FILE&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;Log file to write errors and information to.  Turning this option on also forces the first&nbsp;&nbsp;verbose level to be  enabled. <br /> -L, --listen=ADDRESS&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Address the server should listen on. Default is&nbsp;&nbsp;INADDR_ANY. <br /> -p, --port=PORT&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; Port the server should listen on. <br /> -P, --pid-file=FILE&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;File to write process ID out to. <br /> -r, --protocol=PROTOCOL&nbsp; &nbsp;&nbsp;&nbsp;Load protocol module. <br /> -R, --round-robin&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;Assign work in round-robin order  per&nbsp;&nbsp;workerconnection. The default is to assign work in&nbsp;&nbsp;the order of  functions added by the worker. <br /> -q, --queue-type=QUEUE&nbsp; &nbsp;&nbsp; &nbsp;Persistent queue type to use. <br /> -t, --threads=THREADS&nbsp; &nbsp;&nbsp; &nbsp; Number of I/O threads to use. Default=0. <br /> -u, --user=USER&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; Switch to given user after startup. <br /> -v, --verbose&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;Increase verbosity level by one. <br /> -V, --version&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;Display the version of gearmand and exit. <br /> -w, --worker-wakeup=WORKERS Number of workers to wakeup for each job received.&nbsp; &nbsp;The default is to wakeup all available workers.<p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">运行Job Server服务</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/gearmand]$ sbin/gearmand -d</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">判断gearmand是否运行</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/gearmand]$ ps -ef|grep gearmand</p><p style="line-height:30px;text-indent:2em;text-align:left">falcon&nbsp; &nbsp; 9083&nbsp; &nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;0 02:46 ?&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;00:00:00 sbin/gearmand -d -vv</p><p style="line-height:30px;text-indent:2em;text-align:left">falcon&nbsp; &nbsp; 9112 28298&nbsp;&nbsp;0 02:47 pts/1&nbsp; &nbsp; 00:00:00 grep gearmand</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/gearmand]$ netstat -an -t|grep 4730</p><p style="line-height:30px;text-indent:2em;text-align:left">tcp&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;0&nbsp; &nbsp;&nbsp; &nbsp;0 0.0.0.0:4730&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; 0.0.0.0:*&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; LISTEN&nbsp;&nbsp;<br /> </p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">到此Job Server运行正常，下面我们可以简单的在本地上测试Worker和Client是否能够正常接收任务</p><p style="line-height:30px;text-indent:2em;text-align:left">我们这里用gearman命令来测试</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/gearmand]$ bin/gearman --help</p><p style="line-height:30px;text-indent:2em;text-align:left">bin/gearman: invalid option -- -</p><p style="line-height:30px;text-indent:2em;text-align:left">Client mode: bin/gearman [options] [&lt;data&gt;]</p><p style="line-height:30px;text-indent:2em;text-align:left">Worker mode: bin/gearman -w [options] [&lt;command&gt; [&lt;args&gt; ...]]</p><p style="line-height:30px;text-indent:2em;text-align:left"><strong>公共参数区</strong></p><p style="line-height:30px;text-indent:2em;text-align:left">Common options to both client and worker modes.&nbsp;&nbsp;</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-f &lt;function&gt; - Function name to use for jobs (can give many)处理任务的函数名</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-h &lt;host&gt;&nbsp; &nbsp;&nbsp;&nbsp;- Job server host&nbsp;&nbsp;（Job Server主机，默认是localhost）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-H&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Print this help menu</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-p &lt;port&gt;&nbsp; &nbsp;&nbsp;&nbsp;- Job server port （Job Server端口，默认是4730）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-t &lt;timeout&gt;&nbsp;&nbsp;- Timeout in milliseconds&nbsp;&nbsp;（执行多长时间超时，微秒）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-i &lt;pidfile&gt;&nbsp;&nbsp;- Create a pidfile for the process （创建进程的pid文件）</p><p style="line-height:30px;text-indent:2em;text-align:left"><strong>Client部分参数</strong></p><p style="line-height:30px;text-indent:2em;text-align:left">Client options:</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-b&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Run jobs in the background （后台运行任务）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-I&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Run jobs as high priority （高优先级运行任务）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-L&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Run jobs as low priority （低优先级运行任务）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-n&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Run one job per line （逐行执行任务）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-N&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Same as -n, but strip off the newline&nbsp;&nbsp;</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-P&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Prefix all output lines with functions names （在输入结果前面加处理的函数名）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-s&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Send job without reading from standard input 执行任务不返回结果</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-u &lt;unique&gt;&nbsp; &nbsp;- Unique key to use for job 任务的唯一标识</p><p style="line-height:30px;text-indent:2em;text-align:left"><strong>Worker部分参数</strong></p><p style="line-height:30px;text-indent:2em;text-align:left">Worker options:</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-c &lt;count&gt;&nbsp; &nbsp; - Number of jobs for worker to run before exiting （统计worker进程处理多少个任务后中止）</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-n&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Send data packet for each line </p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-N&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Same as -n, but strip off the newline</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;-w&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;- Run in worker mode&nbsp; &nbsp;以worker模式运行</p><br /> <p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left"><strong>示例一</strong>、以命令行方式模拟worker 和 client来处理任务</p><p style="line-height:30px;text-indent:2em;text-align:left">开启一个worker，以function name 为 tongji 来处理输入的数据，统计行数并返回结果</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/gearmand]$ bin/gearman -w -f tongji -- wc -l&nbsp;&nbsp;</p><p style="line-height:30px;text-indent:2em;text-align:left">模拟客户端连接到Job Server，以tongji函数名来提交一个文件，并接收结果</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/gearmand]$ bin/gearman -f tongji&nbsp;&nbsp;&lt; /etc/profile</p><p style="line-height:30px;text-indent:2em;text-align:left">54</p><br /> <p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">示例二、利用Gearman的php扩展来测试Gearman</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">安装PHP的Gearman扩展模块 </p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/src]$ wget&nbsp;&nbsp;<u>http://pecl.php.net/get/gearman-0.7.0.tgz</u></p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/src]$ cd gearman-0.7.0</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/src/gearman-0.7.0]$ /home/falcon/php/bin/phpize </p><p style="line-height:30px;text-indent:2em;text-align:left">......</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/src/gearman-0.7.0]$ ./configure \</p><p style="line-height:30px;text-indent:2em;text-align:left">--with-php-config=/home/falcon/php/bin/php-config --with-gearman=/home/falcon/gearmand</p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/src/gearman-0.7.0]$ make &amp;&amp; make install</p><p style="line-height:30px;text-indent:2em;text-align:left">将gearman.so加入到php.ini配置文件使其生效</p><p style="line-height:30px;text-indent:2em;text-align:left">测试php是否加载gearman模块</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">[falcon@www-001&nbsp;&nbsp;~/php/bin]$ php -m|grep gearman</p><br /> <p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">官方示例：</p><p style="line-height:30px;text-indent:2em;text-align:left">将提交的字符串翻转后返回</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left"><strong>Worker ：worker_reverse.php</strong></p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">&lt;?php</p><p style="line-height:30px;text-indent:2em;text-align:left">$worker= new GearmanWorker();</p><p style="line-height:30px;text-indent:2em;text-align:left">$worker-&gt;addServer();</p><p style="line-height:30px;text-indent:2em;text-align:left">$worker-&gt;addFunction("reverse", "my_reverse_function");</p><p style="line-height:30px;text-indent:2em;text-align:left">while ($worker-&gt;work());</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">function my_reverse_function($job)</p><p style="line-height:30px;text-indent:2em;text-align:left">{</p><p style="line-height:30px;text-indent:2em;text-align:left">&nbsp;&nbsp;return <a href="http://www.php.net/strrev" target="_blank">strrev</a>($job-&gt;workload());</p><p style="line-height:30px;text-indent:2em;text-align:left">}</p><p style="line-height:30px;text-indent:2em;text-align:left">?&gt;</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">运行worker </p><p style="line-height:30px;text-indent:2em;text-align:left">$php work_reverse.php &amp;</p><br /> <p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left"><strong>Client：client_reverse.php</strong></p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">&lt;?php</p><p style="line-height:30px;text-indent:2em;text-align:left">$client= new GearmanClient();</p><p style="line-height:30px;text-indent:2em;text-align:left">$client-&gt;addServer();</p><p style="line-height:30px;text-indent:2em;text-align:left"><a href="http://www.php.net/print" target="_blank">print</a> $client-&gt;do("reverse", "Hello World!");</p><p style="line-height:30px;text-indent:2em;text-align:left">?&gt;</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">执行client_reverse.php</p><p style="line-height:30px;text-indent:2em;text-align:left"><br /> <br /> </p><p style="line-height:30px;text-indent:2em;text-align:left">$ php client_reverse.php</p><p style="line-height:30px;text-indent:2em;text-align:left">!dlroW olleH</p><p style="line-height:30px;text-indent:2em;text-align:left">参考资料：</p><br /> <p style="line-height:30px;text-indent:2em;text-align:left">http://gearman.org/index.php?id=getting_started</p><br /> <p style="line-height:30px;text-indent:2em;text-align:left">http://pecl.php.net/package/gearman</p><br /> http://www.ibm.com/developerworks/cn/opensource/os-php-gearman/</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196738.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-12-27 20:19 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/12/27/196738.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yii - Create your own Validation Rule</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196679.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 26 Dec 2012 07:39:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196679.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196679.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196679.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196679.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196679.html</trackback:ping><description><![CDATA[<div><p>Some times the core validation rules provided by Yii won't satisfy  all your needs, so you'll need to create your very own validation rule.</p>  <h2>Easy approach: inside-model rule </h2>  <p>The easiest way to create a new validation rule is inside the model that is going to use it.</p>  <p>Let's say that you want to check if a user password is safe enough.<br /> Usually you could achieve this result just by using the <a href="http://www.yiiframework.com/doc/api/CRegularExpressionValidator">CRegularExpressionValidator</a> but for the sake of this guide let's pretend that validator does not exist.</p>  <p>first of all in your model class you'll have to add two constants</p>  <div><div><pre>const WEAK = 0<span>; </span>const STRONG = 1;</pre></div></div>  <p>then in your rules method you'll have to set the rule</p>  <div><div><pre>/*<span>*  *</span> @return <span>array validation rules for model attributes.  </span>*/ public function rules() {     return array(        array('password', 'passwordStrength', 'strength'=&gt;self::STRONG)<span>,     </span>)<span>; </span>}</pre></div></div>  <p>make sure that you won't give the rule the name of an existing one, otherwise you are going to have some troubles later.</p>  <p>Now the only thing you need to do is create a new method inside the model, named after the validation rule you just declared.</p>  <div><div><pre>/*<span>*  * check if the user password is strong enough  * check the password against the pattern requested  * by the strength parameter  * This is the 'passwordStrength' validator as declared in rules().  </span>*/ public function passwordStrength($attribute,$params) {     if ($params['strength'] === self::WEAK)         $pattern = '/^(?=.*[a-zA-Z0-9]).{5,}$/'<span>;       </span>elseif ($params['strength'] === self::STRONG)         $pattern = '/^(?=.*\d(?=.*\d))(?=.*[a-zA-Z](?=.*[a-zA-Z])).{5,}$/'<span>;         </span>if(!preg_match($pattern, $this-&gt;$attribute))       $this-&gt;addError($attribute, 'your password is not strong enough!')<span>; </span>}</pre></div></div>  <p>The new method you just created accepts two arguments:</p>  <ul><li>$attribute = is the name of the attribute that the method is validating  </li><li>$params = additional parameters that you could define in the rules  </li></ul><p>In our rules method we used this rule on the password attribute, so the value of attribute inside our validation model will be <strong>password</strong></p>  <p>In the rule we also setted an additional parameter named <strong>strength</strong><br /> the value of that parameter will be inside the $params array</p>  <p>As you can see inside the method we are making a call to <a href="http://www.yiiframework.com/doc/api/1.1/CModel#addError-detail">CModel::addError()</a>.<br /> Add Error accepts two parameters: the first one is the name of the  attribute that you want to display the error in your form, the second  one is the actual error string you want to be displayed.</p>  <h2>Complete approach: extending the CValidator class </h2>  <p>If you need your custom validation rule in more then one model the best thing to do is extending the CValidator class.<br /> Extending this class you also can take advantage of other features, like <a href="http://www.yiiframework.com/doc/api/1.1/CActiveForm#enableClientValidation-detail">CActiveForm::$enableClientValidation</a>, first implemented with Yii 1.1.7 release.</p>  <h2>Creating the class file </h2>  <p>The first thing that you have to do is create your class file. The  best thing is to always name it after your class name, to best use Yii  lazy loading feature. Let's create a new directory inside your application extensions  directory (which is located inside the protected directory).<br /> Name this directory <em>MyValidators</em>.<br /> Then we create our own file: <strong>passwordStrength.php</strong></p>  <p>Inside this file create our CValidator class</p>  <div><div><pre>class passwordStrength extends CValidator {       public $strength<span>;       </span>private $weak_pattern = '/^(?=.*[a-zA-Z0-9]).{5,}$/'<span>;     </span>private $strong_pattern = '/^(?=.*\d(?=.*\d))(?=.*[a-zA-Z](?=.*[a-zA-Z])).{5,}$/'<span>; ...</span></pre></div></div>  <p>In the class file create one attribute for each additional parameter that you want to use inside your validation rule.<br /> CValidator will take care to populate that attribute with the parameter value all by itself.<br /> We also created two other attributes, each containing the patterns we want to use in our preg_match function.</p>  <p>Now we have to override the parent abstract method <a href="http://www.yiiframework.com/doc/api/1.1/CValidator#validateAttribute-detail">validateAttribute</a></p>  <div><div><pre>/*<span>*  * Validates the attribute of the object.  * If there is any error, the error message is added to the object.  *</span> @param <span>CModel $object the object being validated  *</span> @param <span>string $attribute the attribute being validated  </span>*/ protected function validateAttribute($object,$attribute) {     // check the strength parameter used in the validation rule of our model     if ($this-&gt;strength == 'weak')       $pattern = $this-&gt;weak_pattern<span>;     </span>elseif ($this-&gt;strength == 'strong')       $pattern = $this-&gt;strong_pattern<span>;       </span>// extract the attribute value from it's model object     $value=$object-&gt;$attribute<span>;     </span>if(!preg_match($pattern, $value))     {         $this-&gt;addError($object,$attribute,'your password is too weak!')<span>;     </span>} }</pre></div></div>  <p>The method above is self explanatory i think.<br /> Of course you could use constants in those IF, and I actually recommend it.</p>  <h2>Implementing Client Validation </h2>  <p>If you want to implement client validation you'll need to override another method inside your class: <a href="http://www.yiiframework.com/wiki/168/create-your-own-validation-rule/">clientValidateAttribute</a></p>  <div><div><pre>/*<span>*  * Returns the JavaScript needed for performing client-side validation.  *</span> @param <span>CModel $object the data object being validated  *</span> @param <span>string $attribute the name of the attribute to be validated.  *</span> @return <span>string the client-side validation script.  *</span> @see <span>CActiveForm::enableClientValidation  </span>*/ public function clientValidateAttribute($object,$attribute) {       // check the strength parameter used in the validation rule of our model     if ($this-&gt;strength == 'weak')       $pattern = $this-&gt;weak_pattern<span>;     </span>elseif ($this-&gt;strength == 'strong')       $pattern = $this-&gt;strong_pattern<span>;            </span>$condition="!value.match({$pattern})"<span>;       </span>return "<span> if(</span>".$condition."<span>) {     messages.push(</span>".CJSON::encode('your password is too weak, you fool!')."<span>); } </span>"<span>; </span>}</pre></div></div>  <p>As you can see this method simply returns the javascript that you need to use for your validation</p>  <h2>Last step: how to use your validation class inside the module rules </h2>  <p>There are several approach you can use here.</p>  <p>You could first use <a href="http://www.yiiframework.com/doc/api/1.1/YiiBase#import-detail">Yii::import</a> in the rules method before returning the rules array, or you can just use Yii dot notation:</p>  <div><div><pre>/*<span>*  *</span> @return <span>array validation rules for model attributes.  </span>*/ public function rules() {     return array(        array('password', 'ext.MyValidators.passwordStrength', 'strength'=&gt;self::STRONG)<span>,     </span>)<span>; </span>}</pre></div></div></div>more:<div>http://www.yiiframework.com/wiki/168/create-your-own-validation-rule/</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196679.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-12-26 15:39 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196679.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yii - How to use AJAX form validation</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196672.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 26 Dec 2012 04:45:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196672.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196672.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196672.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196672.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196672.html</trackback:ping><description><![CDATA[<div><h3> </h3> <div>  </div> <div entry-content"="" id="post-body-4570586111110913639" itemprop="description articleBody"> Yii supports AJAX form validation, which essentially posts the form  values to the server, validates them, and sends back the validation  errors, all without leaving the page. It does this every time you tab  out of a (changed) field. <br /> <br /> As of 1.1.7, Yii supports regular Javascript validation in addition to  AJAX validation, but I'll talk about that in another post.<br /> <br /> Here's how Yii's AJAX validation works:<br /> <br /> <ol><li>in your yii form declaration, put:<br /> <pre>&lt;php $form = $this-&gt;beginWidget('CActiveForm', array(</pre><pre>'id'=&gt;'lowercasemodelname-form', //not technically required but works w gii generated controllers</pre><pre>'enableAjaxValidation'=&gt;true //turn on ajax validation on the client side )); </pre>And have at least one form element with a matching error function:<br /> <pre>&lt;?php echo $form-&gt;textField($model, 'my_attribute'); ?&gt;</pre><pre>&lt;?php echo $form-&gt;error($model, 'my_attribute'); ?&gt; </pre>This makes Yii include the JQuery javascript library, as well as a Yii javascript file called jquery.yiiactiveform.js<br /> </li><li>In your controller, in create or update, after you load the model, but before you load it from POST, call this<br /> <pre>if(Yii::app()-&gt;getRequest()-&gt;getIsAjaxRequest()) {</pre><pre>echo CActiveForm::validate( array( $model));&nbsp;</pre><pre>Yii::app()-&gt;end();&nbsp;</pre><pre>} </pre>Which is sligtly different than how Gii generates it, but no big  diff. CActiveForm::validate() can take an array of models, which is not  clear the way Gii does it. <br /> </li><li>Also make sure that your model has at lease one validation rule for  the insert or update scenario. After you tab out of a changed field, Yii  sends a standard AJAX POST to the server, and gets back a JSON response  like this:<br /> <pre>{"Field_id":["Validation error a"],"Another_field_id":["Validation error B"]} </pre>which yii then plugs into the error field below your field.<br /> </li><li>When you use the $form-&gt;error() function, Yii adds a hidden div after your form element:<br /> <pre>&lt;div id="Model_attributename_em_" class="errorMessage" style="display:none"&gt;&lt;/div&gt;</pre>If  that field has a validation error, then Yii sets the display to block,  writes the validation error message to its innerHtml, and then you see  the error. If it later validates, yii hides it again. </li><li>Yii will also add class names to the parent container of the field  that it's validating. In most cases, this is a &lt;div class="row"&gt;.  When a form field is valid, it adds "success" class to the div - which  makes it green. When it's invalid, it adds "error" class, which makes it  red. It also quickly adds a "validating" class, which does nothing, but  you can supply it yourself and change the look of a field while it's  validating.</li></ol></div></div>转自:http://learnyii.blogspot.tw/2010/12/yii.html<img src ="http://www.cppblog.com/guojingjia2006/aggbug/196672.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-12-26 12:45 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/12/26/196672.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分布式基础学习【二】 —— 分布式计算系统（Map/Reduce）(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/12/19/196448.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 19 Dec 2012 11:18:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/12/19/196448.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196448.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/12/19/196448.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196448.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196448.html</trackback:ping><description><![CDATA[<div><div id="cnblogs_post_body"><h2>二. 分布式计算（Map/Reduce）<br /> </h2> <div>分布式式计算，同样是一个宽泛的概念，在这里，它狭义的指代，按Google Map/Reduce框架所设计的分布式框架。在Hadoop中，分布式文件系统，很大程度上，是为各种分布式计算需求所服务的。我们说分布式文件系统就是加了分布式的文件系统，类似的定义推广到分布式计算上，我们可以将其视为<strong>增加了分布式支持的计算函数</strong>。 从计算的角度上看，Map/Reduce框架接受各种格式的键值对文件作为输入，读取计算后，最终生成自定义格式的输出文件。而从分布式的角度上看，分布 式计算的输入文件往往规模巨大，且分布在多个机器上，单机计算完全不可支撑且效率低下，因此Map/Reduce框架需要提供一套机制，将此计算扩展到无 限规模的机器集群上进行。依照这样的定义，我们对整个Map/Reduce的理解，也可以分别沿着这两个流程去看。。。</div> <div>在Map/Reduce框架中，每一次计算请求，被称为<strong>作业</strong>。在分布式计算Map/Reduce框架中，为了完成这个作业，它进行两步走的战略，首先是将其拆分成若干个<strong>Map任务</strong>， 分配到不同的机器上去执行，每一个Map任务拿输入文件的一部分作为自己的输入，经过一些计算，生成某种格式的中间文件，这种格式，与最终所需的文件格式 完全一致，但是仅仅包含一部分数据。因此，等到所有Map任务完成后，它会进入下一个步骤，用以合并这些中间文件获得最后的输出文件。此时，系统会生成若 干个<strong>Reduce任务</strong>，同样也是分配到不同的机器去执行，它的目标，就是将若干个Map任务生成的中间文件为汇总到最后的输出文件中去。当然，这个汇总不总会像1 + 1 = 2那么直接了当，这也就是Reduce任务的价值所在。经过如上步骤，最终，作业完成，所需的目标文件生成。整个算法的关键，就在于增加了一个中间文件生成的流程，大大提高了灵活性，使其分布式扩展性得到了保证。。。</div> <h3>I. 术语对照<br /> </h3> <div>和分布式文件系统一样，Google、Hadoop和....我，各执一种方式表述统一概念，为了保证其统一性，特有下表。。。</div> <div><br /> </div> <div> <div> <table id="wc5x" border="1" cellpadding="3" cellspacing="0" width="100%">     <tbody><tr>         <td style="text-align: center; " width="25%"><strong>文中翻译</strong></td>         <td style="text-align: center; " width="25%"><strong>Hadoop术语</strong></td>         <td style="text-align: center; " width="25%"><strong>Google术语</strong></td>         <td style="text-align: center; " width="25%"><strong>相关解释</strong></td>     </tr>     <tr>         <td width="25%">作业</td>         <td width="25%">Job</td>         <td width="25%">Job</td>         <td width="25%">用户的每一个计算请求，就称为一个作业。</td>     </tr>     <tr>         <td width="25%">作业服务器</td>         <td width="25%">JobTracker</td>         <td width="25%">Master</td>         <td width="25%">用户提交作业的服务器，同时，它还负责各个作业任务的分配，管理所有的任务服务器。</td>     </tr>     <tr>         <td width="25%">任务服务器</td>         <td width="25%">TaskTracker</td>         <td width="25%">Worker</td>         <td width="25%">任劳任怨的工蜂，负责执行具体的任务。</td>     </tr>     <tr>         <td width="25%">任务</td>         <td width="25%">Task</td>         <td width="25%">Task</td>         <td width="25%">每一个作业，都需要拆分开了，交由多个服务器来完成，拆分出来的执行单位，就称为任务。</td>     </tr>     <tr>         <td width="25%">备份任务</td>         <td width="25%">Speculative Task</td>         <td width="25%">Buckup Task</td>         <td width="25%">每一个任务，都有可能执行失败或者缓慢，为了降低为此付出的代价，系统会未雨绸缪的实现在另外的任务服务器上执行同样一个任务，这就是备份任务。</td>     </tr> </tbody></table> </div> </div> <h3>II. 基本架构<br /> </h3> <div>与分布式文件系统类似，Map/Reduce的集群，也由三类服务器构成。其中<strong>作业服务器</strong>，在Hadoop中称为<strong>Job Tracker</strong>，在Google论文中称为<strong>Master</strong>。前者告诉我们，作业服务器是负责管理运行在此框架下所有作业的，后者告诉我们，它也是为各个作业分配任务的核心。与HDFS的主控服务器类似，它也是作为单点存在的，简化了负责的同步流程。具体的<strong>负责执行用户定义操作</strong>的，是<strong>任务服务器</strong>，每一个作业被拆分成很多的<strong>任务</strong>，包括<strong>Map任务</strong>和<strong>Reduce任务</strong>等，任务是具体执行的基本单元，它们都需要分配到合适任务服务器上去执行，任务服务器一边执行一边向作业服务器汇报各个任务的状态，以此来帮助作业服务器了解作业执行的整体情况，分配新的任务等等。。。</div> <div>除了作业的管理者执行者，还需要有一个<strong>任务的提交者</strong>，这就是客户端。与分布式文件系统一样，客户端也不是一个单独的进程，而是一组API，用户需要自定义好自己需要的内容，经由客户端相关的代码，将作业及其相关内容和配置，提交到作业服务器去，并时刻监控执行的状况。。。</div> <div>同作为Hadoop的实现，与HDFS的通信机制相同，Hadoop Map/Reduce也是用了协议接口来进行服务器间的交流。实现者作为RPC服务器，调用者经由RPC的代理进行调用，如此，完成大部分的通信，具体服 务器的架构，和其中运行的各个协议状况，参见下图。从图中可以看到，与HDFS相比，相关的协议少了几个，客户端与任务服务器，任务服务器之间，都不再有 直接通信关系。这并不意味着客户端就不需要了解具体任务的执行状况，也不意味着，任务服务器之间不需要了解别家任务执行的情形，只不过，由于整个集群各机 器的联系比HDFS复杂的多，直接通信过于的难以维系，所以，都统一由作业服务器整理转发。另外，从这幅图可以看到，任务服务器不是一个人在战斗，它会像 孙悟空一样招出一群宝宝帮助其具体执行任务。这样做的好处，个人觉得，应该有安全性方面的考虑，毕竟，任务的代码是用户提交的，数据也是用户指定的，这质 量自然良莠不齐，万一碰上个搞破坏的，把整个任务服务器进程搞死了，就因小失大了。因此，放在单独的地盘进行，爱咋咋地，也算是权责明确了。。。</div> <div> <div style="padding-right: 0px; padding-left: 0px; padding-bottom: 1em; padding-top: 1em;" id="bzsx"><img style="width: 599px; height: 507px" src="http://docs.google.com/File?id=ddwgxw9r_805f72bj3gj_b" alt="" /></div> </div> <div>与分布式文件系统相比，Map/Reduce框架的还有一个特点，就是<strong>可定制性强</strong>。文件系统中很多的算法， 都是很固定和直观的，不会由于所存储的内容不同而有太多的变化。而作为通用的计算框架，需要面对的问题则要复杂很多，在各种不同的问题、不同的输入、不同 的需求之间，很难有一种包治百病的药能够一招鲜吃遍天。作为Map/Reduce框架而言，一方面要尽可能的抽取出公共的一些需求，实现出来。更重要的， 是需要提供良好的可扩展机制，满足用户自定义各种算法的需求。Hadoop是由Java来实现的，因此通过反射来实现自定义的扩展，显得比较小菜一碟了。 在<strong>JobConf</strong>类中，定义了大量的接口，这基本上是Hadoop Map/Reduce框架所有可定制内容的一次集中展示。在JobConf中，有大量set接口接受一个<strong>Class&lt;? extends xxx&gt;</strong>的参数，通常它都有一个默认实现的类，用户如果不满意，则可自定义实现。。。</div> <h3>III. 计算流程<br /> </h3> <div>如果一切都按部就班的进行，那么整个作业的计算流程，应该是作业的提交 -&gt; Map任务的分配和执行 -&gt; Reduce任务的分配和执行 -&gt; 作业的完成。而在每个任务的执行中，又包含输入的准备 -&gt; 算法的执行 -&gt; 输出的生成，三个子步骤。沿着这个流程，我们可以很快的整理清晰整个Map/Reduce框架下作业的执行。。。</div> <h4>1、作业的提交<br /> </h4> <div>一个作业，在提交之前，需要把所有应该配置的东西都配置好，因为一旦提交到了作业服务器上，就陷入了完全自动化的流程，用户除了观望，最多也就能起一个监督作用，惩治一些不好好工作的任务。。。</div> <div>基本上，用户在提交代码阶段，需要做的工作主要是这样的：</div> <div>首先，书写好所有自定的代码，最起码，需要有Map和Reduce的执行代码。在Hadoop中，Map需要派生自<strong>Mapper&lt;K1, V1, K2, V2&gt;</strong>接口，Reduce需要派生自<strong>Reducer&lt;K2, V2, K3, V3&gt;</strong>接口。这里都是用的泛型，用以支持不同的键值类型。这两个接口都仅有一个方法，一个是map，一个是reduce，这两个方法都直接受四个参数，前两个是输入的<strong>键</strong>和<strong>值</strong>相关的数据结构，第三个是作为<strong>输出</strong>相关的数据结构，最后一个，是一个<strong>Reporter</strong>类的实例，实现的时候可以利用它来统计一些计数。除了这两个接口，还有大量可以派生的接口，比如分割的<strong>Partitioner&lt;K2, V2&gt;</strong>接口。。。</div> <div>然后，需要书写好主函数的代码，其中最主要的内容就是实例化一个<strong>JobConf</strong>类的对象，然后调用其丰富的setXXX接口，设定好所需的内容，包括输入输出的文件路径，Map和Reduce的类，甚至包括读取写入文件所需的格式支持类，等等。。。</div> <div>最后，调用<strong>JobClient</strong>的<strong>runJob</strong>方法，提交此JobConf对象。runJob方法会先行调用到<strong>JobSubmissionProtocol</strong>接口所定义的<strong>submitJob</strong>方法，将此作业，提交给作业服务器。接着，runJob开始循环，不停的调用JobSubmissionProtocol的<strong>getTaskCompletionEvents</strong>方法，获得<strong>TaskCompletionEvent</strong>类的对象实例，了解此作业各任务的执行状况。。。</div> <h4>2、Map任务的分配</h4> <div>当一个作业提交到了作业服务器上，作业服务器会生成若干个Map任务，每一个Map任务，负责将一部分的输入转换成格式与最终格式相同的中间文件。通常一个<strong>作业的输入都是基于分布式文件系统的文件</strong>（当然在单机环境下，文件系统单机的也可以...），因为，它可以很天然的和分布式的计算产生联系。而对于一个Map任务而言，它的输入往往是输入文件的一个数据块，或者是数据块的一部分，但通常，<strong>不跨数据块</strong>。因为，一旦跨了数据块，就可能涉及到多个服务器，带来了不必要的复杂性。。。</div> <div>当一个作业，从客户端提交到了作业服务器上，作业服务器会生成一个<strong>JobInProgress</strong>对象，作为与 之对应的标识，用于管理。作业被拆分成若干个Map任务后，会预先挂在作业服务器上的任务服务器拓扑树。这是依照分布式文件数据块的位置来划分的，比如一 个Map任务需要用某个数据块，这个数据块有三份备份，那么，在这三台服务器上都会挂上此任务，可以视为是一个预分配。。。</div> <div>关于任务管理和分配的大部分的真实功能和逻辑的实现，JobInProgress则依托<strong>JobInProgressListener</strong>和<strong>TaskScheduler</strong>的子类。TaskScheduler，顾名思义是用于任务分配的策略类（为了简化描述，用它代指所有TaskScheduler的子类...）。它会掌握好所有作业的任务信息，其<strong>assignTasks</strong>函数，接受一个<strong>TaskTrackerStatus</strong>作为参数，依照此任务服务器的状态和现有的任务状况，为其分配新的任务。而为了掌握所有作业相关任务的状况，TaskScheduler会将若干个JobInProgressListener注册到<strong>JobTracker</strong>中去，当有新的作业到达、移除或更新的时候，JobTracker会告知给所有的JobInProgressListener，以便它们做出相应的处理。。。</div> <div>任务分配是一个重要的环节，所谓任务分配，就是<strong>将合适作业的合适任务分配到合适的服务器上</strong>。不难看出，里面 蕴含了两个步骤，先是选择作业，然后是在此作业中选择任务。和所有分配工作一样，任务分配也是一个复杂的活。不良好的任务分配，可能会导致网络流量增加、 某些任务服务器负载过重效率下降，等等。不仅如此，任务分配还是一个无一致模式的问题，不同的业务背景，可能需要不同的算法才能满足需求。因此，在 Hadoop中，有很多TaskScheduler的子类，像Facebook，Yahoo，都为其贡献出了自家用的算法。在Hadoop中，默认的任务 分配器，是<strong>JobQueueTaskScheduler</strong>类。它选择作业的基本次序是：Map Clean Up Task（Map任务服务器的清理任务，用于清理相关的过期的文件和环境...） -&gt; Map Setup Task（Map任务服务器的安装任务，负责配置好相关的环境...） -&gt; Map Tasks -&gt; Reduce Clean Up Task -&gt; Reduce Setup Task -&gt; Reduce Tasks。在这个前提下，具体到Map任务的分配上来。当一个任务服务器工作的游刃有余，期待获得新的任务的时候，JobQueueTaskScheduler会按照各个作业的优先级，从<strong>最高优先级的作业</strong>开 始分配。每分配一个，还会为其留出余量，已被不时之需。举一个例子：系统目前有优先级3、2、1的三个作业，每个作业都有一个可分配的Map任务，一个任 务服务器来申请新的任务，它还有能力承载3个任务的执行，JobQueueTaskScheduler会先从优先级3的作业上取一个任务分配给它，然后再 留出一个1任务的余量。此时，系统只能在将优先级2作业的任务分配给此服务器，而不能分配优先级1的任务。这样的策略，基本思路就是<strong>一切为高优先级的作业服务</strong>，优先分配不说，分配了好保留有余力以备不时之需，如此优待，足以让高优先级的作业喜极而泣，让低优先级的作业感慨既生瑜何生亮，甚至是活活饿死。。。</div> <div>确定了从哪个作业提取任务后，具体的分配算法，经过一系列的调用，最后实际是由<strong>JobInProgress</strong>的<strong>findNewMapTask</strong>函数完成的。它的算法很简单，就是<strong>尽全力为此服务器非配且尽可能好的分配任务</strong>， 也就是说，只要还有可分配的任务，就一定会分给它，而不考虑后来者。作业服务器会从离它最近的服务器开始，看上面是否还挂着未分配的任务（预分配上的）， 从近到远，如果所有的任务都分配了，那么看有没有开启多次执行，如果开启，考虑把未完成的任务再分配一次（后面有地方详述...）。。。</div> <div>对于作业服务器来说，把一个任务分配出去了，并不意味着它就彻底解放，可以对此任务可以不管不顾了。因为任务可以在任务服务器上执行失败，可能执行缓慢，这都需要作业服务器帮助它们再来一次。因此在Task中，记录有一个<strong>TaskAttemptID</strong>，对于任务服务器而言，它们每次跑的，其实都只是一个Attempt而已，Reduce任务只需要采信一个的输出，其他都算白忙乎了。。。</div> <h4>3、Map任务的执行</h4> <div>与HDFS类似，任务服务器是通过心跳消息，向作业服务器汇报此时此刻其上各个任务执行的状况，并向作业服务器申请新的任务的。具体实现，是<strong>TaskTracker</strong>调用<strong>InterTrackerProtocol</strong>协议的<strong>heartbeat</strong>方法来做的。这个方法接受一个<strong>TaskTrackerStatus</strong>对象作为参数，它描述了此时此任务服务器的状态。当其有余力接受新的任务的时候，它还会传入<strong>acceptNewTasks</strong>为true的参数，表示希望作业服务器委以重任。<strong>JobTracker</strong>接收到相关的参数后，经过处理，会返回一个<strong>HeartbeatResponse</strong>对象。这个对象中，定义了一组TaskTrackerAction，用于指导任务服务器进行下一步的工作。系统中已定义的了一堆其TaskTrackerAction的子类，有的对携带的参数进行了扩充，有的只是标明了下ID，具体不详写了，一看便知。。。</div> <div>当TaskTracker收到的TaskTrackerAction中，包含了<strong>LaunchTaskAction</strong>，它会开始执行所分配的新的任务。在TaskTracker中，有一个<strong>TaskTracker.TaskLauncher</strong>线程（确切的说是两个，一个等Map任务，一个等Reduce任务），它们在痴痴的守候着新任务的来到。一旦等到了，会最终调用到Task的<strong>createRunner</strong>方法，构造出一个<strong>TaskRunner</strong>对象，新建一个线程来执行。对于一个Map任务，它对应的Runner是TaskRunner的子类<strong>MapTaskRunner</strong>， 不过，核心部分都在TaskRunner的实现内。TaskRunner会先将所需的文件全部下载并拆包好，并记录到一个全局缓存中，这是一个全局的目 录，可以供所有此作业的所有任务使用。它会用一些软链接，将一些文件名链接到这个缓存中来。然后，根据不同的参数，配置出一个JVM执行的环境，这个环境 与<strong>JvmEnv</strong>类的对象对应。</div> <div style="margin-top: 0px; margin-bottom: 0px">接着，TaskRunner会调用<strong>JvmManager</strong>的<strong>launchJvm</strong>方 法，提交给JvmManager处理。JvmManager用于管理该TaskTracker上所有运行的Task子进程。在目前的实现中，尝试的是池化 的方式。有若干个固定的槽，如果槽没有满，那么就启动新的子进程，否则，就寻找idle的进程，如果是同Job的直接放进去，否则杀死这个进程，用一个新 的进程代替。每一个进程都是由JvmRunner来管理的，它也是位于单独线程中的。但是从实现上看，这个机制好像没有部署开，子进程是死循环等待，而不 会阻塞在父进程的相关线程上，父线程的变量一直都没有个调整，一旦分配，始终都处在繁忙的状况了。</div> <div style="margin-top: 0px; margin-bottom: 0px">真实的执行载体，是Child，它包含一个 main函数，进程执行，会将相关参数传进来，它会拆解这些参数，并且构造出相关的Task实例，调用其run函数进行执行。每一个子进程，可以执行指定 个数量的Task，这就是上面所说的池化的配置。但是，这套机制在我看来，并没有运行起来，每个进程其实都没有机会不死而执行新的任务，只是傻傻的等待进 程池满，而被一刀毙命。也许是我老眼昏花，没看出其中实现的端倪。。。</div> <h4>4、Reduce任务的分配与执行</h4> <div>比之Map任务，Reduce的分配及其简单，基本上是所有Map任务完成了，有空闲的任务服务器，来了就给分配一个Job任务。因为Map任 务的结果星罗棋布，且变化多端，真要搞一个全局优化的算法，绝对是得不偿失。而Reduce任务的执行进程的构造和分配流程，与Map基本完全的一致，没 有啥可说的了。。。</div> <div>但其实，Reduce任务与Map任务的最大不同，是Map任务的文件都在本地隔着，而Reduce任务需要到处采集。这个流程是作业服务器经 由此Reduce任务所处的任务服务器，告诉Reduce任务正在执行的进程，它需要的Map任务执行过的服务器地址，此Reduce任务服务器会于原 Map任务服务器联系（当然本地就免了...），通过FTP服务，下载过来。这个隐含的直接数据联系，就是执行Reduce任务与执行Map任务最大的不 同了。。。</div> <h4>5、作业的完成</h4> <div>当所有Reduce任务都完成了，所需数据都写到了分布式文件系统上，整个作业才正式完成了。此中，涉及到很多的类，很多的文件，很多的服务器，所以说起来很费劲，话说，一图解千语，说了那么多，我还是画两幅图，彻底表达一下吧。。。</div> <div>首先，是一个时序图。它模拟了一个由3个Map任务和1个Reduce任务构成的作业执行流程。我们可以看到，在执行的过程中，只要有人太慢， 或者失败，就会增加一次尝试，以此换取最快的执行总时间。一旦所有Map任务完成，Reduce开始运作（其实，不一定要这样的...），对于每一个 Map任务来说，只有执行到Reduce任务把它上面的数据下载完成，才算成功，否则，都是失败，需要重新进行尝试。。。</div> <div> <div style="padding-right: 0px; padding-left: 0px; padding-bottom: 1em; padding-top: 1em;" id="e3.3"> <div style="padding-right: 1em; padding-left: 1em; padding-bottom: 1em; padding-top: 1em;" id="r.iq"><img style="width: 988px; height: 347px" src="http://docs.google.com/File?id=ddwgxw9r_809gzj5zpdt_b" alt="" /></div> </div> </div> <div>而第二副图，不是我画的，就不转载了，参见<a id="i15g" title="这里" href="http://www.cppblog.com/javenstudio/articles/43073.html">这里</a>， 它描述了整个Map/Reduce的服务器状况图，包括整体流程、所处服务器进程、输入输出等，看清楚这幅图，对Map/Reduce的基本流程应该能完 全跑通了。有这几点，可能图中描述的不够清晰需要提及一下，一个是在HDFS中，其实还有日志文件，图中没有标明；另一个是步骤5，其实是由 TaskTracker主动去拉取而不是JobTracker推送过来的；还有步骤8和步骤11，创建出来的MapTask和ReduceTask，在 Hadoop中都是运行在独立的进程上的。。。</div> <h3>IV. Map任务详请</h3> <div>从上面，可以了解到整个Map和Reduce任务的整体流程，而后面要啰嗦的，是具体执行中的细节。Map任务的输入，是分布式文件系统上的， 包含键值对信息的文件。为了给每一个Map任务指定输入，我们需要掌握文件格式把它分切成块，并从每一块中分离出键值信息。在HDFS中，输入的文件格 式，是由<strong>InputFormat&lt;K, V&gt;</strong>类来表示的，在JobConf中，它的默认值是<strong>TextInputFormat</strong>类（见<strong>getInputFormat</strong>），此类是特化的<strong>FileInputFormat&lt;LongWritable, Text&gt;</strong>子类，而<strong>FileInputFormat&lt;K, V&gt;</strong>正是InputFormat&lt;K, V&gt;的子类。通过这样的关系我们可以很容易的理解，默认的文件格式是<strong>文本文件</strong>，且键是<strong>LongWritable</strong>类型（整形数），值是<strong>Text</strong>类型（字符串）。仅仅知道文件类型是不够的，我们还需要将文件中的每一条数据，分离成键值对，这个工作，是<strong>RecordReader&lt;K, V&gt;</strong>来做的。在TextInputFormat的<strong>getRecordReader</strong>方法中我们可以看到，与TextInputFormat默认配套使用的，是<strong>LineRecordReader</strong>类，是特化的<strong>RecordReader&lt;LongWritable, Text&gt;</strong>的子类，它将每<strong>一行作为一个记录，起始的位置作为键，整行的字符串作为值</strong>。有了格式，分出了键值，还需要切开分给每一个Map任务。每一个Map任务的输入用<strong>InputSplit</strong>接口表示，对于一个文件输入而言，其实现是<strong>FileSplit</strong>，它包含着<strong>文件名、起始位置、长度和存储它的一组服务器地址</strong>。。。</div> <div>当Map任务拿到所属的InputSplit后，就开始一条条读取记录，并调用用于定义的Mapper，进行计算（参见MapRunner&lt;K1, V1, K2, V2&gt;和MapTask的run方法），然后，输出。MapTask会传递给Mapper一个OutputCollector&lt;K, V&gt;对象，作为输出的数据结构。它定义了一个collect的函数，接受一个键值对。在MapTask中，定义了两个OutputCollector的子类，一个是MapTask.DirectMapOutputCollector&lt;K, V&gt;，人如其名，它的实现确实很Direct，直截了当。它会利用一个RecordWriter&lt;K, V&gt;对象，collect一调用，就直接调用RecordWriter&lt;K, V&gt;的write方法，写入本地的文件中去。如果觉着RecordWriter&lt;K, V&gt;出现的很突兀，那么看看上一段提到的RecordReader&lt;K, V&gt;，基本上，数据结构都是对应着的，一个是输入一个是输出。输出很对称也是由RecordWriter&lt;K, V&gt;和OutputFormat&lt;K, V&gt;来协同完成的，其默认实现是LineRecordWriter&lt;K, V&gt;和TextOutputFormat&lt;K, V&gt;，多么的眼熟啊。。。</div> <div>除了这个非常直接的实现之外，MapTask中还有一个复杂的多的实现，是MapTask.MapOutputBuffer&lt;K  extends Object, V extends Object&gt;。有道是简单压倒一切，那为什么有很简单的实现，要琢磨一个复杂的呢。原因在于，看上去很美的往往带着刺，简单的输出实现，每调用一 次collect就写一次文件，频繁的硬盘操作很有可能导致此方案的低效。为了解决这个问题，这就有了这个复杂版本，它先开好一段内存做<strong>缓存</strong>，然后制定一个比例做<strong>阈值</strong>，<strong>开一个线程监控</strong>此缓存。collect来的内容，先写到缓存中，当监控线程发现缓存的内容比例超过阈值，挂起所有写入操作，建一个<strong>新的文件</strong>，把缓存的内容批量<strong>刷到此文件中</strong>去，清空缓存，重新开放，接受继续collect。。。</div> <div>为什么说是刷到文件中去呢。因为这不是一个简单的照本宣科简单复制的过程，在写入之前，会先将缓存中的内存，经过排序、合并器 （Combiner）统计之后，才会写入。如果你觉得Combiner这个名词听着太陌生，那么考虑一下Reducer，Combiner也就是一个 Reducer类，通过JobConf的setCombinerClass进行设置，在常用的配置中，Combiner往往就是用用户为Reduce任务 定义的那个Reducer子类。只不过，Combiner只是服务的范围更小一些而已，它在Map任务执行的服务器本地，依照Map处理过的那一小部分数 据，先做一次Reduce操作，这样，可以压缩需要传输内容的大小，提高速度。每一次刷缓存，都会开一个新的文件，等此任务所有的输入都处理完成后，就有 了若干个有序的、经过合并的输出文件。系统会将这些文件搞在一起，再做一个多路的归并外排，同时使用合并器进行合并，最终，得到了唯一的、有序的、经过合 并的中间文件（注：文件数量等同于分类数量，在不考虑分类的时候，简单的视为一个...）。它，就是Reduce任务梦寐以求的输入文件。。。</div> <div>除了做合并，复杂版本的OutputCollector，还具有<strong>分类</strong>的功能。分类，是通过<strong>Partitioner&lt;K2, V2&gt;</strong>来定义的，默认实现是<strong>HashPartitioner&lt;K2, V2&gt;，</strong>作业提交者可以通过JobConf的<strong>setPartitionerClass</strong>来自定义。分类的含义是什么呢，简单的说，就是将Map任务的输出，划分到若干个文件中（通常与Reduce任务数目相等），使得每一个Reduce任务，可以处理某一类文件。这样的好处是大大的，举一个例子说明一下。比如有一个作业是进行<strong>单词统计</strong>的，其Map任务的中间结果应该是<strong>以单词为键，以单词数量为值的文件</strong>。如果这时候只有一个Reduce任务，那还好说，从<strong>全部的Map任务</strong>那里收集文件过来，分别统计得到最后的输出文件就好。但是，如果单Reduce任务无法承载此负载或效率太低，就需要多个Reduce任务并行执行。此时，再沿用之前的模式就有了问题。每个Reduce任务从<strong>一部分Map任务</strong>那 里获得输入文件，但最终的输出结果并不正确，因为同一个单词可能在不同的Reduce任务那里都有统计，需要想方法把它们统计在一起才能获得最后结果，这 样就没有将Map/Reduce的作用完全发挥出来。这时候，就需要用到分类。如果此时有两个Reduce任务，那么将输出分成两类，一类存放字母表排序 较高的单词，一类存放字母表排序低的单词，每一个Reduce任务从<strong>所有的Map任务</strong>那里获取一类的中间文件，得到自己的输出结果。最终的结果，只需要把各个Reduce任务输出的，拼接在一起就可以了。本质上，这就是将Reduce任务的输入，<strong>由垂直分割，变成了水平分割</strong>。Partitioner的作用，正是接受一个键值，返回一个分类的序号。它会在从缓存刷到文件之前做这个工作，其实只是多了一个文件名的选择而已，别的逻辑都不需要变化。。。</div> <div>除了缓存、合并、分类等附加工作之外，复杂版本的OutputCollector还支持错误数据的跳过功能，在后面分布式将排错的时候，还会提及，标记一下，按下不表。。。</div> <h3>V. Reduce任务详情</h3> <div>理论上看，Reduce任务的整个执行流程要比Map任务更为的罗嗦一些，因为，它需要收集输入文件，然后才能进行处理。Reduce任务，主要有这么三个步骤：<strong>Copy</strong>、<strong>Sort</strong>、<strong>Reduce</strong>（参见ReduceTask的run方法）。所谓Copy，就是从执行各个Map任务的服务器那里，收罗到本地来。拷贝的任务，是由<strong>ReduceTask.ReduceCopier</strong>类来负责，它有一个内嵌类，叫<strong>MapOutputCopier</strong>， 它会在一个单独的线程内，负责某个Map任务服务器上文件的拷贝工作。远程拷贝过来的内容（当然也可以是本地了...），作为MapOutput对象存 在，它可以在内存中也可以序列化在磁盘上，这个根据内存使用状况来自动调节。整个拷贝过程是一个动态的过程，也就是说它不是一次给好所有输入信息就不再变 化了。它会不停的调用<strong>TaskUmbilicalProtocol</strong>协议的<strong>getMapCompletionEvents</strong>方 法，向其父TaskTracker询问此作业个Map任务的完成状况（TaskTracker要向JobTracker询问后再转告给它...）。当获取 到相关Map任务执行服务器的信息后，都会有一个线程开启，做具体的拷贝工作。同时，还有一个内存Merger线程和一个文件Merger线程在同步工 作，它们将新鲜下载过来的文件（可能在内存中，简单的统称为文件...），做着归并排序，以此，节约时间，降低输入文件的数量，为后续的排序工作减 负。。。</div> <div>Sort，排序工作，就相当于上述排序工作的一个延续。它会在所有的文件都拷贝完毕后进行，因为虽然同步有做着归并的工作，但可能留着尾巴，没 做彻底。经过这一个流程，该彻底的都彻底了，一个崭新的、合并了所有所需Map任务输出文件的新文件，诞生了。而那些千行万苦从其他各个服务器网罗过来的 Map任务输出文件，很快的结束了它们的历史使命，被扫地出门一扫而光，全部删除了。。。<br /> 所谓好戏在后头，Reduce任务的最后一个阶段，正是Reduce本身。它也会准备一个<strong>OutputCollector</strong>收集输出，与MapTask不同，这个OutputCollector更为简单，仅仅是打开一个<strong>RecordWriter</strong>，collect一次，write一次。最大的不同在于，这次传入RecordWriter的文件系统，基本都是<strong>分布式文件系统</strong>， 或者说是HDFS。而在输入方面，ReduceTask会从JobConf那里调用一堆getMapOutputKeyClass、 getMapOutputValueClass、getOutputKeyComparator等等之类的自定义类，构造出Reducer所需的键类型， 和值的迭代类型Iterator（一个键到了这里一般是对应一组值）。具体实现颇为拐弯抹角，建议看一下<strong>Merger.MergeQueue</strong>，<strong>RawKeyValueIterator</strong>，<strong>ReduceTask.ReduceValuesIterator</strong>等等之类的实现。有了输入，有了输出，不断循环调用自定义的Reducer，最终，Reduce阶段完成。。。</div> <h3>VI. 分布式支持</h3> <h4>1、服务器正确性保证</h4> <div>Hadoop Map/Reduce服务器状况和HDFS很类似，由此可知，救死扶伤的方法也是大同小异。废话不多说了，直接切正题。同作为客户端，Map /Reduce的客户端只是将作业提交，就开始搬个板凳看戏，没有占茅坑的行动。因此，一旦它挂了，也就挂了，不伤大雅。而任务服务器，也需要随时与作业 服务器保持心跳联系，一旦有了问题，作业服务器可以将其上运行的任务，移交给它人完成。作业服务器，作为一个单点，非常类似的是利用还原点（等同于 HDFS的镜像）和历史记录（等同于HDFS的日志），来进行恢复。其上，需要持久化用于恢复的内容，包含作业状况、任务状况、各个任务尝试的工作状况 等。有了这些内容，再加上任务服务器的动态注册，就算挪了个窝，还是很容易恢复的。<strong>JobHistory</strong>是历史记录相 关的一个静态类，本来，它也就是一个干写日志活的，只是在Hadoop的实现中，对日志的写入做了面向对象的封装，同时又大量用到观察者模式做了些嵌入， 使得看起来不是那么直观。本质上，它就是打开若干个日志文件，利用各类接口来往里面写内容。只不过，这些日志，会放在分布式文件系统中，就不需要像 HDFS那样，来一个SecondXXX随时候命，由此可见，有巨人在脚下踩着，真好。JobTracker.RecoveryManager类是作业服 务器中用于进行恢复相关的事情，当作业服务器启动的时候，会调用其recover方法，恢复日志文件中的内容。其中步骤，注释中写的很清楚，请自行查 看。。。</div> <h4>2、任务执行的正确和速度</h4> <div>整个作业流程的执行，秉承着木桶原理。执行的最慢的Map任务和Reduce任务，决定了系统整体执行时间（当然，如果执行时间在整个流程中占 比例很小的话，也许就微不足道了...）。因此，尽量加快最慢的任务执行速度，成为提高整体速度关键。所使用的策略，简约而不简单，就是<strong>一个任务多次执行</strong>。 当所有未执行的任务都分配出去了，并且先富起来的那部分任务已经完成了，并还有任务服务器孜孜不倦的索取任务的时候，作业服务器会开始炒剩饭，把那些正在 吭哧吭哧在某个服务器上慢慢执行的任务，再把此任务分配到一个新的任务服务器上，同时执行。两个服务器各尽其力，成王败寇，先结束者的结果将被采纳。这样 的策略，隐含着一个假设，就是我们相信，输入文件的分割算法是公平的，某个任务执行慢，并不是由于这个任务本身负担太重，而是由于服务器不争气负担太重能 力有限或者是即将撒手西去，给它换个新环境，人挪死树挪活事半功倍。。。</div> 当然，肯定有哽咽的任务，不论是在哪个服务器上，都无法顺利完成。这就说明，此问题不在于服务器上，而是任务本身天资有缺憾。缺憾在何处？每个作业，功能 代码都是一样的，别的任务成功了，就是这个任务不成功，很显然，问题出在输入那里。输入中有非法的输入条目，导致程序无法辨识，只能挥泪惜别。说到这里， 解决策略也浮出水面了，三十六计走位上，惹不起，还是躲得起的。在MapTask中的 MapTask.SkippingRecordReader&lt;K, V&gt;和ReduceTask里的 ReduceTask.SkippingReduceValuesIterator&lt;KEY,VALUE&gt;，都是用于干这个事情的。它们的原 理很简单，就是在读一条记录前，把当前的位置信息，封装成SortedRanges.Range对象，经由Task的 reportNextRecordRange方法提交到TaskTracker上去。TaskTracker会把这些内容，搁在TaskStatus对象 中，随着心跳消息，汇报到JobTracker上面。这样，作业服务器就可以随时随刻了解清楚，每个任务正读取在那个位置，一旦出错，再次执行的时候，就 在分配的任务信息里面添加一组SortedRanges信息。MapTask或ReduceTask读取的时候，会看一下这些区域，如果当前区域正好处于 上述雷区，跳过不读。如此反复，正可谓，道路曲折，前途光明啊。。。 <h3>VII. 总结</h3> <div>对于Map/Reduce而言，真正的困难，在于提高其适应能力，打造一款能够包治百病的执行框架。Hadoop已经做得很好了，但只有真正搞清楚了整个流程，你才能帮助它做的更好。。。</div></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196448.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-12-19 19:18 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/12/19/196448.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用Yii进行PHP的命令行程序（Console command）开发</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/12/12/196195.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 12 Dec 2012 06:41:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/12/12/196195.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196195.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/12/12/196195.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196195.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196195.html</trackback:ping><description><![CDATA[more: <div>http://www.yiiframework.com/doc/guide/1.1/zh_cn/topics.console</div><br /><div><a href="http://dao.daimaku.com/post/view/id/177">PHP提供的cli模式</a>可以进行一些简单的shell程序开发，<a href="http://dao.daimaku.com/post/show/tag/Yii">Yii框架</a>也提供了cli程序开发的解决方案。 <p>在Yii项目的protected目录下，存在yiic和yii.bat两个文件，它们分别是类unix系统和windows系统下执行Yii项目的命令行程序的入口，例如：</p>  		<div id="crayon-4f83382caa1c3" crayon-theme-classic="" crayon-font-monaco="" crayon-os-pc=""  print-yes"="" data-settings=" scroll-mouseover" style=" max-width: 620px; margin-top: 12px; margin-bottom: 12px; float: none; clear: both; "> 		 			 			 			<div><textarea wrap="off"  print-no"="" data-settings="dblclick" readonly="readonly" style="-moz-tab-size: 4; z-index: 0; opacity: 0; overflow: hidden; height: 15px;">$ yiic command action --param=value</textarea></div> 			<div style="max-width: 620px; position: relative; z-index: 1; overflow: hidden;"> 				<table> 					<tbody><tr> 				<td "="" data-settings="show"> 					<div><div>1</div></div> 				</td> 						<td><div><div id="crayon-4f83382caa1c3-1">$ yiic command action --param=value</div></div></td> 					</tr> 				</tbody></table> 			</div> 		</div>  <p>或者</p>  		<div id="crayon-4f83382caa5ad" crayon-theme-classic="" crayon-font-monaco="" crayon-os-pc=""  print-yes"="" data-settings=" scroll-mouseover" style=" max-width: 620px; margin-top: 12px; margin-bottom: 12px; float: none; clear: both; "> 		 			 			 			<div><textarea wrap="off"  print-no"="" data-settings="dblclick" readonly="readonly" style="-moz-tab-size: 4; z-index: 0; opacity: 0; overflow: hidden; height: 15px;">&nbsp;$ php yiic sitemap test --type=value</textarea></div> 			<div style="max-width: 620px; position: relative; z-index: 1; overflow: hidden;"> 				<table> 					<tbody><tr> 				<td "="" data-settings="show"> 					<div><div>1</div></div> 				</td> 						<td><div><div id="crayon-4f83382caa5ad-1">&nbsp;$ php yiic sitemap test --type=value</div></div></td> 					</tr> 				</tbody></table> 			</div> 		</div>   <p>具体使用哪种写法，取决于入口程序是否有执行权限，例如，在linux系统下，如果执行命令：</p>  		<div id="crayon-4f83382caa9c9" crayon-theme-classic="" crayon-font-monaco="" crayon-os-pc=""  print-yes"="" data-settings=" scroll-mouseover" style=" max-width: 620px; margin-top: 12px; margin-bottom: 12px; float: none; clear: both; "> 		 			 			 			<div><textarea wrap="off"  print-no"="" data-settings="dblclick" readonly="readonly" style="-moz-tab-size: 4; z-index: 0; opacity: 0; overflow: hidden; height: 15px;">chmod&nbsp;+x&nbsp;yiic</textarea></div> 			<div style="max-width: 620px; position: relative; z-index: 1; overflow: hidden;"> 				<table> 					<tbody><tr> 				<td "="" data-settings="show"> 					<div><div>1</div></div> 				</td> 						<td><div><div id="crayon-4f83382caa9c9-1">chmod&nbsp;+x&nbsp;yiic</div></div></td> 					</tr> 				</tbody></table> 			</div> 		</div>  <p>给予了yiic执行权限，就可以用第一种方式来执行php命令行程序，否则需要使用第二种方式。</p> <p>执行Yii的命令行程序的命令有四部分组成:<br />命令行入口程序yiic<br />要执行的命令名称，类似Yii框架web程序的controller<br />要执行的动作名称，类似Yii框架web程序controller的action<br />提供给程序的外部参数，以两个短横线&#8220;&#8211;&#8221;开头，参数没有顺序</p> <p>要建立一个命令行程序，需要继承一个CConsoleCommand的子类：</p>  		<div id="crayon-4f83382caadd1" crayon-theme-classic="" crayon-font-monaco="" crayon-os-pc=""  print-yes"="" data-settings=" scroll-mouseover" style=" max-width: 620px; margin-top: 12px; margin-bottom: 12px; float: none; clear: both; "> 		 			 			 			<div><textarea wrap="off"  print-no"="" data-settings="dblclick" readonly="readonly" style="-moz-tab-size: 4; z-index: 0; opacity: 0; overflow: hidden; height: 105px;">class&nbsp;SitemapCommand&nbsp;extends&nbsp;CConsoleCommand  {  &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;actionTest($type, $limit=5) { ... }  }</textarea></div> 			<div style="max-width: 620px; position: relative; z-index: 1; overflow: hidden;"> 				<table> 					<tbody><tr> 				<td "="" data-settings="show"> 					<br /> 				</td> 						<td><div><div id="crayon-4f83382caadd1-1">class&nbsp;SitemapCommand&nbsp;extends&nbsp;CConsoleCommand</div><div id="crayon-4f83382caadd1-3">{</div><div id="crayon-4f83382caadd1-5">&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;function&nbsp;actionTest($type, $limit=5) { ... }</div><div id="crayon-4f83382caadd1-7">}</div></div></td> 					</tr> 				</tbody></table> 			</div> 		</div>  <p>保存到protected/commands/SitemapCommand.php文件。</p> <p>在命令行下执行：</p>  		<div id="crayon-4f83382cab1ac" crayon-theme-classic="" crayon-font-monaco="" crayon-os-pc=""  print-yes"="" data-settings=" scroll-mouseover" style=" max-width: 620px; margin-top: 12px; margin-bottom: 12px; float: none; clear: both; "> 		 			 			 			<div><textarea wrap="off"  print-no"="" data-settings="dblclick" readonly="readonly" style="-moz-tab-size: 4; z-index: 0; opacity: 0; overflow: hidden; height: 15px;">$ php yiic sitemap test --type=value</textarea></div> 			<div style="max-width: 620px; position: relative; z-index: 1; overflow: hidden;"> 				<table> 					<tbody><tr> 				<td "="" data-settings="show"> 					<div><div>1</div></div> 				</td> 						<td><div><div id="crayon-4f83382cab1ac-1">$ php yiic sitemap test --type=value</div></div></td> 					</tr> 				</tbody></table> 			</div> 		</div>   <p>SitemapCommand类的&nbsp;actionTest&nbsp;方法就会被执行，并获得值为value的$type参数。</p> <p>可以在protected/config/console.php文件中进行命令行模式下相关参数的配置，例如数据库连接信息等，配置方法和Yii的web模式一样。</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-12-12 14:41 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/12/12/196195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux tomcat安装</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/11/13/195106.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 13 Nov 2012 03:09:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/11/13/195106.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/195106.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/11/13/195106.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/195106.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/195106.html</trackback:ping><description><![CDATA[1) 下载jdk,解压(1.7)<br />2) 下载tomcat,解压 (version 7)<br />3) 修改tomcat bin目录下setclasspath.sh,<div>增加 export JRE_HOME=/usr/local/src/jdk1.7.0_04<br /><br />启动tomcat,如果正常的话，可以看见猫了</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/195106.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-11-13 11:09 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/11/13/195106.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>yii (3)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/08/30/188729.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 30 Aug 2012 04:16:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/08/30/188729.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/188729.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/08/30/188729.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/188729.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/188729.html</trackback:ping><description><![CDATA[<div>$criteria = new CDbCriteria;&nbsp;<div><wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;addCondition("id=1"); //查询条件，即where id = 1 &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;addInCondition('id', array(1,2,3,4,5)); //代表where id IN (1,23,,4,5,); &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;addNotInCondition('id', array(1,2,3,4,5));//与上面正好相法，是NOT IN &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;addCondition('id=1','OR');//这是OR条件，多个条件的时候，该条件是OR而非AND &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;addSearchCondition('name', '分类');//搜索条件，其实代表了。。where name like '%分类%' &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;addBetweenCondition('id', 1, 4);//between 1 and 4&nbsp;<wbr> &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;compare('id', 1);&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //这个方法比较特殊，他会根据你的参数自动处理成addCondition或者addInCondition， &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //即如果第二个参数是数组就会调用addInCondition &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;addCondition("id = :id"); &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;params[':id']=1; &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;select = 'id,parentid,name'; //代表了要查询的字段，默认select='*'; &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;join = 'xxx'; //连接表 &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;with = 'xxx'; //调用relations&nbsp;<wbr> &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;limit = 10;&nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> //取1条数据，如果小于0，则不作处理 &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;offset = 1;&nbsp;<wbr>&nbsp;<wbr> //两条合并起来，则表示 limit 10 offset 1,或者代表了。limit 1,10 &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;order = 'xxx DESC,XXX ASC' ;//排序条件 &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;group = 'group 条件'; &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;having = 'having 条件 '; &nbsp;<wbr><br /> &nbsp;<wbr>&nbsp;<wbr>&nbsp;<wbr> $criteria-&gt;distinct = FALSE; //是否唯一查询&nbsp;<wbr></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/188729.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-08-30 12:16 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/08/30/188729.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>phpunit</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/05/04/173650.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 04 May 2012 03:39:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/05/04/173650.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/173650.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/05/04/173650.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/173650.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/173650.html</trackback:ping><description><![CDATA[<div><p><span style="font-size:16px">最近研究php的单元测试功能，在centos下和widows下安装了phpunit</span></p><p><span style="font-size:16px">首先要保证你装的php中安装了pear</span></p><p><span style="font-size:16px">linux下输入命令pear 回车可看一下是否安装了</span></p><p><span style="font-size:16px">windows下可以用dos进入到php的安装目录 ，输入命令pear 回车可看一下是否安装了&nbsp;</span></p><p><span style="font-size:16px">在默认情况下php中都会安装的</span></p><p><strong><span style="font-size:16px">pear的安装</span></strong></p><p><span style="font-size:16px">wwindows下用dos进入php的安装根目录 &nbsp;运行go-pear，r然后输入两次yes 然后 后边的选项直接用回车</span><img src="http://hiphotos.baidu.com/1024114660/pic/item/211bcaf50675a637ddc4749f.jpg" border="0"  alt="" /></p><p><span style="font-size:16px">然后我们要添加Channel</span></p><p><span style="font-size:16px">pear channel-discover pear.phpunit.de</span></p><p><span style="font-size:16px">pear channel-discover components.ez.no</span></p><p><span style="font-size:16px">pear channel-discover pear.symfony-project.com</span></p><p><img src="http://hiphotos.baidu.com/1024114660/pic/item/bc4ae4a5c5a602ae9052ee85.jpg" border="0"  alt="" /><br /><span style="font-size:16px">我在这个地方遇到了&nbsp;.lock 访问权限的错误而安装失败，这是我们可以在PEAR文件夹下删除此文件</span></p><p><span style="font-size:16px">接下来执行pear install phpunit/PHPUnit，此时我遇到了下图所示的问题，包依赖</span></p><p><span style="font-size:16px">很简单 我们把这些包用pear install命令安装了 即可</span></p><p><img src="http://hiphotos.baidu.com/1024114660/pic/item/4f3e7534c47c89d2a61e1286.jpg" border="0"  alt="" /></p><p><img src="http://hiphotos.baidu.com/1024114660/pic/item/8a31ce54f091e09db745ae80.jpg" border="0"  alt="" /></p><p><span style="font-size:16px">可能执行完这个之后你的phpunit还是提示安装失败</span></p><p><img src="http://hiphotos.baidu.com/1024114660/pic/item/b234530bcebc2e4694ca6b2a.jpg" border="0"  alt="" /></p><p><span style="font-size:16px">它提示我们要更新pear包</span></p><p><span style="font-size:16px">pear upgrade-all&nbsp;</span></p><p><span style="font-size:16px">按照提示操作，可能会提示你更新Channel，那么更新即可</span></p><p><img src="http://hiphotos.baidu.com/1024114660/pic/item/def524ff7938b0685c60081d.jpg" border="0"  alt="" /></p><p><span style="font-size:16px">此时在执行pear install phpunit/PHPUnit 可以看到提示安装成功了</span><img src="http://img.baidu.com/hi/jx2/j_0058.gif"  alt="" /></p><p><img src="http://hiphotos.baidu.com/1024114660/pic/item/ec302d25db86a5584c088d1f.jpg" border="0"  alt="" /><img src="http://hiphotos.baidu.com/1024114660/pic/item/4b996d002929625f1d958319.jpg" border="0"  alt="" /><br /><br /><span style="font-size:16px">我们会发现在PEAR目录下多了PHPUnit 这表明安装成功，另外在安装pear的时候回修改php.ini文件</span></p><p><span style="font-size:16px">;***** Added by go-pear</span></p><p><span style="font-size:16px">include_path=".;E:\webserver\php\pear"</span></p><p><span style="font-size:16px">;*****</span></p><p><span style="font-size:16px">小提示：直接输入pear可现实pear命令下的所有选项</span></p><p><span style="line-height: 28px;">phpunit 使用手册&nbsp;</span><a href="http://www.phpunit.de/manual/3.5/en/index.html">http://www.phpunit.de/manual/3.5/en/index.html</a></p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/173650.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-05-04 11:39 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/05/04/173650.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>yii 路由</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/03/20/168433.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 20 Mar 2012 12:59:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/03/20/168433.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/168433.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/03/20/168433.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/168433.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/168433.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 分类：             YII               2011-11-21 16:57     737人阅读     评论(0)     收藏     举报                   &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;http://www.localyii.com/testwebap/index.php?r=testmod/default/i...&nbsp;&nbsp;<a href='http://www.cppblog.com/guojingjia2006/archive/2012/03/20/168433.html'>阅读全文</a><img src ="http://www.cppblog.com/guojingjia2006/aggbug/168433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-03-20 20:59 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/03/20/168433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JQuery ajax 参数详细列表</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/01/15/164209.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 15 Jan 2012 05:02:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/01/15/164209.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/164209.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/01/15/164209.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/164209.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/164209.html</trackback:ping><description><![CDATA[<p>下面是Jquery中AJAX参数详细列表：<br />&nbsp;</p>
<p><br />参数名<br />&nbsp;<br />类型<br />&nbsp;<br />描述</p>
<p>&nbsp;</p>
<p>url </p>
<p>String<br />&nbsp;<br />(默认: 当前页地址) 发送请求的地址。</p>
<p>&nbsp;</p>
<p>type<br />&nbsp;<br />String<br />&nbsp;<br />(默认: "GET") 请求方式 ("POST" 或 "GET")， 默认为 "GET"。注意：其它 HTTP 请求方法，如 PUT 和 DELETE 也可以使用，但仅部分浏览器支持。</p>
<p>&nbsp;</p>
<p>timeout<br />&nbsp;<br />Number<br />&nbsp;<br />设置请求超时时间（毫秒）。此设置将覆盖全局设置。</p>
<p>&nbsp;</p>
<p>async </p>
<p>Boolean<br />&nbsp;<br />(默认: true) 默认设置下，所有请求均为异步请求。如果需要发送同步请求，请将此选项设置为 false。注意，同步请求将锁住浏览器，用户其它操作必须等待请求完成才可以执行。</p>
<p>&nbsp;</p>
<p>beforeSend </p>
<p>Function<br />&nbsp;<br />发送请求前可修改 XMLHttpRequest 对象的函数，如添加自定义 HTTP 头。XMLHttpRequest 对象是唯一的参数。<br />function (XMLHttpRequest) { this; // the options for this ajax request } </p>
<p><br />cache </p>
<p>Boolean<br />&nbsp;<br />(默认: true) jQuery 1.2 新功能，设置为 false 将不会从浏览器缓存中加载请求信息。</p>
<p>&nbsp;</p>
<p>complete </p>
<p>Function<br />&nbsp;<br />请求完成后回调函数 (请求成功或失败时均调用)。参数： XMLHttpRequest 对象，成功信息字符串。<br />function (XMLHttpRequest, textStatus) { this; // the options for this ajax request } </p>
<p><br />contentType </p>
<p>String<br />&nbsp;<br />(默认: "application/x-www-form-urlencoded") 发送信息至服务器时内容编码类型。默认值适合大多数应用场合。</p>
<p>&nbsp;</p>
<p>data </p>
<p>Object,<br />String<br />&nbsp;<br />发送到服务器的数据。将自动转换为请求字符串格式。GET 请求中将附加在 URL 后。查看 processData 选项说明以禁止此自动转换。必须为 Key/Value 格式。如果为数组，jQuery 将自动为不同值对应同一个名称。如 {foo:["bar1", "bar2"]} 转换为 '&amp;foo=bar1&amp;foo=bar2'。</p>
<p>&nbsp;</p>
<p>dataType </p>
<p>String<br />&nbsp;</p>
<p>预期服务器返回的数据类型。如果不指定，jQuery 将自动根据 HTTP 包 MIME 信息返回 responseXML 或 responseText，并作为回调函数参数传递，可用值:<br />&nbsp;<br />"xml": 返回 XML 文档，可用 jQuery 处理。<br />&nbsp;<br />"html": 返回纯文本 HTML 信息；包含 script 元素。<br />&nbsp;<br />"script": 返回纯文本 JavaScript 代码。不会自动缓存结果。<br />&nbsp;<br />"json": 返回 JSON 数据 。<br />&nbsp;<br />"jsonp": JSONP 格式。使用 JSONP 形式调用函数时，如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名，以执行回调函数。<br />&nbsp;</p>
<p><br />error </p>
<p>Function<br />&nbsp;<br />(默认: 自动判断 (xml 或 html)) 请求失败时将调用此方法。这个方法有三个参数：XMLHttpRequest 对象，错误信息，（可能）捕获的错误对象。<br />function (XMLHttpRequest, textStatus, errorThrown) { // 通常情况下textStatus和errorThown只有其中一个有值&nbsp; this; // the options for this ajax request } </p>
<p><br />global </p>
<p>Boolean<br />&nbsp;<br />(默认: true) 是否触发全局 AJAX 事件。设置为 false 将不会触发全局 AJAX 事件，如 ajaxStart 或 ajaxStop 。可用于控制不同的Ajax事件</p>
<p>&nbsp;</p>
<p>ifModified </p>
<p>Boolean<br />&nbsp;<br />(默认: false) 仅在服务器数据改变时获取新数据。使用 HTTP 包 Last-Modified 头信息判断。</p>
<p>&nbsp;</p>
<p>processData </p>
<p>Boolean<br />&nbsp;<br />(默认: true) 默认情况下，发送的数据将被转换为对象(技术上讲并非字符串) 以配合默认内容类型 "application/x-www-form-urlencoded"。如果要发送 DOM 树信息或其它不希望转换的信息，请设置为 false。</p>
<p>&nbsp;</p>
<p>success </p>
<p>Function<br />&nbsp;<br />请求成功后回调函数。这个方法有两个参数：服务器返回数据，返回状态<br />function (data, textStatus) { // data could be xmlDoc, jsonObj, html, text, etc... this; // the options for this ajax request } </p>
<p><br />代码：$(document).ready(function() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jQuery("#clearCac").click(function() {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; jQuery.ajax({<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url: "/Handle/Do.aspx",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type: "post",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; data: { id: '0' },<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dataType: "json",<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; success: function(msg) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert(msg);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; error: function(XMLHttpRequest, textStatus, errorThrown) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert(XMLHttpRequest.status);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert(XMLHttpRequest.readyState);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert(textStatus);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; },<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; complete: function(XMLHttpRequest, textStatus) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this; // 调用本次AJAX请求时传递的options参数<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br />&nbsp;<br />&nbsp;<br />&nbsp;<br />一、error：function (XMLHttpRequest, textStatus, errorThrown) <br />{ <br />} <br />(默认: 自动判断 (xml 或 html)) 请求失败时调用时间。参数有以下三个：XMLHttpRequest 对象、错误信息、（可选）捕获的错误对象。如果发生了错误，错误信息（第二个参数）除了得到null之外，还可能是"timeout", "error", "notmodified" 和 "parsererror"。<br />&nbsp;<br />textStatus:<br />&nbsp;<br />&nbsp;"timeout", "error", "notmodified" 和 "parsererror"。<br />&nbsp;<br />二、error事件返回的第一个参数XMLHttpRequest有一些有用的信息：<br />&nbsp;<br />XMLHttpRequest.readyState: </p>
<p>状态码&nbsp; </p>
<p>0 － （未初始化）还没有调用send()方法&nbsp; </p>
<p>1 － （载入）已调用send()方法，正在发送请求&nbsp; </p>
<p>2 － （载入完成）send()方法执行完成，已经接收到全部响应内容&nbsp; </p>
<p>3 － （交互）正在解析响应内容&nbsp; </p>
<p>4 － （完成）响应内容解析完成，可以在客户端调用了<br />&nbsp;<br />三、data:"{}", data为空也一定要传"{}"；不然返回的是xml格式的。并提示parsererror.<br />&nbsp;<br />四、parsererror的异常和Header 类型也有关系。及编码header('Content-type: text/html; charset=utf8'); </p>
<p>五、XMLHttpRequest.status:<br />1xx-信息提示&nbsp; <br />这些状态代码表示临时的响应。客户端在收到常规响应之前，应准备接收一个或多个1xx响应。&nbsp; <br />100-继续。&nbsp; <br />101-切换协议。&nbsp; <br />2xx-成功&nbsp; <br />这类状态代码表明服务器成功地接受了客户端请求。&nbsp; <br />200-确定。客户端请求已成功。&nbsp; <br />201-已创建。&nbsp; <br />202-已接受。&nbsp; <br />203-非权威性信息。&nbsp; <br />204-无内容。&nbsp; <br />205-重置内容。&nbsp; <br />206-部分内容。&nbsp; <br />3xx-重定向&nbsp; <br />客户端浏览器必须采取更多操作来实现请求。例如，浏览器可能不得不请求服务器上的不同的页面，或通过代理服务器重复该请求。&nbsp; <br />301-对象已永久移走，即永久重定向。&nbsp; <br />302-对象已临时移动。&nbsp; <br />304-未修改。&nbsp; <br />307-临时重定向。&nbsp; <br />4xx-客户端错误&nbsp; <br />发生错误，客户端似乎有问题。例如，客户端请求不存在的页面，客户端未提供有效的身份验证信息。400-错误的请求。&nbsp; <br />401-访问被拒绝。IIS定义了许多不同的401错误，它们指明更为具体的错误原因。这些具体的错误代码在浏览器中显示，但不在IIS日志中显示：&nbsp; <br />401.1-登录失败。&nbsp; <br />401.2-服务器配置导致登录失败。&nbsp; <br />401.3-由于ACL对资源的限制而未获得授权。&nbsp; <br />401.4-筛选器授权失败。&nbsp; <br />401.5-ISAPI/CGI应用程序授权失败。&nbsp; <br />401.7&#8211;访问被Web服务器上的URL授权策略拒绝。这个错误代码为IIS6.0所专用。&nbsp; <br />403-禁止访问：IIS定义了许多不同的403错误，它们指明更为具体的错误原因：&nbsp; <br />403.1-执行访问被禁止。&nbsp; <br />403.2-读访问被禁止。&nbsp; <br />403.3-写访问被禁止。&nbsp; <br />403.4-要求SSL。&nbsp; <br />403.5-要求SSL128。&nbsp; <br />403.6-IP地址被拒绝。&nbsp; <br />403.7-要求客户端证书。&nbsp; <br />403.8-站点访问被拒绝。&nbsp; <br />403.9-用户数过多。&nbsp; <br />403.10-配置无效。&nbsp; <br />403.11-密码更改。&nbsp; <br />403.12-拒绝访问映射表。&nbsp; <br />403.13-客户端证书被吊销。&nbsp; <br />403.14-拒绝目录列表。&nbsp; <br />403.15-超出客户端访问许可。&nbsp; <br />403.16-客户端证书不受信任或无效。&nbsp; <br />403.17-客户端证书已过期或尚未生效。&nbsp; <br />403.18-在当前的应用程序池中不能执行所请求的URL。这个错误代码为IIS6.0所专用。&nbsp; <br />403.19-不能为这个应用程序池中的客户端执行CGI。这个错误代码为IIS6.0所专用。&nbsp; <br />403.20-Passport登录失败。这个错误代码为IIS6.0所专用。&nbsp; <br />404-未找到。&nbsp; <br />404.0-（无）&#8211;没有找到文件或目录。&nbsp; <br />404.1-无法在所请求的端口上访问Web站点。&nbsp; <br />404.2-Web服务扩展锁定策略阻止本请求。&nbsp; <br />404.3-MIME映射策略阻止本请求。&nbsp; <br />405-用来访问本页面的HTTP谓词不被允许（方法不被允许）&nbsp; <br />406-客户端浏览器不接受所请求页面的MIME类型。&nbsp; <br />407-要求进行代理身份验证。&nbsp; <br />412-前提条件失败。&nbsp; <br />413&#8211;请求实体太大。&nbsp; <br />414-请求URI太长。&nbsp; <br />415&#8211;不支持的媒体类型。&nbsp; <br />416&#8211;所请求的范围无法满足。&nbsp; <br />417&#8211;执行失败。&nbsp; <br />423&#8211;锁定的错误。&nbsp; <br />5xx-服务器错误&nbsp; <br />服务器由于遇到错误而不能完成该请求。&nbsp; <br />500-内部服务器错误。&nbsp; <br />500.12-应用程序正忙于在Web服务器上重新启动。&nbsp; <br />500.13-Web服务器太忙。&nbsp; <br />500.15-不允许直接请求Global.asa。&nbsp; <br />500.16&#8211;UNC授权凭据不正确。这个错误代码为IIS6.0所专用。&nbsp; <br />500.18&#8211;URL授权存储不能打开。这个错误代码为IIS6.0所专用。&nbsp; <br />500.100-内部ASP错误。&nbsp; <br />501-页眉值指定了未实现的配置。&nbsp; <br />502-Web服务器用作网关或代理服务器时收到了无效响应。&nbsp; <br />502.1-CGI应用程序超时。&nbsp; <br />502.2-CGI应用程序出错。application.&nbsp; <br />503-服务不可用。这个错误代码为IIS6.0所专用。&nbsp; <br />504-网关超时。&nbsp; <br />505-HTTP版本不受支持。&nbsp; <br />FTP&nbsp; <br />1xx-肯定的初步答复&nbsp; <br />这些状态代码指示一项操作已经成功开始，但客户端希望在继续操作新命令前得到另一个答复。&nbsp; <br />110重新启动标记答复。&nbsp; <br />120服务已就绪，在nnn分钟后开始。&nbsp; <br />125数据连接已打开，正在开始传输。&nbsp; <br />150文件状态正常，准备打开数据连接。&nbsp; <br />2xx-肯定的完成答复&nbsp; <br />一项操作已经成功完成。客户端可以执行新命令。200命令确定。&nbsp; <br />202未执行命令，站点上的命令过多。&nbsp; <br />211系统状态，或系统帮助答复。&nbsp; <br />212目录状态。&nbsp; <br />213文件状态。&nbsp; <br />214帮助消息。&nbsp; <br />215NAME系统类型，其中，NAME是AssignedNumbers文档中所列的正式系统名称。&nbsp; <br />220服务就绪，可以执行新用户的请求。&nbsp; <br />221服务关闭控制连接。如果适当，请注销。&nbsp; <br />225数据连接打开，没有进行中的传输。&nbsp; <br />226关闭数据连接。请求的文件操作已成功（例如，传输文件或放弃文件）。&nbsp; <br />227进入被动模式(h1,h2,h3,h4,p1,p2)。&nbsp; <br />230用户已登录，继续进行。&nbsp; <br />250请求的文件操作正确，已完成。&nbsp; <br />257已创建&#8220;PATHNAME&#8221;。&nbsp; <br />3xx-肯定的中间答复&nbsp; <br />该命令已成功，但服务器需要更多来自客户端的信息以完成对请求的处理。331用户名正确，需要密码。&nbsp; <br />332需要登录帐户。&nbsp; <br />350请求的文件操作正在等待进一步的信息。&nbsp; <br />4xx-瞬态否定的完成答复&nbsp; <br />该命令不成功，但错误是暂时的。如果客户端重试命令，可能会执行成功。421服务不可用，正在关闭控制连接。如果服务确定它必须关闭，将向任何命令发送这一应答。&nbsp; <br />425无法打开数据连接。&nbsp; <br />426Connectionclosed;transferaborted.&nbsp; <br />450未执行请求的文件操作。文件不可用（例如，文件繁忙）。&nbsp; <br />451请求的操作异常终止：正在处理本地错误。&nbsp; <br />452未执行请求的操作。系统存储空间不够。&nbsp; <br />5xx-永久性否定的完成答复&nbsp; <br />该命令不成功，错误是永久性的。如果客户端重试命令，将再次出现同样的错误。500语法错误，命令无法识别。这可能包括诸如命令行太长之类的错误。&nbsp; <br />501在参数中有语法错误。&nbsp; <br />502未执行命令。&nbsp; <br />503错误的命令序列。&nbsp; <br />504未执行该参数的命令。&nbsp; <br />530未登录。&nbsp; <br />532存储文件需要帐户。&nbsp; <br />550未执行请求的操作。文件不可用（例如，未找到文件，没有访问权限）。&nbsp; <br />551请求的操作异常终止：未知的页面类型。&nbsp; <br />552请求的文件操作异常终止：超出存储分配（对于当前目录或数据集）。&nbsp; <br />553未执行请求的操作。不允许的文件名。&nbsp; </p>
<p>本篇文章来源于 Linux公社网站(<a href="http://www.linuxidc.com">www.linuxidc.com</a>)&nbsp; 原文链接：<a href="http://www.linuxidc.com/Linux/2011-11/47495.htm">http://www.linuxidc.com/Linux/2011-11/47495.htm</a></p><img src ="http://www.cppblog.com/guojingjia2006/aggbug/164209.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-01-15 13:02 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/01/15/164209.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yii sql (3)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/01/13/164104.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 13 Jan 2012 01:51:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/01/13/164104.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/164104.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/01/13/164104.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/164104.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/164104.html</trackback:ping><description><![CDATA[<div class="entry">$criteria = new CDbCriteria; <br /><br />$criteria-&gt;addCondition("id=1"); //查询条件，即where id = 1 <br /><br />$criteria-&gt;addInCondition('id', array(1,2,3,4,5)); //代表where id IN (1,23,,4,5,); <br /><br />$criteria-&gt;addNotInCondition('id', array(1,2,3,4,5));//与上面正好相法，是NOT IN <br /><br />$criteria-&gt;addCondition('id=1','OR');//这是OR条件，多个条件的时候，该条件是OR而非AND <br /><br />$criteria-&gt;addSearchCondition('name', '分类');//搜索条件，其实代表了。。where name like '%分类%' <br /><br />$criteria-&gt;addBetweenCondition('id', 1, 4);//between 1 and 4 <br /><br />$criteria-&gt;compare('id', 1); //这个方法比较特殊，他会根据你的参数自动处理成addCondition或者addInCondition，<br /><br />//即如果第二个参数是数组就会调用addInCondition <br />$criteria-&gt;addCondition("id = :id"); <br /><br />$criteria-&gt;params[':id']=1; <br /><br />//一些public vars <br /><br />$criteria-&gt;select = 'id,parentid,name'; //代表了要查询的字段，默认select='*'; <br /><br />$criteria-&gt;join = 'xxx'; //连接表 <br /><br />$criteria-&gt;with = 'xxx'; //调用relations <br /><br />$criteria-&gt;limit = 10; //取1条数据，如果小于0，则不作处理 <br /><br />$criteria-&gt;offset = 1; //两条合并起来，则表示 limit 10 offset 1,或者代表了。limit 1,10 <br /><br />$criteria-&gt;order = 'xxx DESC,XXX ASC' ;//排序条件 <br /><br />$criteria-&gt;group = 'group 条件'; $criteria-&gt;having = 'having 条件 '; <br /><br />$criteria-&gt;distinct = FALSE; //是否唯一查询 </div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/164104.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-01-13 09:51 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/01/13/164104.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yii 数据库 (2)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163555.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 04 Jan 2012 08:18:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163555.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/163555.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163555.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/163555.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/163555.html</trackback:ping><description><![CDATA[<ol><li><span>
<div id="blog_text" class="cnt">
<p>目录 <br />一、增删查改 <br />二、验证规则 <br />三、事务管理 <br />四、名字空间。参考：Yii数据库操作&#8212;&#8212;名字空间(named scopes)的三种用法 <br /><br /><span><strong>一、增删查改</strong></span><br />1，创建 <br />$post = new Post; <br />$post-&gt;title = ""; <br />$post-&gt;content = ""; <br />$post-&gt;created_at = "CDbExpression('NOW()')"; <br />$post-&gt;save(); <br /><br />(1) 插入后可立即获得主键id。 <br />$id = $post-&gt;id;&nbsp;&nbsp; // 前提是auto_increment <br /><br />(2) 某一个字段的值为缺省值时，可以在models/Class.php中修改 <br />Class Post extends CActiveRecord{ <br />public $title = 'new title'; <br />$post = new Post; <br />echo $post-&gt;title; // 输出是: new title <br />} <br /><br />(3) 使用CDbExpression <br />$post-&gt;create_time = new CDbExpression('NOW()'); <br /><br /><br />2，查询【待补充】 <br />(1) 通过主键查询 <br />find("postID=:postID", array(':postID' =&gt; postID) <br />findByPk($id) // 单主键 <br /><br />(2) 通过非主键查询 <br />find("postID=:postID", array(':postID' =&gt; postID) <br />findAll( id = $id ) <br />findAll( id IN ( $id ) ) <br /><br /><br /><br />3，更新【待补充】 <br />先find，并将对应字段赋新值，再保存 <br /><br />可以通过CActiveRecord::isNewRecord来判断是新建，还是更新。 <br /><br /><br />4，删除 <br />(1) 如果是一条记录 <br />先找到后删除 <br />$post=Post::model-&gt;findByPk(10); <br />$post-&gt;delete(); <br /><br />直接通过主键删除（类级别删除，不需要先载入记录） <br />Post::model-&gt;deleteByPk(10); <br /><br />(2) 如果是多条记录（类级别删除，不需要先载入记录） <br />Post::model-&gt;deleteAll(); <br /><br /><br /><span><strong>二、验证规则</strong></span><br />验证规则（Data validation）发生在调用save()方法的时候。验证是基于在rules()方法中的定义。 <br /><br />if( $post-&gt;save() ){ <br />// 验证通过 <br />} else { <br />// 验证失败。通过getErrors()返回错误信息。 <br />} <br /><br />获取用户从表单提交的数据 <br />$post-&gt;title&nbsp;&nbsp; = $_POST['title']; <br />$post-&gt;content = $_POST['content']; <br />$post-&gt;save(); <br /><br />如果多了，可以通过下面的方式减轻（alleviate）复杂程度： <br /></p>
<div>
<div>
<div>Php代码 </div></div>
<ol><li><span>$post</span><span>-&gt;attributes&nbsp;=&nbsp;</span><span>$_POST</span><span>[</span><span>'Post'</span><span>]; &nbsp;&nbsp;</span></li><li><span></span><span>$post</span><span>-&gt;save(); &nbsp;&nbsp;</span></li><li><span></span><span>//类似于： </span><span>&nbsp;&nbsp;</span></li><li><span></span><span>foreach</span><span>(</span><span>$_POST</span><span>[</span><span>'Post'</span><span>]&nbsp;</span><span>as</span><span>&nbsp;</span><span>$name</span><span>=&gt;</span><span>$value</span><span>){ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>if</span><span>(</span><span>$name</span><span>&nbsp;is&nbsp;a&nbsp;safe&nbsp;attribute) &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$model</span><span>-&gt;</span><span>$name</span><span>&nbsp;=&nbsp;</span><span>$value</span><span>; &nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre title="yii数据库操作&#8212;&#8212;单表的增删查改">$post-&gt;attributes = $_POST['Post'];$post-&gt;save();//类似于：foreach($_POST['Post'] as $name=&gt;$value){	if($name is a safe attribute)		$model-&gt;$name = $value;}</pre>
<p><br />注意：里面的验证检验非常重要，否则用户可能绕过授权。 <br /><br /><br /><span><strong>三、事务管理</strong></span><br />dbConnection是CDbConnection的实例 <br />官方文档 <br /></p>
<div>
<div>
<div>Php代码</div></div>
<ol><li><span>$model</span><span>&nbsp;=&nbsp;Post::model(); &nbsp;&nbsp;</span></li><li><span></span><span>$transaction</span><span>&nbsp;=&nbsp;</span><span>$model</span><span>-&gt;dbConnection-&gt;beginTransaction(); &nbsp;&nbsp;</span></li><li><span>try{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$post</span><span>&nbsp;=&nbsp;</span><span>$model</span><span>-&gt;findByPk(10); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$post</span><span>-&gt;title&nbsp;=&nbsp;</span><span>'new&nbsp;post&nbsp;title'</span><span>; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$post</span><span>-&gt;save(); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$transaction</span><span>-&gt;commit(); &nbsp;&nbsp;</span></li><li><span>}&nbsp;catch&nbsp;(Exception&nbsp;</span><span>$e</span><span>){ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$transaction</span><span>-&gt;rollback(); &nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre title="yii数据库操作&#8212;&#8212;单表的增删查改">$model = Post::model();$transaction = $model-&gt;dbConnection-&gt;beginTransaction();try{	$post = $model-&gt;findByPk(10);	$post-&gt;title = 'new post title';	$post-&gt;save();	$transaction-&gt;commit();} catch (Exception $e){	$transaction-&gt;rollback();}</pre>
<p><br /><br />实际项目 <br /></p>
<div>
<div>
<div>Php代码</div></div>
<ol><li><span>$trans</span><span>&nbsp;=&nbsp;Yii::app()-&gt;db-&gt;beginTransaction(); &nbsp;&nbsp;</span></li><li><span>try&nbsp;{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$manufacturer</span><span>&nbsp;=&nbsp;</span><span>new</span><span>&nbsp;Manufacturer();&nbsp; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$manufacturer</span><span>-&gt;name&nbsp;=&nbsp;</span><span>$name</span><span>; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$manufacturer</span><span>-&gt;email&nbsp;=&nbsp;</span><span>$email</span><span>; &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$manufacturer</span><span>-&gt;save(); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$trans</span><span>-&gt;commit(); &nbsp;&nbsp;</span></li><li><span>}&nbsp;catch&nbsp;(Exception&nbsp;</span><span>$e</span><span>)&nbsp;{ &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$trans</span><span>-&gt;rollback(); &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>$this</span><span>-&gt;response(</span><span>array</span><span>(</span><span>'status'</span><span>&nbsp;=&gt;&nbsp;1,&nbsp;</span><span>'msg'</span><span>&nbsp;=&gt;&nbsp;</span><span>$e</span><span>-&gt;getMessage()));&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre title="yii数据库操作&#8212;&#8212;单表的增删查改">$trans = Yii::app()-&gt;db-&gt;beginTransaction();try {	$manufacturer = new Manufacturer();		$manufacturer-&gt;name = $name;	$manufacturer-&gt;email = $email;	$manufacturer-&gt;save();	$trans-&gt;commit();} catch (Exception $e) {	$trans-&gt;rollback();	$this-&gt;response(array('status' =&gt; 1, 'msg' =&gt; $e-&gt;getMessage()));	}</pre>
<p><br /><br />其实使用的时候跟凡客体的我是凡客或淘宝体的亲一样。 <br /><br />注：Yii::app()后面的db在../config/main.php中已配置 <br /></p>
<div>
<div>
<div>Php代码 </div></div>
<ol><li><span>'components'</span><span>=&gt;</span><span>array</span><span>( &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>'user'</span><span>=&gt;</span><span>array</span><span>(</span><span>'allowAutoLogin'</span><span>=&gt;true,), &nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span>'db'</span><span>=&gt;</span><span>array</span><span>(</span><span>"数据库连接参数"</span><span>), &nbsp;&nbsp;</span></li><li><span>)&nbsp;&nbsp;</span></li></ol></div></div><br /></span></li></ol><img src ="http://www.cppblog.com/guojingjia2006/aggbug/163555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-01-04 16:18 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Yii 框架里数据库操作详解-[增加、查询、更新、删除的方法 'AR一、查询数据集合</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163553.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 04 Jan 2012 08:06:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163553.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/163553.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163553.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/163553.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/163553.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一、查询数据集合1、$admin=Admin::model()-&gt;findAll($condition,$params);该方法是根据一个条件查询一个集合，如： &nbsp;findAll("username=:name",array(":name"=&gt;$username));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2、$admin=Admin::mod...&nbsp;&nbsp;<a href='http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163553.html'>阅读全文</a><img src ="http://www.cppblog.com/guojingjia2006/aggbug/163553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-01-04 16:06 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/01/04/163553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>YII</title><link>http://www.cppblog.com/guojingjia2006/archive/2011/12/02/161321.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 02 Dec 2011 05:16:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2011/12/02/161321.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/161321.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2011/12/02/161321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/161321.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/161321.html</trackback:ping><description><![CDATA[<a href="http://www.yiiframework.com/">http://www.yiiframework.com/</a><br /><a href="http://www.yiiframework.com/doc/guide/1.1/zh_cn/quickstart.what-is-yii">http://www.yiiframework.com/doc/guide/1.1/zh_cn/quickstart.what-is-yii</a><br /><a href="http://yp.oss.org.cn/blog/show_resource.php?resource_id=774">http://yp.oss.org.cn/blog/show_resource.php?resource_id=774</a><br /><a href="http://www.yiieye.com/book_cn/">http://www.yiieye.com/book_cn/</a><br /><a href="http://blog.csdn.net/dxxgiupel/article/details/5803864">http://blog.csdn.net/dxxgiupel/article/details/5803864</a><br /><a href="http://wenku.baidu.com/view/7d7d65ecaeaad1f346933fb5.html">http://wenku.baidu.com/view/7d7d65ecaeaad1f346933fb5.html</a><br />
<div>http://www.yiichina.org/news/43/<br /><br /><a href="http://blog.csdn.net/hy840429/article/details/5415218">http://blog.csdn.net/hy840429/article/details/5415218</a></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/161321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2011-12-02 13:16 <a href="http://www.cppblog.com/guojingjia2006/archive/2011/12/02/161321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts2 - result</title><link>http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143462.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 05 Apr 2011 10:17:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143462.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/143462.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143462.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/143462.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/143462.html</trackback:ping><description><![CDATA[提交服务器处理业务后结果返回页面的处理,Struts2提供了对不同种类返回结果的支持，常见的有JSP，FreeMarker，Velocity等。<br><br>struts.xml配置文件中result的语法：&lt;result name="" type=""&gt;xxxxx&lt;/result&gt;<br><br>Struts2支持的不同类型的返回结果为：<br><br>Chain Result--&gt;type="chain"<br>用来处理Action链<br><br>Dispatcher Result --&gt;type="dispatcher"<br>用来转向页面，通常处理JSP<br><br>FreeMarker Result --&gt;type="freemarker"<br>处理FreeMarker模板<br><br>HttpHeader Result --&gt;type="httpheader"<br>用来控制特殊的Http行为<br><br>Redirect Result --&gt;type="redirect"<br>重定向到一个URL<br><br>Redirect Action Result --&gt;type="redirectAction"<br>重定向到一个Action<br><br>Stream Result --&gt;type="stream"<br>向浏览器发送InputSream对象，通常用来处理文件下载<br><br>Velocity Result --&gt;type="velocity"<br>处理Velocity模板<br><br>XLST Result --&gt;type="xslt"<br>处理XML/XLST模板<br><br>PlainText Result --&gt;type="plainText"<br>显示原始文件内容，例如文件源代码<br><br><br>另外第三方的result类型还包括JasperReports Plugin，专门用来处理JasperReport类型的报表输出。<br><br>在struts-default.xml文件中已经有了对于所有类型Result的定义：<br><br>Java 代码<br><br>1. &lt;result-types&gt;&nbsp;&nbsp; <br>2.&nbsp;&nbsp; <br>3.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="chain"&nbsp;&nbsp; <br>4.&nbsp;&nbsp; <br>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="com.opensymphony.xwork2.ActionChainResult"/&gt;&nbsp;&nbsp; <br>6.&nbsp;&nbsp; <br>7.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="dispatcher"&nbsp;&nbsp; <br>8.&nbsp;&nbsp; <br>9.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletDispatcherResult"&nbsp;&nbsp; <br>10.&nbsp;&nbsp; <br>11.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default="true"/&gt;&nbsp;&nbsp; <br>12.&nbsp;&nbsp; <br>13.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="freemarker"&nbsp;&nbsp; <br>14.&nbsp;&nbsp; <br>15.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.views.freemarker.FreemarkerResult"/&gt;&nbsp;&nbsp; <br>16.&nbsp;&nbsp; <br>17.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="httpheader"&nbsp;&nbsp; <br>18.&nbsp;&nbsp; <br>19.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.HttpHeaderResult"/&gt;&nbsp;&nbsp; <br>20.&nbsp;&nbsp; <br>21.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="redirect"&nbsp;&nbsp; <br>22.&nbsp;&nbsp; <br>23.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletRedirectResult"/&gt;&nbsp;&nbsp; <br>24.&nbsp;&nbsp; <br>25.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="redirectAction"&nbsp;&nbsp; <br>26.&nbsp;&nbsp; <br>27.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/&gt;&nbsp;&nbsp; <br>28.&nbsp;&nbsp; <br>29.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="stream"&nbsp;&nbsp; <br>30.&nbsp;&nbsp; <br>31.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.StreamResult"/&gt;&nbsp;&nbsp; <br>32.&nbsp;&nbsp; <br>33.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="velocity"&nbsp;&nbsp; <br>34.&nbsp;&nbsp; <br>35.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.VelocityResult"/&gt;&nbsp;&nbsp; <br>36.&nbsp;&nbsp; <br>37.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="xslt"&nbsp;&nbsp; <br>38.&nbsp;&nbsp; <br>39.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.views.xslt.XSLTResult"/&gt;&nbsp;&nbsp; <br>40.&nbsp;&nbsp; <br>41.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="plainText"&nbsp;&nbsp; <br>42.&nbsp;&nbsp; <br>43.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.PlainTextResult" /&gt;&nbsp;&nbsp; <br>44.&nbsp;&nbsp; <br>45.&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- Deprecated name form scheduled for removal in Struts 2.1.0.&nbsp;&nbsp; <br>46.&nbsp;&nbsp; <br>47.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The camelCase versions are preferred. See ww-1707 --&gt;&nbsp;&nbsp; <br>48.&nbsp;&nbsp; <br>49.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="redirect-action"&nbsp;&nbsp; <br>50.&nbsp;&nbsp; <br>51.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/&gt;&nbsp;&nbsp; <br>52.&nbsp;&nbsp; <br>53.&nbsp;&nbsp;&nbsp;&nbsp; &lt;result-type name="plaintext"&nbsp;&nbsp; <br>54.&nbsp;&nbsp; <br>55.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class="org.apache.struts2.dispatcher.PlainTextResult" /&gt;&nbsp;&nbsp; <br>56.&nbsp;&nbsp; <br>57. &lt;/result-types&gt;&nbsp;&nbsp; <br><br>&lt;result-types&gt; <br><br>&lt;result-type name="chain" <br><br>class="com.opensymphony.xwork2.ActionChainResult"/&gt; <br><br>&lt;result-type name="dispatcher" <br><br>class="org.apache.struts2.dispatcher.ServletDispatcherResult" <br><br>default="true"/&gt; <br><br>&lt;result-type name="freemarker" <br><br>class="org.apache.struts2.views.freemarker.FreemarkerResult"/&gt; <br><br>&lt;result-type name="httpheader" <br><br>class="org.apache.struts2.dispatcher.HttpHeaderResult"/&gt; <br><br>&lt;result-type name="redirect" <br><br>class="org.apache.struts2.dispatcher.ServletRedirectResult"/&gt; <br><br>&lt;result-type name="redirectAction" <br><br>class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/&gt; <br><br>&lt;result-type name="stream" <br><br>class="org.apache.struts2.dispatcher.StreamResult"/&gt; <br><br>&lt;result-type name="velocity" <br><br>class="org.apache.struts2.dispatcher.VelocityResult"/&gt; <br><br>&lt;result-type name="xslt" <br><br>class="org.apache.struts2.views.xslt.XSLTResult"/&gt; <br><br>&lt;result-type name="plainText" <br><br>class="org.apache.struts2.dispatcher.PlainTextResult" /&gt; <br><br>&lt;!-- Deprecated name form scheduled for removal in Struts 2.1.0. <br><br>The camelCase versions are preferred. See ww-1707 --&gt; <br><br>&lt;result-type name="redirect-action" <br><br>class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/&gt; <br><br>&lt;result-type name="plaintext" <br><br>class="org.apache.struts2.dispatcher.PlainTextResult" /&gt; <br><br>&lt;/result-types&gt; <br><br><br><br>从上述代码中可以看出在不指定Result类型的时候默认使用dispatcher类型。<br><br><br>定义一个Result值，<br><br>Java 代码<br><br>1. &lt;result name="success" type="dispatcher"&gt;&nbsp;&nbsp; <br>2.&nbsp;&nbsp; <br>3.&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="location"&gt;/myjsp.jsp&lt;/param&gt;&nbsp;&nbsp; <br>4.&nbsp;&nbsp; <br>5. &lt;/result&gt;&nbsp;&nbsp; <br><br>&lt;result name="success" type="dispatcher"&gt; <br><br>&lt;param name="location"&gt;/myjsp.jsp&lt;/param&gt; <br><br>&lt;/result&gt; <br><br><br>由于type默认值是dispatcher，所以这里不需要定义，另外name的默认值为success所以这里也不需要定义。<br>上述代码可以简写为：<br><br>Java 代码<br><br>1. &lt;result&gt;&nbsp;&nbsp; <br>2.&nbsp;&nbsp; <br>3.&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="location"&gt;/myjsp.jsp&lt;/param&gt;&nbsp;&nbsp; <br>4.&nbsp;&nbsp; <br>5. &lt;/result&gt;&nbsp;&nbsp; <br><br>&lt;result&gt; <br><br>&lt;param name="location"&gt;/myjsp.jsp&lt;/param&gt; <br><br>&lt;/result&gt; <br><br><br><br><br>另外location参数也可以直接卸载result标签内部(也就是无需再result里面使用)，所以上述代码的最简单的写法为：<br><br>Java 代码<br><br>1. &lt;result&gt;/myjsp.jsp&lt;/result&gt;&nbsp;&nbsp; <br><br>&lt;result&gt;/myjsp.jsp&lt;/result&gt; <br><br><br><br>我们也可以定义多个不同的result<br><br>Java 代码<br><br>1. &lt;action name="Hello"&gt;&nbsp;&nbsp; <br>2.&nbsp;&nbsp; <br>3. &lt;result&gt;/hello/hello.jsp&lt;/result&gt;&nbsp;&nbsp; <br>4.&nbsp;&nbsp; <br>5. &lt;result name="error"&gt;/hello/error.jsp&lt;/result&gt;&nbsp;&nbsp; <br>6.&nbsp;&nbsp; <br>7. &lt;result name="input"&gt;/hello/input.jsp&lt;/result&gt;&nbsp;&nbsp; <br>8.&nbsp;&nbsp; <br>9. &lt;/action&gt;&nbsp;&nbsp; <br><br>&lt;action name="Hello"&gt; <br><br>&lt;result&gt;/hello/hello.jsp&lt;/result&gt; <br><br>&lt;result name="error"&gt;/hello/error.jsp&lt;/result&gt; <br><br>&lt;result name="input"&gt;/hello/input.jsp&lt;/result&gt; <br><br>&lt;/action&gt; <br><br><br><br>上 述代码的含义为，名字为Hello的Action有三个返回结果，并且都是 dispatcher类型（默认类型），这三个返回值的名字分别为success（默认值），error，input(当输入不通过时，action 方法返回input)，对应的页面的路径分别为 /hello/result.jsp，/hello/error.jsp，/hello/input.jsp。<br><br>有些时候我们需要一个定义在全局的result，这个时候我们可以在package内部定义全局的result，例如：<br><br>Java 代码<br><br>1. &lt;global-results&gt;&nbsp;&nbsp; <br>2.&nbsp;&nbsp; <br>3. &lt;result name="error"&gt;/error.jsp&lt;/result&gt;&nbsp;&nbsp; <br>4.&nbsp;&nbsp; <br>5. &lt;result name="invalid.token"&gt;/error.jsp&lt;/result&gt;&nbsp;&nbsp; <br>6.&nbsp;&nbsp; <br>7. &lt;result name="login" type="redirect-action"&gt;login!input&lt;/result&gt;&nbsp;&nbsp; <br>8.&nbsp;&nbsp; <br>9. &lt;/global-results&gt;&nbsp;&nbsp; <br><br>&lt;global-results&gt; <br><br>&lt;result name="error"&gt;/error.jsp&lt;/result&gt; <br><br>&lt;result name="invalid.token"&gt;/error.jsp&lt;/result&gt; <br><br>&lt;result name="login" type="redirect-action"&gt;login!input&lt;/result&gt; <br><br>&lt;/global-results&gt; <br><br><br><br>动态返回结果<br><br>有些时候，只有当Action执行完璧的时候我们才知道要返回哪个结果，这个时候我们可以在Action内部定义一个属性，这个属性用来存储 Action执行完璧之后的Result值，例如：<br><br>Java 代码<br><br>1. private String nextAction;&nbsp;&nbsp; <br>2.&nbsp;&nbsp; <br>3. public String getNextAction() {&nbsp;&nbsp; <br>4.&nbsp;&nbsp; <br>5.&nbsp;&nbsp;&nbsp;&nbsp; return nextAction;&nbsp;&nbsp; <br>6.&nbsp;&nbsp; <br>7. }&nbsp;&nbsp; <br><br>private String nextAction; <br><br>public String getNextAction() { <br><br>return nextAction; <br><br>} <br><br><br><br>在strutx.xml配置文件中，我们可以使用${nextAction}来引用到Action中的属性，通过${nextAction}表示的内容来动态的返回结果，例如：<br><br>Java 代码<br><br>1. &lt;action name="fragment" class="FragmentAction"&gt;&nbsp;&nbsp; <br>2.&nbsp;&nbsp; <br>3. &lt;result name="next" type="redirect-action"&gt;${nextAction}&lt;/result&gt;&nbsp;&nbsp; <br>4.&nbsp;&nbsp; <br>5. &lt;/action&gt;&nbsp;&nbsp; <br><br>&lt;action name="fragment" class="FragmentAction"&gt; <br><br>&lt;result name="next" type="redirect-action"&gt;${nextAction}&lt;/result&gt; <br><br>&lt;/action&gt; <br><br><br><br>上述Action的execute方法返回next的时候，还需要根据nextAction的属性来判断具体定位到哪个Action。<br><br><br>在struts.xml配置文件中，我们可以使用method=""来设置调用类的哪个方法，这样就可以在一个JAVA类中使用不同的方法来实现不同的功能,就无需每个功能写一类了,例如：<br>Java 代码<br><br>1. &lt;action name="fragment" class="cn.com.web.FragmentAction" method="add"&gt;&nbsp;&nbsp; <br>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;result&gt;/success.jsp&lt;/result&gt;&nbsp;&nbsp; <br>3. &lt;/action&gt;&nbsp; 
<img src ="http://www.cppblog.com/guojingjia2006/aggbug/143462.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2011-04-05 18:17 <a href="http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143462.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts2 - constant </title><link>http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143458.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 05 Apr 2011 09:58:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143458.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/143458.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143458.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/143458.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/143458.html</trackback:ping><description><![CDATA[<div id=sina_keyword_ad_area2 class="articalContent  ">
<div>
<p>在struts的配置文件中的形式为：</p>
<p>&lt;constant name="struts.i18n.encoding" value="UTF-8" /&gt;<br></p>
<p>struts.action.extension<br>The URL extension to use to determine if the request is meant for a Struts action<br>用URL扩展名来确定是否这个请求是被用作Struts action，其实也就是设置 action的后缀，例如login.do的'do'字。</p>
<p>struts.configuration<br>The org.apache.struts2.config.Configuration implementation class<br>org.apache.struts2.config.Configuration接口名</p>
<p>struts.configuration.files<br>A list of configuration files automatically loaded by Struts<br>struts自动加载的一个配置文件列表</p>
<p>struts.configuration.xml.reload<br>Whether to reload the XML configuration or not<br>是否加载xml配置(true,false)</p>
<p>struts.continuations.package<br>The package containing actions that use Rife continuations<br>含有actions的完整连续的package名称</p>
<p>struts.custom.i18n.resources<br>Location of additional localization properties files to load<br>加载附加的国际化属性文件（不包含.properties后缀）</p>
<p>struts.custom.properties<br>Location of additional configuration properties files to load<br>加载附加的配置文件的位置</p>
<p><br>struts.devMode<br>Whether Struts is in development mode or not<br>是否为struts开发模式</p>
<p>struts.dispatcher.parametersWorkaround<br>Whether to use a Servlet request parameter workaround necessary for some versions of WebLogic<br>（某些版本的weblogic专用）是否使用一个servlet请求参数工作区（PARAMETERSWORKAROUND）</p>
<p>struts.enable.DynamicMethodInvocation<br>Allows one to disable dynamic method invocation from the URL<br>允许动态方法调用</p>
<p>struts.freemarker.manager.classname<br>The org.apache.struts2.views.freemarker.FreemarkerManager implementation class<br>org.apache.struts2.views.freemarker.FreemarkerManager接口名</p>
<p>struts.i18n.encoding<br>The encoding to use for localization messages<br>国际化信息内码</p>
<p>struts.i18n.reload<br>Whether the localization messages should automatically be reloaded<br>是否国际化信息自动加载</p>
<p>struts.locale<br>The default locale for the Struts application<br>默认的国际化地区信息</p>
<p>struts.mapper.class<br>The org.apache.struts2.dispatcher.mapper.ActionMapper implementation class<br>org.apache.struts2.dispatcher.mapper.ActionMapper接口</p>
<p>struts.multipart.maxSize<br>The maximize size of a multipart request (file upload)<br>multipart请求信息的最大尺寸（文件上传用）</p>
<p>struts.multipart.parser<br>The org.apache.struts2.dispatcher.multipart.MultiPartRequest parser implementation for a multipart request (file upload)<br>专为multipart请求信息使用的 org.apache.struts2.dispatcher.multipart.MultiPartRequest解析器接口（文件上传用）</p>
<p><br>struts.multipart.saveDir<br>The directory to use for storing uploaded files<br>设置存储上传文件的目录夹</p>
<p>struts.objectFactory<br>The com.opensymphony.xwork2.ObjectFactory implementation class<br>com.opensymphony.xwork2.ObjectFactory接口（spring）</p>
<p>struts.objectFactory.spring.autoWire<br>Whether Spring should autoWire or not<br>是否自动绑定Spring</p>
<p>struts.objectFactory.spring.useClassCache<br>Whether Spring should use its class cache or not<br>是否spring应该使用自身的cache</p>
<p>struts.objectTypeDeterminer<br>The com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation class<br>com.opensymphony.xwork2.util.ObjectTypeDeterminer接口</p>
<p>struts.serve.static.browserCache<br>If static content served by the Struts filter should set browser caching header properties or not<br>是否struts过滤器中提供的静态内容应该被浏览器缓存在头部属性中</p>
<p>struts.serve.static<br>Whether the Struts filter should serve static content or not<br>是否struts过滤器应该提供静态内容</p>
<p>struts.tag.altSyntax<br>Whether to use the alterative syntax for the tags or not<br>是否可以用替代的语法替代tags</p>
<p>struts.ui.templateDir<br>The directory containing UI templates<br>UI templates的目录夹</p>
<p>struts.ui.theme<br>The default UI template theme<br>默认的UI template主题</p>
<p>struts.url.http.port<br>The HTTP port used by Struts URLs<br>设置http端口</p>
<p>struts.url.https.port<br>The HTTPS port used by Struts URLs<br>设置https端口</p>
<p>struts.url.includeParams<br>The default includeParams method to generate Struts URLs<br>在url中产生 默认的includeParams</p>
<p><br>struts.velocity.configfile<br>The Velocity configuration file path<br>velocity配置文件路径</p>
<p>struts.velocity.contexts<br>List of Velocity context names<br>velocity的context列表</p>
<p><br>struts.velocity.manager.classname<br>org.apache.struts2.views.velocity.VelocityManager implementation class<br>org.apache.struts2.views.velocity.VelocityManager接口名</p>
<p>struts.velocity.toolboxlocation<br>The location of the Velocity toolbox<br>velocity工具盒的位置<br>struts.xslt.nocache<br>Whether or not XSLT templates should not be cached<br>是否XSLT模版应该被缓存</p>
<p>【原创】struts2的struts.properties配置文件详解</p>
<p>struts.action.extension<br>The URL extension to use to determine if the request is meant for a Struts action<br>用URL扩展名来确定是否这个请求是被用作Struts action，其实也就是设置 action的后缀，例如login.do的'do'字。</p>
<p>struts.configuration<br>The org.apache.struts2.config.Configuration implementation class<br>org.apache.struts2.config.Configuration接口名</p>
<p>struts.configuration.files<br>A list of configuration files automatically loaded by Struts<br>struts自动加载的一个配置文件列表</p>
<p>struts.configuration.xml.reload<br>Whether to reload the XML configuration or not<br>是否加载xml配置(true,false)</p>
<p>struts.continuations.package<br>The package containing actions that use Rife continuations<br>含有actions的完整连续的package名称</p>
<p>struts.custom.i18n.resources<br>Location of additional localization properties files to load<br>加载附加的国际化属性文件（不包含.properties后缀）</p>
<p>struts.custom.properties<br>Location of additional configuration properties files to load<br>加载附加的配置文件的位置</p>
<p><br>struts.devMode<br>Whether Struts is in development mode or not<br>是否为struts开发模式</p>
<p>struts.dispatcher.parametersWorkaround<br>Whether to use a Servlet request parameter workaround necessary for some versions of WebLogic<br>（某些版本的weblogic专用）是否使用一个servlet请求参数工作区（PARAMETERSWORKAROUND）</p>
<p>struts.enable.DynamicMethodInvocation<br>Allows one to disable dynamic method invocation from the URL<br>允许动态方法调用</p>
<p>struts.freemarker.manager.classname<br>The org.apache.struts2.views.freemarker.FreemarkerManager implementation class<br>org.apache.struts2.views.freemarker.FreemarkerManager接口名</p>
<p>struts.i18n.encoding<br>The encoding to use for localization messages<br>国际化信息内码</p>
<p>struts.i18n.reload<br>Whether the localization messages should automatically be reloaded<br>是否国际化信息自动加载</p>
<p>struts.locale<br>The default locale for the Struts application<br>默认的国际化地区信息</p>
<p>struts.mapper.class<br>The org.apache.struts2.dispatcher.mapper.ActionMapper implementation class<br>org.apache.struts2.dispatcher.mapper.ActionMapper接口</p>
<p>struts.multipart.maxSize<br>The maximize size of a multipart request (file upload)<br>multipart请求信息的最大尺寸（文件上传用）</p>
<p>struts.multipart.parser<br>The org.apache.struts2.dispatcher.multipart.MultiPartRequest parser implementation for a multipart request (file upload)<br>专为multipart请求信息使用的 org.apache.struts2.dispatcher.multipart.MultiPartRequest解析器接口（文件上传用）</p>
<p><br>struts.multipart.saveDir<br>The directory to use for storing uploaded files<br>设置存储上传文件的目录夹</p>
<p>struts.objectFactory<br>The com.opensymphony.xwork2.ObjectFactory implementation class<br>com.opensymphony.xwork2.ObjectFactory接口（spring）</p>
<p>struts.objectFactory.spring.autoWire<br>Whether Spring should autoWire or not<br>是否自动绑定Spring</p>
<p>struts.objectFactory.spring.useClassCache<br>Whether Spring should use its class cache or not<br>是否spring应该使用自身的cache</p>
<p>struts.objectTypeDeterminer<br>The com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation class<br>com.opensymphony.xwork2.util.ObjectTypeDeterminer接口</p>
<p>struts.serve.static.browserCache<br>If static content served by the Struts filter should set browser caching header properties or not<br>是否struts过滤器中提供的静态内容应该被浏览器缓存在头部属性中</p>
<p>struts.serve.static<br>Whether the Struts filter should serve static content or not<br>是否struts过滤器应该提供静态内容</p>
<p>struts.tag.altSyntax<br>Whether to use the alterative syntax for the tags or not<br>是否可以用替代的语法替代tags</p>
<p>struts.ui.templateDir<br>The directory containing UI templates<br>UI templates的目录夹</p>
<p>struts.ui.theme<br>The default UI template theme<br>默认的UI template主题</p>
<p>struts.url.http.port<br>The HTTP port used by Struts URLs<br>设置http端口</p>
<p>struts.url.https.port<br>The HTTPS port used by Struts URLs<br>设置https端口</p>
<p>struts.url.includeParams<br>The default includeParams method to generate Struts URLs<br>在url中产生 默认的includeParams</p>
<p><br>struts.velocity.configfile<br>The Velocity configuration file path<br>velocity配置文件路径</p>
<p>struts.velocity.contexts<br>List of Velocity context names<br>velocity的context列表</p>
<p><br>struts.velocity.manager.classname<br>org.apache.struts2.views.velocity.VelocityManager implementation class<br>org.apache.struts2.views.velocity.VelocityManager接口名</p>
<p>struts.velocity.toolboxlocation<br>The location of the Velocity toolbox<br>velocity工具盒的位置<br>struts.xslt.nocache<br>Whether or not XSLT templates should not be cached<br>是否XSLT模版应该被缓存</p>
</div>
</div>
<div id=cnblogs_post_body>
<p>struts2加载常量的顺序<br>struts-default.xml<br>struts-plugin.xml<br>struts.xml<br>struts.properties<br>web.xml<br>后面的会覆盖掉前面的常量，最好在struts.xml中定义 </p>
<p>&nbsp;</p>
<p>怎么由.action改为.do<br>&lt;constant name="struts.action.extension" value="do"/&gt;<br>do或action<br>&lt;constant name="struts.action.extension" value="do,action"/&gt;</p>
<p><br>truts2用来指定默认编码的<br>&lt;constant name="struts.i18n.encoding" value="UTF-8"/&gt;</p>
<p>&nbsp;</p>
<p>改变常量后不许重启服务器<br>&lt;constant name="struts.configuration.xml.reload" value="true"/&gt;<br>系统默认为false&nbsp; </p>
<p><br>便于排错,打印出更详细的错误信息<br>&lt;constant name="struts.devMode" value="true"&gt;</p>
<p>&nbsp;</p>
<p>设置浏览器是否缓存静态内容，默认为TRUE&nbsp; 开发阶段最好关闭<br>&lt;constant name="struts.server.static.browserCache" valur="false"/&gt;</p>
<p>&nbsp;</p>
<p>默认的视图主题<br>&lt;constant name="struts.ui.theme" value="simple"/&gt;</p>
<p>&nbsp;</p>
<p>与spring集成时，指定spring负责action对象的创建<br>&lt;struts name="struts.objectFactory" value="spring"/&gt;</p>
<p>&nbsp;</p>
<p>上传文件大小限制<br>&lt;struts name="struts.multipart.maxSize" value="10241024"/&gt;</p>
</div>
<img src ="http://www.cppblog.com/guojingjia2006/aggbug/143458.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2011-04-05 17:58 <a href="http://www.cppblog.com/guojingjia2006/archive/2011/04/05/143458.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>flex  获取 flickr 图片 </title><link>http://www.cppblog.com/guojingjia2006/archive/2010/07/20/120905.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 20 Jul 2010 14:10:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2010/07/20/120905.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/120905.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2010/07/20/120905.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/120905.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/120905.html</trackback:ping><description><![CDATA[这两天主要看了flex的cairngorm框架，顺便写了个用flex获取flickr网站的图片,其中不乏艰难的过程,第一个就是flickr库api和实际编译出来的有出入,其中Photo.as缺少farm就是一个明显，所以只能自己手工修改源码重新编译,网上讨论这个问题的比较少，不知道为什么，我找了好久才找到一篇关于这个的。还有一个问题就是大墙，其中网上有段这么描述:<br>
<div class="articalTitle"><span style="color: #888888;"><strong>最
近打开Flickr发现有些图片总是显示小红叉，开始以为是网速问题没有在意，昨天有个朋友说他存在Flickr上的图片都不能显示了，发觉情况不对劲
了。<br>今天看到了这篇帖子：</strong></span><a href="http://www.flickr.com/help/forum/zh-hk/117995/" target="_blank"><span style="color: #888888;"><strong>http://www.flickr.com/help/forum/zh-hk/117995/</strong></span></a><br><span style="color: #888888;"><strong>原来又是伟大的墙在作怪，这次的症状是所有的网通线路都无法
访问farm3.static.flickr.com和farm5.static.flickr.com这两个服务器，由于这次只是让域名无法解析，所以
最简单的解决办法是修改host文件，方法如下：<br>用记事本打开C:\Windows\System32\drivers\etc\hosts
这个文件，然后在文件最后追加两行:</strong></span></div>
<span style="color: #888888;"><strong></strong></span><span style="color: #888888;"><strong><img src="http://filer.blogbus.com/4552913/455291312659442693.png" alt="" border="0"></strong></span><br><span style="color: #888888;"><strong>然
后重启一下浏览器，我们亲爱的Flickr又复活了&nbsp; : )</strong></span><br><br>由于自己是网通的，图片是farm5服务器的，所以图片也显示不了，不过修改下host表就OK了<br><br>写这个的主要目的还是学习下cairgorm框架，学习他的MVC思想，目的算基本达到，flickr的问题实在有点烦，不过还是走过来了，下面是运行效果:<br><img alt="" src="http://www.cppblog.com/images/cppblog_com/guojingjia2006/ss.JPG" height="522" width="920"><br><br>有用的几个网址：<br>http://code.google.com/p/as3flickrlib/issues/detail?id=14#makechanges<br>http://www.flickr.com/services/api/<br>http://naramiki.blogbus.com/logs/57133710.html<br><br>最后附上flickr自己编译的库<br><a  href="http://www.cppblog.com/Files/guojingjia2006/flickr087.swc.rar">http://www.cppblog.com/Files/guojingjia2006/flickr087.swc.rar</a><br><br> <img src ="http://www.cppblog.com/guojingjia2006/aggbug/120905.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2010-07-20 22:10 <a href="http://www.cppblog.com/guojingjia2006/archive/2010/07/20/120905.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jQuery 左右移动</title><link>http://www.cppblog.com/guojingjia2006/archive/2009/08/29/94781.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sat, 29 Aug 2009 14:22:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2009/08/29/94781.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/94781.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2009/08/29/94781.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/94781.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/94781.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&lt;!DOCTYPE&nbsp;HTML&nbsp;PUBLIC&nbsp;"-//W3C//DTD&nbsp;HTML&nbsp;4.01&nbsp;Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"&gt;&lt;html&nbsp;xmlns="http://www.w3.org/1999/xhtml"&gt;&...&nbsp;&nbsp;<a href='http://www.cppblog.com/guojingjia2006/archive/2009/08/29/94781.html'>阅读全文</a><img src ="http://www.cppblog.com/guojingjia2006/aggbug/94781.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2009-08-29 22:22 <a href="http://www.cppblog.com/guojingjia2006/archive/2009/08/29/94781.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>commons-fileupload 中文乱码问题的解决</title><link>http://www.cppblog.com/guojingjia2006/archive/2009/08/25/94366.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 25 Aug 2009 06:33:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2009/08/25/94366.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/94366.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2009/08/25/94366.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/94366.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/94366.html</trackback:ping><description><![CDATA[1.原页面我用utf-8编码<br>2.设置一个filter,统一用utf-8<br>3.文件域乱码解决:<br>String encode=request.getCharacterEncoding();<br>ServletFileUpload upload = new ServletFileUpload(factory);<br>upload.setHeaderEncoding(encoding);<br><br>4.表单域乱码解决:<br>item.getString(encode); 
<img src ="http://www.cppblog.com/guojingjia2006/aggbug/94366.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2009-08-25 14:33 <a href="http://www.cppblog.com/guojingjia2006/archive/2009/08/25/94366.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>