登录|免费注册
[搜索][菜单]
®
高级...

浏览选项

  • 手机网站排名
[子菜单]

(无标题)

?博客园_首页代码改变世界uuid:b8e24a94-b1d3-4b29-9243-6f0ff0b30917;id=64692014-10-26T00:34:42Zfeed.cnblogs.comhttp://www.cnblogs.com/jiagoushi/p/4051270.htmlEF 的 霸气配置,秒杀一切 - baidixing通过EF 作为操作数据库的工具有一段时间了,也做了几个相对不大的项目,慢慢的也对EF的使用摸索出来了一些规则,虽然说不是技术难点,但是,我说的是但是,能够提高我们开发效率的棉花糖有时我们还是必须要吃的,因为他确实很甜很甜。现在Ef已经更新到6.1.1了,从原来的5.0 到现在也不过是短短的一年多.....2014-10-25T16:53:00Z2014-10-25T16:53:00Zbaidixinghttp://www.cnblogs.com/jiagoushi/<p>&nbsp; &nbsp; 通过EF 作为操作数据库的工具有一段时间了,也做了几个相对不大的项目,慢慢的也对EF的使用摸索出来了一些规则,虽然说不是技术难点,但是,我说的是但是,能够提高我们开发效率的棉花糖有时我们还是必须要吃的,因为他确实很甜很甜。现在Ef已经更新到6.1.1了,从原来的5.0 到现在也不过是短短的一年多,所以说Ef的生命力还是很强的。什么 你要我对比一下EF和NHibernate的优缺点,这不是本文的重点,我只说一句,EF侧重代码配置,NHibernate 侧重配置文件配置,但是说哪种好,萝卜白菜 各有所爱吧。</p><p>&nbsp; 刚开始使用EF操作数据表我们是这样使用的,通过在DBContext中添加Dbset&lt;T&gt; 这种形式的属性来实现,但是,我说的是但是,这种方式随着我们的实体Domain越来越多的时候我们不得不一个一个的添加到DbContext中,这不禁让我很苦恼,有没有更好的办法呢?</p><p>&nbsp;为了说明的方便,我建立了一个控制台的程序,毕竟EF和具体的项目类型无关。</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Program<br/></span><span style="color: #008080;"> 2</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)<br/></span><span style="color: #008080;"> 4</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 5</span> TestContext testContext = <span style="color: #0000ff;">new</span><span style="color: #000000;"> TestContext();<br/></span><span style="color: #008080;"> 6</span> <span style="color: #808080;">///</span><span style="color: #008000;">获取数据库表Person中的所有数据 在查询的时候最好加上AsNoTracking 禁止EF跟踪</span><br/><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">var</span> personList =<span style="color: #000000;"> testContext.Persons.AsNoTracking().ToList();<br/></span><span style="color: #008080;"> 8</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 9</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">10</span> <br/><span style="color: #008080;">11</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> TestContext : DbContext<br/></span><span style="color: #008080;">12</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">13</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> TestContext _instance;<br/></span><span style="color: #008080;">14</span> <br/><span style="color: #008080;">15</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> TestContext Instance<br/></span><span style="color: #008080;">16</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">17</span> <span style="color: #0000ff;">get</span><br/><span style="color: #008080;">18</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">19</span> <span style="color: #0000ff;">if</span> (_instance == <span style="color: #0000ff;">null</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">20</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">21</span> _instance = <span style="color: #0000ff;">new</span><span style="color: #000000;"> TestContext();<br/></span><span style="color: #008080;">22</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">23</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> _instance;<br/></span><span style="color: #008080;">24</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">25</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">26</span> <br/><span style="color: #008080;">27</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> _connectionString;<br/></span><span style="color: #008080;">28</span> <br/><span style="color: #008080;">29</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> ConnectionString<br/></span><span style="color: #008080;">30</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">31</span> <span style="color: #0000ff;">get</span><br/><span style="color: #008080;">32</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">33</span> <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">string</span><span style="color: #000000;">.IsNullOrWhiteSpace(_connectionString))<br/></span><span style="color: #008080;">34</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">35</span> _connectionString = ConfigurationManager.ConnectionStrings[<span style="color: #800000;">"</span><span style="color: #800000;">testConn</span><span style="color: #800000;">"</span><span style="color: #000000;">].ConnectionString;<br/></span><span style="color: #008080;">36</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">37</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> _connectionString;<br/></span><span style="color: #008080;">38</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">39</span> <span style="color: #0000ff;">set</span><br/><span style="color: #008080;">40</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">41</span> _connectionString =<span style="color: #000000;"> value;<br/></span><span style="color: #008080;">42</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">43</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">44</span> <br/><span style="color: #008080;">45</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> TestContext()<br/></span><span style="color: #008080;">46</span> : <span style="color: #0000ff;">base</span>(<span style="color: #800000;">"</span><span style="color: #800000;">name=testConn</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">47</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">48</span> _connectionString = ConfigurationManager.ConnectionStrings[<span style="color: #800000;">"</span><span style="color: #800000;">testConn</span><span style="color: #800000;">"</span><span style="color: #000000;">].ConnectionString;<br/></span><span style="color: #008080;">49</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">50</span> <span style="color: #0000ff;">public</span> TestContext(<span style="color: #0000ff;">string</span><span style="color: #000000;"> connectionString)<br/></span><span style="color: #008080;">51</span> : <span style="color: #0000ff;">base</span><span style="color: #000000;">(connectionString)<br/></span><span style="color: #008080;">52</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">53</span> <br/><span style="color: #008080;">54</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">55</span> <br/><span style="color: #008080;">56</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">57</span> <span style="color: #808080;">///</span><span style="color: #008000;"> 定义的实体<br/></span><span style="color: #008080;">58</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">59</span> <span style="color: #0000ff;">public</span> DbSet&lt;Person&gt; Persons { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;">60</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">61</span> [Table(<span style="color: #800000;">"</span><span style="color: #800000;">Person</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br/></span><span style="color: #008080;">62</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Person<br/></span><span style="color: #008080;">63</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">64</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Name { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;">65</span> <br/><span style="color: #008080;">66</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Age { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;">67</span> }</div><p>&nbsp;</p><p>&nbsp;</p><p>每次添加实体Domain 都要在DbContext 中添加一个对应的属性,很令人苦恼,并且如果属性为string 类型,在数据库中创建的表的长度为max,当然我们可以修改EF的默认约定来让string 类型在数据表中具有一定的长度。我们有没有更好的方式来控制EF创建的数据表呢,并且要易于维护,让所有同事都可以很轻松的掌握。当然,有一个新大陆被发现了。</p><p>我们通过反射来找到所有继承自EntityTypeConfiguration的类,这些类就是EF的映射类,我们把这些映射类添加到EF &nbsp;configuration中就可以实现我们的功能,说太多,上代码。</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Program<br/></span><span style="color: #008080;"> 2</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span> Main(<span style="color: #0000ff;">string</span><span style="color: #000000;">[] args)<br/></span><span style="color: #008080;"> 4</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 5</span> TestContext testContext = <span style="color: #0000ff;">new</span><span style="color: #000000;"> TestContext();<br/></span><span style="color: #008080;"> 6</span> <span style="color: #808080;">///</span><span style="color: #008000;">获取数据库表Person中的所有数据 在查询的时候最好加上AsNoTracking 禁止EF跟踪</span><br/><span style="color: #008080;"> 7</span> <span style="color: #008000;">//</span><span style="color: #008000;"> var personList = testContext.Persons.AsNoTracking().ToList();</span><br/><span style="color: #008080;"> 8</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 9</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 10</span> <br/><span style="color: #008080;"> 11</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> TestContext : DbContext<br/></span><span style="color: #008080;"> 12</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 13</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> TestContext _instance;<br/></span><span style="color: #008080;"> 14</span> <br/><span style="color: #008080;"> 15</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span><span style="color: #000000;"> TestContext Instance<br/></span><span style="color: #008080;"> 16</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 17</span> <span style="color: #0000ff;">get</span><br/><span style="color: #008080;"> 18</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 19</span> <span style="color: #0000ff;">if</span> (_instance == <span style="color: #0000ff;">null</span><span style="color: #000000;">)<br/></span><span style="color: #008080;"> 20</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 21</span> _instance = <span style="color: #0000ff;">new</span><span style="color: #000000;"> TestContext();<br/></span><span style="color: #008080;"> 22</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 23</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> _instance;<br/></span><span style="color: #008080;"> 24</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 25</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 26</span> <br/><span style="color: #008080;"> 27</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> _connectionString;<br/></span><span style="color: #008080;"> 28</span> <br/><span style="color: #008080;"> 29</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span><span style="color: #000000;"> ConnectionString<br/></span><span style="color: #008080;"> 30</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 31</span> <span style="color: #0000ff;">get</span><br/><span style="color: #008080;"> 32</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 33</span> <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">string</span><span style="color: #000000;">.IsNullOrWhiteSpace(_connectionString))<br/></span><span style="color: #008080;"> 34</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 35</span> _connectionString = ConfigurationManager.ConnectionStrings[<span style="color: #800000;">"</span><span style="color: #800000;">testConn</span><span style="color: #800000;">"</span><span style="color: #000000;">].ConnectionString;<br/></span><span style="color: #008080;"> 36</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 37</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> _connectionString;<br/></span><span style="color: #008080;"> 38</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 39</span> <span style="color: #0000ff;">set</span><br/><span style="color: #008080;"> 40</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 41</span> _connectionString =<span style="color: #000000;"> value;<br/></span><span style="color: #008080;"> 42</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 43</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 44</span> <br/><span style="color: #008080;"> 45</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> TestContext()<br/></span><span style="color: #008080;"> 46</span> : <span style="color: #0000ff;">base</span>(<span style="color: #800000;">"</span><span style="color: #800000;">name=testConn</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br/></span><span style="color: #008080;"> 47</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 48</span> _connectionString = ConfigurationManager.ConnectionStrings[<span style="color: #800000;">"</span><span style="color: #800000;">testConn</span><span style="color: #800000;">"</span><span style="color: #000000;">].ConnectionString;<br/></span><span style="color: #008080;"> 49</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 50</span> <span style="color: #0000ff;">public</span> TestContext(<span style="color: #0000ff;">string</span><span style="color: #000000;"> connectionString)<br/></span><span style="color: #008080;"> 51</span> : <span style="color: #0000ff;">base</span><span style="color: #000000;">(connectionString)<br/></span><span style="color: #008080;"> 52</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 53</span> <br/><span style="color: #008080;"> 54</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 55</span> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">override</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> OnModelCreating(DbModelBuilder modelBuilder)<br/></span><span style="color: #008080;"> 56</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 57</span> <span style="color: #808080;">///</span><span style="color: #008000;">DomainMapping 所在的程序集一定要写对,因为目前在当前项目所以是采用的当前正在运行的程序集 如果你的mapping在单独的项目中 记得要加载对应的assembly<br/></span><span style="color: #008080;"> 58</span> <span style="color: #808080;">///</span><span style="color: #008000;">这是重点</span><br/><span style="color: #008080;"> 59</span> <span style="color: #0000ff;">var</span> typesToRegister =<span style="color: #000000;"> Assembly.GetExecutingAssembly().GetTypes()<br/></span><span style="color: #008080;"> 60</span> .Where(type =&gt; !<span style="color: #000000;">String.IsNullOrEmpty(type.Namespace))<br/></span><span style="color: #008080;"> 61</span> .Where(type =&gt; type.BaseType != <span style="color: #0000ff;">null</span> &amp;&amp; type.BaseType.BaseType != <span style="color: #0000ff;">null</span> &amp;&amp; type.BaseType.BaseType.GetGenericTypeDefinition() == <span style="color: #0000ff;">typeof</span>(EntityTypeConfiguration&lt;&gt;<span style="color: #000000;">));<br/></span><span style="color: #008080;"> 62</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> type <span style="color: #0000ff;">in</span><span style="color: #000000;"> typesToRegister)<br/></span><span style="color: #008080;"> 63</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 64</span> dynamic configurationInstance =<span style="color: #000000;"> Activator.CreateInstance(type);<br/></span><span style="color: #008080;"> 65</span> <span style="color: #000000;"> modelBuilder.Configurations.Add(configurationInstance);<br/></span><span style="color: #008080;"> 66</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 67</span> <br/><span style="color: #008080;"> 68</span> <span style="color: #0000ff;">base</span><span style="color: #000000;">.OnModelCreating(modelBuilder);<br/></span><span style="color: #008080;"> 69</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 70</span> <br/><span style="color: #008080;"> 71</span> <br/><span style="color: #008080;"> 72</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 73</span> <br/><span style="color: #008080;"> 74</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> BaseDomain<br/></span><span style="color: #008080;"> 75</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 76</span> <br/><span style="color: #008080;"> 77</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 78</span> [Table(<span style="color: #800000;">"</span><span style="color: #800000;">Person</span><span style="color: #800000;">"</span><span style="color: #000000;">)]<br/></span><span style="color: #008080;"> 79</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> Person<br/></span><span style="color: #008080;"> 80</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 81</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> ID { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;"> 82</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Name { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;"> 83</span> <br/><span style="color: #008080;"> 84</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Age { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;"> 85</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 86</span> <br/><span style="color: #008080;"> 87</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> PersonMapping : BaseDomainMapping&lt;Person&gt;<br/><span style="color: #008080;"> 88</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 89</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">override</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Init()<br/></span><span style="color: #008080;"> 90</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 91</span> <span style="color: #0000ff;">this</span>.ToTable(<span style="color: #800000;">"</span><span style="color: #800000;">Person</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 92</span> <span style="color: #0000ff;">this</span>.HasKey(l =&gt;<span style="color: #000000;"> l.ID);<br/></span><span style="color: #008080;"> 93</span> <span style="color: #0000ff;">this</span>.Property(l =&gt; l.Name).HasMaxLength(<span style="color: #800080;">200</span>).IsRequired();<span style="color: #008000;">//</span><span style="color: #008000;">设置Name属性长度为200 并且是必填</span><br/><span style="color: #008080;"> 94</span> <span style="color: #0000ff;">this</span>.Property(l =&gt; l.Age).HasMaxLength(<span style="color: #800080;">200</span>).IsOptional(); <span style="color: #008000;">//</span><span style="color: #008000;">设置Age长度为200 并且可为空</span><br/><span style="color: #008080;"> 95</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 96</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 97</span> <br/><span style="color: #008080;"> 98</span> <br/><span style="color: #008080;"> 99</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">abstract</span> <span style="color: #0000ff;">class</span> BaseDomainMapping&lt;T&gt; : EntityTypeConfiguration&lt;T&gt;<br/><span style="color: #008080;">100</span> <span style="color: #0000ff;">where</span> T : BaseDomain, <span style="color: #0000ff;">new</span><span style="color: #000000;">()<br/></span><span style="color: #008080;">101</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">102</span> <br/><span style="color: #008080;">103</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> BaseDomainMapping()<br/></span><span style="color: #008080;">104</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">105</span> <span style="color: #000000;"> Init();<br/></span><span style="color: #008080;">106</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">107</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">108</span> <span style="color: #808080;">///</span><span style="color: #008000;"> 初始化代码<br/></span><span style="color: #008080;">109</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">110</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Init()<br/></span><span style="color: #008080;">111</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">112</span> Console.WriteLine(<span style="color: #800000;">"</span><span style="color: #800000;">Init</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">113</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">114</span> }</div><p>&nbsp;</p><p>这个其实用到了主要两个知识点,一个就是抽象类中定义的virtual方法,在抽象类中进行调用,在继承自抽象类的类中override这个方法,此文为Init,那么子类中的这个方法也会被调用,避免在每个子类中都要写调用Init的方法。</p><p>&nbsp;</p><p>第二个就是,注意OnModelCreating &nbsp;方法,他找到所有继承自</p>EntityTypeConfiguration的类,然后添加到Configuration中,也就是我们实现了多个配置,统一添加到EF的配置中,EF在执行的时候会执行所有的配置类,当然包括我们自己定义的映射Mapping。<br /><br /><br /><br />大家可能要说了,这样是可以只写一个映射类就可以,但是我们怎么访问呢?没有了原来的通过属性 TestContext testContext = new<span> TestContext();<br/> ///获取数据库表Person中的所有数据 在查询的时候最好加上AsNoTracking 禁止EF跟踪<br/> var personList = testContext.Persons.AsNoTracking().ToList(); <span style="color: #ff0000;">通过属性访问很简单方便</span></span>,我们需要想办法获取到DbSet 类通过EF访问数据库,现在我们的思路就是通过我们定义的TestContext ,找到我们通过反射注册的所有配置类。<br /><br /><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 2</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Entity Framework repository<br/></span><span style="color: #008080;"> 3</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">class</span> EfRepository&lt;T&gt; : IRepository&lt;T&gt; <span style="color: #0000ff;">where</span><span style="color: #000000;"> T : BaseDomain<br/></span><span style="color: #008080;"> 5</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">readonly</span><span style="color: #000000;"> IDbContext _context; ///<span style="color: #ff0000;">可以认为就是我们定义的TestContext<br/></span></span><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">private</span> IDbSet&lt;T&gt;<span style="color: #000000;"> _entities;<br/></span><span style="color: #008080;"> 8</span> <br/><span style="color: #008080;"> 9</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 10</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Ctor<br/></span><span style="color: #008080;"> 11</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 12</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="context"&gt;</span><span style="color: #008000;">Object context</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;"> 13</span> <span style="color: #0000ff;">public</span><span style="color: #000000;"> EfRepository(IDbContext context)<br/></span><span style="color: #008080;"> 14</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 15</span> <span style="color: #0000ff;">this</span>._context =<span style="color: #000000;"> context;<br/></span><span style="color: #008080;"> 16</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 17</span> <br/><span style="color: #008080;"> 18</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 19</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Get entity by identifier<br/></span><span style="color: #008080;"> 20</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 21</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="id"&gt;</span><span style="color: #008000;">Identifier</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;"> 22</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;returns&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/returns&gt;</span><br/><span style="color: #008080;"> 23</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> T GetById(<span style="color: #0000ff;">object</span><span style="color: #000000;"> id)<br/></span><span style="color: #008080;"> 24</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 25</span> <span style="color: #008000;">//</span><span style="color: #008000;">see some suggested performance optimization (not tested)<br/></span><span style="color: #008080;"> 26</span> <span style="color: #008000;">//</span><span style="color: #008000; text-decoration: underline;">http://stackoverflow.com/questions/11686225/dbset-find-method-ridiculously-slow-compared-to-singleordefault-on-id/11688189</span><span style="color: #008000;">#comment34876113_11688189</span><br/><span style="color: #008080;"> 27</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.Entities.Find(id);<br/></span><span style="color: #008080;"> 28</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 29</span> <br/><span style="color: #008080;"> 30</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 31</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Insert entity<br/></span><span style="color: #008080;"> 32</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 33</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="entity"&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;"> 34</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Insert(T entity)<br/></span><span style="color: #008080;"> 35</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 36</span> <span style="color: #0000ff;">try</span><br/><span style="color: #008080;"> 37</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 38</span> <span style="color: #0000ff;">if</span> (entity == <span style="color: #0000ff;">null</span><span style="color: #000000;">)<br/></span><span style="color: #008080;"> 39</span> <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentNullException(<span style="color: #800000;">"</span><span style="color: #800000;">entity</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 40</span> <br/><span style="color: #008080;"> 41</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.Entities.Add(entity);<br/></span><span style="color: #008080;"> 42</span> <br/><span style="color: #008080;"> 43</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">._context.SaveChanges();<br/></span><span style="color: #008080;"> 44</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 45</span> <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (DbEntityValidationException dbEx)<br/></span><span style="color: #008080;"> 46</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 47</span> <span style="color: #0000ff;">var</span> msg = <span style="color: #0000ff;">string</span><span style="color: #000000;">.Empty;<br/></span><span style="color: #008080;"> 48</span> <br/><span style="color: #008080;"> 49</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> validationErrors <span style="color: #0000ff;">in</span><span style="color: #000000;"> dbEx.EntityValidationErrors)<br/></span><span style="color: #008080;"> 50</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> validationError <span style="color: #0000ff;">in</span><span style="color: #000000;"> validationErrors.ValidationErrors)<br/></span><span style="color: #008080;"> 51</span> msg += <span style="color: #0000ff;">string</span>.Format(<span style="color: #800000;">"</span><span style="color: #800000;">Property: {0} Error: {1}</span><span style="color: #800000;">"</span>, validationError.PropertyName, validationError.ErrorMessage) +<span style="color: #000000;"> Environment.NewLine;<br/></span><span style="color: #008080;"> 52</span> <br/><span style="color: #008080;"> 53</span> <span style="color: #0000ff;">var</span> fail = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Exception(msg, dbEx);<br/></span><span style="color: #008080;"> 54</span> <span style="color: #008000;">//</span><span style="color: #008000;">Debug.WriteLine(fail.Message, fail);</span><br/><span style="color: #008080;"> 55</span> <span style="color: #0000ff;">throw</span><span style="color: #000000;"> fail;<br/></span><span style="color: #008080;"> 56</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 57</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 58</span> <br/><span style="color: #008080;"> 59</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 60</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Update entity<br/></span><span style="color: #008080;"> 61</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 62</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="entity"&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;"> 63</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Update(T entity)<br/></span><span style="color: #008080;"> 64</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 65</span> <span style="color: #0000ff;">try</span><br/><span style="color: #008080;"> 66</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 67</span> <span style="color: #0000ff;">if</span> (entity == <span style="color: #0000ff;">null</span><span style="color: #000000;">)<br/></span><span style="color: #008080;"> 68</span> <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentNullException(<span style="color: #800000;">"</span><span style="color: #800000;">entity</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 69</span> <br/><span style="color: #008080;"> 70</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">._context.SaveChanges();<br/></span><span style="color: #008080;"> 71</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 72</span> <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (DbEntityValidationException dbEx)<br/></span><span style="color: #008080;"> 73</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 74</span> <span style="color: #0000ff;">var</span> msg = <span style="color: #0000ff;">string</span><span style="color: #000000;">.Empty;<br/></span><span style="color: #008080;"> 75</span> <br/><span style="color: #008080;"> 76</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> validationErrors <span style="color: #0000ff;">in</span><span style="color: #000000;"> dbEx.EntityValidationErrors)<br/></span><span style="color: #008080;"> 77</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> validationError <span style="color: #0000ff;">in</span><span style="color: #000000;"> validationErrors.ValidationErrors)<br/></span><span style="color: #008080;"> 78</span> msg += Environment.NewLine + <span style="color: #0000ff;">string</span>.Format(<span style="color: #800000;">"</span><span style="color: #800000;">Property: {0} Error: {1}</span><span style="color: #800000;">"</span><span style="color: #000000;">, validationError.PropertyName, validationError.ErrorMessage);<br/></span><span style="color: #008080;"> 79</span> <br/><span style="color: #008080;"> 80</span> <span style="color: #0000ff;">var</span> fail = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Exception(msg, dbEx);<br/></span><span style="color: #008080;"> 81</span> <span style="color: #008000;">//</span><span style="color: #008000;">Debug.WriteLine(fail.Message, fail);</span><br/><span style="color: #008080;"> 82</span> <span style="color: #0000ff;">throw</span><span style="color: #000000;"> fail;<br/></span><span style="color: #008080;"> 83</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 84</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 85</span> <br/><span style="color: #008080;"> 86</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 87</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Delete entity<br/></span><span style="color: #008080;"> 88</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 89</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="entity"&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;"> 90</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Delete(T entity)<br/></span><span style="color: #008080;"> 91</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 92</span> <span style="color: #0000ff;">try</span><br/><span style="color: #008080;"> 93</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 94</span> <span style="color: #0000ff;">if</span> (entity == <span style="color: #0000ff;">null</span><span style="color: #000000;">)<br/></span><span style="color: #008080;"> 95</span> <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> ArgumentNullException(<span style="color: #800000;">"</span><span style="color: #800000;">entity</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 96</span> <br/><span style="color: #008080;"> 97</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.Entities.Remove(entity);<br/></span><span style="color: #008080;"> 98</span> <br/><span style="color: #008080;"> 99</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">._context.SaveChanges();<br/></span><span style="color: #008080;">100</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">101</span> <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (DbEntityValidationException dbEx)<br/></span><span style="color: #008080;">102</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">103</span> <span style="color: #0000ff;">var</span> msg = <span style="color: #0000ff;">string</span><span style="color: #000000;">.Empty;<br/></span><span style="color: #008080;">104</span> <br/><span style="color: #008080;">105</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> validationErrors <span style="color: #0000ff;">in</span><span style="color: #000000;"> dbEx.EntityValidationErrors)<br/></span><span style="color: #008080;">106</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> validationError <span style="color: #0000ff;">in</span><span style="color: #000000;"> validationErrors.ValidationErrors)<br/></span><span style="color: #008080;">107</span> msg += Environment.NewLine + <span style="color: #0000ff;">string</span>.Format(<span style="color: #800000;">"</span><span style="color: #800000;">Property: {0} Error: {1}</span><span style="color: #800000;">"</span><span style="color: #000000;">, validationError.PropertyName, validationError.ErrorMessage);<br/></span><span style="color: #008080;">108</span> <br/><span style="color: #008080;">109</span> <span style="color: #0000ff;">var</span> fail = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Exception(msg, dbEx);<br/></span><span style="color: #008080;">110</span> <span style="color: #008000;">//</span><span style="color: #008000;">Debug.WriteLine(fail.Message, fail);</span><br/><span style="color: #008080;">111</span> <span style="color: #0000ff;">throw</span><span style="color: #000000;"> fail;<br/></span><span style="color: #008080;">112</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">113</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">114</span> <br/><span style="color: #008080;">115</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">116</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Gets a table<br/></span><span style="color: #008080;">117</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">118</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> IQueryable&lt;T&gt;<span style="color: #000000;"> Table<br/></span><span style="color: #008080;">119</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">120</span> <span style="color: #0000ff;">get</span><br/><span style="color: #008080;">121</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">122</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.Entities;<br/></span><span style="color: #008080;">123</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">124</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">125</span> <br/><span style="color: #008080;">126</span> <br/><span style="color: #008080;">127</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">128</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Gets a table with "no tracking" enabled (EF feature) Use it only when you load record(s) only for read-only operations<br/></span><span style="color: #008080;">129</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">130</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">virtual</span> IQueryable&lt;T&gt;<span style="color: #000000;"> TableNoTracking<br/></span><span style="color: #008080;">131</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">132</span> <span style="color: #0000ff;">get</span><br/><span style="color: #008080;">133</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">134</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.Entities.AsNoTracking();<br/></span><span style="color: #008080;">135</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">136</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">137</span> <br/><span style="color: #008080;">138</span> <br/><span style="color: #008080;">139</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">140</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Entities<br/></span><span style="color: #008080;">141</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">142</span> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">virtual</span> IDbSet&lt;T&gt;<span style="color: #000000;"> Entities<br/></span><span style="color: #008080;">143</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">144</span> <span style="color: #0000ff;">get</span><br/><span style="color: #008080;">145</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">146</span> <span style="color: #0000ff;">if</span> (_entities == <span style="color: #0000ff;">null</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">147</span> _entities = _context.Set&lt;T&gt;<span style="color: #000000;">();<br/></span><span style="color: #008080;">148</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> _entities;<br/></span><span style="color: #008080;">149</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">150</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">151</span> }</div><p>&nbsp;</p>接口类:<div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 2</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Repository<br/></span><span style="color: #008080;"> 3</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">partial</span> <span style="color: #0000ff;">interface</span> IRepository&lt;T&gt; <span style="color: #0000ff;">where</span><span style="color: #000000;"> T : BaseEntity<br/></span><span style="color: #008080;"> 5</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 6</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;"> 7</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Get entity by identifier<br/></span><span style="color: #008080;"> 8</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;"> 9</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="id"&gt;</span><span style="color: #008000;">Identifier</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;">10</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;returns&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/returns&gt;</span><br/><span style="color: #008080;">11</span> T GetById(<span style="color: #0000ff;">object</span><span style="color: #000000;"> id);<br/></span><span style="color: #008080;">12</span> <br/><span style="color: #008080;">13</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">14</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Insert entity<br/></span><span style="color: #008080;">15</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">16</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="entity"&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;">17</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Insert(T entity);<br/></span><span style="color: #008080;">18</span> <br/><span style="color: #008080;">19</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">20</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Update entity<br/></span><span style="color: #008080;">21</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">22</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="entity"&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;">23</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Update(T entity);<br/></span><span style="color: #008080;">24</span> <br/><span style="color: #008080;">25</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">26</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Delete entity<br/></span><span style="color: #008080;">27</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">28</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;param name="entity"&gt;</span><span style="color: #008000;">Entity</span><span style="color: #808080;">&lt;/param&gt;</span><br/><span style="color: #008080;">29</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> Delete(T entity);<br/></span><span style="color: #008080;">30</span> <br/><span style="color: #008080;">31</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">32</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Gets a table<br/></span><span style="color: #008080;">33</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">34</span> IQueryable&lt;T&gt; Table { <span style="color: #0000ff;">get</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;">35</span> <br/><span style="color: #008080;">36</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;summary&gt;</span><br/><span style="color: #008080;">37</span> <span style="color: #808080;">///</span><span style="color: #008000;"> Gets a table with "no tracking" enabled (EF feature) Use it only when you load record(s) only for read-only operations<br/></span><span style="color: #008080;">38</span> <span style="color: #808080;">///</span> <span style="color: #808080;">&lt;/summary&gt;</span><br/><span style="color: #008080;">39</span> IQueryable&lt;T&gt; TableNoTracking { <span style="color: #0000ff;">get</span><span style="color: #000000;">; }<br/></span><span style="color: #008080;">40</span> }</div><p>&nbsp;</p>可以看到这个实现类很简单,就是通过传入我们定义的TestContext,然后通过_context.Set&lt;T&gt;<span>(); 可以获取到我们定义的DbSet,剩下的就是正常的属性定义一样了。<br /><br />说了那么多,该歇歇了,总结一下思路,就是通过反射注册所有的实现EntityTypeConfiguration的类,(注意实现类 所在的assembly),然后通过context.set&lt;T&gt;()方法获取到我们定义的Domain,就可以进行增删改查等操作。另外还有一点就是,如果只是查询数据,我建议使用AsNoTracking ,禁止EF跟踪,提高一下性能,另外也可以禁止EF缓存查询的数据。</span><br />有图有真相。<p><img src="http://images.cnitblog.com/blog/280403/201410/260049453089834.png" alt="" /></p>总结一下:这只是一个简单的实例,在实际的项目中肯定Domain和mapping是分开的,所以注册的时候我们一定要设定好注册的assembly。再次强调。<br />源代码下载:<br /><a href="http://files.cnblogs.com/jiagoushi/ConsoleApplication2.zip" target="_blank">源码</a><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4051270" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/jiagoushi/p/4051270.html" target="_blank">EF 的 霸气配置,秒杀一切</a>,转载请注明。</p>http://www.cnblogs.com/zrtqsk/p/4044687.htmlSpring源码分析——BeanFactory体系之抽象类、类分析(一) - Chandler Qian上一篇介绍了BeanFactory体系的所有接口——Spring源码分析——BeanFactory体系之接口详细分析,本篇就接着介绍BeanFactory体系的抽象类和接口。一、BeanFactory的基本类体系结构(类为主): 上图可与 Spring源码分析——BeanFactory体系之接...2014-10-25T16:29:00Z2014-10-25T16:29:00ZChandler Qianhttp://www.cnblogs.com/zrtqsk/<p>  上一篇介绍了BeanFactory体系的所有接口&mdash;&mdash;<a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/zrtqsk/p/4028453.html">Spring源码分析&mdash;&mdash;BeanFactory体系之接口详细分析</a>,本篇就接着介绍BeanFactory体系的抽象类和接口。</p><p><span style="font-size: 18pt;">一、BeanFactory的基本类体系结构(类为主):</span></p><p><img style="display: block; margin-left: auto; margin-right: auto;" src="data:image/png;base64,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" alt="" width="494" height="509" /></p><p>  上图可与 <a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/zrtqsk/p/4028453.html">Spring源码分析&mdash;&mdash;BeanFactory体系之接口详细分析</a><span class="postTitle2"> 的图</span>结合分析,一个以接口为主,一个以类为主(PS:Spring的体系结构要分析清楚,不得不曲线救国啊!不然27寸屏幕给我画估计都装不下。)。</p><p>具体:</p><p>  1、7层的类体系继承。</p><p>  2、AbstractBeanFactory实现了最重要的ConfigurableBeanFactory接口,DefaultSingletonBeanRegistry实现了SingletonBeanRegistry单例类注册接口,SimpleAliasRegistry实现了AliasRegistry别名注册接口。</p><p>  3、祖先类SimpleAliasRegistry、DefaultSingletonBeanRegistry和子孙类XmlBeanFactory、DefaultListableBeanFactory是完整的类,而中间的类FactoryBeanRegistrySupport、AbstractBeanFactory、AbstractAutowireCapableBeanFactory都是抽象类。</p><p>总结:</p><p>  具体上来说,XmlBeanFactory光是父类就有6个了,加上自身,总共7层了。实际上分析接口结构就会看到,作为IOC类工厂而言,XmlBeanFactory的类体系结构实际是从祖先AbstractBeanFactory这个类开始的,因为是它实现了BeanFactory的子接口ConfigurableBeanFactory,虽然它继承自FactoryBeanRegistrySupport,但可以说这只是工厂功能的扩充,扩展了对工厂Bean以及工厂所产生的Bean的操作。</p><p>&nbsp;</p><p><span style="font-size: 18pt;">二、简单的别名注册器&mdash;&mdash;SimpleAliasRegistry</span></p><p>  上篇已经讲过AliasRegistry,非常简单的4个方法,体现了对别名注册的支持,而SimpleAliasRegistry就是它的简单实现。</p><p>源码:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('2f39bb69-0273-47fb-ae77-8b64299389db')"><div id="cnblogs_code_open_2f39bb69-0273-47fb-ae77-8b64299389db" class="cnblogs_code_hide"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> SimpleAliasRegistry <span style="color: #0000ff;">implements</span><span style="color: #000000;"> AliasRegistry {<br/><br/> </span><span style="color: #008000;">/*</span><span style="color: #008000;"><br/> *用一个支持高并发的ConcurrentHashMap来放置所有的别名<br/> </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, String&gt; aliasMap = <span style="color: #0000ff;">new</span> ConcurrentHashMap&lt;String, String&gt;<span style="color: #000000;">(<br/> </span>16<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> AliasRegistry的接口方法,注册别名。不允许重复注册。</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> registerAlias(String name, String alias) {<br/> Assert.hasText(name, </span>"'name' must not be empty"<span style="color: #000000;">);<br/> Assert.hasText(alias, </span>"'alias' must not be empty"<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (alias.equals(name)) {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.remove(alias);<br/> } </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {<br/> </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">allowAliasOverriding()) {<br/> String registeredName </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.get(alias);<br/> </span><span style="color: #0000ff;">if</span> (registeredName != <span style="color: #0000ff;">null</span> &amp;&amp; !<span style="color: #000000;">registeredName.equals(name)) {<br/> </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalStateException("Cannot register alias '"<br/> + alias + "' for name '" +<span style="color: #000000;"> name<br/> </span>+ "': It is already registered for name '"<br/> + registeredName + "'."<span style="color: #000000;">);<br/> }<br/> }<br/> checkForAliasCircle(name, alias);</span><span style="color: #008000;">//</span><span style="color: #008000;">alias不能等于name在map中最后的对应(详见checkForAliasCircle方法)</span><br/> <span style="color: #0000ff;">this</span>.aliasMap.put(alias, name);<span style="color: #008000;">//</span><span style="color: #008000;">alias是key,name是value</span><br/><span style="color: #000000;"> }<br/> }<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"><br/> * 返回是否允许Alias重写,默认为允许<br/> </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> allowAliasOverriding() {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #000000;">;<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> AliasRegistry的接口方法,移除别名,如果别名未注册,则抛出异常</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> removeAlias(String alias) {<br/> String name </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.remove(alias);<br/> </span><span style="color: #0000ff;">if</span> (name == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalStateException("No alias '" +<span style="color: #000000;"> alias<br/> </span>+ "' registered"<span style="color: #000000;">);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> AliasRegistry的接口方法,给定名称判断是否为别名</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isAlias(String name) {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.containsKey(name);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> AliasRegistry的接口方法</span><br/> <span style="color: #0000ff;">public</span><span style="color: #000000;"> String[] getAliases(String name) {<br/> List</span>&lt;String&gt; result = <span style="color: #0000ff;">new</span> ArrayList&lt;String&gt;<span style="color: #000000;">();<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap) {<br/> retrieveAliases(name, result);<br/> }<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> StringUtils.toStringArray(result);<br/> }<br/><br/> </span><span style="color: #008000;">/*</span><span style="color: #008000;"><br/> * 找出名字说对应的所有别名。<br/> </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">void</span> retrieveAliases(String name, List&lt;String&gt;<span style="color: #000000;"> result) {<br/> </span><span style="color: #0000ff;">for</span> (Map.Entry&lt;String, String&gt; entry : <span style="color: #0000ff;">this</span>.aliasMap.entrySet()) {<span style="color: #008000;">//</span><span style="color: #008000;">遍历aliasMap</span><br/> String registeredName = entry.getValue();<span style="color: #008000;">//</span><span style="color: #008000;">取aliasMap的每个value</span><br/> <span style="color: #0000ff;">if</span> (registeredName.equals(name)) {<span style="color: #008000;">//</span><span style="color: #008000;">如果value等于指定的这个name</span><br/> String alias = entry.getKey();<span style="color: #008000;">//</span><span style="color: #008000;">取value对应的key</span><br/> result.add(alias);<span style="color: #008000;">//</span><span style="color: #008000;">将alias加入</span><br/> retrieveAliases(alias, result);<span style="color: #008000;">//</span><span style="color: #008000;">继续查看以alias为value的key</span><br/><span style="color: #000000;"> }<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">/*</span><span style="color: #008000;"><br/> * 处理所有的别名,如果处理正确,把原来的用解析后的替换<br/> </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> resolveAliases(StringValueResolver valueResolver) {<br/> Assert.notNull(valueResolver, </span>"StringValueResolver must not be null"<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap) {<br/> Map</span>&lt;String, String&gt; aliasCopy = <span style="color: #0000ff;">new</span> HashMap&lt;String, String&gt;<span style="color: #000000;">(<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap);<br/> </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (String alias : aliasCopy.keySet()) {<br/> String registeredName </span>= aliasCopy.get(alias);<span style="color: #008000;">//</span><span style="color: #008000;">取出key对应的value</span><br/> String resolvedAlias = valueResolver.resolveStringValue(alias);<span style="color: #008000;">//</span><span style="color: #008000;">解析后的key</span><br/> String resolvedName =<span style="color: #000000;"> valueResolver<br/> .resolveStringValue(registeredName);</span><span style="color: #008000;">//</span><span style="color: #008000;">解析后的value</span><br/> <span style="color: #0000ff;">if</span> (resolvedAlias.equals(resolvedName)) {<span style="color: #008000;">//</span><span style="color: #008000;">若解析后的key、name相等,就把它们从aliasMap中移除</span><br/> <span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.remove(alias);<br/> } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (!resolvedAlias.equals(alias)) {<span style="color: #008000;">//</span><span style="color: #008000;">若解析后的key不等于原来的Key</span><br/> String existingName = <span style="color: #0000ff;">this</span>.aliasMap.get(resolvedAlias);<span style="color: #008000;">//</span><span style="color: #008000;">取出解析后的key对应的value</span><br/> <span style="color: #0000ff;">if</span> (existingName != <span style="color: #0000ff;">null</span><span style="color: #008000;">//</span><span style="color: #008000;">如果不为空且不等于解析后的value,就抛出异常</span><br/> &amp;&amp; !<span style="color: #000000;">existingName.equals(resolvedName)) {<br/> </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> IllegalStateException(<br/> </span>"Cannot register resolved alias '"<br/> +<span style="color: #000000;"> resolvedAlias<br/> </span>+ "' (original: '"<br/> +<span style="color: #000000;"> alias<br/> </span>+ "') for name '"<br/> +<span style="color: #000000;"> resolvedName<br/> </span>+ "': It is already registered for name '"<br/> + registeredName + "'."<span style="color: #000000;">);<br/> }<br/> checkForAliasCircle(resolvedName, resolvedAlias);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.remove(alias);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.put(resolvedAlias, resolvedName);<br/> } </span><span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (!<span style="color: #000000;">registeredName.equals(resolvedName)) {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.aliasMap.put(alias, resolvedName);<br/> }<br/> }<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">/*</span><span style="color: #008000;"><br/> * 根据name这个Key,在aliasMap中不断循环的取对应的value,如果取得到,就继续根据这个value取值,不断循环继续。<br/> * 直到取不到,就把这个在aliasMap中无对应值的key返回。<br/> </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">public</span><span style="color: #000000;"> String canonicalName(String name) {<br/> String canonicalName </span>= name; <span style="color: #008000;">//</span><span style="color: #008000;">规范名<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Handle aliasing...</span><br/> String resolvedName;<span style="color: #008000;">//</span><span style="color: #008000;">已解析名</span><br/> <span style="color: #0000ff;">do</span><span style="color: #000000;"> {<br/> resolvedName </span>= <span style="color: #0000ff;">this</span>.aliasMap.get(canonicalName);<span style="color: #008000;">//</span><span style="color: #008000;">aliasMap中规范名对应的值赋值给已解析名</span><br/> <span style="color: #0000ff;">if</span> (resolvedName != <span style="color: #0000ff;">null</span>) {<span style="color: #008000;">//</span><span style="color: #008000;">如果已解析名存在(即规范名在aliasMap中有对应的值)</span><br/> canonicalName = resolvedName; <span style="color: #008000;">//</span><span style="color: #008000;"> 这个已解析名赋值给标准名</span><br/><span style="color: #000000;"> }<br/> } </span><span style="color: #0000ff;">while</span> (resolvedName != <span style="color: #0000ff;">null</span>);<span style="color: #008000;">//</span><span style="color: #008000;">不断循环,直到已解析名不存在</span><br/> <span style="color: #0000ff;">return</span><span style="color: #000000;"> canonicalName;<br/> }<br/><br/> </span><span style="color: #008000;">/*</span><span style="color: #008000;"><br/> * 如果别名alias等于canonicalName(name)就抛出异常<br/> </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> checkForAliasCircle(String name, String alias) {<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (alias.equals(canonicalName(name))) {<br/> </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalStateException("Cannot register alias '" +<span style="color: #000000;"> alias<br/> </span>+ "' for name '" + name + "': Circular reference - '"<br/> + name + "' is a direct or indirect alias for '" +<span style="color: #000000;"> alias<br/> </span>+ "' already"<span style="color: #000000;">);<br/> }<br/> }<br/><br/>}</span></div></div><p>&nbsp;具体:</p><p>  1、1个支持高并发的ConcurrentHashMap来放置所有的别名,其中key是别名,value是真名。</p><p>  2、4个方法实现了SimpleAliasRegistry。</p><p>  3、3个用来辅助实现4个接口方法的方法。其中canonicalName(String name)的实现非常优雅,用来循环来回判断,把aliasMap中无对应值的key返回。</p><p>  4、2个添加额外功能的方法 retrieveAliases 和 resolveAliases ,前者是找出名字对应的所有别名,后者是用一个StringValueResolver处理解析所有的别名-名称。</p><p>总结:</p><p>  这是一个非常简单的别名注册器,一个简单的接口实现。不过其中包含了非常优雅的方法实现,值得一看!</p><p>&nbsp;</p><p><span style="font-size: 18pt;">三、默认单例注册类&mdash;&mdash;DefaultSingletonBeanRegistry</span></p><p>源码:  </p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('e1ffda42-cd31-4625-a789-2f1227fcafae')"><div id="cnblogs_code_open_e1ffda42-cd31-4625-a789-2f1227fcafae" class="cnblogs_code_hide"><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span> DefaultSingletonBeanRegistry <span style="color: #0000ff;">extends</span> SimpleAliasRegistry <span style="color: #0000ff;">implements</span><span style="color: #000000;"> SingletonBeanRegistry {<br/><br/> </span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">final</span> Object NULL_OBJECT = <span style="color: #0000ff;">new</span> Object();<span style="color: #008000;">//</span><span style="color: #008000;">空object</span><br/><br/><br/> <span style="color: #008000;">/**</span><span style="color: #008000;"> Logger available to subclasses </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">final</span> Log logger =<span style="color: #000000;"> LogFactory.getLog(getClass());<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 单例缓存: bean name --&gt; bean instance </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Object&gt; singletonObjects = <span style="color: #0000ff;">new</span> ConcurrentHashMap&lt;String, Object&gt;(64<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 单例工厂缓存: bean name --&gt; ObjectFactory </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, ObjectFactory&gt; singletonFactories = <span style="color: #0000ff;">new</span> HashMap&lt;String, ObjectFactory&gt;(16<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 早期单例对象缓存: bean name --&gt; bean instance </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Object&gt; earlySingletonObjects = <span style="color: #0000ff;">new</span> HashMap&lt;String, Object&gt;(16<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 注册过的单例类(单例工厂) </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Set&lt;String&gt; registeredSingletons = <span style="color: #0000ff;">new</span> LinkedHashSet&lt;String&gt;(64<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 即将创建的单例类 (using a ConcurrentHashMap as a Set) </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Boolean&gt; singletonsCurrentlyInCreation = <span style="color: #0000ff;">new</span> ConcurrentHashMap&lt;String, Boolean&gt;(16<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 正在创建的单例类 (using a ConcurrentHashMap as a Set) </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Boolean&gt; inCreationCheckExclusions = <span style="color: #0000ff;">new</span> ConcurrentHashMap&lt;String, Boolean&gt;(16<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 被压制的异常集合 </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> Set&lt;Exception&gt;<span style="color: #000000;"> suppressedExceptions;<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> 单例类是否真正被销毁 </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span> singletonsCurrentlyInDestruction = <span style="color: #0000ff;">false</span><span style="color: #000000;">;<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> Disposable接口的实例: bean name --&gt; disposable instance </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Object&gt; = <span style="color: #0000ff;">new</span> LinkedHashMap&lt;String, Object&gt;<span style="color: #000000;">();<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> bean名称和bean所有包含的Bean的名称的map: bean name --&gt; Set of bean names that the bean contains </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Set&lt;String&gt;&gt; containedBeanMap = <span style="color: #0000ff;">new</span> ConcurrentHashMap&lt;String, Set&lt;String&gt;&gt;(16<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> bean名称和所有依赖于Bean的名称的map: bean name --&gt; Set of dependent bean names </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Set&lt;String&gt;&gt; dependentBeanMap = <span style="color: #0000ff;">new</span> ConcurrentHashMap&lt;String, Set&lt;String&gt;&gt;(64<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"> bean名称和bean所依赖的所有名称的map --&gt; Set of bean names for the bean's dependencies </span><span style="color: #008000;">*/</span><br/> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> Map&lt;String, Set&lt;String&gt;&gt; dependenciesForBeanMap = <span style="color: #0000ff;">new</span> ConcurrentHashMap&lt;String, Set&lt;String&gt;&gt;(64<span style="color: #000000;">);<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">SingletonBeanRegistry接口的实现类&mdash;&mdash;&mdash;&mdash;注册单例Bean,不能重复注册</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> registerSingleton(String beanName, Object singletonObject) <span style="color: #0000ff;">throws</span><span style="color: #000000;"> IllegalStateException {<br/> Assert.notNull(beanName, </span>"'beanName' must not be null"<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> Object oldObject </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects.get(beanName);<br/> </span><span style="color: #0000ff;">if</span> (oldObject != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalStateException("Could not register object [" + singletonObject +<br/> "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound"<span style="color: #000000;">);<br/> }<br/> addSingleton(beanName, singletonObject);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">注册一个单例类,注册之后,从singletonFactories、earlySingletonObjects中删去</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> addSingleton(String beanName, Object singletonObject) {<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> </span><span style="color: #0000ff;">this</span>.singletonObjects.put(beanName, (singletonObject != <span style="color: #0000ff;">null</span> ?<span style="color: #000000;"> singletonObject : NULL_OBJECT));<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonFactories.remove(beanName);<br/> </span><span style="color: #0000ff;">this</span>.earlySingletonObjects.remove(beanName);<span style="color: #008000;">//<br/></span> <span style="color: #0000ff;">this</span>.registeredSingletons.add(beanName);<span style="color: #008000;">//</span><span style="color: #008000;">加入,注册过的单例类集合</span><br/><span style="color: #000000;"> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">注册一个单例工厂类,注册后从earlySingletonObjects移除</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> addSingletonFactory(String beanName, ObjectFactory singletonFactory) {<br/> Assert.notNull(singletonFactory, </span>"Singleton factory must not be null"<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> </span><span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">this</span>.singletonObjects.containsKey(beanName)) { <span style="color: #008000;">//</span><span style="color: #008000;">单例工厂类不能和单例类同名</span><br/> <span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonFactories.put(beanName, singletonFactory);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.earlySingletonObjects.remove(beanName);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.registeredSingletons.add(beanName);<br/> }<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">SingletonBeanRegistry接口的实现类</span><br/> <span style="color: #0000ff;">public</span><span style="color: #000000;"> Object getSingleton(String beanName) {<br/> </span><span style="color: #0000ff;">return</span> getSingleton(beanName, <span style="color: #0000ff;">true</span><span style="color: #000000;">);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">根据beanName返回单例类</span><br/> <span style="color: #0000ff;">protected</span> Object getSingleton(String beanName, <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> allowEarlyReference) {<br/> Object singletonObject </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects.get(beanName);<br/> </span><span style="color: #0000ff;">if</span> (singletonObject == <span style="color: #0000ff;">null</span> &amp;&amp; isSingletonCurrentlyInCreation(beanName)) { <span style="color: #008000;">//</span><span style="color: #008000;"> 如果取不到,且该bean正在创建</span><br/> <span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> singletonObject </span>= <span style="color: #0000ff;">this</span><span style="color: #000000;">.earlySingletonObjects.get(beanName);<br/> </span><span style="color: #0000ff;">if</span> (singletonObject == <span style="color: #0000ff;">null</span> &amp;&amp; allowEarlyReference) { <span style="color: #008000;">//</span><span style="color: #008000;"> 如果从早期单例缓存中获取不到,且允许早期引用</span><br/> ObjectFactory singletonFactory = <span style="color: #0000ff;">this</span>.singletonFactories.get(beanName); <span style="color: #008000;">//</span><span style="color: #008000;"> 那么就从单例工厂缓存中获取单例工厂</span><br/> <span style="color: #0000ff;">if</span> (singletonFactory != <span style="color: #0000ff;">null</span>) { <span style="color: #008000;">//</span><span style="color: #008000;"> 如果还是获取不到,就创建一个单例工厂,并把它放进早期单例缓存中,并返回</span><br/> singletonObject =<span style="color: #000000;"> singletonFactory.getObject();<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.earlySingletonObjects.put(beanName, singletonObject);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonFactories.remove(beanName);<br/> }<br/> }<br/> }<br/> }<br/> </span><span style="color: #0000ff;">return</span> (singletonObject != NULL_OBJECT ? singletonObject : <span style="color: #0000ff;">null</span><span style="color: #000000;">);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">获取指定的单例Bean,如果取不到就调用指定的singletonFactory的getObject来返回</span><br/> <span style="color: #0000ff;">public</span><span style="color: #000000;"> Object getSingleton(String beanName, ObjectFactory singletonFactory) {<br/> Assert.notNull(beanName, </span>"'beanName' must not be null"<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> Object singletonObject </span>= <span style="color: #0000ff;">this</span>.singletonObjects.get(beanName);<span style="color: #008000;">//</span><span style="color: #008000;">从单例缓存中获取</span><br/> <span style="color: #0000ff;">if</span> (singletonObject == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span>.singletonsCurrentlyInDestruction) {<span style="color: #008000;">//</span><span style="color: #008000;">如果单例类正在被销毁,就抛出异常</span><br/> <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> BeanCreationNotAllowedException(beanName,<br/> </span>"Singleton bean creation not allowed while the singletons of this factory are in destruction " +<br/> "(Do not request a bean from a BeanFactory in a destroy method implementation!)"<span style="color: #000000;">);<br/> }<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (logger.isDebugEnabled()) {<br/> logger.debug(</span>"Creating shared instance of singleton bean '" + beanName + "'"<span style="color: #000000;">);<br/> }<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">如果不在inCreationCheckExclusions中,且可以向singletonsCurrentlyInCreation中添加,就抛出异常</span><br/><span style="color: #000000;"> beforeSingletonCreation(beanName);<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">是否有记录被压制的异常</span><br/> <span style="color: #0000ff;">boolean</span> recordSuppressedExceptions = (<span style="color: #0000ff;">this</span>.suppressedExceptions == <span style="color: #0000ff;">null</span><span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">if</span> (recordSuppressedExceptions) {<span style="color: #008000;">//</span><span style="color: #008000;">如果没有记录,即没有被压制的异常,就创建被压制的异常容器</span><br/> <span style="color: #0000ff;">this</span>.suppressedExceptions = <span style="color: #0000ff;">new</span> LinkedHashSet&lt;Exception&gt;<span style="color: #000000;">();<br/> }<br/> </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/> singletonObject </span>= singletonFactory.getObject();<span style="color: #008000;">//</span><span style="color: #008000;">以上都没有异常产生,那么就从指定的facgtory中取</span><br/><span style="color: #000000;"> }<br/> </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (BeanCreationException ex) {<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (recordSuppressedExceptions) {<br/> </span><span style="color: #0000ff;">for</span> (Exception suppressedException : <span style="color: #0000ff;">this</span><span style="color: #000000;">.suppressedExceptions) {<br/> ex.addRelatedCause(suppressedException);<br/> }<br/> }<br/> </span><span style="color: #0000ff;">throw</span><span style="color: #000000;"> ex;<br/> }<br/> </span><span style="color: #0000ff;">finally</span><span style="color: #000000;"> {<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (recordSuppressedExceptions) {<br/> </span><span style="color: #0000ff;">this</span>.suppressedExceptions = <span style="color: #0000ff;">null</span><span style="color: #000000;">;<br/> }<br/> afterSingletonCreation(beanName);<br/> }<br/> addSingleton(beanName, singletonObject);</span><span style="color: #008000;">//</span><span style="color: #008000;">取成功就放进singletonObjects中</span><br/><span style="color: #000000;"> }<br/> </span><span style="color: #0000ff;">return</span> (singletonObject != NULL_OBJECT ? singletonObject : <span style="color: #0000ff;">null</span><span style="color: #000000;">);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">添加一个被压制的异常</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onSuppressedException(Exception ex) {<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> </span><span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">this</span>.suppressedExceptions != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.suppressedExceptions.add(ex);<br/> }<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">根据名称移除本容器中缓存的对应的单例Bean,把对应的单例从Bean集合、单例工厂集合、早期单例对象集合、注册过的单例集合都统统移除</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> removeSingleton(String beanName) {<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects.remove(beanName);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonFactories.remove(beanName);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.earlySingletonObjects.remove(beanName);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.registeredSingletons.remove(beanName);<br/> }<br/> }<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">SingletonBeanRegistry接口的实现类</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> containsSingleton(String beanName) {<br/> </span><span style="color: #0000ff;">return</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects.containsKey(beanName));<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">SingletonBeanRegistry接口的实现类</span><br/> <span style="color: #0000ff;">public</span><span style="color: #000000;"> String[] getSingletonNames() {<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> </span><span style="color: #0000ff;">return</span> StringUtils.toStringArray(<span style="color: #0000ff;">this</span><span style="color: #000000;">.registeredSingletons);<br/> }<br/> }<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">SingletonBeanRegistry接口的实现类</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> getSingletonCount() {<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.registeredSingletons.size();<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 设置某个Bean是否正在创建</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> setCurrentlyInCreation(String beanName, <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> inCreation) {<br/> Assert.notNull(beanName, </span>"Bean name must not be null"<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">inCreation) {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.inCreationCheckExclusions.put(beanName, Boolean.TRUE);<br/> }<br/> </span><span style="color: #0000ff;">else</span><span style="color: #000000;"> {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.inCreationCheckExclusions.remove(beanName);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">判断某个Bean是否正在被创建</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isCurrentlyInCreation(String beanName) {<br/> Assert.notNull(beanName, </span>"Bean name must not be null"<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">return</span> (!<span style="color: #0000ff;">this</span>.inCreationCheckExclusions.containsKey(beanName) &amp;&amp;<span style="color: #000000;"> isActuallyInCreation(beanName));<br/> }<br/><br/> </span><span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isActuallyInCreation(String beanName) {<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> isSingletonCurrentlyInCreation(beanName);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">是否即将被创建</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isSingletonCurrentlyInCreation(String beanName) {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonsCurrentlyInCreation.containsKey(beanName);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">单例类创建开始之前调用<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">如果不在正在创建的单例类集合中,且可以向即将创建的单例类中添加,就抛出异常</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> beforeSingletonCreation(String beanName) {<br/> </span><span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">this</span>.inCreationCheckExclusions.containsKey(beanName) &amp;&amp;<br/> <span style="color: #0000ff;">this</span>.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> BeanCurrentlyInCreationException(beanName);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">单例类创建之后调用<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">如果不在正在创建的单例类中,也不在即将创建的单例类中移除失败,就抛出异常</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> afterSingletonCreation(String beanName) {<br/> </span><span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">this</span>.inCreationCheckExclusions.containsKey(beanName) &amp;&amp;<br/> !<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonsCurrentlyInCreation.remove(beanName)) {<br/> </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"<span style="color: #000000;">);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">往Disposable实例集合注册Disposable实例</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> registerDisposableBean(String beanName, DisposableBean bean) {<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.disposableBeans) {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.disposableBeans.put(beanName, bean);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">注册一个被包含的Bean和一个包含它的Bean(子-&gt;父)</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> registerContainedBean(String containedBeanName, String containingBeanName) {<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.containedBeanMap) {<br/> Set</span>&lt;String&gt; containedBeans = <span style="color: #0000ff;">this</span><span style="color: #000000;">.containedBeanMap.get(containingBeanName);<br/> </span><span style="color: #0000ff;">if</span> (containedBeans == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> containedBeans </span>= <span style="color: #0000ff;">new</span> LinkedHashSet&lt;String&gt;(8);<span style="color: #008000;">//</span><span style="color: #008000;">containedBeans的初始容量为8</span><br/> <span style="color: #0000ff;">this</span>.containedBeanMap.put(containingBeanName, containedBeans);<span style="color: #008000;">//</span><span style="color: #008000;">注意!containedBeanMap的Key是父bean,value是其所包含的所有子Bean(父-&gt;子)</span><br/><span style="color: #000000;"> }<br/> containedBeans.add(containedBeanName);<br/> }<br/> registerDependentBean(containedBeanName, containingBeanName);</span><span style="color: #008000;">//</span><span style="color: #008000;">因为包含也是依赖的一种,所以此时也要注册在dependentBeanMap中</span><br/><span style="color: #000000;"> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">给指定的Bean注册一个其依赖的Bean</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> registerDependentBean(String beanName, String dependentBeanName) {<br/> String canonicalName </span>= canonicalName(beanName);<span style="color: #008000;">//</span><span style="color: #008000;">在aliasMap中取规范名</span><br/> <span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span>.dependentBeanMap) { <span style="color: #008000;">//</span><span style="color: #008000;"> 这里是注册依赖BeanMap,key是bean的名称,value是依赖这个bean的所有bean的名称</span><br/> Set&lt;String&gt; dependentBeans = <span style="color: #0000ff;">this</span><span style="color: #000000;">.dependentBeanMap.get(canonicalName);<br/> </span><span style="color: #0000ff;">if</span> (dependentBeans == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> dependentBeans </span>= <span style="color: #0000ff;">new</span> LinkedHashSet&lt;String&gt;(8);<span style="color: #008000;">//</span><span style="color: #008000;">dependentBeans的初始容量也为8</span><br/> <span style="color: #0000ff;">this</span>.dependentBeanMap.put(canonicalName, dependentBeans);<span style="color: #008000;">//</span><span style="color: #008000;">dependentBeanMap中Key为beanName的规范名,value是依赖它的所有Bean的名称</span><br/><span style="color: #000000;"> }<br/> dependentBeans.add(dependentBeanName);<br/> }<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span>.dependenciesForBeanMap) { <span style="color: #008000;">//</span><span style="color: #008000;"> 这里相反,注册的是某个Bean和其所依赖的Bean的集合,key是这个beanName,value是这个Bean的依赖的所有Bean的Name</span><br/> Set&lt;String&gt; dependenciesForBean = <span style="color: #0000ff;">this</span><span style="color: #000000;">.dependenciesForBeanMap.get(dependentBeanName);<br/> </span><span style="color: #0000ff;">if</span> (dependenciesForBean == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> dependenciesForBean </span>= <span style="color: #0000ff;">new</span> LinkedHashSet&lt;String&gt;(8<span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.dependenciesForBeanMap.put(dependentBeanName, dependenciesForBean);<br/> }<br/> dependenciesForBean.add(canonicalName);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">判断某个Bean是否被其他Bean所依赖</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> hasDependentBean(String beanName) {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.dependentBeanMap.containsKey(beanName);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">返回依赖于给定Bean的Bean名称的集合</span><br/> <span style="color: #0000ff;">public</span><span style="color: #000000;"> String[] getDependentBeans(String beanName) {<br/> Set</span>&lt;String&gt; dependentBeans = <span style="color: #0000ff;">this</span><span style="color: #000000;">.dependentBeanMap.get(beanName);<br/> </span><span style="color: #0000ff;">if</span> (dependentBeans == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span> String[0<span style="color: #000000;">];<br/> }<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> StringUtils.toStringArray(dependentBeans);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">返回某个Bean所依赖的所有Bean的名称</span><br/> <span style="color: #0000ff;">public</span><span style="color: #000000;"> String[] getDependenciesForBean(String beanName) {<br/> Set</span>&lt;String&gt; dependenciesForBean = <span style="color: #0000ff;">this</span><span style="color: #000000;">.dependenciesForBeanMap.get(beanName);<br/> </span><span style="color: #0000ff;">if</span> (dependenciesForBean == <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">new</span> String[0<span style="color: #000000;">];<br/> }<br/> </span><span style="color: #0000ff;">return</span> dependenciesForBean.toArray(<span style="color: #0000ff;">new</span><span style="color: #000000;"> String[dependenciesForBean.size()]);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">这个方法居然连注释都没有?太奇怪了!</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> destroySingletons() {<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (logger.isInfoEnabled()) {<br/> logger.info(</span>"Destroying singletons in " + <span style="color: #0000ff;">this</span><span style="color: #000000;">);<br/> }<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span>.singletonObjects) {<span style="color: #008000;">//</span><span style="color: #008000;">首先标记,所有的单例Bean正在被销毁,那么getSingleton就无法获得单例Bean了</span><br/> <span style="color: #0000ff;">this</span>.singletonsCurrentlyInDestruction = <span style="color: #0000ff;">true</span><span style="color: #000000;">;<br/> }<br/><br/> String[] disposableBeanNames;<br/> </span><span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span>.disposableBeans) {<span style="color: #008000;">//</span><span style="color: #008000;">然后把所有的disposableBean都放进数组,一个个按名称销毁</span><br/> disposableBeanNames = StringUtils.toStringArray(<span style="color: #0000ff;">this</span><span style="color: #000000;">.disposableBeans.keySet());<br/> }<br/> </span><span style="color: #0000ff;">for</span> (<span style="color: #0000ff;">int</span> i = disposableBeanNames.length - 1; i &gt;= 0; i--<span style="color: #000000;">) {<br/> destroySingleton(disposableBeanNames[i]);<br/> }<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 把本容器的所有的包含关系、依赖关系、被依赖关系的集合全部清空</span><br/> <span style="color: #0000ff;">this</span><span style="color: #000000;">.containedBeanMap.clear();<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.dependentBeanMap.clear();<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.dependenciesForBeanMap.clear();<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">然后把本容器的所有其他集合全部清空</span><br/> <span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects) {<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects.clear();<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonFactories.clear();<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.earlySingletonObjects.clear();<br/> </span><span style="color: #0000ff;">this</span><span style="color: #000000;">.registeredSingletons.clear();<br/> </span><span style="color: #0000ff;">this</span>.singletonsCurrentlyInDestruction = <span style="color: #0000ff;">false</span><span style="color: #000000;">;<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">销毁某个单例Bean</span><br/> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> destroySingleton(String beanName) {<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> Remove a registered singleton of the given name, if any.</span><br/> removeSingleton(beanName);<span style="color: #008000;">//</span><span style="color: #008000;">先把它销毁</span><br/><span style="color: #000000;"><br/> DisposableBean disposableBean;</span><span style="color: #008000;">//</span><span style="color: #008000;">它相应的DisposableBean实例</span><br/> <span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.disposableBeans) {<br/> disposableBean </span>= (DisposableBean) <span style="color: #0000ff;">this</span>.disposableBeans.remove(beanName);<span style="color: #008000;">//</span><span style="color: #008000;">从disposableBeans移除这个实例</span><br/><span style="color: #000000;"> }<br/> destroyBean(beanName, disposableBean);<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 销毁指定名称的Bean,且销毁依赖于它的所有Bean</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> destroyBean(String beanName, DisposableBean bean) {<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 首先销毁依赖它的所有Bean</span><br/> Set&lt;String&gt; dependencies = <span style="color: #0000ff;">this</span>.dependentBeanMap.remove(beanName);<span style="color: #008000;">//</span><span style="color: #008000;">取依赖于指定Bean的所有Bean</span><br/> <span style="color: #0000ff;">if</span> (dependencies != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (logger.isDebugEnabled()) {<br/> logger.debug(</span>"Retrieved dependent beans for bean '" + beanName + "': " +<span style="color: #000000;"> dependencies);<br/> }<br/> </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (String dependentBeanName : dependencies) {<br/> destroySingleton(dependentBeanName);</span><span style="color: #008000;">//</span><span style="color: #008000;">一个个销毁</span><br/><span style="color: #000000;"> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 然后销毁它</span><br/> <span style="color: #0000ff;">if</span> (bean != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/> bean.destroy();<br/> }<br/> </span><span style="color: #0000ff;">catch</span><span style="color: #000000;"> (Throwable ex) {<br/> logger.error(</span>"Destroy method on bean with name '" + beanName + "' threw an exception"<span style="color: #000000;">, ex);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 然后销毁它所包含的Bean</span><br/> Set&lt;String&gt; containedBeans = <span style="color: #0000ff;">this</span><span style="color: #000000;">.containedBeanMap.remove(beanName);<br/> </span><span style="color: #0000ff;">if</span> (containedBeans != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/> </span><span style="color: #0000ff;">for</span><span style="color: #000000;"> (String containedBeanName : containedBeans) {<br/> destroySingleton(containedBeanName);<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 然后把所有它依赖的Bean的依赖关系删除,首先删除dependentBeanMap中的依赖关系</span><br/> <span style="color: #0000ff;">synchronized</span> (<span style="color: #0000ff;">this</span><span style="color: #000000;">.dependentBeanMap) {<br/> </span><span style="color: #008000;">//</span><span style="color: #008000;">这样的for循环用法实在是经典</span><br/> <span style="color: #0000ff;">for</span> (Iterator&lt;Map.Entry&lt;String, Set&lt;String&gt;&gt;&gt; it = <span style="color: #0000ff;">this</span><span style="color: #000000;">.dependentBeanMap.entrySet().iterator(); it.hasNext();) {<br/> Map.Entry</span>&lt;String, Set&lt;String&gt;&gt; entry =<span style="color: #000000;"> it.next();<br/> Set</span>&lt;String&gt; dependenciesToClean =<span style="color: #000000;"> entry.getValue();<br/> dependenciesToClean.remove(beanName);<br/> </span><span style="color: #0000ff;">if</span><span style="color: #000000;"> (dependenciesToClean.isEmpty()) {<br/> it.remove();<br/> }<br/> }<br/> }<br/><br/> </span><span style="color: #008000;">//</span><span style="color: #008000;"> 然后删除dependenciesForBeanMap中的依赖关系</span><br/> <span style="color: #0000ff;">this</span><span style="color: #000000;">.dependenciesForBeanMap.remove(beanName);<br/> }<br/><br/> </span><span style="color: #008000;">/**</span><span style="color: #008000;"><br/> * Expose the singleton mutex to subclasses.<br/> * &lt;p&gt;Subclasses should synchronize on the given Object if they perform<br/> * any sort of extended singleton creation phase. In particular, subclasses<br/> * should &lt;i&gt;not&lt;/i&gt; have their own mutexes involved in singleton creation,<br/> * to avoid the potential for deadlocks in lazy-init situations.<br/> </span><span style="color: #008000;">*/</span><br/> <span style="color: #008000;">//</span><span style="color: #008000;">返回子类单例类的互斥体?这个暂且放着。</span><br/> <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">final</span><span style="color: #000000;"> Object getSingletonMutex() {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #0000ff;">this</span><span style="color: #000000;">.singletonObjects;<br/> }<br/><br/>}</span></div></div><p>&nbsp;</p><p>具体:</p><p>  1、一个静态不可变的空对象NULL_OBJECT、一个简单的日志对象。</p><p>  2、本类有如下集合:</p><p>    (1)、一个单例缓存集合&mdash;&mdash;singletonObjects</p><p>    (2)、一个单例工厂缓存集合&mdash;&mdash;singletonFactories</p><p>    (3)、一个早期单例对象缓存集合&mdash;&mdash;earlySingletonObjects</p><p>    (4)、一个注册过的单例类(单例工厂)集合&mdash;&mdash;registeredSingletons</p><p>    (5)、一个即将创建的单例类集合&mdash;&mdash;singletonsCurrentlyInCreation</p><p>    (6)、一个正在创建的单例类集合&mdash;&mdash;inCreationCheckExclusions</p><p>    (7)、一个被压制的异常集合&mdash;&mdash;suppressedExceptions(这种设计模式实在是经典!)</p><p>    (8)、一个判断所有单例类是否马上被销毁的标记&mdash;&mdash;singletonsCurrentlyInDestruction</p><p>    (9)、一个Disposable接口(即可以自定义回收资源的接口)实例的集合&mdash;&mdash;disposableBeans</p><p>    (10)、一个bean名称和bean所有包含的Bean的名称的集合&mdash;&mdash;containedBeanMap</p><p>    (11)、bean名称和所有依赖于Bean的名称的集合&mdash;&mdash;dependentBeanMap</p><p>    (12)、bean名称和bean所依赖的所有名称的集合&mdash;&mdash;dependenciesForBeanMap</p><p>  3、2个注册单例方法,实际是暴露在外的SingletonBeanRegistry接口的实现方法registerSingleton加锁后调用另一个addSingleton方法。</p><p>  4、1个注册单例工厂的方法。单例工厂类不能和单例类同名。</p><p>  5、3个获取单例类的方法。一种是从单例类集合中获取,如果获取不到,boolean控制要么返回空对象,要么返回一个单例工厂。另一种是从单例集合中获取,如果取不到,就从指定的工厂中获取。还有一种?呵,就是暴露在外的SingletonBeanRegistry接口方法呗,直接调用第一种。</p><p>  6、1个添加被压制的异常集合中添加异常的方法,我觉得这个设计非常经典。但需要记录异常,却不想处理的时候,可以采用这种设计模式。</p><p>  7、1个移除单例的方法、1个判断是否包含单例的方法、1个返回所有单例名数组的方法、1个返回单例总数目的方法。</p><p>  8、1个设置某个Bean是否正在创建的方法、1个判断某个Bean是否正在被创建的方法、2个判断某个Bean是否即将被创建的方法(一个调用另一个,用于重写)。</p><p>  9、1个单例类创建开始之前调用的方法、1个单单例类创建之后调用的方法</p><p>  10、1个往Disposable实例集合注册Disposable实例的方法,这个是Bean销毁前的准备。</p><p>  11、1个注册一个被包含的Bean和一个包含的Bean的名称到containedBeanMap集合的方法。这个方法设置了Bean之间的包含关系。</p><p>  12、1个给指定的Bean注册一个其依赖的Bean的方法。这个方法设置了Bean自己的依赖关系。</p><p>  13、1个判断是否被依赖的方法、1个返回给定Bean名称的所有依赖的数组的方法、1个返回依赖于给定Bean的所有Bean名的数组的方法。</p><p>  14、1个销毁所有单例类的方法(这个方法居然完全没有注释,有没搞错!)、1个销毁某个单例的方法、1个// 销毁指定名称的Bean,且销毁依赖于它的所有Bean的方法。</p><p>  15、1个返回子类单例类的互斥体的方法。这个暂且待下一篇分析子类再看。</p><p>总结:</p><p>  类如其名,默认的单例注册器。这个工厂的写法实在功能丰富,为了监控到一个单例类构建过程中的方方面面,简直就是不择手段啊,居然准备了12个集合,除了一个一个被压制的异常集合,其余全是跟单例类有直接关系的。可以说,这个单例注册器监听、实现了Spring单例注册的各个过程,具体的解读分析,在上面的源代码中可以看到,读者阅读我注释过的源代码应该会很轻松。</p><p>&nbsp;</p><p>  源码分析,路漫漫其修远啊。这个DefaultSingletonBeanRegistry实在是让我有些元气大伤。一个简单的单例注册,复杂的让人咋舌!Spring容器对单例类的监听考虑之完备,令人佩服。阅读源码,对系统构建和功能实现的理解实在有用!嗯!要加快进度才行!</p><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4044687" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/zrtqsk/p/4044687.html" target="_blank">Spring源码分析——BeanFactory体系之抽象类、类分析(一)</a>,转载请注明。</p>http://www.cnblogs.com/zgfLawliet/p/4051239.html原创 正则引擎完工,记录下思路和设计 - IceCrystals最近20天都在写这个...终于完工了(走向无尽的重构道路...)...感谢VC聚聚的博文和RE2作者的博客指导,感谢VC聚聚的源码参考.非常感谢!启发很大.vc聚聚的正则语法树遍历部分的方案.真是精妙!之前我虽然知道用Visitor模式遍历异构树,但是不知道怎么写vistor的框架满足需求.用的时候...2014-10-25T16:11:00Z2014-10-25T16:11:00ZIceCrystalshttp://www.cnblogs.com/zgfLawliet/<p>最近20天都在写这个...终于完工了(走向无尽的重构道路...)...感谢VC聚聚的博文和RE2作者的博客指导,感谢VC聚聚的源码参考.非常感谢!启发很大.vc聚聚的正则语法树遍历部分的方案.真是精妙!之前我虽然知道用Visitor模式遍历异构树,但是不知道怎么写vistor的框架满足需求.用的时候不断地感叹设计的好.不过我也就抄了这块框架代码:)因为实现的太好了.其他都是根据博文给的参考设计自己去想设计和实现</p><p>整个引擎实现了http://blog.csdn.net/lxcnn/article/details/4268033提到的全部功能,另外添加了VC聚聚引擎中包含的命名子表达式的功能.在有些场合可以简化正则表达式长度.书写更加方便.</p><p>高层设计:</p><p>  基本上来说正则引擎的实现需要完成:</p><p>  词法分析</p><p>  语法分析</p><p>  字符集合正交化</p><p>  构建NFA</p><p>  根据NFA的边类型将NFA的不同部分分解,能构建DFA的构建DFA</p><p>  构建Regex解析类 包括正则的DFA和NFA的实现.</p><p>  写出正则的匹配算法,在正则匹配的不同阶段,切换DFA和NFA匹配过程.</p><p>模块设计:<br />正则语言的词法分析部分是很简单的,整个都可以用字符串匹配匹配出来,不用构建DFA之类的去做.<br />具体要解析的token如下文法中的""包括的内容<br />Alert = Unit "|" Alert<br />Unit;<br />Unit = Express Unit | Express<br />Express = Factor Loop | Factor<br />Loop = &ldquo;{&rdquo; Number &ldquo;}&rdquo;<br />= &ldquo;{&rdquo; Number &ldquo;,&rdquo; &ldquo;}&rdquo;<br />= &ldquo;{&rdquo;Number &ldquo;,&rdquo; Number &ldquo;}&rdquo;<br />= &ldquo;{&rdquo; Number &ldquo;}?&rdquo;<br />= &ldquo;{&rdquo; Number &ldquo;,&rdquo; &ldquo;}?&rdquo;<br />= &ldquo;{&rdquo;Number &ldquo;,&rdquo; Number &ldquo;}?&rdquo;<br />= "*"<br />= "?"<br />= "+"<br />= "*?"<br />= "??"<br />= "+?"<br />Factor= &ldquo;(&rdquo; Alert &ldquo;)&rdquo;<br />= &ldquo;(&lt;&rdquo; Name "&gt;" Alert &ldquo;)&rdquo;<br />= "(?:" Alert ")"<br />= "(?=" Alert ")"<br />= "(?!" Alert ")"<br />= "(?&lt;" Alert ")"<br />= "(?&lt;!"Alert ")"<br />= "$"<br />= "^"<br />= Backreference<br />= CharSet<br />= NormalChar<br />CharSet = "[^" CharSetCompnent "]" |"[" CharSetCompnent "]" | Char | "\X"<br />CharSetCompnent = CharUnit CharSetCompnent | CharUnit<br />CharUnit = Char "-" Char | Char<br />Backreference = "\k" &lt;&rdquo; Name "&gt;" | "\" Number<br />Note = "(#" ... ")"<br />词法分析:<br />整个解析的框架是:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;">Ptr&lt;vector&lt;RegexToken&gt;&gt; RegexLex::ParsingPattern(<span style="color: #0000ff;">int</span> start_index, <span style="color: #0000ff;">int</span><span style="color: #000000;"> end_index)<br/>{<br/>Ptr</span>&lt;vector&lt;RegexToken&gt;&gt; result(make_shared&lt;vector&lt;RegexToken&gt;&gt;<span style="color: #000000;">());<br/></span><span style="color: #0000ff;">for</span>(auto index = start_index; index &lt;<span style="color: #000000;"> end_index;)<br/>{<br/></span><span style="color: #0000ff;">for</span>(auto catch_length = <span style="color: #800080;">4</span>; catch_length &gt;= <span style="color: #800080;">1</span>; catch_length--<span style="color: #000000;">)<br/>{<br/>auto</span>&amp;&amp; key =<span style="color: #000000;"> pattern.substr(index, catch_length);<br/></span><span style="color: #0000ff;">if</span>(RegexLex::action_map.find(key) !=<span style="color: #000000;"> RegexLex::action_map.end())<br/>{<br/></span><span style="color: #008000;">//</span><span style="color: #008000;">RegexLex::action_map执行完后,index指向正确的位置了.也就不用++了.</span><br/><span style="color: #000000;">RegexLex::action_map[key](pattern, index, result, optional);<br/></span><span style="color: #0000ff;">break</span><span style="color: #000000;">;<br/>}<br/><br/></span><span style="color: #0000ff;">if</span>(catch_length == <span style="color: #800080;">1</span><span style="color: #000000;">)<br/>{<br/></span><span style="color: #008000;">//</span><span style="color: #008000;">说明是普通字符. normal长度5 :)</span><br/>RegexLex::action_map[L<span style="color: #800000;">"</span><span style="color: #800000;">normal</span><span style="color: #800000;">"</span><span style="color: #000000;">](pattern, index, result, optional);<br/>}<br/>}<br/>}<br/></span><span style="color: #0000ff;">return</span><span style="color: #000000;"> move(result);<br/>}</span></div><p>&nbsp;</p><p> action_map的key就是token的字符串形式,返回的是一个enum token表明符号类型.<br />optional是.NET正则匹配时候的可选选项的内容.<br />词法分析的结果是一个RegexToken类型的vector,<br />class RegexToken<br />{<br />public:<br />TokenType type;<br />CharRange position;<br />}<br />包含了token类型和发现的位置区间.<br />之后vector作为语法分析器的输入和原始的模式串一起进行语法分析.(根据token的位置去模式串里面找需要的信息);<br />词法分析部分需要注意的地方:<br />1.[]内的-左右是[或者]时候,当做普通字符看待.[]内的字符除了无转义的]都当做普通字符看待.<br />2.(?=)+LookAround的)后面的表达重复的元字符当做普通字符看待.<br />3.要考虑到表达式嵌套.处理的时候遇到(XXX这种表示一个子表达式开始的字符,要先用栈找到匹配的结尾的")" ( ")"可能和多个元字符匹配成子表达式).例如(12(321))解析外层括号的时候,遇到"("需要正确处理它的结尾是最后一个")";<br />语法分析部分:<br />语法分析部分根据龙书地语法分析教程写的.之前轮yacc的时候写过了LALR语法分析器,所以这回换换口味,写了个LL的语法分析器.具体的做法参考龙书的LL语法分析器部分.整个语法分析部分的文法是:<br /><br />文法:</p><p>Alert = Unit "Alternation" Alert | Unit<br />Unit = Express Unit | Express<br />Express = Factor Loop | Factor<br />Loop = &ldquo;LoopBegin&rdquo; |"ChoseLoop" | "ChoseLoopGreedy" | "PositiveLoop" | "PositiveLoopGreedy" | "KleeneLoop" | "KleeneLoopGreedy";</p><p>Factor<br />= &ldquo;CaptureBegin&rdquo; CaptureRight<br />= "AnonymityCaptureBegin" AnonymityCaptureRight<br />= "RegexMacro" CaptureRight <br />= "NoneCapture" Alert"CaptureEnd"<br />= "PositivetiveLookahead" Alert "CaptureEnd"<br />= "NegativeLookahead" Alert"CaptureEnd"<br />= "PositiveLookbehind" Alert"CaptureEnd"<br />= "NegativeLookbehind" Alert"CaptureEnd"<br />= "StringHead"<br />= "StringTail"<br />= "Backreference"<br />= "CharSet"<br />= "NormalChar"<br />= "LineBegin"<br />= "LineEnd"<br />= "MatchAllSymbol"<br />= "GeneralMatch"<br />= "MacroReference"<br />= "AnonymityBackReference"<br />CaptureRight = "Named" Alert "CaptureEnd" |Alert "CaptureEnd"<br />""包含的是词法分析过程中返回的正则的token.语法分析的难点....额..和手写LL语法分析器的难点差不多.首先要构造出first表.反正也不是写yacc=.=...我就人脑构造first表了.之后根据文法写出LL分析器.返回一个语法树.<br />语法树的节点类型:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">class</span> Expression :<span style="color: #0000ff;">public</span> enable_shared_from_this &lt; Expression &gt;<span style="color: #000000;"><br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/></span><span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Apply(IRegexAlogrithm&amp; algorithm) = <span style="color: #800080;">0</span><span style="color: #000000;">;<br/></span><span style="color: #0000ff;">bool</span> IsEqual(Ptr&lt;Expression&gt;&amp;<span style="color: #000000;"> target);<br/>Ptr</span>&lt;vector&lt;CharRange&gt;&gt; GetCharSetTable(<span style="color: #0000ff;">const</span> Ptr&lt;vector&lt;RegexControl&gt;&gt;&amp;<span style="color: #000000;"> optional);<br/></span><span style="color: #0000ff;">void</span> SetTreeCharSetOrthogonal(Ptr&lt;CharTable&gt;&amp;<span style="color: #000000;"> target);<br/>pair</span>&lt;State*, State*&gt; BuildNFA(AutoMachine*<span style="color: #000000;"> target);<br/></span><span style="color: #0000ff;">private</span><span style="color: #000000;">:<br/></span><span style="color: #0000ff;">void</span> BuildOrthogonal(Ptr&lt;vector&lt;<span style="color: #0000ff;">int</span>&gt;&gt;&amp;<span style="color: #000000;">target);<br/>};<br/><br/></span><span style="color: #008000;">//</span><span style="color: #008000;">字符集合</span><br/><span style="color: #0000ff;">class</span> CharSetExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/></span><span style="color: #0000ff;">bool</span><span style="color: #000000;"> reverse;<br/>vector</span>&lt;CharRange&gt;<span style="color: #000000;"> range;<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>};<br/></span><span style="color: #008000;">//</span><span style="color: #008000;">普通字符</span><br/><span style="color: #0000ff;">class</span> NormalCharExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>CharRange range;<br/>};<br/><br/></span><span style="color: #008000;">//</span><span style="color: #008000;">循环</span><br/><span style="color: #0000ff;">class</span> LoopExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> begin;<br/></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> end;<br/></span><span style="color: #0000ff;">bool</span><span style="color: #000000;"> greedy;<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>};<br/><br/></span><span style="color: #0000ff;">class</span> SequenceExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> left;<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> right;<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>};<br/><br/></span><span style="color: #0000ff;">class</span> AlternationExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> left;<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> right;<br/>};<br/><br/></span><span style="color: #0000ff;">class</span> BeginExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>};<br/><br/></span><span style="color: #0000ff;">class</span> EndExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/>};<br/><br/></span><span style="color: #0000ff;">class</span> CaptureExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>wstring name;<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};<br/></span><span style="color: #0000ff;">class</span> AnonymityCaptureExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/></span><span style="color: #0000ff;">int</span> index = <span style="color: #800080;">0</span><span style="color: #000000;">;<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};<br/><br/></span><span style="color: #0000ff;">class</span> MacroExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>wstring name;<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};<br/></span><span style="color: #0000ff;">class</span> MacroReferenceExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>wstring name;<br/>};<br/></span><span style="color: #008000;">//</span><span style="color: #008000;">非捕获组</span><br/><span style="color: #0000ff;">class</span> NoneCaptureExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};<br/></span><span style="color: #008000;">//</span><span style="color: #008000;">命名后向引用</span><br/><span style="color: #0000ff;">class</span> BackReferenceExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>wstring name;<br/>};<br/></span><span style="color: #0000ff;">class</span> AnonymityBackReferenceExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> index;<br/>};<br/><br/></span><span style="color: #0000ff;">class</span> NegativeLookbehindExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};<br/></span><span style="color: #0000ff;">class</span> PositiveLookbehindExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};<br/></span><span style="color: #0000ff;">class</span> NegativeLookaheadExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};<br/></span><span style="color: #0000ff;">class</span> PositivetiveLookaheadExpression : <span style="color: #0000ff;">public</span><span style="color: #000000;"> Expression<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/>Ptr</span>&lt;Expression&gt;<span style="color: #000000;"> expression;<br/>};</span></div><p>&nbsp;</p><p> 除了多了几个类型和V大的语法树类型差不多,然后是语法树遍历和构造部分,这块参考v大的博文就好.<br />http://www.cppblog.com/vczh/archive/2009/10/18/98862.html 语法树的构造与遍历<br />http://www.cppblog.com/vczh/archive/2009/10/18/98873.html 字符集和正规化<br />NFA构造,DFA构造:<br />这块欢迎去看v大的扩展正则表达式构造方法的博文.http://www.cppblog.com/vczh/archive/2008/05/22/50763.html<br />不过我的写法不太一样.v大整个正则表达式,所有节点都在一张图上.因为有命令边和end边来控制子表达式范围.我没有加入end边.所以我是用子图的方式.命令边上绑定一个子表达式是的索引.<br />匹配到命令边后,根据索引去找子表达式去匹配.<br />关于有向图这块,用shared_ptr为了避免循环引用,推荐弄个shared_ptr的节点数组.节点池.暴露出原始指针来操作.只要记得自己别蛋疼delete就木有事了.<br />在ENFA到NFA的转换这块.V大直接把大部分边都合并了....合并所有不消耗字符的边是很酷炫...不过我自己的边的数据结构(vector&lt;Edge*&gt;)遇到这种会有些问题...当不消耗字符的边匹配失败后,因为所有后续边都拿过来了(不知道我在什么的可以LSURL先看v大那两篇文章).<br />会不知道重启匹配的下一条边位置.所以我没这么合并...只是合并了空边.为了保证每个子表达式都有唯一的开始和结束节点,我加入了Final边链接子表达式末尾,在Final上无条件匹配成功,但是final边不会被优化掉.<br />这里有个难点就是逆向LookAround的处理.因为是逆向的.所以里面的子表达式要返过来匹配.例如34(&lt;=34)54.匹配3454当正则表达式到达4和5之间的位置.启动逆向环视.匹配字符的顺序是先匹配4再匹配3.而不是子表达式里面写的顺序(&lt;=34).<br />所以这里的问题就是在构造完全部NFA后,遍历NFA一遍,把NFA的第一层(每个子表达式都被绑在功能边上)的逆向LookAround边下属的表达式子图全部逆图.并且如果子图中包含了LookAround,要反向(例如蛋疼的(?&lt;=3(?=5))这样的写法- -....这样才能保证匹配成功.<br />匹配的算法难点:<br />匹配算法...难点有一个,需要输入串用迭代器指向.而不是普通的索引来遍历字符串.因为在逆向环视中,需要逆向匹配方向.普通的索引int类型没法反向,所以用迭代器比较方便,套个反向迭代器就OK了- -.因为子图会调用匹配算法去匹配.所以<br />这里编译时是个递归的过程.so...反向迭代器的嵌套(不断地进入LookBehind边时候套层新的反向迭代器)会导致模板编译递归.这里需要分解LookBehind边的处理函数.对于由反向迭代器传入的索引.调用.base()对于正向迭代器传入的,调用reverse_iter(iter)构造反向.<br />大概设计是:当前状态的子图有DFA就用DFA匹配,没有DFA就用NFA匹配.NFA测试每一条边,NFA匹配过程中的每一个状态都要压栈.匹配成功进入下一状态,失败就尝试下一条边,如果当前状态所有边都失败,pop当前状态.新的back()的状态恢复.执行下一条边.如此往复.<br />编译选项的设计:<br />ExplicitCapture,//不使用匿名捕获组功能,词法分析的时候做,匹配到"("时候,如果optional里面包含了这个,就返回NoneCatupure Token<br />IgnoreCase,//大小写不敏感的匹配,构造字符集和正交化的时候处理.遍历字符集的时候加上大写或者小写部分.<br />Multiline,// $^ 匹配行结尾和开头 转换为LookAround<br />RightToLeft,// 使用逆向迭代器传入input串<br />Singleline,//更改"."代表的字符集合范围.<br />难点大概就这些吧...其他的看v大的博文就知道了,写的都很棒.好顶赞.<br />整个项目大概5000行代码,从各个博客和,NET正则引擎参考 MSDN上找了几百个不同测试样例,写完真心感觉学到了不少东西- -....虽然C++已经写了快2年了,很多低级错误还是会犯...,emplace_back和push_back的区别.还有&amp; *的混合使用的错误(对指针的引用)...搭配上有向图这种调试起来麻烦的东东- -...推荐写个打印DFA和NFA有向图信息的debug辅助函数,比断点调试快多了<br />希望以后造轮子可以少犯点低级错误..<br />再次感谢V大的博文指导!^_^<br />差不多今年第一次写博客...希望以后多写写:)<br />参考资料:<br />1.http://www.cppblog.com/vczh/category/12070.html?Show=All<br />2.http://www.cppblog.com/vczh/archive/2008/05/22/50763.html<br />3.编译原理的龙书</p><img src="http://counter.cnblogs.com/blog/rss/4051239" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/zgfLawliet/p/4051239.html" target="_blank">原创 正则引擎完工,记录下思路和设计</a>,转载请注明。</p>http://www.cnblogs.com/coderkian/p/4051165.htmllua编程之元表与元方法 - coderkian一、 前言lua是一种非常轻量的动态类型语言,在1993年由由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo等人发明,lua的设计目标是轻便地嵌入宿主语言,增强系统的可扩展性和可定制性。lua的源码只有两万余行,非...2014-10-25T15:33:00Z2014-10-25T15:33:00Zcoderkianhttp://www.cnblogs.com/coderkian/<p><span style="font-size: 14px;"><strong>一、 前言</strong></span></p><p>lua是一种非常轻量的动态类型语言,在1993年由由Roberto Ierusalimschy、Waldemar Celes 和 Luiz Henrique de Figueiredo等人发明,lua的设计目标是轻便地嵌入宿主语言,增强系统的可扩展性和可定制性。lua的源码只有两万余行,非常精简小巧,在目前的脚本引擎中,lua的速度是最快的,这也是lua进入程序设计语言前20名,如今已经广泛应用于游戏行业,这几篇文章将会讨论下lua的几个比较重要的特性。</p><p>一门语言的类型系统是其最根本的特征,所以本文先从与lua的类型系统关系最紧密的元表和元方法谈起。作为一门轻量级语言,lua的核心非常精简,它的基本类型只有8种:nil,boolean,number,string,userdata,function,thread和table,其中table是唯一的数据结构,是lua中最重要的类型,可以作为其他数据结构的基础,如数组,链表,队列和集合等都可以通过table实现。更强大的是,lua还为table提供了自定义操作的功能。在c++等面向对象语言中,类的可操作行为由成员函数决定。lua中,元方法就是table的&ldquo;成员函数&rdquo;,为不同的table提供特殊的操作行为,元表是元方法的集合。通过元表和元方法,table可以直接实现类,继承等面向对象特性。</p><p><span style="font-size: 14px;"><strong>二、 元表元方法介绍</strong></span></p><p>lua中每个值其实都有元表,不过每个table和userdata都可以有自己专有的元表,(userdata是宿主中的数据结构,可以使用宿主语言的方法,为了限制过度对其使用元表,不能在lua脚本中直接设置,需通过<a name="lua_setmetatable"></a>lua_setmetatable创建,这里不讨论),而其他类型的预定义操作都在一个共享的元表中,新的table默认没有元表,必须通过setmetatable和getmetatable设置和查询元表。</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="background-color: #f5f5f5; border: #cccccc 1px solid; padding: 5px;">t =<span style="color: #000000;"> {}<br/></span><span style="color: #ff00ff;">assert</span>(<span style="color: #ff00ff;">getmetatable</span>(t)== <span style="color: #0000ff;">nil</span><span style="color: #000000;">) <br/>t1 </span>=<span style="color: #000000;"> {}<br/></span><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(t, t1)<br/></span><span style="color: #ff00ff;">assert</span>(<span style="color: #ff00ff;">getmetatable</span>(t) == t1)</div><p>在元表中定义的函数就是元方法,table的元方法分为算数类,关系类,库定义和访问类的元方法。</p><p>1. 算数类元方法</p><p>lua的算数类元方法都有对应的字段名,包括__add, __mul,__sub, __div,__mod和__pow等,下面示例了如何定义两个table的加法操作,</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="background-color: #f5f5f5; border: #cccccc 1px solid; padding: 5px;">a = { <span style="color: #800000;">"</span><span style="color: #800000;">a1</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">a2</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">a3</span><span style="color: #800000;">"</span><span style="color: #000000;"> }<br/>b </span>= { <span style="color: #800000;">"</span><span style="color: #800000;">b1</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b2</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b3</span><span style="color: #800000;">"</span><span style="color: #000000;"> }<br/>meta </span>=<span style="color: #000000;"> { }<br/>meta.__add </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(t1, t2)<br/> t </span>=<span style="color: #000000;"> { }<br/> </span><span style="color: #0000ff;">for</span> k, v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">ipairs</span>(t1) <span style="color: #0000ff;">do</span><br/> <span style="color: #ff00ff;">table.insert</span><span style="color: #000000;">(t, v)<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">for</span> k, v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">ipairs</span>(t2) <span style="color: #0000ff;">do</span><br/> <span style="color: #ff00ff;">table.insert</span><span style="color: #000000;">(t, v)<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">return</span><span style="color: #000000;"> t<br/></span><span style="color: #0000ff;">end</span><br/><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(a, meta)<br/>c </span>= a+<span style="color: #000000;">b<br/></span><span style="color: #0000ff;">for</span> _,v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">ipairs</span>(c) <span style="color: #0000ff;">do</span><br/> <span style="color: #ff00ff;">print</span><span style="color: #000000;">(v)<br/></span><span style="color: #0000ff;">end</span></div><p>上面代码中只需要给表a设置了元表,表b没有元表也能正常运行,这与lua查找元表的顺序有关系。lua先查找第一个table,如果有元表并且其中有 __add方法就调用该方法,不关心第二个table有没有元表;否则查找第二个table有没有__add的元方法,有就调用第二个table的元方法;如果都没有这个元方法就引发一个错误。</p><p>2. 关系类元方法</p><p>关系类元方法只有等于__eq,小于__lt和小于等于__le这3个操作,其他3个会自动转化,如a&gt;b会自动转为b&lt;a.</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="background-color: #f5f5f5; border: #cccccc 1px solid; padding: 5px;">a = { <span style="color: #800000;">"</span><span style="color: #800000;">a1</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">a2</span><span style="color: #800000;">"</span><span style="color: #000000;"> }<br/>b </span>= { <span style="color: #800000;">"</span><span style="color: #800000;">b1</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b2</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b3</span><span style="color: #800000;">"</span><span style="color: #000000;"> }<br/>meta </span>=<span style="color: #000000;"> { }<br/>meta.__le </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(a, b) <br/> </span><span style="color: #0000ff;">for</span> k <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(a) <span style="color: #0000ff;">do</span><br/> <span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span> b[k] <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span> <span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><br/><span style="color: #0000ff;">end</span><span style="color: #000000;"><br/>meta.__lt </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(a, b)<br/> </span><span style="color: #0000ff;">return</span> a&lt;=b <span style="color: #0000ff;">and</span> <span style="color: #0000ff;">not</span> (b&lt;=<span style="color: #000000;">a)<br/></span><span style="color: #0000ff;">end</span><span style="color: #000000;"><br/>meta.__eq </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(a, b)<br/> </span><span style="color: #0000ff;">return</span> a&lt;=b <span style="color: #0000ff;">and</span> b&lt;=<span style="color: #000000;">a<br/></span><span style="color: #0000ff;">end</span><br/><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(a, meta)<br/></span><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(b, meta)<br/></span><span style="color: #ff00ff;">print</span>(a&lt;=<span style="color: #000000;">b)<br/></span><span style="color: #ff00ff;">print</span>(a&lt;<span style="color: #000000;">b)<br/></span><span style="color: #ff00ff;">print</span>(a&gt;=<span style="color: #000000;">a)<br/></span><span style="color: #ff00ff;">print</span>(b&gt;<span style="color: #000000;">a)<br/></span><span style="color: #ff00ff;">print</span>(b&lt;a)</div><p>与算法类元方法不同,table必须具有相同的元方法才能用于比较操作。</p><p>3. 库定义的元方法</p><p>上面的元方法都是lua核心具有的,是lua虚拟机定义的,除此之外,各种程序库也会用自己的字段定义元方法,比如print总是调用table的tostring方法,</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="background-color: #f5f5f5; border: #cccccc 1px solid; padding: 5px;">a = { <span style="color: #800000;">"</span><span style="color: #800000;">a1</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">a2</span><span style="color: #800000;">"</span><span style="color: #000000;"> }<br/>meta.__tostring </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(a)<br/> </span><span style="color: #0000ff;">local</span> l =<span style="color: #000000;"> { }<br/> </span><span style="color: #0000ff;">for</span> _,k <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(a) <span style="color: #0000ff;">do</span><span style="color: #000000;"><br/> l[</span>#l+<span style="color: #800080;">1</span>] =<span style="color: #000000;"> k;<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">return</span> <span style="color: #800000;">"</span><span style="color: #800000;">{</span><span style="color: #800000;">"</span>..<span style="color: #ff00ff;">table.concat</span>(l, <span style="color: #800000;">"</span><span style="color: #800000;">,</span><span style="color: #800000;">"</span>)..<span style="color: #800000;">"</span><span style="color: #800000;">}</span><span style="color: #800000;">"</span><br/><span style="color: #0000ff;">end</span><br/><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(a, meta)<br/></span><span style="color: #ff00ff;">print</span>(a)</div><p>4. 访问类元方法</p><p>访问元方法使用最普遍的是__index和__newindex。一般当访问一个table中不存在的元素时会返回nil,但是如果table具有__index元方法,就不返回nil而是调用这个元方法。利用__index可以方便地实现继承,</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="background-color: #f5f5f5; border: #cccccc 1px solid; padding: 5px;">mt =<span style="color: #000000;"> { }<br/>mt.__index </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(t, k)<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> base[k]<br/></span><span style="color: #0000ff;">end</span><span style="color: #000000;"><br/><br/>base </span>= { b1 = <span style="color: #800080;">1</span>, b2 = <span style="color: #800080;">2</span>, b3 = <span style="color: #800080;">3</span><span style="color: #000000;"> }<br/>derive </span>= { d = <span style="color: #800080;">4</span><span style="color: #000000;"> }<br/><br/></span><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(derive, mt)<br/><br/></span><span style="color: #ff00ff;">print</span><span style="color: #000000;">(derive.b1)<br/></span><span style="color: #ff00ff;">print</span>(derive.d)</div><p>当对table中不存在的索引赋值时就会调用__newindex元方法,</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="background-color: #f5f5f5; border: #cccccc 1px solid; padding: 5px;">mt =<span style="color: #000000;"> { }<br/>mt.__newindex </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(t, k, v)<br/> base[k] </span>=<span style="color: #000000;"> v<br/></span><span style="color: #0000ff;">end</span><span style="color: #000000;"><br/>base </span>= { b1 = <span style="color: #800080;">1</span>, b2 = <span style="color: #800080;">2</span>, b3 = <span style="color: #800080;">3</span><span style="color: #000000;"> }<br/>derive </span>= { d1 = <span style="color: #800080;">4</span><span style="color: #000000;"> }<br/></span><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(derive, mt)<br/>derive[</span><span style="color: #800000;">"</span><span style="color: #800000;">d2</span><span style="color: #800000;">"</span>] = <span style="color: #800080;">5</span><br/><span style="color: #ff00ff;">print</span>(base.d2)</div><p><span style="font-size: 14px;"><strong>三、 元表元方法实例</strong></span></p><p>下面是一个使用元方法的实例,用于产生迭代递增表,</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="background-color: #f5f5f5; border: #cccccc 1px solid; padding: 5px;">T = { container =<span style="color: #000000;"> { } }<br/><br/>T.mt </span>=<span style="color: #000000;"> {<br/><br/> __add </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(a, b)<br/> </span><span style="color: #0000ff;">local</span> c =<span style="color: #000000;"> T.new{}<br/> </span><span style="color: #0000ff;">for</span> k,v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(T.new(a)) <span style="color: #0000ff;">do</span><span style="color: #000000;"><br/> c[k] </span>=<span style="color: #000000;"> v<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">for</span> k,v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(T.new(b)) <span style="color: #0000ff;">do</span><span style="color: #000000;"><br/> c[k] </span>=<span style="color: #000000;"> v<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">return</span><span style="color: #000000;"> c<br/> </span><span style="color: #0000ff;">end</span><span style="color: #000000;">,<br/><br/> __sub </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(a, b)<br/> </span><span style="color: #0000ff;">local</span> c =<span style="color: #000000;"> T.new{}<br/> </span><span style="color: #0000ff;">for</span> k,v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(T.new(a)) <span style="color: #0000ff;">do</span><span style="color: #000000;"><br/> c[k] </span>=<span style="color: #000000;"> v<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">for</span> k,v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(T.new(b)) <span style="color: #0000ff;">do</span><span style="color: #000000;"><br/> c[k] </span>= <span style="color: #0000ff;">nil</span><br/> <span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">return</span><span style="color: #000000;"> c<br/> </span><span style="color: #0000ff;">end</span><span style="color: #000000;">,<br/><br/> __tostring </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(a)<br/> </span><span style="color: #0000ff;">local</span> l =<span style="color: #000000;"> { }<br/> </span><span style="color: #0000ff;">for</span> k <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(a) <span style="color: #0000ff;">do</span><span style="color: #000000;"><br/> l[</span>#l+<span style="color: #800080;">1</span>] =<span style="color: #000000;"> k;<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">return</span> <span style="color: #800000;">"</span><span style="color: #800000;">{</span><span style="color: #800000;">"</span>..<span style="color: #ff00ff;">table.concat</span>(l, <span style="color: #800000;">"</span><span style="color: #800000;">,</span><span style="color: #800000;">"</span>)..<span style="color: #800000;">"</span><span style="color: #800000;">}</span><span style="color: #800000;">"</span><br/> <span style="color: #0000ff;">end</span><span style="color: #000000;"><br/>}<br/><br/>T.new </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(t)<br/> </span><span style="color: #0000ff;">if</span> (t == <span style="color: #0000ff;">nil</span>) <span style="color: #0000ff;">then</span> t = {} <span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">if</span> (<span style="color: #ff00ff;">getmetatable</span>(t) == T.mt) <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">return</span> t <span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">local</span> r =<span style="color: #000000;"> {}<br/> </span><span style="color: #0000ff;">for</span> _, b <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">ipairs</span>(t) <span style="color: #0000ff;">do</span><span style="color: #000000;"><br/> r[</span><span style="color: #ff00ff;">tostring</span>(b)] = <span style="color: #0000ff;">true</span><br/> <span style="color: #0000ff;">end</span><br/> <span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(r, T.mt)<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> r<br/></span><span style="color: #0000ff;">end</span><span style="color: #000000;"><br/><br/>T.</span><span style="color: #ff00ff;">print</span> = <span style="color: #0000ff;">function</span><span style="color: #000000;">(t) <br/> </span><span style="color: #0000ff;">for</span> k, v <span style="color: #0000ff;">in</span> <span style="color: #ff00ff;">pairs</span>(t.container) <span style="color: #0000ff;">do</span><br/> <span style="color: #ff00ff;">print</span><span style="color: #000000;">(k)<br/> </span><span style="color: #ff00ff;">print</span><span style="color: #000000;">(v)<br/> </span><span style="color: #0000ff;">end</span><br/> <span style="color: #0000ff;">end</span><br/><br/><span style="color: #0000ff;">local</span> mt =<span style="color: #000000;"> {<br/> __newindex </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(t, k, v)<br/> t.container[k] </span>=<span style="color: #000000;"> T.new(v)<br/> </span><span style="color: #0000ff;">end</span><span style="color: #000000;">,<br/><br/> __index </span>= <span style="color: #0000ff;">function</span><span style="color: #000000;">(t, k)<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> t.container[k]<br/> </span><span style="color: #0000ff;">end</span><span style="color: #000000;">,<br/>}<br/><br/></span><span style="color: #ff00ff;">setmetatable</span><span style="color: #000000;">(T, mt)<br/><br/>T[</span><span style="color: #800000;">"</span><span style="color: #800000;">first</span><span style="color: #800000;">"</span>] = { <span style="color: #800000;">"</span><span style="color: #800000;">a1</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b1</span><span style="color: #800000;">"</span><span style="color: #000000;">}<br/></span><span style="color: #ff00ff;">print</span>(<span style="color: #800000;">"</span><span style="color: #800000;">elements in table first</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br/>T.</span><span style="color: #ff00ff;">print</span><span style="color: #000000;">(T)<br/>T[</span><span style="color: #800000;">"</span><span style="color: #800000;">second</span><span style="color: #800000;">"</span>] = T[<span style="color: #800000;">"</span><span style="color: #800000;">first</span><span style="color: #800000;">"</span>] + { <span style="color: #800000;">"</span><span style="color: #800000;">a2</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b2</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">a3</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b3</span><span style="color: #800000;">"</span><span style="color: #000000;">}<br/></span><span style="color: #ff00ff;">print</span>(<span style="color: #800000;">"</span><span style="color: #800000;">elements in table first and second</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br/>T.</span><span style="color: #ff00ff;">print</span><span style="color: #000000;">(T)<br/>T[</span><span style="color: #800000;">"</span><span style="color: #800000;">third</span><span style="color: #800000;">"</span>] = T[<span style="color: #800000;">"</span><span style="color: #800000;">second</span><span style="color: #800000;">"</span>] - { <span style="color: #800000;">"</span><span style="color: #800000;">a3</span><span style="color: #800000;">"</span>, <span style="color: #800000;">"</span><span style="color: #800000;">b3</span><span style="color: #800000;">"</span><span style="color: #000000;"> }<br/></span><span style="color: #ff00ff;">print</span>(<span style="color: #800000;">"</span><span style="color: #800000;">elements in table first, second and third</span><span style="color: #800000;">"</span><span style="color: #000000;">)<br/>T.</span><span style="color: #ff00ff;">print</span>(T)</div><img src="http://counter.cnblogs.com/blog/rss/4051165" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/coderkian/p/4051165.html" target="_blank">lua编程之元表与元方法</a>,转载请注明。</p>http://www.cnblogs.com/ohmygirl/p/CIRead-1.htmlCI框架源码阅读笔记1 - 环境准备、基本术语和框架流程 - ohmygirl最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动。最近项目少,总算是有了一些时间去写一些东西。于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时刻提醒自己:借鉴和学习才有出路,忘记过去意味着背叛!基本术语说明 在本文开始之前,有必要对文中...2014-10-25T15:18:00Z2014-10-25T15:18:00Zohmygirlhttp://www.cnblogs.com/ohmygirl/<p><span style="font-size: 14px;">  最开始使用CI框架的时候,就打算写一个CI源码阅读的笔记系列,可惜虎头蛇尾,一直没有行动。最近项目少,总算是有了一些时间去写一些东西。于是准备将之前的一些笔记和经验记录下来,一方面权作备忘,另一方面时刻提醒自己:借鉴和学习才有出路,忘记过去意味着背叛!</span></p><p><strong>基本术语说明</strong></p><p><span style="font-size: 14px;">  </span>在本文开始之前,有必要对文中反复出现的术语做一个简单的说明,如果你对这一部分已经熟谙,完全可以略过。本文中反复出现和提及的术语包括:</p><p><span style="color: #800080;"><strong>前端控制器(Front Controller):</strong></span></p><p>  用于集中控制用户的所有请求的组件,将用户的请求发送到具体的应用程序控制器。在CI框架中,指的就是框架的入口文件Index.php.前端控制器本身是一种设计模式,详细可参考《J2EE设计模式》。</p><p><span style="color: #800080;"><strong>应用程序控制器</strong></span></p><p>  应用程序控制器是具体的处理用户请求URL的控制器,通常将一组相关的处理或者请求放置在一个应用程序控制器中,例如:UserController可能包含用户的注册、验证、个人信息、个人页面等相关操作。</p><p><span style="color: #800080;"><strong>MVC</strong></span></p><p><strong>  </strong>老生常谈的一个术语,是一种代码分层和组织模式。将代码分为M(Model,业务逻辑),V(view ,视图),C(Controller,控制器)等层次,便于将业务逻辑部分和视图渲染部分分离,减少代码的耦合。目前PHP中许多框架都基于MVC模式,如ZF,YII,CI等</p><p><span style="color: #800080;"><strong>Route</strong><strong>路由</strong></span></p><p>  虽然名为Route,但这里并不是路由器,而是指截取用户的请求并将请求转发到特定的Controller处理的过程。不同的框架的路由不同,但基本原理相同。</p><p><span style="color: #800080;"><strong>Hook</strong><strong>钩子</strong></span></p><p>  最初的Hook是指&ldquo;消息传递中一个环节,用于监控消息的传递,并在消息处理之前,添加特定的处理&rdquo;。这里的Hook是指,在不改变框架核心源码的基础上增加或更改系统的核心功能,最典型的情况包括:在控制器加载之前或加载完成之后运行特定的脚本。</p><h3 align="left">CI框架配置</strong></p><p><span style="font-size: 14px;">  本文的基本环境:Linux &nbsp;x86_64 &nbsp;GNU/Linux .安装了PHP(CGI)+Nginx+Mysql+redis(所以本文的许多服务器相关的配置都是以Nginx为主,而暂时忽略Apache服务器)。</span></p><p><span style="font-size: 14px;">  首先下载CI框架的源码,下载地址为:<a href="http://codeigniter.org.cn/downloads">http://codeigniter.org.cn/downloads</a> 目前稳定版本是2.2.0&nbsp; 。将源码解压到文件夹(假设为<span style="color: #993366;">/usr/nginx/html/CI</span> 目录)。</span></p><p><span style="font-size: 14px;">  配置CI框架之前,先浏览一下框架的目录结构:</span></p><p><img src="http://images.cnitblog.com/blog/679164/201410/252302393401971.png" alt="" /></p><p>其中:</p><p><span style="font-size: 14px;"><span style="color: #993366;"><strong>Application</strong></span> : &nbsp;   应用程序的目录,你的所有的应用代码都应该位于这个目录</span></p><p><span style="font-size: 14px;"><span style="color: #993366;"><strong>index.php</strong></span> &nbsp;: &nbsp;   框架的入口文件</span></p><p><span style="font-size: 14px;"><span style="color: #993366;"><strong>static&nbsp;</strong></span>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; :&nbsp;&nbsp;&nbsp;  我们自己建立的目录,放置一些CSS,image和js等静态文件(这完全可以放到application目录下,看个人喜好)</span></p><p><span style="font-size: 14px;"><span style="color: #993366;"><strong>system</strong>&nbsp;&nbsp;</span>&nbsp;&nbsp; &nbsp; : &nbsp;  CI框架的系统文件,也是源码阅读的主要部分</span></p><p><span style="font-size: 14px;"><span style="color: #993366;"><strong>user_guide</strong></span> :&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用户指导,类似于离线的用户手册。</span></p><p>CI框架需要配置的地方比较少:</p><p><span style="color: #3366ff;"><strong>1.  配置routes</strong></span></p><p>  Routes.php中配置的是默认的应用程序控制器和404页面. 打开application/config/routes.php文件, 配置如下:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #800080;">$route</span>['default_controller'] = "index"<span style="color: #000000;">;<br/></span><span style="color: #800080;">$route</span>['404_override'] = '';</div><p><span style="color: #3366ff; font-size: 14px;"><strong>2.  配置数据库database.php</strong></span></p><p><span style="font-size: 14px;">  如果你的应用程序需要提供动态内容,那么数据库几乎是必不可少的配置。打开application/config/database.php文件,该文件内容如下:</span></p><p><img src="http://images.cnitblog.com/blog/679164/201410/252306468404358.png" alt="" /></p><p><span style="font-size: 14px;">  CI框架是支持多数据流连接的,default是当前默认的连接,active_record用于指定是否启用ARM(Active Record Model)。每个配置项非常简明,这里不再做过多介绍。</span></p><p><span style="color: #3366ff; font-size: 14px;"><strong>3.  去掉index.php</strong></span></p><p><span style="font-size: 14px;">  现在访问你的应用程序,url应该类似于这样:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #000000;">test.xq.com/index.php/index<br/>test.xq.com/index.php/welcome</span></div><p><span style="font-size: 14px;">注意每个请求都会带有index.php段。去掉index.php会让URI更加美观。</span></p><p><span style="font-size: 14px;">打开刚刚添加的test.xq.com.conf文件,在server中添加如下配置:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #000000;">if ($request_filename !~* /(favicon.ico|static|uploads|js|javascript|css|images|robots\.txt|index\.php|index\.html))<br/>{<br/> rewrite ^/(.*)$ /index.php?$</span>1 last<span style="color: #008000;">;<br/></span>}</div><p><span style="font-size: 14px;">重启服务器后,现在,URL的访问方式变成了:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #000000;">test.xq.com/index<br/>test.xq.com/welcome</span></div><p>&nbsp;是不是简洁多了 :D</p><p><span style="font-size: 14px;"><strong><span style="color: #3366ff;">4.  添加.html访问后缀</span></strong></span></p><p><span style="font-size: 14px;">  可能还有人喜欢url中添加特定的后缀,例如.html后缀使你的应用程序更类似于一系列静态文件。配置方法是,在<span style="color: #993366;">application/config/config.php</span>中,更改如下配置为:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #800080;">$config</span>['url_suffix'] = '.html';</div><p><span style="font-size: 14px;">CI框架的更多配置可以参考:</span></p><ol><li><span style="font-size: 14px;">让Nginx支持.htaccess(本文没有提及使用.htaccess重写的内容,可以参考之)<a href="http://www.php100.com/html/program/nginx/2013/0905/5537.html">http://www.php100.com/html/program/nginx/2013/0905/5537.html</a></span></li><li><span style="font-size: 14px;">CI框架集成Smarty,习惯用smarty模板引擎的童鞋可以看看&nbsp; <a href="http://www.kankanews.com/ICkengine/archives/70302.shtml">http://www.kankanews.com/ICkengine/archives/70302.shtml</a></span></li></ol><h3 align="left">配置Vhost</strong></p><p><span style="font-size: 14px;">  为了方便访问(相比ip地址访问的方式,域名访问有更好的可记忆性),我们可以配置vhost,配置方式为:进入nginx的vhost目录,新建配置文件(本文中为test.xq.com.conf,一般情况下,我们的每个vhost都会以域名命名)。在配置文件中输入如下内容:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #000000;">server {<br/> listen </span>80<span style="color: #008000;">;<br/></span> server_name test.xq.com<span style="color: #008000;">;<br/></span> root /usr/nginx/html/CI/<span style="color: #008000;">;<br/></span><span style="color: #000000;"><br/> access_log logs/xq_access_log main</span><span style="color: #008000;">;<br/></span> error_log logs/testsq.log error<span style="color: #008000;">;<br/></span> charset GBK<span style="color: #008000;">;<br/></span> index index.php<span style="color: #008000;">;<br/></span><span style="color: #000000;"><br/> location ~ .*\.(php|php5)?$<br/> {<br/> include fastcgi_params</span><span style="color: #008000;">;<br/></span> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name<span style="color: #008000;">;<br/></span> fastcgi_pass 127.0.0.1:9000<span style="color: #008000;">;<br/></span><span style="color: #000000;"> }<br/><br/>}</span></div><p><span style="font-size: 14px;">Server中暂时没有其他rewrite配置,稍后在配置CI框架的时候,我们可以添加更多的配置类支持CI的友好URL.</span></p><p><span style="font-size: 14px;">打开本地的host文件,在host中添加条目:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;">10.130.130.130 test.xq.com </div><p><span style="font-size: 14px;">其中10.130.130.130应该是你的服务器的IP地址。</span></p><p><span style="font-size: 14px;">现在,在浏览器中可以通过域名访问CI框架了。</span></p><h3 align="left">框架流程</strong></p><p><span style="font-size: 14px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在结束本文之前,我们再看看CI框架的基本流程,这个流程将贯穿源码阅读的始终,所以,很有必要认真研读一下。引用CI框架用户手册的上的流程图:</span></p><p>&nbsp;<img src="http://images.cnitblog.com/blog/679164/201410/252313495748544.png" alt="" /></p><p><span style="font-size: 14px;">基本的执行流程如下:</span></p><ol><li><span style="font-size: 14px;">Index.php是前端控制器,初始化框架所需的所有资源,加载应用程序基本配置,接收所有用户的请求,并通过Route路由用户请求</span></li><li><span style="font-size: 14px;">若缓存文件存在,它将绕过通常的执行顺序,直接发送到客户端。</span></li><li><span style="font-size: 14px;">Security数据过滤。这位于应用程序控制器装载之前。</span></li><li><span style="font-size: 14px;">应用程序控制器加载数据库驱动、类库、业务逻辑类和可能的其他资源,处理用户的请求</span></li><li><span style="font-size: 14px;">视图发送到客户端。如果开启缓存,则视图会被缓存,用于之后的请求。</span></li></ol><p><span style="font-size: 14px;">下一步开始,将开始CI的源码阅读之旅。</span></p><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4051156" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/ohmygirl/p/CIRead-1.html" target="_blank">CI框架源码阅读笔记1 - 环境准备、基本术语和框架流程</a>,转载请注明。</p>http://www.cnblogs.com/TeyGao/p/4050972.html统计--过滤(筛选)索引的统计信息过期问题测试 - 笑东风基础知识普及:对于筛选索引,MSDN如是说:筛选索引是一种经过优化的非聚集索引,尤其适用于涵盖从定义完善的数据子集中选择数据的查询。 筛选索引使用筛选谓词对表中的部分行进行索引。 与全表索引相比,设计良好的筛选索引可以提高查询性能、减少索引维护开销并可降低索引存储开销。筛选索引与全表索引相比具有以下...2014-10-25T15:11:00Z2014-10-25T15:11:00Z笑东风http://www.cnblogs.com/TeyGao/<p>基础知识普及:</p><p>对于筛选索引,MSDN如是说:</p><p>筛选索引是一种经过优化的非聚集索引,尤其适用于涵盖从定义完善的数据子集中选择数据的查询。 筛选索引使用筛选谓词对表中的部分行进行索引。 与全表索引相比,设计良好的筛选索引可以提高查询性能、减少索引维护开销并可降低索引存储开销。</p><p>筛选索引与全表索引相比具有以下优点:</p><p>提高了查询性能和计划质量 设计良好的筛选索引可以提高查询性能和执行计划质量,因为它比全表非聚集索引小并且具有经过筛选的统计信息。&nbsp; 与全表统计信息相比,经过筛选的统计信息更加准确,因为它们只涵盖筛选索引中的行。</p><p>减少了索引维护开销 仅在数据操作语言 (DML) 语句对索引中的数据产生影响时,才对索引进行维护。&nbsp; 与全表非聚集索引相比,筛选索引减少了索引维护开销,因为它更小并且仅在索引中的数据更改时才进行维护。 筛选索引的数量可以非常多,特别是在其中包含很少更改的数据时。 同样,如果筛选索引只包含频繁修改的数据,则索引大小较小时可以减少更新统计信息的开销。</p><p>减少了索引存储开销 在没必要创建全表索引时,创建筛选索引可以减少非聚集索引的磁盘存储开销。&nbsp; 可以使用多个筛选索引替换一个全表非聚集索引而不会明显增加存储需求。</p><p>MSDN地址:<a href="http://msdn.microsoft.com/zh-cn/library/cc280372(v=sql.105).aspx">http://msdn.microsoft.com/zh-cn/library/cc280372(v=sql.105).aspx</a></p><p>&nbsp;--========================================================</p><p>基础案例介绍:</p><p>在很多场景中,过滤索引能解决很多复合索引无法处理的问题,成为一些特殊问题的必杀技,如下面的查询:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">10</span><span style="color: #000000;">) C2<br/></span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TB1<br/></span><span style="color: #0000ff;">WHERE</span> C1<span style="color: #808080;">&gt;</span><span style="color: #800000; font-weight: bold;">5</span><br/><span style="color: #0000ff;">ORDER</span> <span style="color: #0000ff;">BY</span> C2 <span style="color: #0000ff;">DESC</span></div><p>如果按C2倒序排序后,排在结果集前面的大多数行都满足C1&gt;5的条件的话,那么我们可以建立以下索引来优化:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> IDX_C2_INC<br/></span><span style="color: #0000ff;">ON</span><span style="color: #000000;"> TB1(C2)<br/>INCLUDE(C1)</span></div><p>但如果满足C1&gt;5的行特别少或者排在结果集尾部的话,那么查询需要遍历索引的大部分才能找到匹配的数据返回给客户,从而导致大量逻辑IO开销。</p><p>如果满足C1&gt;5的行比较少,那么可以使用以下索引来优化:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> IDX_C1_C2<br/></span><span style="color: #0000ff;">ON</span> TB1(C1,C2)</div><p>虽然以上索引能帮助快速找到所有C1&lt;5的行,但仍需要经过一次排序后才能获得TOP(5)的数据,而排序又会导致CPU资源开销。</p><p>随着SQL SERVER 2008引入过滤索引后,这样的查询便可以轻松搞定,我们只需要建立以下索引:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> IDX_C2_WH<br/></span><span style="color: #0000ff;">ON</span><span style="color: #000000;"> TB1(C2)<br/></span><span style="color: #0000ff;">WHERE</span> C1<span style="color: #808080;">&gt;</span><span style="color: #800000; font-weight: bold;">5</span></div><p>查询可以通过索引很快找到满足C1&gt;5并且按C2排序的TOP 5的数据,最小化地消耗CPU和IO资源。<br />--===========================================================</p><p>在SQL Server中,数据库选择的&ldquo;自动创建统计(Auto Create Statistics)&rdquo;选项默认为开启状态, 随着索引的创建,数据库会自动创建与之对应的统计信息,创建过滤索引的过程同样会创建对于的统计信息。</p><p>当数据库设置为自动更新统计时(数据库未开启跟踪标志情况下),SQL Server 监控表中的数据更改,当更改满足一下条件之一时更新:<br />1.向空表插入数据时 <br />2.少于500行的表增加500行或者更多 <br />3.当表中行多于500行时,数据的变化量大于20%时 <br />(在SQL SERVER 2000中,指的是20%的行被修改,而在SQL SERVER 2005/2008中,指的是20%的列数据被修改)</p><p>PS: 20%不是一个绝对值</p><p>--===========================================================</p><p>那么问题出来了,这个20%比例对过滤索引的统计信息是否满足呢?如果满足的话,哪基数是什么呢?是表中的数据还是当前满足条件的数据呢?</p><p>让我们来做个测试吧</p><p>首先准备测试数据</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;">--</span><span style="color: #008080;">创建表,并插入5000行数据</span><br/><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">5000</span><span style="color: #000000;">) <br/></span><span style="color: #ff00ff;">IDENTITY</span>(<span style="color: #0000ff;">INT</span>,<span style="color: #800000; font-weight: bold;">1</span>,<span style="color: #800000; font-weight: bold;">1</span>) <span style="color: #0000ff;">AS</span><span style="color: #000000;"> ID,<br/></span><span style="color: #808080;">*</span> <br/><span style="color: #0000ff;">INTO</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SYS.all_columns<br/></span><span style="color: #0000ff;">GO</span><br/><span style="color: #008080;">--</span><span style="color: #008080;">创建聚簇索引</span><br/><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">CLUSTERED</span> <span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> IDX_ID<br/></span><span style="color: #0000ff;">ON</span><span style="color: #000000;"> TB001(ID)<br/></span><span style="color: #0000ff;">GO</span><br/><span style="color: #008080;">--</span><span style="color: #008080;">创建过滤索引</span><br/><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">INDEX</span><span style="color: #000000;"> IDX_COLUMNID<br/></span><span style="color: #0000ff;">ON</span> TB001(<span style="color: #ff00ff;">object_id</span><span style="color: #000000;">)<br/></span><span style="color: #0000ff;">WHERE</span> Column_id<span style="color: #808080;">&lt;</span><span style="color: #800000; font-weight: bold;">3</span><br/><span style="color: #0000ff;">GO</span><br/><span style="color: #008080;">--</span><span style="color: #008080;">再导入25000行数据</span><br/><span style="color: #0000ff;">INSERT</span> <span style="color: #0000ff;">INTO</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">5000</span><span style="color: #000000;">) <br/></span><span style="color: #808080;">*</span> <br/><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SYS.all_columns<br/></span><span style="color: #0000ff;">GO</span> <span style="color: #800000; font-weight: bold;">5</span><br/><span style="color: #008080;">--</span><span style="color: #008080;">更新统计信息</span><br/><span style="color: #0000ff;">UPDATE</span> <span style="color: #0000ff;">STATISTICS</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">GO</span></div><p>查看过滤索引的统计信息</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;">--</span><span style="color: #008080;">查看过滤索引的统计信息</span><br/><span style="color: #0000ff;">DBCC</span> SHOW_STATISTICS(<span style="color: #ff0000;">'</span><span style="color: #ff0000;">dbo.TB001</span><span style="color: #ff0000;">'</span>,<span style="color: #ff0000;">'</span><span style="color: #ff0000;">IDX_COLUMNID</span><span style="color: #ff0000;">'</span><span style="color: #000000;">)<br/></span><span style="color: #0000ff;">GO</span></div><p><img src="http://images.cnitblog.com/blog/174228/201410/252116298088865.png" alt="" /></p><p>目前表中有30000行数据,满足条件的数据是5412行,都超过500行的限制,考虑20%这是一个参考值而不是绝对值,我们测试值调整到50%;为了避免版本问题导致更新行还是更新列的问题,我们统一使用插入方式来测试。</p><p>1.首先测试插入5412*50%=2706行数据</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;">--</span><span style="color: #008080;">再导入2706行数据</span><br/><span style="color: #0000ff;">INSERT</span> <span style="color: #0000ff;">INTO</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">2706</span><span style="color: #000000;">) <br/></span><span style="color: #808080;">*</span> <br/><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SYS.all_columns<br/></span><span style="color: #0000ff;">GO</span><br/><span style="color: #008080;">--</span><span style="color: #008080;">执行查询尝试触发统计更新</span><br/><span style="color: #0000ff;"><span style="font-family: Courier New;">SELECT TOP(1) object_id,COUNT(1)<br />FROM TB001<br />WHERE Column_id&lt;3<br />GROUP BY object_id<br />ORDER BY COUNT(1) DESC</span></span><br/><span style="color: #008080;">--</span><span style="color: #008080;">查看过滤索引的统计信息</span><br/><span style="color: #0000ff;">DBCC</span> SHOW_STATISTICS(<span style="color: #ff0000;">'</span><span style="color: #ff0000;">dbo.TB001</span><span style="color: #ff0000;">'</span>,<span style="color: #ff0000;">'</span><span style="color: #ff0000;">IDX_COLUMNID</span><span style="color: #ff0000;">'</span><span style="color: #000000;">)<br/></span><span style="color: #0000ff;">GO</span></div><p>统计信息未发生变化,仍旧是:<br /><img src="http://images.cnitblog.com/blog/174228/201410/252116298088865.png" alt="" /></p><p>2.首先测试插入30000*50%=15000行数据(需要考虑之前已插入的2706条数据)</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;">--</span><span style="color: #008080;">再导入25000行数据</span><br/><span style="color: #0000ff;">INSERT</span> <span style="color: #0000ff;">INTO</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">5000</span><span style="color: #000000;">) <br/></span><span style="color: #808080;">*</span> <br/><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SYS.all_columns<br/></span><span style="color: #0000ff;">GO</span><br/><span style="color: #0000ff;">INSERT</span> <span style="color: #0000ff;">INTO</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">5000</span><span style="color: #000000;">) <br/></span><span style="color: #808080;">*</span> <br/><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SYS.all_columns<br/></span><span style="color: #0000ff;">GO</span><br/><span style="color: #008080;">--</span><span style="color: #008080;">由于之前插入2706条数据,因此第三次插入2294</span><br/><span style="color: #0000ff;">INSERT</span> <span style="color: #0000ff;">INTO</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">2294</span><span style="color: #000000;">) <br/></span><span style="color: #808080;">*</span> <br/><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> SYS.all_columns<br/></span><span style="color: #0000ff;">GO</span><br/><span style="color: #0000ff;">SELECT</span> <span style="color: #ff00ff;">COUNT</span>(<span style="color: #800000; font-weight: bold;">1</span>) <span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TB001<br/><br/></span><span style="color: #008080;">--</span><span style="color: #008080;">执行查询尝试触发统计更新</span><br/><span style="color: #0000ff;"><span style="font-family: Courier New;">SELECT TOP(1) object_id,COUNT(1)<br />FROM TB001<br />WHERE Column_id&lt;3<br />GROUP BY object_id<br />ORDER BY COUNT(1) DESC</span></span><br/><span style="color: #0000ff;">GO</span><br/><span style="color: #008080;">--</span><span style="color: #008080;">查看过滤索引的统计信息</span><br/><span style="color: #0000ff;">DBCC</span> SHOW_STATISTICS(<span style="color: #ff0000;">'</span><span style="color: #ff0000;">dbo.TB001</span><span style="color: #ff0000;">'</span>,<span style="color: #ff0000;">'</span><span style="color: #ff0000;">IDX_COLUMNID</span><span style="color: #ff0000;">'</span><span style="color: #000000;">)<br/></span><span style="color: #0000ff;">GO</span></div><p><img src="http://images.cnitblog.com/blog/174228/201410/252202335123538.png" alt="" /></p><p>感谢上苍,感谢党,统计更新了,世界和平了,妈妈再也不用担心我的成绩了(毕业很多年啦,泪流满面啊)!!!</p><p>--=====================================================</p><p>在测试过程中,最开始想使用以下查询来触发:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">SELECT</span> <span style="color: #0000ff;">TOP</span>(<span style="color: #800000; font-weight: bold;">1</span>) <span style="color: #ff00ff;">object_id</span><br/><span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">WHERE</span> Column_id<span style="color: #808080;">&lt;</span><span style="color: #800000; font-weight: bold;">3</span><br/><span style="color: #808080;">AND</span> Column_id<span style="color: #808080;">=</span><span style="color: #800000; font-weight: bold;">82873218</span><br/><span style="color: #0000ff;">ORDER</span> <span style="color: #0000ff;">BY</span> <span style="color: #ff00ff;">object_id</span><br/><span style="color: #0000ff;">GO</span><br/><span style="color: #0000ff;">SELECT</span> <span style="color: #ff00ff;">COUNT</span>(<span style="color: #800000; font-weight: bold;">1</span>) <span style="color: #0000ff;">FROM</span><span style="color: #000000;"> TB001<br/></span><span style="color: #0000ff;">WHERE</span> Column_id<span style="color: #808080;">&lt;</span><span style="color: #800000; font-weight: bold;">3</span><br/><span style="color: #0000ff;">GO</span></div><p>结果得出一个错误结论,经多次测试后才发现上述两个查询虽然使用到索引,但是无法触发统计更新。</p><p>--=====================================================</p><p>总结:无论是复合索引还是过滤索引的统计信息,都是以上一次统计信息更新时表的行数作为基数,当更新达到按20%左右的比例左右后,由查询执行来触发统计自动更新。</p><p>PS1: 更新数指的是操作影响的行数,如执行10次UPDATE操作,每次UPDATE影响50行数据,那么更新数为500,即使这10次UPDATE没有改变任何一条数据(类似UPDATE T1 SET C1=C1这类操作)</p><p>PS2: 即使更新数达到20%左右,查询使用到该过滤索引,也不一定会触发统计更新,只有查询优化器认为该统计过期并且需要一个更新过的统计信息来生成执行计划时,才会触发统计自动更新</p><p>PS2:由于过滤索引的只存放满足过滤条件的数据的特殊性,存在一些场景下,索引数据变化很多而对应的统计信息尚未满足过期(无效)条件,从而导致生成不高效的执行计划,因此有很多高手大神都建议专门针对这些有过滤条件的统计信息制定更新计划,提高其更新频率</p><p>PS3:除创建过滤索引会生成有过滤条件的统计信息外,数据库管理员也可以主动添加有过滤条件的统计信息,供执行优化器使用。</p><p>--=============================================</p><p>漂亮妹子看多了,来点普通的,哈哈</p><p><img src="http://images.cnitblog.com/blog/174228/201410/252310002773529.jpg" alt="" /></p><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4050972" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/TeyGao/p/4050972.html" target="_blank">统计--过滤(筛选)索引的统计信息过期问题测试</a>,转载请注明。</p>http://www.cnblogs.com/fengyunyu/p/4051140.htmlAsyncdisplaykit 指南(一) - 风云语#Asyncdisplaykit[Asyncdisplaykit github地址](https://github.com/facebook/AsyncDisplayKit)##基本概念 AsyncDisplayKit的基本单元是node. ASDisplayNode是UIView和CALayer....2014-10-25T15:08:00Z2014-10-25T15:08:00Z风云语http://www.cnblogs.com/fengyunyu/<h1 id="asyncdisplaykit">Asyncdisplaykit</strong></p><p><a href="https://github.com/facebook/AsyncDisplayKit">Asyncdisplaykit github地址</a></p><p><strong>基本概念</strong></p><p>??AsyncDisplayKit的基本单元是node. ASDisplayNode是UIView和CALayer的抽象。ASDisplayNode是线程安全的,可以在工作线程中并行地初始化和配置整个node树。</p><p>??如果保证帧率到60fps,那么所有的layout和drawing需要在16ms内完成。由于系统的开销,留给我们的只有大概10ms。</p><p>??AsyncDisplayKit能够将image decoding, text sizing和rendering以及其他耗时的UI操作剥离主线程。</p><h2 id="nodesview">nodes替代view</strong></p><p>??Node的API与UIView相似,而且可以直接访问CALayer属性。<br /> 添加view和layer,可以直接使用node.view 和 node.layer.</p><p>AsyncDisplayKit包括几个强大的模块:</p><p>* ASDisplayNode - 相当于UIView,子类化实现自定义nodes<br /> * ASControlNode - 相当于UIControl,子类化实现buttons<br /> * ASImageNode - 相当于UIimageView,异步decode image<br /> * ASTextNode - 相当于UITextView,基于TextKit实现,支持富文本<br /> * ASTableView - 相当于UITableView</p><p>?? 我们可以直接用node替换UIKit,全部基于node实现的图层树的ASDK效率更高,但即使仅仅替换一个view也会提高效率。</p><p>??首先我们在主线程 同步的使用node.</p><p>??代码示例:</p><code>_imageView = [[UIImageView alloc] init];<br/>_imageView.image = [UIImage imageNamed:@&quot;hello&quot;];<br/>_imageView.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f);<br/>[self.view addSubview:_imageView];</code><p>??使用Node替换:</p><code>_imageNode = [[ASImageNode alloc] init];<br/>_imageNode.backgroundColor = [UIColor lightGrayColor];<br/>_imageNode.image = [UIImage imageNamed:@&quot;hello&quot;];<br/>_imageNode.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f);<br/>[self.view addSubview:_imageNode.view];</code><p>??这里我们没有利用ASDK的异步 sizing 和 layout,但是性能已经有所提高。第一段代码在主线程decode image,第二段代码则在工作线程decode,而且可能在不同的CPU核心。</p><blockquote><p>这里我们先展示了一个placeholder,然后再展示真实图片。但是对于text,这种延迟加载的方法不可行,后面会进行讨论。</p></blockquote><h2 id="botton-nodes">Botton nodes</strong></p><p>??ASImageNode 和 ASTextNode 都继承自ASControlNode,可以当做button使用,比如我们想做一个音乐播放器,先添加一个shuffle按钮:</p><p>??view controller的代码:</p><code>- (void)viewDidLoad<br/>{<br/> [super viewDidLoad];<br/><br/> // attribute a string<br/> NSDictionary *attrs = @{<br/> NSFontAttributeName: [UIFont systemFontOfSize:12.0f],<br/> NSForegroundColorAttributeName: [UIColor redColor],<br/> };<br/> NSAttributedString *string = [[NSAttributedString alloc] initWithString:@&quot;shuffle&quot;<br/> attributes:attrs];<br/><br/> // create the node<br/> _shuffleNode = [[ASTextNode alloc] init];<br/> _shuffleNode.attributedString = string;<br/><br/> // configure the button<br/> _shuffleNode.userInteractionEnabled = YES; // opt into touch handling<br/> [_shuffleNode addTarget:self<br/> action:@selector(buttonTapped:)<br/> forControlEvents:ASControlNodeEventTouchUpInside];<br/><br/> // size all the things<br/> CGRect b = self.view.bounds; // convenience<br/> CGSize size = [_shuffleNode measure:CGSizeMake(b.size.width, FLT_MAX)];<br/> CGPoint origin = CGPointMake(roundf( (b.size.width - size.width) / 2.0f ),<br/> roundf( (b.size.height - size.height) / 2.0f ));<br/> _shuffleNode.frame = (CGRect){ origin, size };<br/><br/> // add to our view<br/> [self.view addSubview:_shuffleNode.view];<br/>}<br/><br/>- (void)buttonTapped:(id)sender<br/>{<br/> NSLog(@&quot;tapped!&quot;);<br/>}</code><p>上述代码可以正常运行,但是text的点击区域太小,解决方法:</p><code> // size all the things<br/> /* ... */<br/><br/> // make the tap target taller<br/> CGFloat extendY = roundf( (44.0f - size.height) / 2.0f );<br/> _shuffleNode.hitTestSlop = UIEdgeInsetsMake(-extendY, 0.0f, -extendY, 0.0f);</code><p>所有的nodes都可以使用Hit-test slops。</p><img src="http://counter.cnblogs.com/blog/rss/4051140" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/fengyunyu/p/4051140.html" target="_blank">Asyncdisplaykit 指南(一)</a>,转载请注明。</p>http://www.cnblogs.com/fecktty2013/p/eventbroker-1.htmlC#编程实践—EventBroker简单实现 - 周信达前言话说EventBroker这玩意已经不是什么新鲜货了,记得第一次接触这玩意是在进第二家公司的时候,公司产品基础架构层中集成了分布式消息中间件,在.net基础服务层中使用EventBroker的模式将消息组装成事件,支持同域、跨域和跨机器进行事件的发布和订阅,后来才知道这玩意叫做EventBrok...2014-10-25T14:58:00Z2014-10-25T14:58:00Z周信达http://www.cnblogs.com/fecktty2013/<p><strong>前言</strong></p><p>话说EventBroker这玩意已经不是什么新鲜货了,记得第一次接触这玩意是在进第二家公司的时候,公司产品基础架构层中集成了分布式消息中间件,在.net基础服务层中使用EventBroker的模式将消息组装成事件,支持同域、跨域和跨机器进行事件的发布和订阅,后来才知道这玩意叫做EventBroker。不得不承认,这是一个非常聪明的东西,它在内部高度封装了消息和事件的处理,将上层应用的事件和委托的依赖进行解耦,并且提供非常简洁的方式进行开发。OK,本篇文章只是实现了一个简化版本的EventBroker,功能非常有限,也没有集成消息组件,所以也不支持跨域和跨机器的分布式应用了,甚至没有经过严格测试(比如并发处理、跨线程处理等等),社区上更好的实现很多。所以必须声明:只是实验性代码,纯粹练手,带着学习的态度写代码,coding不易,大家不喜勿喷</p><p><strong>准备</strong></p><p>本篇主要使用.net C#技术,包括委托、反射、弱引用和弱事件模式,写代码也是为了学习这些,找找码感。说明:为了不影响阅读,所贴代码均有一些阉割,如需源码,后续我把附件传上来,不过这源码真没啥东西,我上传就是自己做一个记录,存储下来</p><p><strong>思路</strong></p><p>思路不用多说,网上搜一下会有很多信息,我比较懒,直接贴一张网上的图可以明确表现出系统的交互场景和交互流程</p><p><img src="http://www.codeproject.com/KB/dotnet/EventBroker/EventBroker.png" alt="EventBroker.png" width="492" height="246" /></p><p><strong>应用</strong></p><p>在应用层使用EventBroker,需要在应用中针对对象进行Register,一般中大型项目使用IOC容器都提供在对象创建时注入特征,比如:</p>// 示范代码<br/>private void OnObjectBuild(ObjectModel builder, object instance)<br/>{<br/> var broker = DIContainer.Resolve&lt;IEventBroker&gt;();<br/> broker.Register(instance);<br/>}<p>这样比较方便,避免在程序中手动Register,不过我这里只是简单实现,不涉及IOC和任何设计的东西,注册对象后,在我们的类中可以像如下的方式实现:</p>[EventPublication("topic://eventbreaker/winform/message", EventScope = EventScope.Local)]<br/>public event EventHandler&lt;EventModelArgs&lt;string&gt;&gt; MessageArrived;<p>以上是事件定义,我们可以把事件委托引用的方法定义在另一个类,而且两者完全不用依赖彼此</p>[EventSubscription("topic://eventbreaker/winform/message", EventScope = EventScope.Local)]<br/>public void MessageReceived(object sender, EventModelArgs&lt;string&gt; message)<br/>{<br/> PrintOut(message.Data);<br/>}<p><strong>源码</strong></p><ul><li>源码目录结构,看看是不是比别的版本精简了?</li></ul><blockquote><p><a href="http://images.cnitblog.com/blog/482289/201410/252254459338466.jpg"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="code" src="http://images.cnitblog.com/blog/482289/201410/252254475909692.jpg" alt="code" width="215" height="244" border="0" /></a></p></blockquote><ul><li>EventBroker,我暂且把这个叫事件总线,内部封装EventTopic,事件的发布者和订阅者信息都间接存储在总线上,除此之外,总线向外部提供统一的API接口,方便调用,相关接口如下:</li></ul><blockquote>namespace TinyEventBroker<br/>{<br/> public class EventBroker<br/> {<br/> private readonly EventTopicCollection topics<br/> = new EventTopicCollection();<br/><br/> /// &lt;summary&gt;<br/> /// 事件主题集合列表<br/> /// &lt;/summary&gt;<br/> public EventTopicCollection Topics<br/> {<br/> get { return topics; }<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 事件场景<br/> /// &lt;/summary&gt;<br/> public virtual EventScope EventScope { get { return EventScope.Local; } }<br/><br/> /// &lt;summary&gt;<br/> /// 将对象注入到事件总线上<br/> /// &lt;/summary&gt;<br/> public void Register(object target)<br/> {<br/> BindingFlags bingdings = BindingFlags.Instance | BindingFlags.Static<br/> | BindingFlags.Public | BindingFlags.NonPublic;<br/> RegisterPublication(target, bingdings);<br/> RegisterSubscription(target, bingdings);<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 注册发布者<br/> /// &lt;/summary&gt;<br/> private void RegisterPublication(object target, BindingFlags bindings)<br/> {<br/> // &hellip;&hellip;<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 注册订阅者<br/> /// &lt;/summary&gt;<br/> /// &lt;param name="target"&gt;&lt;/param&gt;<br/> /// &lt;param name="bindings"&gt;&lt;/param&gt;<br/> private void RegisterSubscription(object target, BindingFlags bindings)<br/> {<br/> // &hellip;&hellip;<br/> }<br/> }<br/>}</blockquote><ul><li>EventTopic,这个我把它称为事件主题,一个主题可以包含多个发布者和订阅者并提供一些处理,主题管理器内部将事件进行桥接,并动态调用订阅者方法,相关接口如下:</li></ul><blockquote>public class EventTopic<br/>{<br/> public EventTopic() { }<br/> public EventTopic(string name)<br/> : this()<br/> {<br/> this.Name = name;<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 事件主题标识<br/> /// &lt;/summary&gt;<br/> public string Name { get; set; }<br/><br/> private List&lt;EventPublication&gt; publishers = new List&lt;EventPublication&gt;();<br/> /// &lt;summary&gt;<br/> /// 发布者列表<br/> /// &lt;/summary&gt;<br/> internal List&lt;EventPublication&gt; Publishers<br/> {<br/> get { return publishers; }<br/> set { publishers = value; }<br/> }<br/><br/> private List&lt;EventSubscription&gt; subscribers = new List&lt;EventSubscription&gt;();<br/> /// &lt;summary&gt;<br/> /// 订阅者列表<br/> /// &lt;/summary&gt;<br/> internal List&lt;EventSubscription&gt; Subscribers<br/> {<br/> get { return subscribers; }<br/> set { subscribers = value; }<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 增加发布者<br/> /// &lt;/summary&gt;<br/> internal void AddPublication(EventPublication publisher)<br/> {<br/> EventContext.Instance.WriteTo("主题:{0} 添加发布者{1}", Name, publisher);<br/> publisher.EventFired += OnEventFired;<br/> publishers.Add(publisher);<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 增加订阅者<br/> /// &lt;/summary&gt;<br/> internal void AddSubscription(EventSubscription subscriber)<br/> {<br/> EventContext.Instance.WriteTo("主题:{0} 添加订阅者{1}", Name, subscriber);<br/> subscribers.Add(subscriber);<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 移除发布者<br/> /// &lt;/summary&gt;<br/> internal void RemovePublication(EventPublication publisher)<br/> {<br/> EventContext.Instance.WriteTo("主题:{0} 移除发布者{1}", Name, publisher);<br/> publishers.Remove(publisher);<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 移除订阅者<br/> /// &lt;/summary&gt;<br/> internal void RemoveSubscription(EventSubscription subscriber)<br/> {<br/> EventContext.Instance.WriteTo("主题:{0} 移除订阅者{1}", Name, subscriber);<br/> subscribers.Remove(subscriber);<br/> }<br/><br/> internal void OnEventFired(EventPublication publication, object sender, EventArgs args)<br/> {<br/> // ......<br/> }<br/><br/> private void CheckInvalidPublications()<br/> {<br/> // ......<br/> }<br/><br/> private void CheckInvalidSubscriptions()<br/> {<br/> // ......<br/> }<br/>}</blockquote><ul><li>Publisher,订阅者,使用弱引用来存储目标对象,防止目标对象无法释放造成内存泄露</li></ul><blockquote>using System;<br/>using System.Collections.Generic;<br/>using System.Linq;<br/>using System.Reflection;<br/>using System.Text;<br/>using System.Threading.Tasks;<br/><br/>namespace TinyEventBroker<br/>{<br/> /// &lt;summary&gt;<br/> /// 发布者<br/> /// &lt;/summary&gt;<br/> internal class EventPublication<br/> {<br/> /// &lt;summary&gt;<br/> /// 弱引用对象包装器<br/> /// &lt;/summary&gt;<br/> private readonly WeakReference wrapper;<br/> /// &lt;summary&gt;<br/> /// 事件名称<br/> /// &lt;/summary&gt;<br/> private readonly string eventName;<br/> /// &lt;summary&gt;<br/> /// 事件处理委托类型<br/> /// &lt;/summary&gt;<br/> private readonly Type eventHandleType;<br/><br/> /// &lt;summary&gt;<br/> /// 对象名称,用于显示<br/> /// &lt;/summary&gt;<br/> private readonly string targetName;<br/><br/> /// &lt;summary&gt;<br/> /// 事件定义,用来桥接对象的Event<br/> /// &lt;/summary&gt;<br/> public event TopicEventHandler EventFired;<br/><br/> public EventPublication(object target, string eventName)<br/> {<br/> wrapper = new WeakReference(target);<br/> this.eventName = eventName;<br/> this.targetName = target.GetType().Name;<br/><br/> EventInfo info = target.GetType().GetEvent(EventName);<br/> eventHandleType = info.EventHandlerType;<br/><br/> Delegate handler = Delegate.CreateDelegate(<br/> EventHandleType, this,<br/> this.GetType().GetMethod("OnEventFired"));<br/> info.AddEventHandler(target, handler);<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 获取对象引用<br/> /// &lt;/summary&gt;<br/> public object Target<br/> {<br/> get { return wrapper.Target; }<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 对象名称,用于显示<br/> /// &lt;/summary&gt;<br/> public string TargetName<br/> {<br/> get { return targetName; }<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 判断对象是否存活<br/> /// &lt;/summary&gt;<br/> public bool IsAlive<br/> {<br/> get { return wrapper.IsAlive; }<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 事件名称<br/> /// &lt;/summary&gt;<br/> public string EventName<br/> {<br/> get { return eventName; }<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 事件处理类型<br/> /// &lt;/summary&gt;<br/> public Type EventHandleType<br/> {<br/> get { return eventHandleType; }<br/> }<br/><br/> public virtual void OnEventFired(object sender, EventArgs e)<br/> {<br/> var handle = EventFired;<br/> if (handle != null)<br/> handle(this, sender, e);<br/> }<br/><br/> public override string ToString()<br/> {<br/> return string.Format("[{0} - {1}]", targetName, eventName);<br/> }<br/> }<br/>}</blockquote><ul><li>订阅者,依然使用弱引用来保存目标对象</li></ul><blockquote>using System;<br/>using System.Collections.Generic;<br/>using System.Linq;<br/>using System.Text;<br/>using System.Threading;<br/>using System.Threading.Tasks;<br/><br/>namespace TinyEventBroker<br/>{<br/> /// &lt;summary&gt;<br/> /// 订阅者<br/> /// &lt;/summary&gt;<br/> public class EventSubscription<br/> {<br/> /// &lt;summary&gt;<br/> /// 弱引用对象包装器<br/> /// &lt;/summary&gt;<br/> private readonly WeakReference wrapper;<br/> /// &lt;summary&gt;<br/> /// 方法名<br/> /// &lt;/summary&gt;<br/> private readonly string methodName;<br/><br/> /// &lt;summary&gt;<br/> /// 对象名称,仅作显示<br/> /// &lt;/summary&gt;<br/> private readonly string targetName;<br/><br/> public EventSubscription(object target, string methodName)<br/> {<br/> this.wrapper = new WeakReference(target);<br/> this.methodName = methodName;<br/> targetName = target.GetType().Name;<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 对象是否存活<br/> /// &lt;/summary&gt;<br/> public bool IsAlive<br/> {<br/> get { return wrapper.IsAlive; }<br/> }<br/><br/> /// &lt;summary&gt;<br/> /// 订阅者对象方法名<br/> /// &lt;/summary&gt;<br/> public string MethodName { get { return methodName; } }<br/> /// &lt;summary&gt;<br/> /// 订阅者对象,通过弱引用包装访问<br/> /// &lt;/summary&gt;<br/> public object Target { get { return wrapper.Target; } }<br/> /// &lt;summary&gt;<br/> /// 订阅者对象显式名<br/> /// &lt;/summary&gt;<br/> public string TargetName { get { return targetName; } }<br/><br/> internal virtual void HandleEvent(EventPublication publication, object sender, EventArgs args)<br/> {<br/> Delegate handler = Delegate.CreateDelegate(<br/> publication.EventHandleType, Target, methodName);<br/><br/> handler.DynamicInvoke(sender, args);<br/> }<br/><br/> public override string ToString()<br/> {<br/> return string.Format("[{0} - {1}]", targetName, methodName);<br/> }<br/> }<br/>}</blockquote><ul><li>EventScope,这东西只是保留属性,以后扩展的时候用</li></ul><p><strong>初步测试结果</strong></p><p><a href="http://images.cnitblog.com/blog/482289/201410/252254478559379.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="windemo" src="http://images.cnitblog.com/blog/482289/201410/252254481521822.png" alt="windemo" width="558" height="399" border="0" /></a></p><p><strong>引用</strong></p><p>针对弱引用这个东东,其实直接使用弱事件模式,微软已经封装好了的</p><p><a href="http://msdn.microsoft.com/en-us/library/aa970850%28v=vs.110%29.aspx">Weak Event Patterns</a>,<a href="http://www.codeproject.com/Articles/29922/Weak-Events-in-C">Weak Event in C#</a></p><p><strong>结语</strong></p><p>本篇只是EventBroker的简单实现,纯粹就是学习练手,我想,如果后续我有充足的时间,或者工作环境允许,我可以实现得更好,比如可以在内部封装多钟策略,异常处理策略、异步事件策略、处理并发、线程安全的考虑等等。更而甚之,可以将它进行抽象和扩展,加入消息中间件,实现分布式发布者和订阅者,那样就比较有实用价值了。不过写代码水平和效率有限,时间和精力也有限,工作是工作学习是学习,区区一文,聊表我的热情和开发,让代码和生活可以持续下去吧!</p><p><a href="http://files.cnblogs.com/fecktty2013/TinyEventBroker.rar" target="_blank">源码下载</a></p><img src="http://counter.cnblogs.com/blog/rss/4051123" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/fecktty2013/p/eventbroker-1.html" target="_blank">C#编程实践—EventBroker简单实现</a>,转载请注明。</p>http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-Decrypt.html微信公众平台消息体加解密实现 - 方倍工作室关键字:微信公众平台 消息体签名 消息体加解密 EncodingAESKey 安全模式原文 http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-Decrypt.html一、消息体加解密微信公众平台在配置服务器时,提供了3种加解密的模式供开发者选择,...2014-10-25T14:29:00Z2014-10-25T14:29:00Z方倍工作室http://www.cnblogs.com/txw1958/<p>关键字:微信公众平台 消息体签名 消息体加解密 EncodingAESKey 安全模式</p><p>原文 <a id="Editor_Edit_hlEntryLink" title="view: 微信公众平台消息体加解密实现" href="http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-Decrypt.html" target="_blank">http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-Decrypt.html</a>&nbsp;&nbsp;</p><p><strong>一、消息体加解密</strong></p><p>微信公众平台在配置服务器时,提供了3种加解密的模式供开发者选择,即明文模式、兼容模式、安全模式,选择兼容模式和安全模式前,需在开发者中心填写消息加解密密钥EncodingAESKey。</p><ul><li>明文模式:维持现有模式,没有适配加解密新特性,消息体明文收发,默认设置为明文模式</li><li>兼容模式:公众平台发送消息内容将同时包括明文和密文,消息包长度增加到原来的3倍左右;公众号回复明文或密文均可,不影响现有消息收发;开发者可在此模式下进行调试</li><li>安全模式(推荐):公众平台发送消息体的内容只含有密文,公众账号回复的消息体也为密文,建议开发者在调试成功后使用此模式收发消息</li></ul><p>什么是EncodingAESKey?</p><ul><li>微信公众平台采用AES对称加密算法对推送给公众帐号的消息体对行加密,EncodingAESKey则是加密所用的秘钥。公众帐号用此秘钥对收到的密文消息体进行解密,回复消息体也用此秘钥加密。AES对称加密算法的原理可以参考 http://www.cnblogs.com/txw1958/p/aes.html</li></ul><p>  加解密的详细技术方案可以参考官方文档 http://mp.weixin.qq.com/wiki/index.php?title=%E6%8A%80%E6%9C%AF%E6%96%B9%E6%A1%88</p><p>适用公众账号类型</p><ul><li>已认证订阅号</li><li>服务号</li><li>企业号</li></ul><p>不能用于未认证订阅号,因为其没有appid参数</p><p><strong><br />二、开发实现及数据分析</strong></p><p><strong>1. 配置</strong></p><p>假设本次的开发配置中URL为</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;">http:<span style="color: #008000;">//</span><span style="color: #008000;">www.fangbei.org/index.php</span></div><p>接口程序中需要配置以下三项参数</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008000;">/*</span><span style="color: #008000;"><br/> 方倍工作室 http://www.cnblogs.com/txw1958/<br/> CopyRight 2014 All Rights Reserved<br/></span><span style="color: #008000;">*/</span><br/><span style="color: #008080;">define</span>("TOKEN", "weixin"<span style="color: #000000;">);<br/></span><span style="color: #008080;">define</span>("AppID", "wxbad0b45542aa0b5e"<span style="color: #000000;">);<br/></span><span style="color: #008080;">define</span>("EncodingAESKey", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"<span style="color: #000000;">);<br/></span><span style="color: #0000ff;">require_once</span>('wxBizMsgCrypt.php');</div><p>&nbsp;</p><p><strong>2. 加解密实现</strong></p><p>当用户向公众账号发送消息时,微信公众账号将会在URL中带上signature、timestamp、nonce、encrypt_type、msg_signature等参数,如下所示</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;">http:<span style="color: #008000;">//</span><span style="color: #008000;">www.fangbei.org/aes/index.php?signature=35703636de2f9df2a77a662b68e521ce17c34db4&amp;timestamp=1414243737&amp;nonce=1792106704&amp;encrypt_type=aes&amp;msg_signature=6147984331daf7a1a9eed6e0ec3ba69055256154</span></div><p>同时向该接口推送如下XML消息 ,即一个已加密的消息</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ToUserName</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">gh_680bdefc8c5d</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ToUserName</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">Encrypt</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">MNn4+jJ/VsFh2gUyKAaOJArwEVYCvVmyN0iXzNarP3O6vXzK62ft1/KG2/XPZ4y5bPWU/jfIfQxODRQ7sLkUsrDRqsWimuhIT8Eq+w4E/28m+XDAQKEOjWTQIOp1p6kNsIV1DdC3B+AtcKcKSNAeJDr7x7GHLx5DZYK09qQsYDOjP6R5NqebFjKt/NpEl/GU3gWFwG8LCtRNuIYdK5axbFSfmXbh5CZ6Bk5wSwj5fu5aS90cMAgUhGsxrxZTY562QR6c+3ydXxb+GHI5w+qA+eqJjrQqR7u5hS+1x5sEsA7vS+bZ5LYAR3+PZ243avQkGllQ+rg7a6TeSGDxxhvLw+mxxinyk88BNHkJnyK//hM1k9PuvuLAASdaud4vzRQlAmnYOslZl8CN7gjCjV41skUTZv3wwGPxvEqtm/nf5fQ=</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">Encrypt</span><span style="color: #0000ff;">&gt;</span><br/><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span></div><p>这时,程序需要从url中获得以下参数</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #800080;">$timestamp</span> = <span style="color: #800080;">$_GET</span>['timestamp'<span style="color: #000000;">];<br/></span><span style="color: #800080;">$nonce</span> = <span style="color: #800080;">$_GET</span>["nonce"<span style="color: #000000;">];<br/></span><span style="color: #800080;">$msg_signature</span> = <span style="color: #800080;">$_GET</span>['msg_signature'<span style="color: #000000;">];<br/></span><span style="color: #800080;">$encrypt_type</span> = <span style="color: #800080;">$_GET</span>['encrypt_type'];</div><p>这些参数将用于加解密过程</p><p>收到消息后,先进行解密,解密部分代码如下</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #800080;">$postStr</span> = <span style="color: #800080;">$GLOBALS</span>["HTTP_RAW_POST_DATA"<span style="color: #000000;">];<br/></span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$encrypt_type</span> == 'aes'<span style="color: #000000;">){<br/> </span><span style="color: #800080;">$pc</span> = <span style="color: #0000ff;">new</span> WXBizMsgCrypt(TOKEN, EncodingAESKey,<span style="color: #000000;"> AppID); <br/> </span><span style="color: #800080;">$this</span>-&gt;logger(" D \r\n".<span style="color: #800080;">$postStr</span><span style="color: #000000;">);<br/> </span><span style="color: #800080;">$decryptMsg</span> = ""; <span style="color: #008000;">//</span><span style="color: #008000;">解密后的明文</span><br/> <span style="color: #800080;">$errCode</span> = <span style="color: #800080;">$pc</span>-&gt;DecryptMsg(<span style="color: #800080;">$msg_signature</span>, <span style="color: #800080;">$timestamp</span>, <span style="color: #800080;">$nonce</span>, <span style="color: #800080;">$postStr</span>, <span style="color: #800080;">$decryptMsg</span><span style="color: #000000;">);<br/> </span><span style="color: #800080;">$postStr</span> = <span style="color: #800080;">$decryptMsg</span><span style="color: #000000;">;<br/>}</span></div><p>解密完成后,把解密内容又返回给$postStr,这是为了保证将消息中解密后的内容和明文模式时的消息统一,方便后续处理,解密后的XML如下</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ToUserName</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">gh_680bdefc8c5d</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ToUserName</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">FromUserName</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">oIDrpjpQ8j8mBuQ8nM26HWzNEZgg</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">FromUserName</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">CreateTime</span><span style="color: #0000ff;">&gt;</span>1414243737<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">CreateTime</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">MsgType</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">text</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">MsgType</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">Content</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">?</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">Content</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">MsgId</span><span style="color: #0000ff;">&gt;</span>6074130599188426998<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">MsgId</span><span style="color: #0000ff;">&gt;</span><br/><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span></div><p>对消息在自己的原来代码中处理,完成之后,要回复的消息如下</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">ToUserName</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">oIDrpjpQ8j8mBuQ8nM26HWzNEZgg</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">ToUserName</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">FromUserName</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">gh_680bdefc8c5d</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">FromUserName</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">CreateTime</span><span style="color: #0000ff;">&gt;</span>1414243733<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">CreateTime</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">MsgType</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">text</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">MsgType</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">Content</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">2014-10-25 21:28:53<br/>技术支持 方倍工作室<br/>http://www.fangbei.org/</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">Content</span><span style="color: #0000ff;">&gt;</span><br/><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span></div><p>把上述消息进行加密,返回给微信公众账号</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008000;">//</span><span style="color: #008000;">加密</span><br/><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$encrypt_type</span> == 'aes'<span style="color: #000000;">){<br/> </span><span style="color: #800080;">$encryptMsg</span> = ''; <span style="color: #008000;">//</span><span style="color: #008000;">加密后的密文</span><br/> <span style="color: #800080;">$errCode</span> = <span style="color: #800080;">$pc</span>-&gt;encryptMsg(<span style="color: #800080;">$result</span>, <span style="color: #800080;">$timeStamp</span>, <span style="color: #800080;">$nonce</span>, <span style="color: #800080;">$encryptMsg</span><span style="color: #000000;">);<br/> </span><span style="color: #800080;">$result</span> = <span style="color: #800080;">$encryptMsg</span><span style="color: #000000;">;<br/> </span><span style="color: #800080;">$this</span>-&gt;logger(" E \r\n".<span style="color: #800080;">$result</span><span style="color: #000000;">);<br/>}</span></div><p>加密后的内容如下</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">&lt;</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">Encrypt</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">pE6gp6qvVBMHwCXwnM7illFBrh9LmvlKFlPUDuyQo9EKNunqbUFMd2KjiYoz+3K1B+93JbMWHt+19TI8awdRdyopRS4oUNg5M2jwpwXTmc6TtafkKNjvqlvPXIWmutw0tuMXke1hDgsqz0SC8h/QjNLxECuwnczrfCMJlt+APHnX2yMMaq/aYUNcndOH387loQvl2suCGucXpglnbxf7frTCz9NQVgKiYrvKOhk6KFiVMnzuxy6WWmoe3GBiUCPTtYf5b1CxzN2IHViEBm28ilV9wWdNOM9TPG7BSSAcpgY4pcwdIG5+4KhgYmnVU3bc/ZJkk42TIdidigOfFpJwET4UWVrLB/ldUud4aPexp3aPCR3Fe53S2HHcl3tTxh4iRvDftUKP3svYPctt1MlYuYv/BZ4JyzUQV03H+0XrVyDY2tyVjimgCrA2c1mZMgHttOHTQ6VTnxrMq0GWlRlH0KPQKqtjUpNQzuOH4upQ8boPsEtuY3wDA2RaXQPJrXon</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">Encrypt</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">MsgSignature</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">6c46904dc1f58b2ddf2dd0399f1c6cf41f33ecb9</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">MsgSignature</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">TimeStamp</span><span style="color: #0000ff;">&gt;</span>1414243733<span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">TimeStamp</span><span style="color: #0000ff;">&gt;</span><br/> <span style="color: #0000ff;">&lt;</span><span style="color: #800000;">Nonce</span><span style="color: #0000ff;">&gt;</span><span style="color: #0000ff;">&lt;![CDATA[</span><span style="color: #808080;">1792106704</span><span style="color: #0000ff;">]]&gt;</span><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">Nonce</span><span style="color: #0000ff;">&gt;</span><br/><span style="color: #0000ff;">&lt;/</span><span style="color: #800000;">xml</span><span style="color: #0000ff;">&gt;</span></div><p>这样,一个安全模式下的加解密消息就完成了。</p><p>&nbsp;</p><p><strong>三、完整代码</strong></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> &lt;?<span style="color: #000000;">php<br/></span><span style="color: #008080;"> 2</span> <span style="color: #008000;">/*</span><br/><span style="color: #008080;"> 3</span> <span style="color: #008000;"> 方倍工作室 http://www.cnblogs.com/txw1958/<br/></span><span style="color: #008080;"> 4</span> <span style="color: #008000;"> CopyRight 2014 All Rights Reserved<br/></span><span style="color: #008080;"> 5</span> <span style="color: #008000;">*/</span><br/><span style="color: #008080;"> 6</span> <span style="color: #008080;">define</span>("TOKEN", "weixin"<span style="color: #000000;">);<br/></span><span style="color: #008080;"> 7</span> <span style="color: #008080;">define</span>("AppID", "wxbad0b45542aa0b5e"<span style="color: #000000;">);<br/></span><span style="color: #008080;"> 8</span> <span style="color: #008080;">define</span>("EncodingAESKey", "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG"<span style="color: #000000;">);<br/></span><span style="color: #008080;"> 9</span> <span style="color: #0000ff;">require_once</span>('wxBizMsgCrypt.php'<span style="color: #000000;">);<br/></span><span style="color: #008080;"> 10</span> <br/><span style="color: #008080;"> 11</span> <span style="color: #800080;">$wechatObj</span> = <span style="color: #0000ff;">new</span><span style="color: #000000;"> wechatCallbackapiTest();<br/></span><span style="color: #008080;"> 12</span> <span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_GET</span>['echostr'<span style="color: #000000;">])) {<br/></span><span style="color: #008080;"> 13</span> <span style="color: #800080;">$wechatObj</span>-&gt;<span style="color: #000000;">responseMsg();<br/></span><span style="color: #008080;"> 14</span> }<span style="color: #0000ff;">else</span><span style="color: #000000;">{<br/></span><span style="color: #008080;"> 15</span> <span style="color: #800080;">$wechatObj</span>-&gt;<span style="color: #000000;">valid();<br/></span><span style="color: #008080;"> 16</span> <span style="color: #000000;">}<br/></span><span style="color: #008080;"> 17</span> <br/><span style="color: #008080;"> 18</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> wechatCallbackapiTest<br/></span><span style="color: #008080;"> 19</span> <span style="color: #000000;">{<br/></span><span style="color: #008080;"> 20</span> <span style="color: #008000;">//</span><span style="color: #008000;">验证签名</span><br/><span style="color: #008080;"> 21</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> valid()<br/></span><span style="color: #008080;"> 22</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 23</span> <span style="color: #800080;">$echoStr</span> = <span style="color: #800080;">$_GET</span>["echostr"<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 24</span> <span style="color: #800080;">$signature</span> = <span style="color: #800080;">$_GET</span>["signature"<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 25</span> <span style="color: #800080;">$timestamp</span> = <span style="color: #800080;">$_GET</span>["timestamp"<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 26</span> <span style="color: #800080;">$nonce</span> = <span style="color: #800080;">$_GET</span>["nonce"<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 27</span> <span style="color: #800080;">$tmpArr</span> = <span style="color: #0000ff;">array</span>(TOKEN, <span style="color: #800080;">$timestamp</span>, <span style="color: #800080;">$nonce</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 28</span> <span style="color: #008080;">sort</span>(<span style="color: #800080;">$tmpArr</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 29</span> <span style="color: #800080;">$tmpStr</span> = <span style="color: #008080;">implode</span>(<span style="color: #800080;">$tmpArr</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 30</span> <span style="color: #800080;">$tmpStr</span> = <span style="color: #008080;">sha1</span>(<span style="color: #800080;">$tmpStr</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 31</span> <span style="color: #0000ff;">if</span>(<span style="color: #800080;">$tmpStr</span> == <span style="color: #800080;">$signature</span><span style="color: #000000;">){<br/></span><span style="color: #008080;"> 32</span> <span style="color: #0000ff;">echo</span> <span style="color: #800080;">$echoStr</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 33</span> <span style="color: #0000ff;">exit</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 34</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 35</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 36</span> <br/><span style="color: #008080;"> 37</span> <span style="color: #008000;">//</span><span style="color: #008000;">响应消息</span><br/><span style="color: #008080;"> 38</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> responseMsg()<br/></span><span style="color: #008080;"> 39</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 40</span> <span style="color: #800080;">$timestamp</span> = <span style="color: #800080;">$_GET</span>['timestamp'<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 41</span> <span style="color: #800080;">$nonce</span> = <span style="color: #800080;">$_GET</span>["nonce"<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 42</span> <span style="color: #800080;">$msg_signature</span> = <span style="color: #800080;">$_GET</span>['msg_signature'<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 43</span> <span style="color: #800080;">$encrypt_type</span> = (<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_GET</span>['encrypt_type']) &amp;&amp; (<span style="color: #800080;">$_GET</span>['encrypt_type'] == 'aes')) ? "aes" : "raw"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 44</span> <br/><span style="color: #008080;"> 45</span> <span style="color: #800080;">$postStr</span> = <span style="color: #800080;">$GLOBALS</span>["HTTP_RAW_POST_DATA"<span style="color: #000000;">];<br/></span><span style="color: #008080;"> 46</span> <span style="color: #0000ff;">if</span> (!<span style="color: #0000ff;">empty</span>(<span style="color: #800080;">$postStr</span><span style="color: #000000;">)){<br/></span><span style="color: #008080;"> 47</span> <span style="color: #008000;">//</span><span style="color: #008000;">解密</span><br/><span style="color: #008080;"> 48</span> <span style="color: #0000ff;">if</span> (<span style="color: #800080;">$encrypt_type</span> == 'aes'<span style="color: #000000;">){<br/></span><span style="color: #008080;"> 49</span> <span style="color: #800080;">$pc</span> = <span style="color: #0000ff;">new</span> WXBizMsgCrypt(TOKEN, EncodingAESKey,<span style="color: #000000;"> AppID); <br/></span><span style="color: #008080;"> 50</span> <span style="color: #800080;">$this</span>-&gt;logger(" D \r\n".<span style="color: #800080;">$postStr</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 51</span> <span style="color: #800080;">$decryptMsg</span> = ""; <span style="color: #008000;">//</span><span style="color: #008000;">解密后的明文</span><br/><span style="color: #008080;"> 52</span> <span style="color: #800080;">$errCode</span> = <span style="color: #800080;">$pc</span>-&gt;DecryptMsg(<span style="color: #800080;">$msg_signature</span>, <span style="color: #800080;">$timestamp</span>, <span style="color: #800080;">$nonce</span>, <span style="color: #800080;">$postStr</span>, <span style="color: #800080;">$decryptMsg</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 53</span> <span style="color: #800080;">$postStr</span> = <span style="color: #800080;">$decryptMsg</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 54</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 55</span> <span style="color: #800080;">$this</span>-&gt;logger(" R \r\n".<span style="color: #800080;">$postStr</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 56</span> <span style="color: #800080;">$postObj</span> = <span style="color: #008080;">simplexml_load_string</span>(<span style="color: #800080;">$postStr</span>, 'SimpleXMLElement',<span style="color: #000000;"> LIBXML_NOCDATA);<br/></span><span style="color: #008080;"> 57</span> <span style="color: #800080;">$RX_TYPE</span> = <span style="color: #008080;">trim</span>(<span style="color: #800080;">$postObj</span>-&gt;<span style="color: #000000;">MsgType);<br/></span><span style="color: #008080;"> 58</span> <br/><span style="color: #008080;"> 59</span> <span style="color: #008000;">//</span><span style="color: #008000;">消息类型分离</span><br/><span style="color: #008080;"> 60</span> <span style="color: #0000ff;">switch</span> (<span style="color: #800080;">$RX_TYPE</span><span style="color: #000000;">)<br/></span><span style="color: #008080;"> 61</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 62</span> <span style="color: #0000ff;">case</span> "event":<br/><span style="color: #008080;"> 63</span> <span style="color: #800080;">$result</span> = <span style="color: #800080;">$this</span>-&gt;receiveEvent(<span style="color: #800080;">$postObj</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 64</span> <span style="color: #0000ff;">break</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 65</span> <span style="color: #0000ff;">case</span> "text":<br/><span style="color: #008080;"> 66</span> <span style="color: #800080;">$result</span> = <span style="color: #800080;">$this</span>-&gt;receiveText(<span style="color: #800080;">$postObj</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 67</span> <span style="color: #0000ff;">break</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 68</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 69</span> <span style="color: #800080;">$this</span>-&gt;logger(" R \r\n".<span style="color: #800080;">$result</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 70</span> <span style="color: #008000;">//</span><span style="color: #008000;">加密</span><br/><span style="color: #008080;"> 71</span> <span style="color: #0000ff;">if</span> (<span style="color: #800080;">$encrypt_type</span> == 'aes'<span style="color: #000000;">){<br/></span><span style="color: #008080;"> 72</span> <span style="color: #800080;">$encryptMsg</span> = ''; <span style="color: #008000;">//</span><span style="color: #008000;">加密后的密文</span><br/><span style="color: #008080;"> 73</span> <span style="color: #800080;">$errCode</span> = <span style="color: #800080;">$pc</span>-&gt;encryptMsg(<span style="color: #800080;">$result</span>, <span style="color: #800080;">$timeStamp</span>, <span style="color: #800080;">$nonce</span>, <span style="color: #800080;">$encryptMsg</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 74</span> <span style="color: #800080;">$result</span> = <span style="color: #800080;">$encryptMsg</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 75</span> <span style="color: #800080;">$this</span>-&gt;logger(" E \r\n".<span style="color: #800080;">$result</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 76</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 77</span> <span style="color: #0000ff;">echo</span> <span style="color: #800080;">$result</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 78</span> }<span style="color: #0000ff;">else</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 79</span> <span style="color: #0000ff;">echo</span> ""<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 80</span> <span style="color: #0000ff;">exit</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 81</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 82</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 83</span> <br/><span style="color: #008080;"> 84</span> <span style="color: #008000;">//</span><span style="color: #008000;">接收事件消息</span><br/><span style="color: #008080;"> 85</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">function</span> receiveEvent(<span style="color: #800080;">$object</span><span style="color: #000000;">)<br/></span><span style="color: #008080;"> 86</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 87</span> <span style="color: #800080;">$content</span> = ""<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 88</span> <span style="color: #0000ff;">switch</span> (<span style="color: #800080;">$object</span>-&gt;<span style="color: #000000;">Event)<br/></span><span style="color: #008080;"> 89</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 90</span> <span style="color: #0000ff;">case</span> "subscribe":<br/><span style="color: #008080;"> 91</span> <span style="color: #800080;">$content</span> = "欢迎关注方倍工作室 "<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 92</span> <span style="color: #0000ff;">break</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 93</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 94</span> <br/><span style="color: #008080;"> 95</span> <span style="color: #800080;">$result</span> = <span style="color: #800080;">$this</span>-&gt;transmitText(<span style="color: #800080;">$object</span>, <span style="color: #800080;">$content</span><span style="color: #000000;">);<br/></span><span style="color: #008080;"> 96</span> <span style="color: #0000ff;">return</span> <span style="color: #800080;">$result</span><span style="color: #000000;">;<br/></span><span style="color: #008080;"> 97</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 98</span> <br/><span style="color: #008080;"> 99</span> <span style="color: #008000;">//</span><span style="color: #008000;">接收文本消息</span><br/><span style="color: #008080;">100</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">function</span> receiveText(<span style="color: #800080;">$object</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">101</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">102</span> <span style="color: #800080;">$keyword</span> = <span style="color: #008080;">trim</span>(<span style="color: #800080;">$object</span>-&gt;<span style="color: #000000;">Content);<br/></span><span style="color: #008080;">103</span> <span style="color: #0000ff;">if</span> (<span style="color: #008080;">strstr</span>(<span style="color: #800080;">$keyword</span>, "文本"<span style="color: #000000;">)){<br/></span><span style="color: #008080;">104</span> <span style="color: #800080;">$content</span> = "这是个文本消息"<span style="color: #000000;">;<br/></span><span style="color: #008080;">105</span> }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (<span style="color: #008080;">strstr</span>(<span style="color: #800080;">$keyword</span>, "单图文"<span style="color: #000000;">)){<br/></span><span style="color: #008080;">106</span> <span style="color: #800080;">$content</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">();<br/></span><span style="color: #008080;">107</span> <span style="color: #800080;">$content</span>[] = <span style="color: #0000ff;">array</span>("Title"=&gt;"单图文标题", "Description"=&gt;"单图文内容", "PicUrl"=&gt;"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =&gt;"http://m.cnblogs.com/?u=txw1958"<span style="color: #000000;">);<br/></span><span style="color: #008080;">108</span> }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (<span style="color: #008080;">strstr</span>(<span style="color: #800080;">$keyword</span>, "图文") || <span style="color: #008080;">strstr</span>(<span style="color: #800080;">$keyword</span>, "多图文"<span style="color: #000000;">)){<br/></span><span style="color: #008080;">109</span> <span style="color: #800080;">$content</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">();<br/></span><span style="color: #008080;">110</span> <span style="color: #800080;">$content</span>[] = <span style="color: #0000ff;">array</span>("Title"=&gt;"多图文1标题", "Description"=&gt;"", "PicUrl"=&gt;"http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" =&gt;"http://m.cnblogs.com/?u=txw1958"<span style="color: #000000;">);<br/></span><span style="color: #008080;">111</span> <span style="color: #800080;">$content</span>[] = <span style="color: #0000ff;">array</span>("Title"=&gt;"多图文2标题", "Description"=&gt;"", "PicUrl"=&gt;"http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" =&gt;"http://m.cnblogs.com/?u=txw1958"<span style="color: #000000;">);<br/></span><span style="color: #008080;">112</span> <span style="color: #800080;">$content</span>[] = <span style="color: #0000ff;">array</span>("Title"=&gt;"多图文3标题", "Description"=&gt;"", "PicUrl"=&gt;"http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" =&gt;"http://m.cnblogs.com/?u=txw1958"<span style="color: #000000;">);<br/></span><span style="color: #008080;">113</span> }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (<span style="color: #008080;">strstr</span>(<span style="color: #800080;">$keyword</span>, "音乐"<span style="color: #000000;">)){<br/></span><span style="color: #008080;">114</span> <span style="color: #800080;">$content</span> = <span style="color: #0000ff;">array</span><span style="color: #000000;">();<br/></span><span style="color: #008080;">115</span> <span style="color: #800080;">$content</span> = <span style="color: #0000ff;">array</span>("Title"=&gt;"最炫民族风", "Description"=&gt;"歌手:凤凰传奇", "MusicUrl"=&gt;"http://121.199.4.61/music/zxmzf.mp3", "HQMusicUrl"=&gt;"http://121.199.4.61/music/zxmzf.mp3"<span style="color: #000000;">);<br/></span><span style="color: #008080;">116</span> }<span style="color: #0000ff;">else</span><span style="color: #000000;">{<br/></span><span style="color: #008080;">117</span> <span style="color: #800080;">$content</span> = <span style="color: #008080;">date</span>("Y-m-d H:i:s",<span style="color: #008080;">time</span>())."\n".<span style="color: #800080;">$object</span>-&gt;FromUserName."\n技术支持 方倍工作室"<span style="color: #000000;">;<br/></span><span style="color: #008080;">118</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">119</span> <br/><span style="color: #008080;">120</span> <span style="color: #0000ff;">if</span>(<span style="color: #008080;">is_array</span>(<span style="color: #800080;">$content</span><span style="color: #000000;">)){<br/></span><span style="color: #008080;">121</span> <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$content</span>[0<span style="color: #000000;">])){<br/></span><span style="color: #008080;">122</span> <span style="color: #800080;">$result</span> = <span style="color: #800080;">$this</span>-&gt;transmitNews(<span style="color: #800080;">$object</span>, <span style="color: #800080;">$content</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">123</span> }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$content</span>['MusicUrl'<span style="color: #000000;">])){<br/></span><span style="color: #008080;">124</span> <span style="color: #800080;">$result</span> = <span style="color: #800080;">$this</span>-&gt;transmitMusic(<span style="color: #800080;">$object</span>, <span style="color: #800080;">$content</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">125</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">126</span> }<span style="color: #0000ff;">else</span><span style="color: #000000;">{<br/></span><span style="color: #008080;">127</span> <span style="color: #800080;">$result</span> = <span style="color: #800080;">$this</span>-&gt;transmitText(<span style="color: #800080;">$object</span>, <span style="color: #800080;">$content</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">128</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">129</span> <span style="color: #0000ff;">return</span> <span style="color: #800080;">$result</span><span style="color: #000000;">;<br/></span><span style="color: #008080;">130</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">131</span> <br/><span style="color: #008080;">132</span> <span style="color: #008000;">//</span><span style="color: #008000;">回复文本消息</span><br/><span style="color: #008080;">133</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">function</span> transmitText(<span style="color: #800080;">$object</span>, <span style="color: #800080;">$content</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">134</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">135</span> <span style="color: #800080;">$xmlTpl</span> = "<span style="color: #000000;">&lt;xml&gt;<br/></span><span style="color: #008080;">136</span> <span style="color: #000000;"> &lt;ToUserName&gt;&lt;![CDATA[%s]]&gt;&lt;/ToUserName&gt;<br/></span><span style="color: #008080;">137</span> <span style="color: #000000;"> &lt;FromUserName&gt;&lt;![CDATA[%s]]&gt;&lt;/FromUserName&gt;<br/></span><span style="color: #008080;">138</span> <span style="color: #000000;"> &lt;CreateTime&gt;%s&lt;/CreateTime&gt;<br/></span><span style="color: #008080;">139</span> <span style="color: #000000;"> &lt;MsgType&gt;&lt;![CDATA[text]]&gt;&lt;/MsgType&gt;<br/></span><span style="color: #008080;">140</span> <span style="color: #000000;"> &lt;Content&gt;&lt;![CDATA[%s]]&gt;&lt;/Content&gt;<br/></span><span style="color: #008080;">141</span> &lt;/xml&gt;"<span style="color: #000000;">;<br/></span><span style="color: #008080;">142</span> <span style="color: #800080;">$result</span> = <span style="color: #008080;">sprintf</span>(<span style="color: #800080;">$xmlTpl</span>, <span style="color: #800080;">$object</span>-&gt;FromUserName, <span style="color: #800080;">$object</span>-&gt;ToUserName, <span style="color: #008080;">time</span>(), <span style="color: #800080;">$content</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">143</span> <span style="color: #0000ff;">return</span> <span style="color: #800080;">$result</span><span style="color: #000000;">;<br/></span><span style="color: #008080;">144</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">145</span> <br/><span style="color: #008080;">146</span> <span style="color: #008000;">//</span><span style="color: #008000;">回复图文消息</span><br/><span style="color: #008080;">147</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">function</span> transmitNews(<span style="color: #800080;">$object</span>, <span style="color: #800080;">$newsArray</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">148</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">149</span> <span style="color: #0000ff;">if</span>(!<span style="color: #008080;">is_array</span>(<span style="color: #800080;">$newsArray</span><span style="color: #000000;">)){<br/></span><span style="color: #008080;">150</span> <span style="color: #0000ff;">return</span><span style="color: #000000;">;<br/></span><span style="color: #008080;">151</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">152</span> <span style="color: #800080;">$itemTpl</span> = "<span style="color: #000000;"> &lt;item&gt;<br/></span><span style="color: #008080;">153</span> <span style="color: #000000;"> &lt;Title&gt;&lt;![CDATA[%s]]&gt;&lt;/Title&gt;<br/></span><span style="color: #008080;">154</span> <span style="color: #000000;"> &lt;Description&gt;&lt;![CDATA[%s]]&gt;&lt;/Description&gt;<br/></span><span style="color: #008080;">155</span> <span style="color: #000000;"> &lt;PicUrl&gt;&lt;![CDATA[%s]]&gt;&lt;/PicUrl&gt;<br/></span><span style="color: #008080;">156</span> <span style="color: #000000;"> &lt;Url&gt;&lt;![CDATA[%s]]&gt;&lt;/Url&gt;<br/></span><span style="color: #008080;">157</span> <span style="color: #000000;"> &lt;/item&gt;<br/></span><span style="color: #008080;">158</span> "<span style="color: #000000;">;<br/></span><span style="color: #008080;">159</span> <span style="color: #800080;">$item_str</span> = ""<span style="color: #000000;">;<br/></span><span style="color: #008080;">160</span> <span style="color: #0000ff;">foreach</span> (<span style="color: #800080;">$newsArray</span> <span style="color: #0000ff;">as</span> <span style="color: #800080;">$item</span><span style="color: #000000;">){<br/></span><span style="color: #008080;">161</span> <span style="color: #800080;">$item_str</span> .= <span style="color: #008080;">sprintf</span>(<span style="color: #800080;">$itemTpl</span>, <span style="color: #800080;">$item</span>['Title'], <span style="color: #800080;">$item</span>['Description'], <span style="color: #800080;">$item</span>['PicUrl'], <span style="color: #800080;">$item</span>['Url'<span style="color: #000000;">]);<br/></span><span style="color: #008080;">162</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">163</span> <span style="color: #800080;">$xmlTpl</span> = "<span style="color: #000000;">&lt;xml&gt;<br/></span><span style="color: #008080;">164</span> <span style="color: #000000;"> &lt;ToUserName&gt;&lt;![CDATA[%s]]&gt;&lt;/ToUserName&gt;<br/></span><span style="color: #008080;">165</span> <span style="color: #000000;"> &lt;FromUserName&gt;&lt;![CDATA[%s]]&gt;&lt;/FromUserName&gt;<br/></span><span style="color: #008080;">166</span> <span style="color: #000000;"> &lt;CreateTime&gt;%s&lt;/CreateTime&gt;<br/></span><span style="color: #008080;">167</span> <span style="color: #000000;"> &lt;MsgType&gt;&lt;![CDATA[news]]&gt;&lt;/MsgType&gt;<br/></span><span style="color: #008080;">168</span> <span style="color: #000000;"> &lt;ArticleCount&gt;%s&lt;/ArticleCount&gt;<br/></span><span style="color: #008080;">169</span> <span style="color: #000000;"> &lt;Articles&gt;<br/></span><span style="color: #008080;">170</span> <span style="color: #800080;">$item_str</span><span style="color: #000000;"> &lt;/Articles&gt;<br/></span><span style="color: #008080;">171</span> &lt;/xml&gt;"<span style="color: #000000;">;<br/></span><span style="color: #008080;">172</span> <br/><span style="color: #008080;">173</span> <span style="color: #800080;">$result</span> = <span style="color: #008080;">sprintf</span>(<span style="color: #800080;">$xmlTpl</span>, <span style="color: #800080;">$object</span>-&gt;FromUserName, <span style="color: #800080;">$object</span>-&gt;ToUserName, <span style="color: #008080;">time</span>(), <span style="color: #008080;">count</span>(<span style="color: #800080;">$newsArray</span><span style="color: #000000;">));<br/></span><span style="color: #008080;">174</span> <span style="color: #0000ff;">return</span> <span style="color: #800080;">$result</span><span style="color: #000000;">;<br/></span><span style="color: #008080;">175</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">176</span> <br/><span style="color: #008080;">177</span> <span style="color: #008000;">//</span><span style="color: #008000;">回复音乐消息</span><br/><span style="color: #008080;">178</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">function</span> transmitMusic(<span style="color: #800080;">$object</span>, <span style="color: #800080;">$musicArray</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">179</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">180</span> <span style="color: #800080;">$itemTpl</span> = "<span style="color: #000000;">&lt;Music&gt;<br/></span><span style="color: #008080;">181</span> <span style="color: #000000;"> &lt;Title&gt;&lt;![CDATA[%s]]&gt;&lt;/Title&gt;<br/></span><span style="color: #008080;">182</span> <span style="color: #000000;"> &lt;Description&gt;&lt;![CDATA[%s]]&gt;&lt;/Description&gt;<br/></span><span style="color: #008080;">183</span> <span style="color: #000000;"> &lt;MusicUrl&gt;&lt;![CDATA[%s]]&gt;&lt;/MusicUrl&gt;<br/></span><span style="color: #008080;">184</span> <span style="color: #000000;"> &lt;HQMusicUrl&gt;&lt;![CDATA[%s]]&gt;&lt;/HQMusicUrl&gt;<br/></span><span style="color: #008080;">185</span> &lt;/Music&gt;"<span style="color: #000000;">;<br/></span><span style="color: #008080;">186</span> <br/><span style="color: #008080;">187</span> <span style="color: #800080;">$item_str</span> = <span style="color: #008080;">sprintf</span>(<span style="color: #800080;">$itemTpl</span>, <span style="color: #800080;">$musicArray</span>['Title'], <span style="color: #800080;">$musicArray</span>['Description'], <span style="color: #800080;">$musicArray</span>['MusicUrl'], <span style="color: #800080;">$musicArray</span>['HQMusicUrl'<span style="color: #000000;">]);<br/></span><span style="color: #008080;">188</span> <br/><span style="color: #008080;">189</span> <span style="color: #800080;">$xmlTpl</span> = "<span style="color: #000000;">&lt;xml&gt;<br/></span><span style="color: #008080;">190</span> <span style="color: #000000;"> &lt;ToUserName&gt;&lt;![CDATA[%s]]&gt;&lt;/ToUserName&gt;<br/></span><span style="color: #008080;">191</span> <span style="color: #000000;"> &lt;FromUserName&gt;&lt;![CDATA[%s]]&gt;&lt;/FromUserName&gt;<br/></span><span style="color: #008080;">192</span> <span style="color: #000000;"> &lt;CreateTime&gt;%s&lt;/CreateTime&gt;<br/></span><span style="color: #008080;">193</span> <span style="color: #000000;"> &lt;MsgType&gt;&lt;![CDATA[music]]&gt;&lt;/MsgType&gt;<br/></span><span style="color: #008080;">194</span> <span style="color: #800080;">$item_str</span><br/><span style="color: #008080;">195</span> &lt;/xml&gt;"<span style="color: #000000;">;<br/></span><span style="color: #008080;">196</span> <br/><span style="color: #008080;">197</span> <span style="color: #800080;">$result</span> = <span style="color: #008080;">sprintf</span>(<span style="color: #800080;">$xmlTpl</span>, <span style="color: #800080;">$object</span>-&gt;FromUserName, <span style="color: #800080;">$object</span>-&gt;ToUserName, <span style="color: #008080;">time</span><span style="color: #000000;">());<br/></span><span style="color: #008080;">198</span> <span style="color: #0000ff;">return</span> <span style="color: #800080;">$result</span><span style="color: #000000;">;<br/></span><span style="color: #008080;">199</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">200</span> <br/><span style="color: #008080;">201</span> <span style="color: #008000;">//</span><span style="color: #008000;">日志记录</span><br/><span style="color: #008080;">202</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> logger(<span style="color: #800080;">$log_content</span><span style="color: #000000;">)<br/></span><span style="color: #008080;">203</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">204</span> <span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">isset</span>(<span style="color: #800080;">$_SERVER</span>['HTTP_APPNAME'])){ <span style="color: #008000;">//</span><span style="color: #008000;">SAE</span><br/><span style="color: #008080;">205</span> sae_set_display_errors(<span style="color: #0000ff;">false</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">206</span> sae_debug(<span style="color: #800080;">$log_content</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">207</span> sae_set_display_errors(<span style="color: #0000ff;">true</span><span style="color: #000000;">);<br/></span><span style="color: #008080;">208</span> }<span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span>(<span style="color: #800080;">$_SERVER</span>['REMOTE_ADDR'] != "127.0.0.1"){ <span style="color: #008000;">//</span><span style="color: #008000;">LOCAL</span><br/><span style="color: #008080;">209</span> <span style="color: #800080;">$max_size</span> = 500000<span style="color: #000000;">;<br/></span><span style="color: #008080;">210</span> <span style="color: #800080;">$log_filename</span> = "log.xml"<span style="color: #000000;">;<br/></span><span style="color: #008080;">211</span> <span style="color: #0000ff;">if</span>(<span style="color: #008080;">file_exists</span>(<span style="color: #800080;">$log_filename</span>) and (<span style="color: #008080;">abs</span>(<span style="color: #008080;">filesize</span>(<span style="color: #800080;">$log_filename</span>)) &gt; <span style="color: #800080;">$max_size</span>)){<span style="color: #008080;">unlink</span>(<span style="color: #800080;">$log_filename</span><span style="color: #000000;">);}<br/></span><span style="color: #008080;">212</span> <span style="color: #008080;">file_put_contents</span>(<span style="color: #800080;">$log_filename</span>, <span style="color: #008080;">date</span>('Y-m-d H:i:s').<span style="color: #800080;">$log_content</span>."\r\n",<span style="color: #000000;"> FILE_APPEND);<br/></span><span style="color: #008080;">213</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">214</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">215</span> <span style="color: #000000;">}<br/></span><span style="color: #008080;">216</span> ?&gt;</div><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4051079" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/txw1958/p/weixin-aes-encrypt-Decrypt.html" target="_blank">微信公众平台消息体加解密实现</a>,转载请注明。</p>http://www.cnblogs.com/sfrost/p/4050915.html冒个泡,还活着??做了个项目,一点感想。 - sfrost的确,成家后,很多时间都由不得自己安安静静地花时间去学习了。从3月底到7月底,香港、买车、婚礼,很多事情都在今年一起办了。8月初的时候接到一个项目,做微信定制开发的,由于是兼职,有持续一周的时间,每天晚上和朋友加班到晚上3、4点,第二天又正常上班。而且之前没做过定制开发(甲方要求用户体验高、很多细节...2014-10-25T14:29:00Z2014-10-25T14:29:00Zsfrosthttp://www.cnblogs.com/sfrost/<p>的确,成家后,很多时间都由不得自己安安静静地花时间去学习了。从3月底到7月底,香港、买车、婚礼,很多事情都在今年一起办了。</p><p>8月初的时候接到一个项目,做微信定制开发的,由于是兼职,有持续一周的时间,每天晚上和朋友加班到晚上3、4点,第二天又正常上班。而且之前没做过定制开发(甲方要求用户体验高、很多细节的技术还要即时攻尖),虽然很累,但是最后做出来了,而且上线20多天,经过2000人左右的体验,没出什么大问题,已经感到很高兴了。</p><p>虽然还有项目尾款没拿到,但还是用之前的钱,为自己换了一台mac pro,自己用了6年多的笔记本,终于要准备退休了??</p><h2 style="text-align: center;">这个项目,给自己的启示。</strong></p><ul><li><span style="color: #0000ff;"><strong>今天的你所做所为,一定会在将来的某个时间点被无限放大(推荐《云图》电影)</strong></span></li></ul><p>能拿到这个项目,完全是自己努力的必然结果(不止是自信)。jobs曾在斯坦福演讲时说过&ldquo;Macintosh电脑能有这么漂亮的字体,就是因为当时他去学习了自己感兴趣的课程,比如美术字课程&rdquo;,其实作为一个混迹于it行业的普通人来说,我觉得对新技术的那种渴望之心是必须要有的(成本范围内)。</p><p>为什么要这么说呢?我对微信公众平台感兴趣是在去年年初的时候,就开始研究了,虽然工作和这个没有什么关系(甚至我都不会编写一个完整项目的代码),但就是这样一点一点地研究着公众平台的资料,每次更新接口我都会第一时间去看有什么新的功能。后来有机会,就在公司试点,做了一个小项目(微信查工资),然后就树立了专业的形象。</p><p>今年能拿到这个项目,就是因为知道我做过这块的东西,所以让我过去参考他们的想法(业务是否合理,用户体验能否达到预期)。</p><ul><li><strong>勿以善小而不为,勿以恶小而为之</strong></li></ul><p>虽然快到而立之年,但是回头看看自己这12年的努力,以前自己学到的很多东西(<span style="color: #808080;">电脑方面的几乎是所有,软件的使用、编程、数据库、平面设计、三维制图&hellip;&hellip;,硬件和外设的维护,企业网络组建,防火墙、VPN、路由器配置,弱电系统的实施等等</span>),几乎都在无形中帮助自己。</p><p>纵然如此,自己还是在不断地学习、积累,比如这两年转型,做erp系统的实施运维,做信息化项目的管理和实施,学习生产、零售行业的基础业务,学习财务、采购业务,研究android、ios开发,学习html5游戏开发。可能现在看来有点游手好闲,什么都要去碰,结果是什么都不专,但我相信,以后,总会用上的,就像去年自己用10年前学习的excel函数+vba,为erp做了一套自动生成公式的工具一样。</p><ul><li><strong>梦想总是要有的,万一实现了呢?</strong></li></ul><p>喜欢阿里,喜欢google,喜欢苹果,喜欢特斯拉,喜欢看商业价值,也喜欢腾讯,没有什么复杂的因素,原因很简单:他们做的很多事情,在我个人看来,都是在让这个社会变得更加美好。突然想起了当年魔兽世界的《网瘾战争》,至今在听到bells of freedom时,还能想到那些感人的画面。</p><p>我不开网店,但是我在阿里上市的那段时间,关注了《纽约中文网》很多关于阿里资(政)本(治)背景的调查报告,得到的一个很深的感触就是:能做到现在,马云在背后不知道花了多少的心血。</p><p>所以,改变世界不是不可能。</p><p>当然,代码还是得坚持写,看着左边定下的目标:年底用C#写一个视频网站。嗯,得抓紧时间了,因为离老婆预产期越来越近了??#</p><img src="http://counter.cnblogs.com/blog/rss/4050915" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/sfrost/p/4050915.html" target="_blank">冒个泡,还活着??做了个项目,一点感想。</a>,转载请注明。</p>http://www.cnblogs.com/littlepanpc/p/4051049.html[翻译]Android 5.0之应用中实现材料设计—Material Design - LittlePanpc上午的时候在刷Google+,看到了Abraham Williams转发了一篇强文,是Android Developers网站新发的一篇博客—Implementing Material Design in your Android App。觉得很前卫,对于新发布的Android版本号Android ...2014-10-25T14:16:00Z2014-10-25T14:16:00ZLittlePanpchttp://www.cnblogs.com/littlepanpc/<p>上午的时候在刷Google+,看到了Abraham Williams转发了一篇强文,是Android Developers网站新发的一篇博客&mdash;Implementing Material Design in your Android App。觉得很前卫,对于新发布的Android版本号Android 5.0是一个很好的学习和了解的机会,所以就花了些时间把它翻译了下来,希望对自己、对其它人有所启发。</p><p>因为翻译Android开发博客和API也只是业余爱好,水平有限,其中不免有不准确的地方,所以把原文地址也一并贴过来,不清楚的地方,可以查看原文。</p><p><a href="http://android-developers.blogspot.com/2014/10/implementing-material-design-in-your.html?m=1" target="_blank">http://android-developers.blogspot.com/2014/10/implementing-material-design-in-your.html?m=1</a>,不幸的是,要查看这篇文章,得FQ。</p><p>好,下面是翻译的详情:</p><p>&nbsp;</p><p>&nbsp;</p><p>对于多屏世界,材料设计(Material Design)是一种实现可视化、交互和动作设计的综合途径。Android 5.0 Lollipop和更新的支持包能够了帮你创建材料UI。下面简要简介一下在应用中能够实现的材料设计、API和控件的一些主要元素。</p><p>&nbsp;<strong><span style="line-height: 1.5;">有形的surface</span></strong></p><p><span style="line-height: 1.5;">在材料设计中,UI由数字&ldquo;纸&amp;墨&rdquo;碎片构成。surface及其投射的阴影对应用的结构,即所能触摸到的界面和感知到的移动,提供了可见的提示。材料设计可以通过移动、扩展和重组来创建灵活的UI。</span></p><p>&nbsp;<strong>阴影</strong>&nbsp;</p><p>Surface的位置和深度导致光线和阴影上面的轻微改变。新的elevation属性使你能够精确的设置视图在Z轴上的位置,由此,framework在该视图后面的子项上面投射出实时动态的阴影。你可以以dip为单位在布局中声明设置elevation:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('4816eb19-1205-4a78-9684-e42fe819b7d2')"><div id="cnblogs_code_open_4816eb19-1205-4a78-9684-e42fe819b7d2" class="cnblogs_code_hide"><span style="color: #008080;">1</span> &lt;<span style="color: #000000;">ImageView &hellip;<br/></span><span style="color: #008080;">2</span> <br/><span style="color: #008080;">3</span> android:elevation="8dp" /&gt;</div></div><p>还可以通过代码getElevation()/setElevation()来设置(ViewCompat中也有相仿的实现)。视图投射的阴影由其轮廓决定,而轮廓默认情况下源自于视图的背景。例如,把FAB(floating action button)的背景设置为圆形drawable,然后,FAB就会投射恰当的阴影。如果想更精细的控制视图的阴影,可以设置ViewOutlineProvider,它能够自定义getOutline()里面的Outline。</p><p>&nbsp;<strong>卡片</strong></p><p>&nbsp;卡片是一种通用模式,用来创建持有清晰信息碎片的surface。新的CardView支持包通过提供轮廓和阴影,允许你更随意的创建CardView(在之前平台上有相同的效果)。</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('c3ba7292-39a9-48ed-a51c-838b1af46968')"><div id="cnblogs_code_open_c3ba7292-39a9-48ed-a51c-838b1af46968" class="cnblogs_code_hide"><span style="color: #008080;">1</span> &lt;<span style="color: #000000;">android.support.v7.widget.CardView<br/></span><span style="color: #008080;">2</span> android:layout_width="match_parent"<br/><span style="color: #008080;">3</span> android:layout_height="wrap_content"&gt;<br/><span style="color: #008080;">4</span> &lt;!-- Your card content --&gt;<br/><span style="color: #008080;">5</span> <br/><span style="color: #008080;">6</span> &lt;/android.support.v7.widget.CardView&gt;</div></div><p><span style="line-height: 1.5;">CardView扩展自FrameLayout,并且提供了默认的elevation和圆角半径,以使卡片在不同的平台上面拥有一致的外观。如果需要的话,可以通过cardElevation和cardCornerRadius属性来设置。记住,卡片并不是实现维度的惟一方式,你应该提防UI过度卡片化!</span></p><p>&nbsp;<strong>类打印设计</strong></p><p>&nbsp;材料利用源于打印设计的经典规则来创建干净、简单的布局,以放置内容在其前面或者中心。粗体权衡了颜色选择、有意而为的空格、雅致的排版和浓烈的底线方格,创建了有层次的、意义明了的和重点突出的效果。</p><p>&nbsp;<strong>排版</strong></p><p>&nbsp;Android 5.0更新了系统字体Roboto以忽略字体大小限制的方式来美观且清晰地展示文本。新的中等权重添加了进来(android:fontFamily=&rdquo;sans-serif-medium&rdquo;),新的文本外观风格实现了广为推荐的typographic scale,用来平衡内容的密度和阅读的舒适感。例如,可以通过设置&rdquo;android:textAppearance=&rsquo;@android:style/TextAppearance.Material.Title&rsquo;&rdquo;来使用Title风格。这些风格可能通过AppCompat支持包来在较老版本上使用,如&rdquo;@style/TextAppearance.AppCompat.Title&rdquo;.</p><p>&nbsp;<strong>色彩</strong></p><p><img src="http://images.cnitblog.com/blog/453582/201410/252202008406419.png" alt="" /></p><p><span style="line-height: 1.5;">应用的调色板给应用带来了印迹和人格,以致我们可以通过以下主题属性来实现UI控制的彩色化。</span></p><ul><li>colorPrimary:应用的首要印迹颜色;常用作actionbar的背景颜色、最近任务的标题以及边缘效果中。</li><li>colorAccent:colorPrimary的生动补充。用于诸如EditTex和Switch等框架的控制。</li><li>colorPrimaryDartk:colorPrimary的更暗色补充。用于状态条。</li></ul><p>&nbsp;更多的属性给予彩色化控制更细粒度的控制,例如:colorControlNormal, colorControlActivated, colorControlHighlight, colorButtonNormal, colorSwitchThumbNormal, colorEdgeEffect, statusBarColor和navigationBarColor.</p><p>&nbsp;AppCompat提供了以上功能的更大子集,允许你在Lollipop之前版本上实现彩色化控制。</p><p>&nbsp;<strong>动态色彩</strong></p><p>&nbsp;<img src="http://images.cnitblog.com/blog/453582/201410/252200502461288.gif" alt="" /></p><p><a href="http://4.bp.blogspot.com/-qX9XNcFEQlQ/VEngSGP2ZyI/AAAAAAAAA6E/PbORZ-3ex-Y/s1600/palette2.gif">http://4.bp.blogspot.com/-qX9XNcFEQlQ/VEngSGP2ZyI/AAAAAAAAA6E/PbORZ-3ex-Y/s1600/palette2.gif</a></p><p>材料设计鼓励色彩的动态使用,尤其是你有许多图片要处理的时候。新的Palette支持包允许你获取从图片到要匹配的UI控制风格的色彩集,以创建拟真的体验。萃取的颜色版将包含强烈的和轻柔的色调,就像为了实现最佳可读性的前景文本颜色(forground text color)一样。例如:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('bcfd4305-3b83-45bd-8991-6e336628d860')"><div id="cnblogs_code_open_bcfd4305-3b83-45bd-8991-6e336628d860" class="cnblogs_code_hide"><span style="color: #008080;"> 1</span> <span style="color: #000000;">Palette.generateAsync(bitmap,<br/></span><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">new</span><span style="color: #000000;"> Palette.PaletteAsyncListener() {<br/></span><span style="color: #008080;"> 3</span> <span style="color: #000000;"> @Override<br/></span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> onGenerated(Palette palette) {<br/></span><span style="color: #008080;"> 5</span> Palette.Swatch vibrant =<br/><span style="color: #008080;"> 6</span> <span style="color: #000000;"> palette.getVibrantSwatch();<br/></span><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">if</span> (swatch != <span style="color: #0000ff;">null</span><span style="color: #000000;">) {<br/></span><span style="color: #008080;"> 8</span> <span style="color: #008000;">//</span><span style="color: #008000;"> If we have a vibrant color<br/></span><span style="color: #008080;"> 9</span> <span style="color: #008000;">//</span><span style="color: #008000;"> update the title TextView</span><br/><span style="color: #008080;">10</span> <span style="color: #000000;"> titleView.setBackgroundColor(<br/></span><span style="color: #008080;">11</span> <span style="color: #000000;"> vibrant.getRgb());<br/></span><span style="color: #008080;">12</span> <span style="color: #000000;"> titleView.setTextColor(<br/></span><span style="color: #008080;">13</span> <span style="color: #000000;"> vibrant.getTitleTextColor());<br/></span><span style="color: #008080;">14</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">15</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">16</span> });</div></div><p>&nbsp;<strong>可信动作</strong></p><p>&nbsp;有形surface显示的就像电影中的跳格剪接。他们移动到能够帮助集中注意力的地方,建立空间联系并维持连续性。材料对触摸作出响应,以确认交互以及所触点发出的波形外向改变。所有的动作都有意义且让人倍感亲切,以协助用户的理解。</p><p>Activity+Fragment转变特效</p><p>通过声明贯穿两个屏幕的通用&rdquo;共享元素&rdquo;,可以创建两种状态间顺滑的转换特效。</p><p>&nbsp;<img src="http://images.cnitblog.com/blog/453582/201410/252212176835704.gif" alt="" /></p><p><a href="http://1.bp.blogspot.com/-Vv4SxVSI2DY/VEqQxAf3PWI/AAAAAAAAA7c/mfq7XBrIGgo/s1600/activity_transitions%2B(1).gif">http://1.bp.blogspot.com/-Vv4SxVSI2DY/VEqQxAf3PWI/AAAAAAAAA7c/mfq7XBrIGgo/s1600/activity_transitions%2B(1).gif</a></p><p>album_grid.xml:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('e4e851b8-44c2-4af4-a71d-c6b83dc3099f')"><div id="cnblogs_code_open_e4e851b8-44c2-4af4-a71d-c6b83dc3099f" class="cnblogs_code_hide"><span style="color: #008080;">1</span> &lt;<span style="color: #000000;">ImageView<br/></span><span style="color: #008080;">2</span> <span style="color: #000000;"> &hellip;<br/></span><span style="color: #008080;">3</span> android:transitionName="@string/transition_album_cover" /&gt;</div></div><p><span style="line-height: 1.5;">album_details.xml</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('ab0e6763-4637-41e0-8183-486ca90eed32')"><div id="cnblogs_code_open_ab0e6763-4637-41e0-8183-486ca90eed32" class="cnblogs_code_hide"><span style="color: #008080;">1</span> &lt;<span style="color: #000000;">ImageView<br/></span><span style="color: #008080;">2</span> <span style="color: #000000;"> &hellip;<br/></span><span style="color: #008080;">3</span> android:transitionName="@string/transition_album_cover" /&gt;</div></div><p><span style="line-height: 1.5;">AlbumActivity.java:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('fb7b4b79-586d-46e2-b244-bc971acba8cf')"><div id="cnblogs_code_open_fb7b4b79-586d-46e2-b244-bc971acba8cf" class="cnblogs_code_hide"><span style="color: #008080;">1</span> Intent intent = <span style="color: #0000ff;">new</span><span style="color: #000000;"> Intent();<br/></span><span style="color: #008080;">2</span> String transitionName =<span style="color: #000000;"> getString(R.string.transition_album_cover);<br/></span><span style="color: #008080;">3</span> <span style="color: #000000;">&hellip;<br/></span><span style="color: #008080;">4</span> ActivityOptionsCompat options =<br/><span style="color: #008080;">5</span> <span style="color: #000000;">ActivityOptionsCompat.makeSceneTransitionAnimation(activity,<br/></span><span style="color: #008080;">6</span> albumCoverImageView, <span style="color: #008000;">//</span><span style="color: #008000;"> The view which starts the transition</span><br/><span style="color: #008080;">7</span> transitionName <span style="color: #008000;">//</span><span style="color: #008000;"> The transitionName of the view we&rsquo;re transitioning to</span><br/><span style="color: #008080;">8</span> <span style="color: #000000;"> );<br/></span><span style="color: #008080;">9</span> ActivityCompat.startActivity(activity, intent, options.toBundle());</div></div><p><span style="line-height: 1.5;">两个屏幕中定义了相同的transitionName。当启动新的Activity的时候,这个转换特效自动地赋予生命。除了共享元素之外,现在也可以精心设计进入和退出元素(转换特效)。</span></p><p>波纹</p><p><img src="http://images.cnitblog.com/blog/453582/201410/252208062776977.gif" alt="" /></p><p><a href="http://3.bp.blogspot.com/-6UtZxpuhI-Q/VEqCMq6q17I/AAAAAAAAA68/oVt3vMIwJs0/s1600/animation-responsiveinteraction-inkreactions-notouchripplepressandrelease_large_xhdpi.gif">http://3.bp.blogspot.com/-6UtZxpuhI-Q/VEqCMq6q17I/AAAAAAAAA68/oVt3vMIwJs0/s1600/animation-responsiveinteraction-inkreactions-notouchripplepressandrelease_large_xhdpi.gif</a></p><p>&nbsp;材料设计通过墨纹surface回应对用户的触摸事件作出响应。拿Button为例,当你使用或继承Theme.Material(android:selectableItemBackground)时,交互控制默认展示这种行为。通过简单地在ripple元素中包裹drawable元素,你可以将这种反馈添加到自己定义的drawable中:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('f283d8d4-23b8-4f2d-a52d-a705a0bcd4a9')"><div id="cnblogs_code_open_f283d8d4-23b8-4f2d-a52d-a705a0bcd4a9" class="cnblogs_code_hide"><span style="color: #008080;"> 1</span> &lt;<span style="color: #000000;">ripple<br/></span><span style="color: #008080;"> 2</span> xmlns:android="http://schemas.android.com/apk/res/android"<br/><span style="color: #008080;"> 3</span> android:color="@color/accent_dark"&gt;<br/><span style="color: #008080;"> 4</span> &lt;item&gt;<br/><span style="color: #008080;"> 5</span> &lt;<span style="color: #000000;">shape<br/></span><span style="color: #008080;"> 6</span> android:shape="oval"&gt;<br/><span style="color: #008080;"> 7</span> &lt;solid android:color="?android:colorAccent" /&gt;<br/><span style="color: #008080;"> 8</span> &lt;/shape&gt;<br/><span style="color: #008080;"> 9</span> &lt;/item&gt;<br/><span style="color: #008080;">10</span> &lt;/ripple&gt;</div></div><p>自定义视图应该扩大触摸定位直到回调View#drawableHotspotChanged里面的drawable,由此,波纹可以从触摸点开始。</p><p><strong>StateListAnimator</strong></p><p>材料设计也可以通过&rdquo;升起&rdquo;以接触手指来回应触摸事件,就像磁铁的吸引力一样。也可以通过使translationZ属性产生动画效果来达到这种效果,其中的translationZ属性相似于elevation属性但却是打算为transient所用;其它是Z=elevation + translationZ。新的StateListAnimator属性允许很轻易就能实现触摸上面的translationZ产生动画(Button默认实现了这种效果):</p><p>layout/yout_layout.xml:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('d734da74-ef1e-4c78-9ac3-7a6647e88e39')"><div id="cnblogs_code_open_d734da74-ef1e-4c78-9ac3-7a6647e88e39" class="cnblogs_code_hide"><span style="color: #008080;">1</span> &lt;<span style="color: #000000;">ImageButton &hellip;<br/></span><span style="color: #008080;">2</span> android:stateListAnimator="@anim/raise" /&gt;</div></div><p><span style="line-height: 1.5;">anim/raise.xml:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('8406da22-5726-4bdb-b2ed-bd04cdbc0320')"><div id="cnblogs_code_open_8406da22-5726-4bdb-b2ed-bd04cdbc0320" class="cnblogs_code_hide"><span style="color: #008080;"> 1</span> &lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;<br/><span style="color: #008080;"> 2</span> &lt;item android:state_enabled="true" android:state_pressed="true"&gt;<br/><span style="color: #008080;"> 3</span> &lt;<span style="color: #000000;">objectAnimator<br/></span><span style="color: #008080;"> 4</span> android:duration="@android:integer/config_shortAnimTime"<br/><span style="color: #008080;"> 5</span> android:propertyName="translationZ"<br/><span style="color: #008080;"> 6</span> android:valueTo="@dimen/touch_raise"<br/><span style="color: #008080;"> 7</span> android:valueType="floatType" /&gt;<br/><span style="color: #008080;"> 8</span> &lt;/item&gt;<br/><span style="color: #008080;"> 9</span> &lt;item&gt;<br/><span style="color: #008080;">10</span> &lt;<span style="color: #000000;">objectAnimator<br/></span><span style="color: #008080;">11</span> android:duration="@android:integer/config_shortAnimTime"<br/><span style="color: #008080;">12</span> android:propertyName="translationZ"<br/><span style="color: #008080;">13</span> android:valueTo="0dp"<br/><span style="color: #008080;">14</span> android:valueType="floatType" /&gt;<br/><span style="color: #008080;">15</span> &lt;/item&gt;<br/><span style="color: #008080;">16</span> &lt;/selector&gt;</div></div><p><strong>Reveal</strong></p><p>用于展示新内容的典型的材料转换特效通过扩展的圆形遮罩来实现这种效果。通过外扩的雷达效果,Reveal协助加强了把用户的触摸点作为所有转换特效的起始。可能通过下面的Animator来实现这种效果:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" onclick="cnblogs_code_show('a25791cf-a9fc-4b2a-9e29-7fc8a1248be4')"><div id="cnblogs_code_open_a25791cf-a9fc-4b2a-9e29-7fc8a1248be4" class="cnblogs_code_hide"><span style="color: #008080;">1</span> Animator reveal =<span style="color: #000000;"> ViewAnimationUtils.createCircularReveal(<br/></span><span style="color: #008080;">2</span> viewToReveal, <span style="color: #008000;">//</span><span style="color: #008000;"> The new View to reveal</span><br/><span style="color: #008080;">3</span> centerX, <span style="color: #008000;">//</span><span style="color: #008000;"> x co-ordinate to start the mask from</span><br/><span style="color: #008080;">4</span> centerY, <span style="color: #008000;">//</span><span style="color: #008000;"> y co-ordinate to start the mask from</span><br/><span style="color: #008080;">5</span> startRadius, <span style="color: #008000;">//</span><span style="color: #008000;"> radius of the starting mask</span><br/><span style="color: #008080;">6</span> endRadius); <span style="color: #008000;">//</span><span style="color: #008000;"> radius of the final mask</span><br/><span style="color: #008080;">7</span> reveal.start();</div></div><p><strong>Interpolators</strong></p><p>动作应该是审慎的、迅捷的、精确的。不像典型的&rdquo;易入易出&rdquo;的转换特效,在材料设计中,对象常常快速开始,然后缓慢地到达他们的最终位置。在动画的过程中,对象花费更多的时间在靠近最终位置的地方。最终,用户不必等待动画结束,由此,动作的负面效果被最小化。新的&rdquo;快进慢出&rdquo;interpolator已被添加进来以实现这种动作。</p><p><img src="http://images.cnitblog.com/blog/453582/201410/252210082775972.gif" alt="" /></p><p><a href="http://3.bp.blogspot.com/-h1tGDao-XK4/VEqCGLnpyQI/AAAAAAAAA60/LE4NO1X_gzk/s1600/animation-authentic-motion-authenticMotion_massAndWeight_ex1_large_xhdpi.gif">http://3.bp.blogspot.com/-h1tGDao-XK4/VEqCGLnpyQI/AAAAAAAAA60/LE4NO1X_gzk/s1600/animation-authentic-motion-authenticMotion_massAndWeight_ex1_large_xhdpi.gif</a></p><p>对于元素的进入屏幕,请分别查看&rdquo;线出慢入&rdquo;和&rdquo;快出线入&rdquo;interpolator。</p><p><strong>可适设计</strong></p><p>材料设计的最终核心概念是创建适应性的设计,这种设计对于所以尺寸形状,从手表到巨型电视,都能够完好地适应。适应性设计技术帮我们实现了这种愿景:在相同的基础系统下,每一个设备展示了不同的视图。每一个视图对于每一种尺寸都是量身定制,每一种交互对于每一个设备都恰到好处。色彩、图像、视图层次结构和空间联系保持恒定。材料设计系统提供了灵活的构件和模式来帮你构建可伸缩的设计。</p><p><strong>工具条(Toolbar)</strong></p><p>Toolbar是action bar模式的泛化,提供了相似的功能,但却更加灵活。不像标准的action bar,toolbar在视图层次结构中只是一个视图,和其它的没有任何区别,所以你可以把它放到任何你喜欢的地方,和其它的视图交叉布局,生成动画,回应滑动事件等待。通过调用Activity.setActionBar(),你可以使Toolbar像Activity中的action bar一样活动。</p><p><img src="http://images.cnitblog.com/blog/453582/201410/252210464654672.png" alt="" /></p><p><a href="http://1.bp.blogspot.com/-np39I5VrQTQ/VEnnefqkroI/AAAAAAAAA6c/--kVt_Wi1vk/s1600/contacts_toolbars.png">http://1.bp.blogspot.com/-np39I5VrQTQ/VEnnefqkroI/AAAAAAAAA6c/--kVt_Wi1vk/s1600/contacts_toolbars.png</a></p><p>在这个例子当中,蓝色的toolbar高度被扩展,贴在了屏幕内容上面,并提供了一个导航按钮。注意:额外的两个toolbar分别用在列表和细节视图中。</p><p><strong>继续前行并材料设计化</strong></p><p>材料设计助你构建易于理解的、美观的且可适的应用,其中充满了动作。我希望这篇博客能够激励你把这些规则应用到你的app中,并指示了一些新的(兼容性)API来达到这个目的。</p><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4051049" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/littlepanpc/p/4051049.html" target="_blank">[翻译]Android 5.0之应用中实现材料设计—Material Design</a>,转载请注明。</p>http://www.cnblogs.com/raison/p/4051033.html契约式设计(DbC)感想 - C++@*NIX契约式设计可以理解为正则编程的一种实践:如果用我的三脚猫能力将这种实践方法形式化的话,大致如下(如有不正确处,请不吝指正):1、对于方法Method的precondition & postcondition: Function(RegularMthod) = ^ RegularFunctio...2014-10-25T14:10:00Z2014-10-25T14:10:00ZC++@*NIXhttp://www.cnblogs.com/raison/<p>契约式设计可以理解为正则编程的一种实践:</p><p>如果用我的三脚猫能力将这种实践方法形式化的话,大致如下(如有不正确处,请不吝指正):</p><p>1、对于方法Method的precondition &amp; postcondition:</p><p>  Function(RegularMthod) =</p><p>    ^ RegularFunction</p><p>    ^ General-Class-Method</p><p>    ^ <strong>Assert</strong>(precondition)</p><p>    ^ <strong>Assert</strong>(postcondition);</p><p>  =&gt; f1( f2 ) { f1, f2 : RegularMethod }</p><p>    |-&gt; Assert(f2.precondition) =&gt; Assert( f1.postcondition )</p><p>  当所有方法都满足上述条件的时候,那就意味着该程序的输入如果满足assert(precondition),那么它的输出也满足assert(postcondition),从而在逻辑上保证程序的正确性。这是针对方法调用或者函数调用上讲的,这个倒是可以在有函数或者过程的语言里面都可以实现。我个人理解为operation组合上的正则性(regularity)。</p><p>2、类Class的不变式Invariant:</p><p>  Class(InvariantClass) =</p><p>    ^ General-Class</p><p>    ^ Invariant : assert(invariant) when any method called.</p><p>  一个类的所有直接活着间接的子类都要满足它的不变式Invariant,从而保证该类及其衍生类在数据上保证正确性,个人理解为data组合的正则性。</p><p>&nbsp;</p><p>综合上述两点,在operation 以及 data的组合上均实现了正则性,即面向对象上的正则性,从而在理论上保证了对象的正则性以及以对象构造出来的程序的正确。</p><p>&nbsp;</p><p>3、适当的DbC</p><p>  过犹不及。如果我们将每一个类都很详细地进行DbC,那也是一件很耗时、痛苦的没有必要的事情,正如你预防着小偷固然好,但是将除了自己之外的其他人都像防贼一样来防着也不合适一样。我们应该是适当地DbC。</p><p>  DbC更是一种思想,一种思维模式,为如何构造出高质量的软件指出一个道道来,它告诉我们,依如是法,达高质量的彼岸。如果在实践中运用则应当根据具体情况而定。</p><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4051033" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/raison/p/4051033.html" target="_blank">契约式设计(DbC)感想</a>,转载请注明。</p>http://www.cnblogs.com/zhnaghui/p/4051027.html二.fstream的使用方法 - 半入尘埃二.fstream的使用方法在C++中,有一个stream这个类,所有的I/O都以这个“流”类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:1、插入器(>) 从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin>>x;就表示....2014-10-25T14:08:00Z2014-10-25T14:08:00Z半入尘埃http://www.cnblogs.com/zhnaghui/<p><span><span><span style="color: #000000; font-family: 微软雅黑;">二.fstream的使用方法</span></span></span></p><div id="blogDetailDiv" data-webp-ctx-e="1"><div class="blog_details_20120222"><div>&nbsp;在C++中,有一个stream这个类,所有的I/O都以这个&ldquo;流&rdquo;类为基础的,包括我们要认识的文件I/O,stream这个类有两个重要的运算符:</div><p>1、插入器(&lt;&lt;)<br />  向流输出数据。比如说系统有一个默认的标准输出流(cout),一般情况下就是指的显示器,所以,cout&lt;&lt;"Write Stdout"&lt;&lt;' ';就表示把字符串"Write Stdout"和换行字符(' ')输出到标准输出流。</p><p>2、析取器(&gt;&gt;)<br />  从流中输入数据。比如说系统有一个默认的标准输入流(cin),一般情况下就是指的键盘,所以,cin&gt;&gt;x;就表示从标准输入流中<a name="1" target="_blank"></a><strong>读取</strong>一个指定类型(即变量x的类型)的数据。</p><p>  在C++中,对文件的操作是通过stream的子类<a name="0" target="_blank"></a><strong>fstream</strong>(file stream)来实现的,所以,要用这种方式操作文件,就必须加入头文件<strong>fstream</strong>.h。下面就把此类的文件操作过程一一道来。</p><p>一、打开文件<br />  在<strong>fstream</strong>类中,有一个成员函数open(),就是用来打开文件的,其原型是:</p><p>void open(const char* filename,int mode,int access);</p><p>参数:</p><p>filename:  要打开的文件名&nbsp;<br />mode:    要打开文件的方式&nbsp;<br />access:   打开文件的属性<br />打开文件的方式在类ios(是所有流式I/O类的基类)中定义,常用的值如下:</p><p>ios::app:   以追加的方式打开文件&nbsp;<br />ios::ate:   文件打开后定位到文件尾,ios:app就包含有此属性&nbsp;<br />ios::binary:  以<a name="2" target="_blank"></a><strong>二进制</strong>方式打开文件,缺省的方式是文本方式。两种方式的区别见前文&nbsp;<br />ios::in:    文件以输入方式打开&nbsp;<br />ios::out:   文件以输出方式打开&nbsp;<br />ios::nocreate: 不建立文件,所以文件不存在时打开失败 &nbsp;<br />ios::noreplace:不覆盖文件,所以打开文件时如果文件存在失败&nbsp;<br />ios::trunc:  如果文件存在,把文件长度设为0&nbsp;<br />  可以用&ldquo;或&rdquo;把以上属性连接起来,如ios::out|ios::binary</p><p>  打开文件的属性取值是:</p><p>0:普通文件,打开访问&nbsp;<br />1:只读文件&nbsp;<br />2:隐含文件&nbsp;<br />4:系统文件&nbsp;<br />  可以用&ldquo;或&rdquo;或者&ldquo;+&rdquo;把以上属性连接起来 ,如3或1|2就是以只读和隐含属性打开文件。</p><p>  例如:以<strong>二进制</strong>输入方式打开文件c:config.sys</p><p>  <strong>fstream</strong>&nbsp;file1;<br />  file1.open("c:\config.sys",ios::binary|ios::in,0);</p><p>  如果open函数只有文件名一个参数,则是以读/写普通文件打开,即:</p><p>  file1.open("c:\config.sys");&lt;=&gt;file1.open("c:\config.sys",ios::in|ios::out,0);</p><p>  另外,<strong>fstream</strong>还有和open()一样的构造函数,对于上例,在定义的时侯就可以打开文件了:</p><p>  <strong>fstream</strong>&nbsp;file1("c:\config.sys");</p><p>  特别提出的是,<strong>fstream</strong>有两个子类:ifstream(input file stream)和ofstream(outpu file stream),ifstream默认以输入方式打开文件,而ofstream默认以输出方式打开文件。</p><p>  ifstream file2("c:\pdos.def");//以输入方式打开文件<br />  ofstream file3("c:\x.123");//以输出方式打开文件</p><p>  所以,在实际应用中,根据需要的不同,选择不同的类来定义:如果想以输入方式打开,就用ifstream来定义;如果想以输出方式打开,就用ofstream来定义;如果想以输入/输出方式来打开,就用<strong>fstream</strong>来定义。</p><p>二、关闭文件<br />  打开的文件使用完成后一定要关闭,<strong>fstream</strong>提供了成员函数close()来完成此操作,如:file1.close();就把file1相连的文件关闭。</p><p>三、读写文件<br />  读写文件分为文本文件和<strong>二进制</strong>文件的<strong>读取</strong>,对于文本文件的<strong>读取</strong>比较简单,用插入器和析取器就可以了;而对于<strong>二进制</strong>的<strong>读取</strong>就要复杂些,下要就详细的介绍这两种方式</p><p>  1、文本文件的读写<br />  文本文件的读写很简单:用插入器(&lt;&lt;)向文件输出;用析取器(&gt;&gt;)从文件输入。假设file1是以输入方式打开,file2以输出打开。示例如下:</p><p>  file2&lt;&lt;"I Love You";//向文件写入字符串"I Love You"<br />  int i;<br />  file1&gt;&gt;i;//从文件输入一个整数值。</p><p>  这种方式还有一种简单的格式化能力,比如可以指定输出为16进制等等,具体的格式有以下一些</p><p>操纵符 功能 输入/输出&nbsp;<br />dec 格式化为十进制数值数据 输入和输出&nbsp;<br />endl 输出一个换行符并刷新此流 输出&nbsp;<br />ends 输出一个空字符 输出&nbsp;<br />hex 格式化为十六进制数值数据 输入和输出&nbsp;<br />oct 格式化为八进制数值数据 输入和输出&nbsp;<br />setpxecision(int p) 设置浮点数的精度位数 输出</p><p>  比如要把123当作十六进制输出:file1&lt;</p><p>  2、<strong>二进制</strong>文件的读写<br />①put()<br />  put()函数向流写入一个字符,其原型是ofstream &amp;put(char ch),使用也比较简单,如file1.put('c');就是向流写一个字符'c'。</p><p>②get()<br />  get()函数比较灵活,有3种常用的重载形式:</p><p>  一种就是和put()对应的形式:ifstream &amp;get(char &amp;ch);功能是从流中<strong>读取</strong>一个字符,结果保存在引用ch中,如果到文件尾,返回空字符。如file2.get(x);表示从文件中<strong>读取</strong>一个字符,并把<strong>读取</strong>的字符保存在x中。</p><p>  另一种重载形式的原型是: int get();这种形式是从流中返回一个字符,如果到达文件尾,返回EOF,如x=file2.get();和上例功能是一样的。</p><p>  还有一种形式的原型是:ifstream &amp;get(char *buf,int num,char delim=' ');这种形式把字符读入由 buf 指向的数组,直到读入了 num 个字符或遇到了由 delim 指定的字符,如果没使用 delim 这个参数,将使用缺省值换行符' '。例如:</p><p>  file2.get(str1,127,'A');//从文件中<strong>读取</strong>字符到字符串str1,当遇到字符'A'或<strong>读取</strong>了127个字符时终止。</p><p>③读写数据块<br />  要读写<strong>二进制</strong>数据块,使用成员函数read()和write()成员函数,它们原型如下:</p><p>    read(unsigned char *buf,int num);<br />    write(const unsigned char *buf,int num);</p><p>  read()从文件中<strong>读取</strong>&nbsp;num 个字符到 buf 指向的缓存中,如果在还未读入 num 个字符时就到了文件尾,可以用成员函数 int gcount();来取得实际<strong>读取</strong>的字符数;而 write() 从buf 指向的缓存写 num 个字符到文件中,值得注意的是缓存的类型是 unsigned char *,有时可能需要类型转换。</p><p>例:</p><p>    unsigned char str1[]="I Love You";<br />    int n[5];<br />    ifstream in("xxx.xxx");<br />    ofstream out("yyy.yyy");<br />    out.write(str1,strlen(str1));//把字符串str1全部写到yyy.yyy中<br />    in.read((unsigned char*)n,sizeof(n));//从xxx.xxx中<strong>读取</strong>指定个整数,注意类型转换<br />    in.close();out.close();</p><p>四、检测EOF<br />  成员函数eof()用来检测是否到达文件尾,如果到达文件尾返回非0值,否则返回0。原型是int eof();</p><p>例:  if(in.eof())ShowMessage("已经到达文件尾!");</p><p>五、文件定位<br />  和C的文件操作方式不同的是,C++ I/O系统管理两个与一个文件相联系的指针。一个是读指针,它说明输入操作在文件中的位置;另一个是写指针,它下次写操作的位置。每次执行输入或输出时,相应的指针自动变化。所以,C++的文件定位分为读位置和写位置的定位,对应的成员函数是 seekg()和 seekp(),seekg()是设置读位置,seekp是设置写位置。它们最通用的形式如下:</p><p>    istream &amp;seekg(streamoff offset,seek_dir origin);<br />    ostream &amp;seekp(streamoff offset,seek_dir origin);</p><p>  streamoff定义于 iostream.h 中,定义有偏移量 offset 所能取得的最大值,seek_dir 表示移动的基准位置,是一个有以下值的枚举:</p><p>ios::beg:  文件开头&nbsp;<br />ios::cur:  文件当前位置&nbsp;<br />ios::end:  文件结尾&nbsp;<br />  这两个函数一般用于<strong>二进制</strong>文件,因为文本文件会因为系统对字符的解释而可能与预想的值不同。</p><p>例:</p><p>     file1.seekg(1234,ios::cur);//把文件的读指针从当前位置向后移1234个字节<br />     file2.seekp(1234,ios::beg);//把文件的写指针从文件开头向后移1234个字节<br /><br />这篇文章总体而言对C++中文件的使用的讲解是非常详细的,从头文件到文件的打开、读写、关闭,以及文件的结束和定位都有一一讲解。</p></div></div><img src="http://counter.cnblogs.com/blog/rss/4051027" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/zhnaghui/p/4051027.html" target="_blank">二.fstream的使用方法</a>,转载请注明。</p>http://www.cnblogs.com/WhyEngine/p/4051001.htmlC语言中将0到1000的浮点数用强制指针类型转换的方式生成一幅图像 - 叶飞影搞过计算机图像的人都知道,图像中的每一个像素通常为一个整型数,它可以分成4个无符号的char类型,以表示其RGBA四个分量。一幅图像可以看做是一个二维整型数组。这里我会生成一个float数组,其数组大小为1000000,刚好1000*1000,数组内的浮点数的数值范围在0到1000.0之间,呈...2014-10-25T13:56:00Z2014-10-25T13:56:00Z叶飞影http://www.cnblogs.com/WhyEngine/<p><span style="font-size: 16px;">&nbsp; &nbsp; &nbsp; 搞过计算机图像的人都知道,图像中的每一个像素通常为一个整型数,它可以分成4个无符号的char类型,以表示其RGBA四个分量。一幅图像可以看做是一个二维整型数组。这里我会生成一个float数组,其数组大小为1000000,刚好1000*1000,数组内的浮点数的数值范围在0到1000.0之间,呈等差数组排列,相邻两数的差为0.001。然后将其每一个浮点数强制转化成一个整型数或三个unsigned char型,以决定像素的RGB三个通道分量,看看其生成的图像是什么样子。</span></p><p><span style="font-size: 16px;">&nbsp; &nbsp; &nbsp; 前几天写了一篇文章是在C语言中<a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/WhyEngine/p/4040246.html">使用异或运算交换两个任意类型变量</a>,引来某人的质疑,说什么&ldquo;指针的强制类型转换有一定限制,不是你想怎么转就怎么转的,结果可能会出错的&rdquo;。用这种莫须有的话来否定我的代码。为嘲笑他的无知,我特意写出这种用强制指针类型转换生成图像的算法。</span></p><p><span style="font-size: 16px;">先上C代码:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="font-size: 16px;">#include &lt;iostream&gt;<span style="color: #000000;"><br/>#include </span>&lt;cmath&gt;<span style="color: #000000;"><br/>#include </span>&lt;cstdlib&gt;<br/><br/><span style="color: #0000ff;">#define</span> DIM 1000<br/><br/><span style="color: #0000ff;">void</span> pixel_write(<span style="color: #0000ff;">int</span>,<span style="color: #0000ff;">int</span><span style="color: #000000;">);<br/>FILE </span>*<span style="color: #000000;">fp;<br/><br/></span><span style="color: #0000ff;">int</span><span style="color: #000000;"> main()<br/>{<br/> fp </span>= fopen(<span style="color: #800000;">"</span><span style="color: #800000;">image.ppm</span><span style="color: #800000;">"</span>,<span style="color: #800000;">"</span><span style="color: #800000;">wb</span><span style="color: #800000;">"</span><span style="color: #000000;">);<br/> </span><span style="color: #0000ff;">if</span> (!<span style="color: #000000;">fp)<br/> {<br/> </span><span style="color: #0000ff;">return</span> -<span style="color: #800080;">1</span><span style="color: #000000;">;<br/> }<br/><br/> fprintf(fp, </span><span style="color: #800000;">"</span><span style="color: #800000;">P6\n%d %d\n255\n</span><span style="color: #800000;">"</span><span style="color: #000000;">, DIM, DIM);<br/> </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> j=<span style="color: #800080;">0</span>;j&lt;DIM;j++<span style="color: #000000;">)<br/> {<br/> </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=<span style="color: #800080;">0</span>;i&lt;DIM;i++<span style="color: #000000;">)<br/> {<br/> pixel_write(i,j);<br/> }<br/> }<br/> fclose(fp);<br/><br/> </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">0</span><span style="color: #000000;">;<br/>}<br/><br/></span><span style="color: #0000ff;">void</span> pixel_write(<span style="color: #0000ff;">int</span> i, <span style="color: #0000ff;">int</span><span style="color: #000000;"> j)<br/>{<br/> </span><span style="color: #0000ff;">static</span> unsigned <span style="color: #0000ff;">char</span> color[<span style="color: #800080;">3</span><span style="color: #000000;">];<br/> </span><span style="color: #0000ff;">float</span> t = j + i*<span style="color: #800080;">0.001f</span><span style="color: #000000;">;<br/> memcpy(color, </span>&amp;t, <span style="color: #800080;">3</span><span style="color: #000000;">);<br/> fwrite(color, </span><span style="color: #800080;">1</span>, <span style="color: #800080;">3</span><span style="color: #000000;">, fp);<br /><br /> // 其实更简单粗爆的方式是</span></span><span> //fwrite(&amp;t, 1, 3<span>, fp);</span></span><span style="font-size: 16px;"><span style="color: #000000;">}</span></span></div><p><span style="font-size: 16px;">&nbsp; &nbsp; &nbsp; 代码运行后会生成一种PPM格式的图像,如下图所示:</span></p><p><span style="font-size: 16px;"><img src="http://images.cnitblog.com/blog/571803/201410/252138511832168.png" alt="" /></span></p><p><span style="font-size: 16px;">&nbsp; &nbsp; &nbsp; 图像多少有点分形的感觉。PPM格式的图像不太常见,它是一种非常简单的图像格式。在我写的软件<a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/WhyEngine/p/4034302.html">Why数学图像生成工具</a>中可以查看,当然我也将该图像的生成算法写到这个软件中,相关代码如下:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="font-size: 16px;"><span style="color: #000000;">#ifndef _PixelFloatConvertInt_H_<br/></span><span style="color: #0000ff;">#define</span> _PixelFloatConvertInt_H_<br/><br/><span style="color: #008000;">//</span><span style="color: #008000;"> --------------------------------------------------------------------------------------</span><br/><span style="color: #000000;"><br/>#include </span><span style="color: #800000;">"</span><span style="color: #800000;">IPixelEquation.h</span><span style="color: #800000;">"</span><br/><br/><span style="color: #008000;">//</span><span style="color: #008000;"> --------------------------------------------------------------------------------------</span><br/><br/><span style="color: #0000ff;">class</span> CPixelFloatConvertInt : <span style="color: #0000ff;">public</span><span style="color: #000000;"> IPixelEquation<br/>{<br/></span><span style="color: #0000ff;">public</span><span style="color: #000000;">:<br/> CPixelFloatConvertInt()<br/> {<br/> m_width </span>= <span style="color: #800080;">1000</span><span style="color: #000000;">;<br/> m_height </span>= <span style="color: #800080;">1000</span><span style="color: #000000;">;<br/> }<br/><br/> </span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span>* GetName() <span style="color: #0000ff;">const</span><span style="color: #000000;"><br/> {<br/> </span><span style="color: #0000ff;">return</span> <span style="color: #800000;">"</span><span style="color: #800000;">Float Convert Int</span><span style="color: #800000;">"</span><span style="color: #000000;">;<br/> }<br/><br/> unsigned </span><span style="color: #0000ff;">int</span> CalculatePixel(unsigned <span style="color: #0000ff;">int</span> x, unsigned <span style="color: #0000ff;">int</span><span style="color: #000000;"> y)<br/> {<br/> </span><span style="color: #0000ff;">float</span> t = y + x*<span style="color: #800080;">0.001f</span><span style="color: #000000;">;<br/> unsigned </span><span style="color: #0000ff;">int</span> rst = *(unsigned <span style="color: #0000ff;">int</span>*)&amp;<span style="color: #000000;">t;<br/> rst </span>|= <span style="color: #800080;">0xff000000</span><span style="color: #000000;">;<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> rst;<br/> }<br/>};<br/><br/></span><span style="color: #008000;">//</span><span style="color: #008000;"> --------------------------------------------------------------------------------------</span><br/><br/><span style="color: #0000ff;">#endif</span></span></div><p><span style="font-size: 16px;">使用<a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/WhyEngine/p/4034302.html">Why数学图像生成工具</a>可以查看该图像的红绿蓝三个分量:</span></p><p><span style="font-size: 16px;">R通道图:</span></p><p><span style="font-size: 16px;"><img src="http://images.cnitblog.com/blog/571803/201410/252140583551017.png" alt="" /></span></p><p><span style="font-size: 16px;">G通道图:</span></p><p><span style="font-size: 16px;"><img src="http://images.cnitblog.com/blog/571803/201410/252141085435238.png" alt="" /></span></p><p><span style="font-size: 16px;">B通道图:</span></p><p><span style="font-size: 16px;"><img src="http://images.cnitblog.com/blog/571803/201410/252141183402344.png" alt="" /></span></p><p>代码稍做修改,分形效果更为明显:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"> unsigned <span style="color: #0000ff;">int</span> CalculatePixel(unsigned <span style="color: #0000ff;">int</span> x, unsigned <span style="color: #0000ff;">int</span><span style="color: #000000;"> y)<br/> {<br/> </span><span style="color: #0000ff;">float</span> t = y/<span style="color: #800080;">4</span>+ x*<span style="color: #800080;">0.001f</span><span style="color: #000000;">;<br/> unsigned </span><span style="color: #0000ff;">int</span> rst = *(unsigned <span style="color: #0000ff;">int</span>*)&amp;<span style="color: #000000;">t;<br/> rst </span>|= <span style="color: #800080;">0xff000000</span><span style="color: #000000;">;<br/> </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> rst;<br/> }</span></div><p><img src="http://images.cnitblog.com/blog/571803/201410/252216025277480.png" alt="" /></p><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4051001" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/WhyEngine/p/4051001.html" target="_blank">C语言中将0到1000的浮点数用强制指针类型转换的方式生成一幅图像</a>,转载请注明。</p>http://www.cnblogs.com/SunBlog/p/4050030.htmljavascript——对象的概念——函数 3 (使用技巧) - 志在天涯1、回调函数:将函数A传给函数B,由函数B来执行A,则称A为回调函数。例1:例2 1 function addone(a){return a+1;}; //定义一个回调函数 2 function mulitiply(a,b,c,callback) ...2014-10-25T13:48:00Z2014-10-25T13:48:00Z志在天涯http://www.cnblogs.com/SunBlog/<p style="margin-left: 30px;"><span style="font-size: 15px;">1、回调函数:将函数A传给函数B,由函数B来执行A,则称A为回调函数。</span></p><p style="margin-left: 60px;"><span style="font-size: 15px;">例1:</span></p><p style="margin-left: 90px;">&nbsp;<img style="font-size: 14px; line-height: 1.5;" src="http://images.cnitblog.com/blog/667906/201410/251348199964522.png" alt="" /></p><p style="margin-left: 60px;"><span style="font-size: 15px;">例2</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="margin-left: 90px;" onclick="cnblogs_code_show('4ae7d22f-80d8-41c4-bab3-78c2ecbf082c')"><div id="cnblogs_code_open_4ae7d22f-80d8-41c4-bab3-78c2ecbf082c" class="cnblogs_code_hide"><span style="color: #008080;"> 1</span> function addone(a){<span style="color: #0000ff;">return</span> a+<span style="color: #800080;">1</span>;}; <span style="color: #008000;">//</span><span style="color: #008000;">定义一个回调函数</span><br/><span style="color: #008080;"> 2</span> function mulitiply(a,b,c,callback) <span style="color: #008000;">//</span><span style="color: #008000;">定义一个可以调用回调函数的函数</span><br/><span style="color: #008080;"> 3</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">var</span> i,ar=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Array();<br/></span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">for</span>(i=<span style="color: #800080;">0</span>;i&lt;<span style="color: #800080;">3</span>;i++<span style="color: #000000;">)<br/></span><span style="color: #008080;"> 6</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 7</span> ar[i]=callback(arguments[i]*<span style="color: #800080;">2</span>); <span style="color: #008000;">//</span><span style="color: #008000;">将输入参数乘以2之后作为回调函数的参数执行。</span><br/><span style="color: #008080;"> 8</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 9</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> ar;<br/></span><span style="color: #008080;">10</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">11</span> <span style="color: #0000ff;">var</span> myarr=mulitiply(<span style="color: #800080;">1</span>,<span style="color: #800080;">2</span>,<span style="color: #800080;">3</span><span style="color: #000000;">,addone);<br/></span><span style="color: #008080;">12</span> myarr; <span style="color: #008000;">//</span><span style="color: #008000;">[3, 5, 7]</span></div></div><p style="margin-left: 90px;"><span style="font-size: 15px; line-height: 1.5;">改进代码,使其可以忽略输入参数个数。将代码修改后如下:</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="margin-left: 90px;" onclick="cnblogs_code_show('76e98b02-c38b-4b7d-b68c-3f17684c701b')"><div id="cnblogs_code_open_76e98b02-c38b-4b7d-b68c-3f17684c701b" class="cnblogs_code_hide"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">function</span> addone(a){<span style="color: #0000ff;">return</span> a+1;}; <span style="color: #008000;">//</span><span style="color: #008000;">定义一个回调函数</span><br/><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">function</span> mulitiply(an) <span style="color: #008000;">//</span><span style="color: #008000;">定义一个可以调用回调函数的函数</span><br/><span style="color: #008080;"> 3</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">var</span> i,ar =<span style="color: #0000ff;">new</span> Array(arguments.length-1<span style="color: #000000;">);<br/></span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">if</span> (<span style="color: #0000ff;">typeof</span> arguments[arguments.length-1]==="function"<span style="color: #000000;">)<br/></span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">for</span>(i=0;i&lt;arguments.length-1;i++<span style="color: #000000;">)<br/></span><span style="color: #008080;"> 7</span> ar[i]=arguments[arguments.length-1](arguments[i]*2); <span style="color: #008000;">//</span><span style="color: #008000;">将输入参数乘以2之后作为回调函数的参数执行。</span><br/><span style="color: #008080;"> 8</span> <span style="color: #0000ff;">return</span><span style="color: #000000;"> ar;<br/></span><span style="color: #008080;"> 9</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">10</span> <span style="color: #0000ff;">var</span> myarr=mulitiply(1,2,3,addone); <span style="color: #008000;">//</span><span style="color: #008000;">这种方式要求回调函数放在参数的最后一个</span><br/><span style="color: #008080;">11</span> myarr; <span style="color: #008000;">//</span><span style="color: #008000;">[3, 5, 7]</span><br/><span style="color: #008080;">12</span> <span style="color: #0000ff;">var</span> myarr=mulitiply(1,2,3,4,addone); <span style="color: #008000;">//</span><span style="color: #008000;">这种方式要求回调函数放在参数的最后一个</span><br/><span style="color: #008080;">13</span> myarr; <span style="color: #008000;">//</span><span style="color: #008000;">[3, 5, 7, 9]</span></div></div><p style="margin-left: 90px;">&nbsp;效果如图:</p><p style="margin-left: 90px;"><img src="http://images.cnitblog.com/blog/667906/201410/251622516834469.png" alt="" /></p><p style="margin-left: 30px;"><span style="font-size: 15px;">&nbsp;2、返回函数的函数:执行的函数返回值是一个函数引用。</span></p><p style="margin-left: 90px;"><img src="http://images.cnitblog.com/blog/667906/201410/251638318714570.png" alt="" /></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="margin-left: 90px;" onclick="cnblogs_code_show('f2e0f8da-9539-4517-8280-5561e6d684b2')"><div id="cnblogs_code_open_f2e0f8da-9539-4517-8280-5561e6d684b2" class="cnblogs_code_hide"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> a()<br/></span><span style="color: #008080;"> 2</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">function</span><span style="color: #000000;"> b()<br/></span><span style="color: #008080;"> 4</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">return</span> 'B'<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 6</span> <span style="color: #000000;"> };<br/></span><span style="color: #008080;"> 7</span> <span style="color: #0000ff;">return</span> b; <span style="color: #008000;">//</span><span style="color: #008000;">返回一个函数的引用</span><br/><span style="color: #008080;"> 8</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 9</span> <span style="color: #0000ff;">var</span> newfunct=a(); <span style="color: #008000;">//</span><span style="color: #008000;">获得一个函数的引用</span><br/><span style="color: #008080;">10</span> <span style="color: #0000ff;">typeof</span> newfunct; <span style="color: #008000;">//</span><span style="color: #008000;">"function"</span><br/><span style="color: #008080;">11</span> newfunct(); <span style="color: #008000;">//</span><span style="color: #008000;">"B"</span><br/><span style="color: #008080;">12</span> a()(); <span style="color: #008000;">//</span><span style="color: #008000;">"B"; a()表示获取一个函数的引用,a()();表示执行获取引用的函数</span></div></div><p style="margin-left: 30px;"><span style="font-size: 15px;">&nbsp;3、重写自己的函数:将一个指向函数的变量指向另一个函数实现重写。</span></p><p style="margin-left: 60px;"><span style="font-size: 15px;">&nbsp;例1:</span></p><p style="margin-left: 90px;"><img src="http://images.cnitblog.com/blog/667906/201410/251719456056929.png" alt="" /></p><p style="margin-left: 60px;"><span style="font-size: 15px;">重写函数常常用于在一个函数执行时必须完成一些初始化工作,这样以后在调用函数就不必重复执行一些不必要的操作。</span></p><p style="margin-left: 60px;"><span style="font-size: 15px;">例2:</span></p><p style="margin-left: 90px;">&nbsp;<img src="http://images.cnitblog.com/blog/667906/201410/251740294493262.png" alt="" />&nbsp;</p><p style="margin-left: 90px;"><span style="font-size: 15px;">结果如下:</span></p><p style="margin-left: 90px;"><img src="http://images.cnitblog.com/blog/667906/201410/252046489966448.png" alt="" /></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;" style="margin-left: 90px;" onclick="cnblogs_code_show('99bf2274-a8df-4196-b543-78bdc561199d')"><div id="cnblogs_code_open_99bf2274-a8df-4196-b543-78bdc561199d" class="cnblogs_code_hide"><span style="color: #008080;">1</span> <span style="color: #0000ff;">var</span> a=<span style="color: #0000ff;">function</span><span style="color: #000000;">()<br/></span><span style="color: #008080;">2</span> <span style="color: #000000;"> {<br/></span><span style="color: #008080;">3</span> <span style="color: #0000ff;">function</span> init(){document.writeln('进行初始化工作&lt;br/&gt;'<span style="color: #000000;">);};<br/></span><span style="color: #008080;">4</span> <span style="color: #0000ff;">function</span> actuall(){ document.writeln('正式进行实际的操作&lt;br/&gt;'<span style="color: #000000;">);};<br/></span><span style="color: #008080;">5</span> init(); <span style="color: #008000;">//</span><span style="color: #008000;">执行初始化工作</span><br/><span style="color: #008080;">6</span> <span style="color: #0000ff;">return</span> actuall; <span style="color: #008000;">//</span><span style="color: #008000;">返回函数引用</span><br/><span style="color: #008080;">7</span> } (); <span style="color: #008000;">//</span><span style="color: #008000;">立即运行,变量 a 指向函数actuall</span></div></div><p style="margin-left: 90px;"><span style="font-size: 15px;">步骤分解如下:</span></p><p style="margin-left: 90px;"><span style="font-size: 15px;">在大函数内包含了两个小函数,其中 init 用于执行初始化函数,而大函数后面带了(),即大函数立即执行,首先执行了init初始化函数,再次将 actuall 函数的引用赋给了变量a,以后再调用 a 时,就只调用&nbsp;actuall 函数,而不再执行 init 函数了。</span></p><p style="margin-left: 90px;">&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4050030" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/SunBlog/p/4050030.html" target="_blank">javascript——对象的概念——函数 3 (使用技巧)</a>,转载请注明。</p>http://www.cnblogs.com/huchaoheng/p/4050951.htmljs filter用法比较 - 胡超讲解一个很实用的JS小语法 filter就是从数组中找到适合条件的元素(比如说大于某一个元素的值)var arr=[1,23,5,78,34,55,13];如何才能找到大于23的所有元素呢,1,下面是传统的解决思路,就是用$.each(),这种用法,先不说这种用法好不好,先看代码:var max23...2014-10-25T13:30:00Z2014-10-25T13:30:00Z胡超http://www.cnblogs.com/huchaoheng/<p>讲解一个很实用的JS小语法 filter</p><p>就是从数组中找到适合条件的元素(比如说大于某一个元素的值)</p><p>var arr=[1,23,5,78,34,55,13];</p><p>如何才能找到大于23的所有元素呢,&nbsp;</p><p>1,下面是传统的解决思路,就是用$.each(),这种用法,先不说这种用法好不好,先看代码:</p><p>var max23=[];</p><p>$.each(arr,function(index,value){if(value&gt;23){ max23.push(value)}});</p><p>然后在console中输入max23 输出值如下:</p><p>&nbsp;<a href="http://drinknet.me/wp-content/uploads/2014/10/QQ截图20141025211032.png"><img class="aligncenter size-full wp-image-210" title="QQ截图20141025211032" src="http://drinknet.me/wp-content/uploads/2014/10/QQ截图20141025211032.png" alt="" width="518" height="99" /></a></p><p>&nbsp;结果一目了然,这种解决方法感觉比较慢如果有个几万个数据再这样一条条查找效率肯定很低,有没有其他的解决办法了呢</p><p>2,下面看一种JS数组的Fliter 这个新属性方法能不能带来质的改变呢</p><p>下面是代码:</p><p>arr.filter(function(element,pos){return element&gt;23})</p><p>在console中运行可以直接看到:</p><p><a href="http://drinknet.me/wp-content/uploads/2014/10/11.png"><img class="aligncenter size-full wp-image-211" title="11" src="http://drinknet.me/wp-content/uploads/2014/10/11.png" alt="" width="422" height="92" /></a></p><p>哈,现在大家看大filter的厉害了吧,主要是filter中的callback 函数直接返回了所有符合条件的函数,下面给大家看个测试的小例子,大家看返回什么值,若果你猜对了,那么filter以后就会用了,</p><div id="file-04-js-LC1">function whatDoesItDo(arr){</div><div id="file-04-js-LC2">&nbsp;</div><div id="file-04-js-LC3">return arr.filter(function(elem, pos) {</div><div id="file-04-js-LC4">return arr.indexOf(elem) == pos;</div><div id="file-04-js-LC5">});</div><div id="file-04-js-LC6">&nbsp;</div><div id="file-04-js-LC7">};</div><div>&nbsp;</div><div>试试效果,js就是这么神奇</div><div>我是Rhino ,欢迎大家加我博客,交流</div><img src="http://counter.cnblogs.com/blog/rss/4050951" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/huchaoheng/p/4050951.html" target="_blank">js filter用法比较</a>,转载请注明。</p>http://www.cnblogs.com/qq809306794/p/4050878.html多线程下HashMap与Hashtable - 笨'小孩最近在多线程环境下操作HashMap,在程序中执行最多的是“查询”,但同时也要维护数据的“添加”和“删除”早在开发前就知道Hashtable是同步的,而HashMap是异步的。好吧在这里承认错误:限于没有犯过这个错误也没有见过实例场景,开发前未做好评估现在说说我的这次需求吧:1、要求新增一个功能页面...2014-10-25T13:04:00Z2014-10-25T13:04:00Z笨'小孩http://www.cnblogs.com/qq809306794/<div class="cnt"><p>最近在多线程环境下操作HashMap,在程序中执行最多的是&ldquo;查询&rdquo;,但同时也要维护数据的&ldquo;添加&rdquo;和&ldquo;删除&rdquo;</p><p>早在开发前就知道Hashtable是同步的,而HashMap是异步的。</p><p>好吧在这里承认错误:限于没有犯过这个错误也没有见过实例场景,开发前未做好评估</p><p>现在说说我的这次需求吧:</p><p>1、要求新增一个功能页面,点击功能按钮弹出页面</p><p>2、页面前后台校验器两个(在这里不做追述)</p><p>3、提交修改后,提交按钮并disabled该按钮,页面特定区域显示动态Loading图标,并要求不影响主功能进程,若关闭弹出页面让其后台继续执行。但执行结果不再展示</p><p>以上是本次需求的大体内容,下面详细说说需求点3使用HashMap出现的场景</p><p>设计思路是这样的:</p><p>1、建立一个静态公有的HashMap</p><p>2、给对象设置一个flag状态:未得到执行结果置为false,得出执行结果置为true</p><p>3、提交页面将页面对象传递到后台,将原可编辑区域全部disabled,以对象Id做HashMap的Key,判断HashMap中是否存在该Key,若存在则将正在执行的提示结果返回,若不存在则将该对象flag值置false添加到HashMap中并创建线程,主线程结束则启动页面定时器</p><p>4、线程任务执行完成后将HashMap中对应的对象flag置为true</p><p>5、通过页面定时器定时执行查询HashMap,若flag为true则将灰显去除,动态Loading图标隐藏,展示执行结果</p><p>6、当我们提交页面后线程任务正在执行,页面仍然Loading状态时关闭页面(关闭页面前停止页面定时查询)</p><p>7、再次打开该页面并重新提交,页面一直处于Loading状态(线程死锁)</p><p>8、当时的规避措施:在每次启动线程前new 一个新对象而不使用当前对象</p><p>今天偶然中看到一篇Hashtable与HashMap的实例文章,让我明白了当时HashMap中判断Key是否存在后才创建线程的想法并没有错误,只是线程中添加、删除需要使用Hashtable</p><p><span style="color: #0000ff;">结论:看来在多线程的环境下,还得用Hashtable,虽说HashMap的性能 能提高一些,但是因为本身是不同步的,所以不能使用在多线程下。当然,如果只是在多线程下进行简单的&ldquo;查询&rdquo;,不对数据进行&ldquo;添加&rdquo;和&ldquo;删除&rdquo;,那用 HashMap是可以的,并且肯定能提高性能的。</span></p><p><strong>下面是我在网上搜索到的别人网友写的一些相关内容:</strong></p><p>1、如果线程要求安全,使用Vector,Hashtable</p><p>2、如果不要求线程安全,应使用ArrayList,LinkedList,HashMap</p><p>3、如果要求键值对,则使用HashMap、Hashtable</p><p>4、如果数据很大,又要线程安全考虑Vector</p><p><br />访问效率最高的是ArrayList,HashTable次之 <br />如果你会进行大量的插入/删除操作,而不是对容器中的元素进行简单的访问,那就该用LinkedList了</p></div><p>在单线程下:vector和hashtable已经被ArrayList和hashMap代替,所以效率是最低的</p><img src="http://counter.cnblogs.com/blog/rss/4050878" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/qq809306794/p/4050878.html" target="_blank">多线程下HashMap与Hashtable</a>,转载请注明。</p>http://www.cnblogs.com/grass-and-moon/p/4050867.html函数----Beginning Visual C# - grass of moon更多相关文章,见本人的个人主页:zhongxiewei.com当函数传递参数通过引用方式传递的时候,语法有所不同// in cppvoid doubleVal(int &val) { // ...}int main() { int val = 20; doubleVal(val);...2014-10-25T12:56:00Z2014-10-25T12:56:00Zgrass of moonhttp://www.cnblogs.com/grass-and-moon/<style><!--table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode { margin: 0; padding: 0; vertical-align: baseline; border: none; }table.sourceCode { width: 100%; }td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }td.sourceCode { padding-left: 5px; }code > span.kw { color: #007020; font-weight: bold; }code > span.dt { color: #902000; }code > span.dv { color: #40a070; }code > span.bn { color: #40a070; }code > span.fl { color: #40a070; }code > span.ch { color: #4070a0; }code > span.st { color: #4070a0; }code > span.co { color: #60a0b0; font-style: italic; }code > span.ot { color: #007020; }code > span.al { color: #ff0000; font-weight: bold; }code > span.fu { color: #06287e; }code > span.er { color: #ff0000; font-weight: bold; }--></style><p><strong><span style="font-size: 15px;">更多相关文章,见本人的个人主页:<a title="zhongxiewei.com" href="http://zhongxiewei.com" target="_blank">zhongxiewei.com</a></span></strong></p><p>当函数传递参数通过引用方式传递的时候,语法有所不同</p><code class="sourceCode cpp"><span class="co">// in cpp</span><br/><span class="dt">void</span> doubleVal(<span class="dt">int</span> &amp;val) {<br/> <span class="co">// ...</span><br/>}<br/><br/><span class="dt">int</span> main() {<br/> <span class="dt">int</span> val = <span class="dv">20</span>;<br/> doubleVal(val);<br/> cout &lt;&lt; val &lt;&lt; endl; <span class="co">// output: 40</span><br/>}</code><code class="sourceCode cs"><span class="co">// in c sharp</span><br/><span class="kw">static</span> <span class="dt">void</span> <span class="fu">doubleVal</span>(<span class="kw">ref</span> <span class="dt">int</span> val) <span class="co">// 使用ref进行标识</span><br/>{<br/> val *= <span class="dv">2</span>; <br/>}<br/><br/><span class="kw">static</span> <span class="dt">void</span> <span class="fu">Main</span>(<span class="dt">string</span>[] args)<br/>{<br/> <span class="dt">int</span> val = <span class="dv">20</span>;<br/> <span class="fu">doubleVal</span>(<span class="kw">ref</span> val);<br/> Console.<span class="fu">WriteLine</span>(val); <span class="co">// output: 40</span><br/>}</code><hr /><p>out 关键字,在c++中没有相似的关键字或用法 out 关键字的使用方式和ref类似,但有两点不同,1)在使用ref参数的时候,传递没有赋值的参数是不合法的。无法通过编译。但是在使用out参数的时候是合法的。2)并且使用out参数的时候,该参数被当作没有赋值的,对该值的调用会发生编译错误。如下:</p><code class="sourceCode cs"><span class="kw">static</span> <span class="dt">void</span> <span class="fu">doubleVal</span>(<span class="kw">out</span> <span class="dt">int</span> val)<br/>{<br/> val *= <span class="dv">2</span>; <span class="co">// 想要使用val中的数值,</span><br/> <span class="co">// 但是val被认为是没有赋值的,因此出现编译错误 </span><br/>}<br/><br/><span class="kw">static</span> <span class="dt">void</span> <span class="fu">Main</span>(<span class="dt">string</span>[] args)<br/>{<br/> <span class="dt">int</span> val=<span class="dv">3</span>;<br/> <span class="fu">doubleVal</span>(<span class="kw">out</span> val);<br/> Console.<span class="fu">WriteLine</span>(val); <span class="co">// output: 40</span><br/>}</code><hr /><p>对于不定量参数输入的关键字为:param,具体实现如下:</p><code class="sourceCode cs"><span class="kw">static</span> <span class="dt">int</span> <span class="fu">sum</span>(param <span class="dt">int</span>[] num) <span class="co">// 这里需要注意的是,param参数必须在参数列表的最后的位置</span><br/>{<br/> <span class="dt">int</span> sumVal = <span class="dv">0</span>;<br/> <span class="kw">foreach</span> (<span class="dt">int</span> n <span class="kw">in</span> num)<br/> {<br/> sum += n;<br/> }<br/> <span class="kw">return</span> sum;<br/>}</code><hr /><p>在c#中对变量作用域的检测更加的严格,比如类似下面的代码能够在c++中编译通过并成功运行,而在c#中则无法通过编译,由于在同一个作用域中调用了没有初始化的变量。</p><code class="sourceCode cs"><span class="dt">string</span> text;<br/><span class="kw">for</span> (<span class="dt">int</span> i=<span class="dv">0</span>; i&lt;<span class="dv">1</span>; i++)<br/>{<br/> text = <span class="st">"hello"</span>;<br/>}<br/>Console.<span class="fu">WriteLine</span>(text); <span class="co">// in cpp: cout &lt;&lt; text &lt;&lt; endl;</span></code><hr /><p>函数重载和c++中的类似,但是由于c#中对于&ldquo;引用&rdquo;,引入了ref关键字,因此,对于引用参数和非引用的参数的函数在c#中也能够重载,这在c++中是不合理的。如:</p><code class="sourceCode cs"><span class="co">// in c#</span><br/><span class="kw">static</span> <span class="dt">void</span> <span class="fu">showDouble</span>(<span class="kw">ref</span> <span class="dt">int</span> val) {}<br/><span class="kw">static</span> <span class="dt">void</span> <span class="fu">showDouble</span>(<span class="dt">int</span> val) {}<br/><br/><span class="co">// in cpp is error</span><br/><span class="dt">void</span> <span class="fu">showDouble</span>(<span class="dt">int</span> &amp;val) {}<br/><span class="dt">void</span> <span class="fu">showDouble</span>(<span class="dt">int</span> val) {}</code><hr /><p>在c#中关于函数,还有<code>delegate</code>关键字,该关键字的含义用来创建一个能够用来表示其他函数的东东。这有点像c中的指针函数。如:</p><code class="sourceCode cs"><span class="co">// in c#</span><br/><span class="kw">delegate</span> <span class="dt">double</span> <span class="fu">processDelegate</span>(<span class="dt">double</span> param1, <span class="dt">double</span> param2);<br/><span class="kw">static</span> <span class="dt">double</span> <span class="fu">Multiply</span>(<span class="dt">double</span> param1, <span class="dt">double</span> param2)<br/>{<br/> <span class="kw">return</span> param1 * param2;<br/>}<br/><br/><span class="kw">static</span> <span class="dt">double</span> <span class="fu">Divide</span>(<span class="dt">double</span> param1, <span class="dt">double</span> param2)<br/>{<br/> <span class="kw">return</span> param1 / param2;<br/>}<br/><br/><span class="kw">static</span> <span class="dt">void</span> <span class="fu">Main</span>(<span class="dt">string</span>[] args)<br/>{<br/> processDelegate process;<br/> process = <span class="kw">new</span> <span class="fu">processDelegate</span>(Multiply);<br/> Console.<span class="fu">WriteLine</span>(<span class="st">"{0}"</span>, <span class="fu">process</span>(<span class="dv">3</span>, <span class="dv">4</span>));<br/> process = <span class="kw">new</span> <span class="fu">processDelegate</span>(Divide);<br/> Console.<span class="fu">WriteLine</span>(<span class="st">"{0}"</span>, <span class="fu">process</span>(<span class="dv">3</span>, <span class="dv">4</span>));<br/>}</code><code class="sourceCode cpp"><span class="co">// in cpp</span><br/><span class="ot">#include &lt;iostream&gt;</span><br/><br/><span class="kw">using</span> <span class="kw">namespace</span> std;<br/><br/><span class="dt">int</span> multi(<span class="dt">int</span> a, <span class="dt">int</span> b) {<br/> <span class="kw">return</span> a * b;<br/>}<br/><br/><span class="dt">int</span> add(<span class="dt">int</span> a, <span class="dt">int</span> b) {<br/> <span class="kw">return</span> a + b;<br/>}<br/><span class="dt">int</span> main() {<br/> <span class="dt">int</span> (*fn)(<span class="dt">int</span>,<span class="dt">int</span>);<br/> <br/> fn = multi;<br/> cout &lt;&lt; <span class="st">"multi "</span> &lt;&lt; fn(<span class="dv">2</span>,<span class="dv">3</span>) &lt;&lt; endl;<br/> fn = add;<br/> cout &lt;&lt; <span class="st">"add "</span> &lt;&lt; add(<span class="dv">2</span>,<span class="dv">3</span>) &lt;&lt; endl;<br/>}</code><img src="http://counter.cnblogs.com/blog/rss/4050867" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/grass-and-moon/p/4050867.html" target="_blank">函数----Beginning Visual C#</a>,转载请注明。</p>http://www.cnblogs.com/smyhvae/p/4050825.htmlMySQL数据库学习笔记(八)----JDBC入门及简单增删改查数据库的操作 - 生命壹号【声明】欢迎转载,但请保留文章原始出处→_→生命壹号:http://www.cnblogs.com/smyhvae/文章来源:http://www.cnblogs.com/smyhvae/p/4050825.html联系方式:smyhvae@163.com【正文】 ...2014-10-25T12:55:00Z2014-10-25T12:55:00Z生命壹号http://www.cnblogs.com/smyhvae/<p>&nbsp;</p><p><strong>【声明】</strong>&nbsp;</p><p>欢迎转载,但请保留文章原始出处&rarr;_&rarr;&nbsp;</p><p>生命壹号:<a href="http://www.cnblogs.com/smyhvae/" target="_blank">http://www.cnblogs.com/smyhvae/</a></p><p>文章来源:<a href="http://www.cnblogs.com/smyhvae/p/4050825.html">http://www.cnblogs.com/smyhvae/p/4050825.html</a></p><p>联系方式:smyhvae@163.com&nbsp;&nbsp;</p><p>&nbsp;</p><p><strong>【正文】</strong><strong><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</strong></strong></p><p><span style="font-size: 18pt; background-color: #008000;"><strong><strong><span style="font-size: 18px;"><span style="color: #ffffff;">一、JDBC的引入&nbsp;</span>&nbsp;</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</strong></strong></span></p><p><span style="font-size: 16px;"><strong>1、JDBC的概念</strong></span></p><p>JDBC:Java Database Connection,表示数据<span style="font-size: 14px;">库连接</span>(任何数据库都支持JDBC的连接),是一个独立于特定数据库管理系统、通用的sql数据库存取和操作的公共接口。它是java中专门提供的一组用于操作数据库的标准,所有的数据库生产商如果要是想为java提供支持,则必须支持此标准。既然是标准的话,所以说<span style="color: #0000ff;"><strong>JDBC实际上是一套访问数据库的接口</strong></span>。</p><p><span style="font-size: 16px;"><strong>2、常用操作类/接口</strong></span></p><p>Connection接口、Statement接口、PreapredStatement接口、ResultSet接口、CallableStatement接口、DriverManager类。</p><p><span style="font-size: 16px;"><strong>3、JDBC应用步骤</strong></span></p><ul><li>1.注册加载一个驱动</li><li>2.创建数据库连接(Connection)</li><li>3.创建statement,发送sql语句</li><li>4.执行sql语句</li><li>5.处理sql结果</li><li>6.关闭statement和connection</li></ul><p>&nbsp;</p><p><span style="font-size: 18px;"><strong>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</strong></span></p><p><span style="color: #ffffff; font-size: 18pt; background-color: #008000;"><strong><span style="font-size: 18px;">二、驱动程序下载:</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</strong></span></p><p>根据上一段的定义,我们明白了,<strong><span style="color: #0000ff;">java定义JDBC接口,数据库来实现这个接口</span>。</strong>不同的厂商对JDBC有不同的实现,所以厂商要提供自己数据库的驱动,让应用程序来访问。而应用程序则只通过自己的一套JDBC接口来访问就行了,然后驱动程序来实现这个接口,从而让驱动来调用数据库。所以我们终于明白了这句话:<span style="color: #0000ff;"><strong>驱动程序由数据库提供商提供下载</strong></span>。</p><p>在Java中,驱动程序是以jar包的形式提供的,MySQL驱动程序的下载地址:<a href="http://dev.mysql.com/downloads/">http://dev.mysql.com/downloads/</a></p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033450907701.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="be475b59-0e1a-4ce9-a806-c3b2b3b0719f" src="http://images.cnitblog.com/blog/641601/201410/252033456528830.png" alt="be475b59-0e1a-4ce9-a806-c3b2b3b0719f" width="758" height="120" border="0" /></a></p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033461218987.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="01bc3198-0a7c-4e3a-b682-0ddecf5639b6" src="http://images.cnitblog.com/blog/641601/201410/252033466211902.png" alt="01bc3198-0a7c-4e3a-b682-0ddecf5639b6" width="992" height="548" border="0" /></a></p><p>上图中,选择&ldquo;Connector/J&rdquo;的版本进行下载,弹出下一个界面,让我们选择平台来下载:如果选择windows平台,界面如下:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033474333786.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="567dacb7-1537-472d-9b92-137ce68deede" src="http://images.cnitblog.com/blog/641601/201410/252033483248114.png" alt="567dacb7-1537-472d-9b92-137ce68deede" width="1110" height="618" border="0" /></a></p><p>如果选择跨平台,界面会变成下面的这个样子:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033490905012.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="9bfcd9a3-a4ee-456f-b3cf-c50e6819da3d" src="http://images.cnitblog.com/blog/641601/201410/252033501216298.png" alt="9bfcd9a3-a4ee-456f-b3cf-c50e6819da3d" width="1145" height="694" border="0" /></a></p><p>上图中,第一个版本是Linux平台的压缩包,第二个是Windows平台中的压缩包,那我们选择上图中的红框部分进行下载:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033508551441.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="796b6f84-526a-40b4-a7b8-1fda0983d1c6" src="http://images.cnitblog.com/blog/641601/201410/252033514331097.png" alt="796b6f84-526a-40b4-a7b8-1fda0983d1c6" width="1005" height="535" border="0" /></a></p><p>上图中,不用注册,直接下载。下载完成后,解压:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033518718497.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="68e84edc-f208-42d5-98de-72fdf568cf7d" src="http://images.cnitblog.com/blog/641601/201410/252033523711412.png" alt="68e84edc-f208-42d5-98de-72fdf568cf7d" width="735" height="313" border="0" /></a></p><p>上图中,红框部分的<span style="color: #0000ff;">mysql-connector-java-5.1.33-bin.jar</span>就是我们所需要的包。</p><p>&nbsp;</p><p><span style="font-size: 18pt; color: #ffffff; background-color: #008000;"><strong><span style="font-size: 18px;">三、JDBC实现简单增删改操作</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</strong></span></p><ul><li>1、JDBC操作前的准备工作</li><li>2、实现插入操作</li><li>3、实现更新操作</li><li>4、实现删除操作</li><li>5、代码优化(写成工具类):将字段换成变量</li></ul><p><span style="color: #0000ff; font-size: 16px;"><strong>1、JDBC操作前的准备工作:</strong></span></p><p><span style="color: #0000ff;">首先创建数据库表</span>:person。字段:id,name,age,description。建表的命令如下:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">TABLE</span><span style="color: #000000;"> person(<br/>id </span><span style="color: #0000ff;">int</span> <span style="color: #0000ff;">primary</span> <span style="color: #0000ff;">key</span><span style="color: #000000;"> auto_increment,<br/>name </span><span style="color: #0000ff;">varchar</span>(<span style="color: #800000; font-weight: bold;">20</span><span style="color: #000000;">),<br/>age </span><span style="color: #0000ff;">int</span>(<span style="color: #800000; font-weight: bold;">2</span><span style="color: #000000;">),<br/>description </span><span style="color: #0000ff;">varchar</span>(<span style="color: #800000; font-weight: bold;">100</span><span style="color: #000000;">)<br/>);</span></div><p>创建的空表如下:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033527935583.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="60645d0c-10b1-49c7-855f-37cf8297ac91" src="http://images.cnitblog.com/blog/641601/201410/252033532462511.png" alt="60645d0c-10b1-49c7-855f-37cf8297ac91" width="642" height="167" border="0" /></a></p><p><strong>紧接着<span style="color: #0000ff;">导入数据库驱动包</span>:</strong></p><p>打开eclipse,新建Java工程JDBC01,然后在根目录下新建一个文件夹libs:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033536686682.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="0060622e-8f67-44bf-92a1-b8210147f4b3" src="http://images.cnitblog.com/blog/641601/201410/252033541688595.png" alt="0060622e-8f67-44bf-92a1-b8210147f4b3" width="525" height="623" border="0" /></a></p><p>然后复制之前下载的驱动包<span style="color: #0000ff;">mysql-connector-java-5.1.33-bin.jar</span>,粘贴到libs目录下,<span style="color: #0000ff;"><strong>然后到了最关键的一步</strong></span>:将该Java包添加到工程的Build path中,操作如下图:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033552936152.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="96965c34-a0e5-4198-8286-0aed4e7bddac" src="http://images.cnitblog.com/blog/641601/201410/252033558249822.png" alt="96965c34-a0e5-4198-8286-0aed4e7bddac" width="796" height="654" border="0" /></a></p><p>如果生效之后,就会多出一个文件出来:(下图中的箭头处)</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033563088507.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="eaacea91-5cb9-4023-993b-e336f5c103fb" src="http://images.cnitblog.com/blog/641601/201410/252033566689165.png" alt="eaacea91-5cb9-4023-993b-e336f5c103fb" width="338" height="172" border="0" /></a></p><p><span style="color: #0000ff; font-size: 16px;"><strong>2、实现插入操作:</strong></span></p><p>步骤如下:</p><ul><li>1、<span style="color: #0000ff;">加载数据库驱动程序</span>:Class.forName(驱动程序类);</li><li>2、<span style="color: #0000ff;">通过用户名密码和连接地址url获取数据库连接对象</span>:Connection connnction = DriverManager.getConnection(连接地址url,用户名,密码)。每个数据库都有指定的url,同一格式如下:<span style="color: #0000ff;">jdbc:mysql://ip地址:端口号/数据库名字</span>。</li><li>3、<span style="color: #0000ff;">构造插入的SQL语句</span>。注:在Java程序当中,<span style="color: #0000ff;">SQL语句是以字符串的形式使用</span>,程序不认识此SQL语句,传到数据库后让数据库来识别。</li><li>4、<span style="color: #0000ff;">Statement实例</span>:Statement stmt = connction.createStatement()。Statement是用来发送SQL语句的载体,因为Java代码无法解析,要交给数据库来解析。</li><li>5、<span style="color: #0000ff;">执行插入SQL语句</span>:stmt.executeUpdate(sql)。这里的执行是发送SQL语句。返回值为int类型,表示有多少条记录被更新了。</li><li>6、<span style="color: #0000ff;">关闭连接</span>:stmt.close()、 connnction.close()。关闭是为了释放资源。</li></ul><p>注:这个步骤是通俗的用法,可以当做模板来用。我们来举个例子。</p><p>在工程文件中新建一个java类,作为主程序:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033571527850.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="821f8625-b677-4617-a8ae-da9d93852d75" src="http://images.cnitblog.com/blog/641601/201410/252033576683993.png" alt="821f8625-b677-4617-a8ae-da9d93852d75" width="573" height="674" border="0" /></a></p><p>JdbcTest.java完整版代码如下:(注释很详细)</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">package</span><span style="color: #000000;"> com.vae.jdbc;<br/></span><span style="color: #008080;"> 2</span> <br/><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.Connection;<br/></span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.DriverManager;<br/></span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.SQLException;<br/></span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.Statement;<br/></span><span style="color: #008080;"> 7</span> <br/><span style="color: #008080;"> 8</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> JdbcTest {<br/></span><span style="color: #008080;"> 9</span> <br/><span style="color: #008080;">10</span> <span style="color: #008000;">/**</span><br/><span style="color: #008080;">11</span> <span style="color: #008000;"> * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> args<br/></span><span style="color: #008080;">12</span> <span style="color: #008000;">*/</span><br/><span style="color: #008080;">13</span> <br/><span style="color: #008080;">14</span> <span style="color: #008000;">//</span><span style="color: #008000;">数据库连接地址</span><br/><span style="color: #008080;">15</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String URL = "jdbc:mysql://localhost:3306/mydb_2"<span style="color: #000000;">;<br/></span><span style="color: #008080;">16</span> <span style="color: #008000;">//</span><span style="color: #008000;">用户名</span><br/><span style="color: #008080;">17</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String USERNAME = "root"<span style="color: #000000;">;<br/></span><span style="color: #008080;">18</span> <span style="color: #008000;">//</span><span style="color: #008000;">密码</span><br/><span style="color: #008080;">19</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String PASSWORD = "smyh"<span style="color: #000000;">;<br/></span><span style="color: #008080;">20</span> <span style="color: #008000;">//</span><span style="color: #008000;">加载的驱动程序类(这个类就在我们导入的jar包中)</span><br/><span style="color: #008080;">21</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String DRIVER = "com.mysql.jdbc.Driver"<span style="color: #000000;">;<br/></span><span style="color: #008080;">22</span> <br/><span style="color: #008080;">23</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {<br/></span><span style="color: #008080;">24</span> <span style="color: #008000;">//</span><span style="color: #008000;"> TODO Auto-generated method stub</span><br/><span style="color: #008080;">25</span> <span style="color: #000000;"> insert();<br/></span><span style="color: #008080;">26</span> <span style="color: #000000;"> } <br/></span><span style="color: #008080;">27</span> <br/><span style="color: #008080;">28</span> <br/><span style="color: #008080;">29</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:插入数据</span><br/><span style="color: #008080;">30</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insert(){<br/></span><span style="color: #008080;">31</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;">32</span> <span style="color: #008000;">//</span><span style="color: #008000;">1、加载数据库驱动程序</span><br/><span style="color: #008080;">33</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;">34</span> <br/><span style="color: #008080;">35</span> <span style="color: #008000;">//</span><span style="color: #008000;">2、获取数据库连接</span><br/><span style="color: #008080;">36</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;">37</span> <br/><span style="color: #008080;">38</span> <span style="color: #008000;">//</span><span style="color: #008000;">3、构造SQL语句(插入具体的数据)</span><br/><span style="color: #008080;">39</span> String sql = "insert into person(name,age,description)values('生命壹号',22,'学到哪里,我的博客就写到哪里')"<span style="color: #000000;">;<br/></span><span style="color: #008080;">40</span> <br/><span style="color: #008080;">41</span> <span style="color: #008000;">//</span><span style="color: #008000;">4、构造一个Statement实例(用来发送SQL语句的载体)</span><br/><span style="color: #008080;">42</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;">43</span> <br/><span style="color: #008080;">44</span> <span style="color: #008000;">//</span><span style="color: #008000;">5、执行SQL语句(其实是想数据库中发送sql语句)</span><br/><span style="color: #008080;">45</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;">46</span> <br/><span style="color: #008080;">47</span> <span style="color: #008000;">//</span><span style="color: #008000;">6、关闭连接(释放资源)</span><br/><span style="color: #008080;">48</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;">49</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;">50</span> <br/><span style="color: #008080;">51</span> System.out.println("insert success"<span style="color: #000000;">);<br/></span><span style="color: #008080;">52</span> <br/><span style="color: #008080;">53</span> <br/><span style="color: #008080;">54</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;">55</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">56</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;">57</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">58</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">59</span> <br/><span style="color: #008080;">60</span> <span style="color: #000000;"> } <br/></span><span style="color: #008080;">61</span> <br/><span style="color: #008080;">62</span> }</div><p><span style="color: #0000ff;">注意程序在导包时,导入的是下面的这些包:</span></p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033588718292.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="59f98e98-25e7-4692-bc00-9eaa3e58c995" src="http://images.cnitblog.com/blog/641601/201410/252033592467477.png" alt="59f98e98-25e7-4692-bc00-9eaa3e58c995" width="319" height="89" border="0" /></a></p><p>代码解释:</p><p>15行的url代表连接接数据库的地址。命名格式统一如下:url = "jdbc:mysql://ip地址:端口号/数据库名字"。如果是本机的话,IP地址可以写成localhost。</p><p>17行、19行:指的是数据库的用户名和密码。如果输入错误,会报错如下:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252033597306162.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="27b8873b-2305-4025-bd10-22f98a66d57c" src="http://images.cnitblog.com/blog/641601/201410/252034002308076.png" alt="27b8873b-2305-4025-bd10-22f98a66d57c" width="917" height="498" border="0" /></a></p><p>21行:我们所加载的驱动程序类的名字是:com.mysql.jdbc.Driver,其实它就指的就是jar包中的com.mysql/jdbc/Driver.class文件。</p><p>程序运行成功后,后台会输出:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252034009494690.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="16bae3e3-831e-4881-9e73-cecebd987187" src="http://images.cnitblog.com/blog/641601/201410/252034015586103.png" alt="16bae3e3-831e-4881-9e73-cecebd987187" width="561" height="87" border="0" /></a></p><p>我们再去数据库看一下,发现数据真的填充进去了:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252034025589931.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border: 0px;" title="1220663a-58dd-44c2-a82e-8e6ff2e63caf" src="http://images.cnitblog.com/blog/641601/201410/252034031212061.png" alt="1220663a-58dd-44c2-a82e-8e6ff2e63caf" width="668" height="222" border="0" /></a></p><p>终于实现了Java代码与数据库之间的联系,任务完成。</p><p><span style="font-size: 16px;"><strong>3、<span style="color: #0000ff;">实现更新操作</span>:</strong></span></p><p>和上面的插入操作相比,<span style="color: #0000ff;">只是sql语句不一样而已</span>(因为插入数据和更新数据其实都是更新嘛)</p><p>步骤如下:</p><p>更新操作的方法如下:(代码解释请参照上面的代码就懂了)</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:更新数据</span><br/><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> update(){<br/></span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 4</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;"> 5</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;"> 6</span> String sql = "update person set age=24 where id=1"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 7</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;"> 8</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;"> 9</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;">10</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;">11</span> System.out.println("update success"<span style="color: #000000;">);<br/></span><span style="color: #008080;">12</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;">13</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">14</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;">15</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">16</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">17</span> }</div><p>核心代码是第6行,我们将之前的22岁改为24岁。程序运行后,数据库里也会对应的进行更新。</p><p><span style="font-size: 16px;"><strong>4、<span style="color: #0000ff;">实现删除操作</span></strong></span></p><p>同样的道理,和上面的插入操作相比<span style="color: #0000ff;">,只是sql语句不一样而已</span>(因为插入数据、更新数据、删除数据其实都是更新嘛)</p><p>删除操作的方法如下:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:删除操作</span><br/><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> delete(){<br/></span><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 4</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;"> 5</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;"> 6</span> String sql = "delete from person where id=1"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 7</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;"> 8</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;"> 9</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;">10</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;">11</span> System.out.println("delete success"<span style="color: #000000;">);<br/></span><span style="color: #008080;">12</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;">13</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">14</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;">15</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">16</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">17</span> }</div><p>核心代码是第06行和第08行。</p><p><span style="font-size: 16px;"><strong>5、</strong><span style="color: #0000ff;"><strong>代码优化(写成工具类</strong>):将字段换成变量</span></span></p><p>我们上面的增删该的操作都是直接在sql里面放入具体的参数,但是有可能这种参数是外面传进来的,所以<span style="color: #0000ff;">一种更方便的写法是把参数换成变量</span>,我们以插入操作为例:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:插入数据(代码优化)</span><br/><span style="color: #008080;"> 2</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insert2(){<br/></span><span style="color: #008080;"> 3</span> String name = "生命贰号"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">int</span> age = 22<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 5</span> String description = "哈哈,我是优化之后的代码哦"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 7</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;"> 8</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;"> 9</span> <span style="color: #008000;">//</span><span style="color: #008000;">拼接SQL语句</span><br/><strong><span style="color: #008080;">10</span> String sql = "insert into person(name,age,description)values('"+name+"',"+age+",'"+description+"')"; <span style="color: #008000;">//</span><span style="color: #008000;">注意拼接的格式</span></strong><br/><span style="color: #008080;">11</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;">12</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;">13</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;">14</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;">15</span> System.out.println("success."<span style="color: #000000;">);<br/></span><span style="color: #008080;">16</span> <br/><span style="color: #008080;">17</span> <br/><span style="color: #008080;">18</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;">19</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">20</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;">21</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">22</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">23</span> <br/><span style="color: #008080;">24</span> }</div><p>核心代码是第10行,这里的sql语句是以变量的形式出现的,符合工具类的特性,<span style="color: #0000ff;"><strong>注意它拼接的格式</strong></span>哦~~~来把它拆开再仔细瞧一瞧:</p><p>String sql = "insert into person(name,age,description)values(' <span style="color: #0000ff;">"+name+"</span> ',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="color: #0000ff;">"+age+"</span>,&nbsp;&nbsp;&nbsp; '&nbsp; <span style="color: #0000ff;">"+description+"</span>&nbsp; ')";</p><p>运行之后,效果如下:</p><p><a href="http://images.cnitblog.com/blog/641601/201410/252034036059745.png"><img style="background-image: none; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border: 0px;" title="97f4bb25-e4b6-460a-94bb-26350c8a73ea" src="http://images.cnitblog.com/blog/641601/201410/252034039963160.png" alt="97f4bb25-e4b6-460a-94bb-26350c8a73ea" width="647" height="183" border="0" /></a></p><p><strong>其实这种拼接的方式很不好:<span style="color: #0000ff;">既麻烦又不安全</span></strong>。详细解释将在下篇文章中学习到,加油!!!</p><p>哦,对了,最后再贴一下上方所有代码的完整版:</p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="color: #008080;"> 1</span> <span style="color: #0000ff;">package</span><span style="color: #000000;"> com.vae.jdbc;<br/></span><span style="color: #008080;"> 2</span> <br/><span style="color: #008080;"> 3</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.Connection;<br/></span><span style="color: #008080;"> 4</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.DriverManager;<br/></span><span style="color: #008080;"> 5</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.SQLException;<br/></span><span style="color: #008080;"> 6</span> <span style="color: #0000ff;">import</span><span style="color: #000000;"> java.sql.Statement;<br/></span><span style="color: #008080;"> 7</span> <br/><span style="color: #008080;"> 8</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">class</span><span style="color: #000000;"> JdbcTest {<br/></span><span style="color: #008080;"> 9</span> <br/><span style="color: #008080;"> 10</span> <span style="color: #008000;">/**</span><br/><span style="color: #008080;"> 11</span> <span style="color: #008000;"> * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> args<br/></span><span style="color: #008080;"> 12</span> <span style="color: #008000;">*/</span><br/><span style="color: #008080;"> 13</span> <br/><span style="color: #008080;"> 14</span> <span style="color: #008000;">//</span><span style="color: #008000;">数据库连接地址</span><br/><span style="color: #008080;"> 15</span> <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String URL = "jdbc:mysql://localhost:3306/mydb_2"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 16</span> <span style="color: #008000;">//</span><span style="color: #008000;">用户名</span><br/><span style="color: #008080;"> 17</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String USERNAME = "root"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 18</span> <span style="color: #008000;">//</span><span style="color: #008000;">密码</span><br/><span style="color: #008080;"> 19</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String PASSWORD = "smyh"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 20</span> <span style="color: #008000;">//</span><span style="color: #008000;">加载的驱动程序类(这个类就在我们导入的jar包中)</span><br/><span style="color: #008080;"> 21</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">final</span> <span style="color: #0000ff;">static</span> String DRIVER = "com.mysql.jdbc.Driver"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 22</span> <br/><span style="color: #008080;"> 23</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {<br/></span><span style="color: #008080;"> 24</span> <span style="color: #008000;">//</span><span style="color: #008000;"> TODO Auto-generated method stub</span><br/><span style="color: #008080;"> 25</span> <span style="color: #000000;"> insert();<br/></span><span style="color: #008080;"> 26</span> <span style="color: #008000;">//</span><span style="color: #008000;">update();<br/></span><span style="color: #008080;"> 27</span> <span style="color: #008000;">//</span><span style="color: #008000;">delete();<br/></span><span style="color: #008080;"> 28</span> <span style="color: #008000;">//</span><span style="color: #008000;">insert2();</span><br/><span style="color: #008080;"> 29</span> <span style="color: #000000;"> } <br/></span><span style="color: #008080;"> 30</span> <br/><span style="color: #008080;"> 31</span> <br/><span style="color: #008080;"> 32</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:插入数据</span><br/><span style="color: #008080;"> 33</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insert(){<br/></span><span style="color: #008080;"> 34</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 35</span> <span style="color: #008000;">//</span><span style="color: #008000;">1、加载数据库驱动程序</span><br/><span style="color: #008080;"> 36</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;"> 37</span> <br/><span style="color: #008080;"> 38</span> <span style="color: #008000;">//</span><span style="color: #008000;">2、获取数据库连接</span><br/><span style="color: #008080;"> 39</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;"> 40</span> <br/><span style="color: #008080;"> 41</span> <span style="color: #008000;">//</span><span style="color: #008000;">3、构造SQL语句(插入具体的数据)</span><br/><span style="color: #008080;"> 42</span> String sql = "insert into person(name,age,description)values('生命壹号',22,'学到哪里,我的博客就写到哪里')"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 43</span> <br/><span style="color: #008080;"> 44</span> <span style="color: #008000;">//</span><span style="color: #008000;">4、构造一个Statement实例(用来发送SQL语句的载体)</span><br/><span style="color: #008080;"> 45</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;"> 46</span> <br/><span style="color: #008080;"> 47</span> <span style="color: #008000;">//</span><span style="color: #008000;">5、执行SQL语句(其实是想数据库中发送sql语句)</span><br/><span style="color: #008080;"> 48</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;"> 49</span> <br/><span style="color: #008080;"> 50</span> <span style="color: #008000;">//</span><span style="color: #008000;">6、关闭连接(释放资源)</span><br/><span style="color: #008080;"> 51</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;"> 52</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;"> 53</span> <br/><span style="color: #008080;"> 54</span> System.out.println("insert success"<span style="color: #000000;">);<br/></span><span style="color: #008080;"> 55</span> <br/><span style="color: #008080;"> 56</span> <br/><span style="color: #008080;"> 57</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;"> 58</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;"> 59</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;"> 60</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;"> 61</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 62</span> <br/><span style="color: #008080;"> 63</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 64</span> <br/><span style="color: #008080;"> 65</span> <br/><span style="color: #008080;"> 66</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:插入数据(代码优化)</span><br/><span style="color: #008080;"> 67</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> insert2(){<br/></span><span style="color: #008080;"> 68</span> String name = "生命贰号"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 69</span> <span style="color: #0000ff;">int</span> age = 22<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 70</span> String description = "哈哈,我是优化之后的代码哦"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 71</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 72</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;"> 73</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;"> 74</span> <span style="color: #008000;">//</span><span style="color: #008000;">拼接SQL语句</span><br/><span style="color: #008080;"> 75</span> String sql = "insert into person(name,age,description)values('"+name+"',"+age+",'"+description+"')"; <span style="color: #008000;">//</span><span style="color: #008000;">注意拼接的格式</span><br/><span style="color: #008080;"> 76</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;"> 77</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;"> 78</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;"> 79</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;"> 80</span> System.out.println("success."<span style="color: #000000;">);<br/></span><span style="color: #008080;"> 81</span> <br/><span style="color: #008080;"> 82</span> <br/><span style="color: #008080;"> 83</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;"> 84</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;"> 85</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;"> 86</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;"> 87</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 88</span> <br/><span style="color: #008080;"> 89</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;"> 90</span> <br/><span style="color: #008080;"> 91</span> <br/><span style="color: #008080;"> 92</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:更新数据</span><br/><span style="color: #008080;"> 93</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> update(){<br/></span><span style="color: #008080;"> 94</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;"> 95</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;"> 96</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;"> 97</span> String sql = "update person set age=24 where id=1"<span style="color: #000000;">;<br/></span><span style="color: #008080;"> 98</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;"> 99</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;">100</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;">101</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;">102</span> System.out.println("update success"<span style="color: #000000;">);<br/></span><span style="color: #008080;">103</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;">104</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">105</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;">106</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">107</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">108</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">109</span> <br/><span style="color: #008080;">110</span> <br/><span style="color: #008080;">111</span> <span style="color: #008000;">//</span><span style="color: #008000;">方法:删除操作</span><br/><span style="color: #008080;">112</span> <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> delete(){<br/></span><span style="color: #008080;">113</span> <span style="color: #0000ff;">try</span><span style="color: #000000;"> {<br/></span><span style="color: #008080;">114</span> <span style="color: #000000;"> Class.forName(DRIVER);<br/></span><span style="color: #008080;">115</span> Connection connection =<span style="color: #000000;"> DriverManager.getConnection(URL, USERNAME, PASSWORD);<br/></span><span style="color: #008080;">116</span> String sql = "delete from person where id=1"<span style="color: #000000;">;<br/></span><span style="color: #008080;">117</span> Statement state =<span style="color: #000000;"> connection.createStatement();<br/></span><span style="color: #008080;">118</span> <span style="color: #000000;"> state.executeUpdate(sql);<br/></span><span style="color: #008080;">119</span> <span style="color: #000000;"> state.close();<br/></span><span style="color: #008080;">120</span> <span style="color: #000000;"> connection.close();<br/></span><span style="color: #008080;">121</span> System.out.println("delete success"<span style="color: #000000;">);<br/></span><span style="color: #008080;">122</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (ClassNotFoundException e) {<br/></span><span style="color: #008080;">123</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">124</span> } <span style="color: #0000ff;">catch</span><span style="color: #000000;"> (SQLException e) {<br/></span><span style="color: #008080;">125</span> <span style="color: #000000;"> e.printStackTrace();<br/></span><span style="color: #008080;">126</span> <span style="color: #000000;"> }<br/></span><span style="color: #008080;">127</span> <span style="color: #000000;"> } <br/></span><span style="color: #008080;">128</span> <br/><span style="color: #008080;">129</span> }</div><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4050825" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/smyhvae/p/4050825.html" target="_blank">MySQL数据库学习笔记(八)----JDBC入门及简单增删改查数据库的操作</a>,转载请注明。</p>http://www.cnblogs.com/anka9080/p/winloginpojie.html『电脑技巧』破解Win7/Win8登录密码 - Anka9080Pic via baidu 0x 00 破解思路 用户的明文密码经过单向Hash加密生成Hash散列,Hash散列又被加密存放在系统盘\Windiws\System32\config文件下 要获得明文就要先得到SAM文件,从中提取出hash散列,然后网上查询或者暴力破...2014-10-25T12:47:00Z2014-10-25T12:47:00ZAnka9080http://www.cnblogs.com/anka9080/<p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    <img src="http://images.cnitblog.com/blog/671902/201410/251855363714539.jpg" alt="" width="784" height="451" /></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">     Pic via baidu</span></p><p><span style="font-size: 15px;">&nbsp;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;"> <span style="color: #008000;"><strong> 0x 00 破解思路</strong></span></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    用户的明文密码经过单向Hash加密生成Hash散列,Hash散列又被加密存放在系统盘\Windiws\System32\config文件下</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    要获得明文就要先得到SAM文件,从中提取出hash散列,然后网上查询或者暴力破解获得明文密码</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    SAM文件的获取可分为两种方法:</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">      1)直接从本机操作系统获取;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">      2) 利用安装了Linux(或是WinPE)的U盘获取;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    获得SAM文件以后可以很简单的提取到用户的hash散列,然后就是破解部分了</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    直接上hash破解网站,让网站解密,简单粗暴,不过需要Money~</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    也可以在本机暴力破解,因为单项加密的不可逆性</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    破解过程实际上是一堆字母组合做hash加密,得到的结果与密文做对比</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    并不是真正的破解,还好计算机有强大的计算能力 = =!</span></p><p><span style="font-size: 15px;"><strong><span style="font-family: 'comic sans ms', sans-serif; color: #008000;">  0x 01 破解测试</span></strong></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    环境&gt;&gt;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    被破解主机:win 7 旗舰版 64位</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    工具:&nbsp;bkhive(生成bootkey文件 用于提取hash散列) </span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">       &nbsp; &nbsp;samdump2 (提取hash工具)</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">       &nbsp; &nbsp;john (暴力破解hash得明文)</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">       上面三个工具都已经集成在U盘(kali)中</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    由于亲测Win8和 Win7 的加密算法一样,加密文件存放位置也是相同的 这里就演示Win7下的</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    <strong>1、 生成被破解账户</strong></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    Win7 CMD下,创建两个待破解用户</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    </span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="font-size: 15px;">net user Frank 1t2e3n /<span style="color: #000000;">add<br/>net user Alice xy4567 </span>/add</span></div><p><span style="font-size: 15px;">&nbsp;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    <strong>2、 提取SAM文件</strong></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    将本机设置为U盘启动,插上U盘,进入kali</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    打开我的电脑,点击Win7的系统盘图标,这时候kali已经把Win7系统盘(Win7OS)挂载到</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    /media下,把/media/Win7OS/Windows/System32/config/下的SAM文件和SYSTEM文件复制出来</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    注意大小写~ </span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">cp /media/Win7OS/Windows/System32/config/SAM /tmp/<span style="color: #000000;">SAM<br/>cp </span>/media/Win7OS/Windows/System32/config/SYSTEM /tmp/SYSTEM<br /></span></div><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    </span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    <strong>3、 提取hash散列</strong></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    先用bkhive从SYSTEM文件生成一个bootkey文件</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    再使用samdump2工具从SAM文件和bootkey中提取出hash散列</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;"><span style="color: #008000;">/*</span><span style="color: #008000;"> 在/tmp目录下执行 </span><span style="color: #008000;">*/</span><span style="color: #000000;"><br/>bkhive SYSTEM bootkey<br/>samdump2 bootkey SAM </span>&gt; hashes.txt</span></div><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    hash散列就被保存在/tmp/hashes.txt中,格式如下:</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    <img src="http://images.cnitblog.com/blog/671902/201410/252010458084913.png" alt="" /></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    现在windows的大多数操作系统已经使用NTLMv2加密方式,所以得到的LM散列一般没什么用(空字符加密的结果)</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    上面的NTLM字符串就是我们想要得到的hash散列</span></p><p><span style="font-size: 15px;">&nbsp;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">  <strong>0x 04 破解hash</strong></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    如果原先明文密码长度在6位以内我们可以使用John the Ripper这款工具进行爆破,很简单的</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    在本机测试的结果是不到一小时所有的6位长度的密码都可以破解成功</span></p><div style="background-color: #F5F5F5;border: 1px solid #CCCCCC;padding:10px;"><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;"><span style="color: #008000;">/*</span><span style="color: #008000;"> 在tmp目录下执行 </span><span style="color: #008000;">*/</span><span style="color: #000000;"><br/>john hashes.txt </span>--format=nt2 <span style="color: #008000;">//</span><span style="color: #008000;"> nt2 表示使用NTLMv2破解方式</span></span></div><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    然后就可以喝茶去了,让他自己跑呗(其实我去睡午觉了我会乱说~)</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    在然后就没了,看截图</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    <img src="http://images.cnitblog.com/blog/671902/201410/252021369188030.png" alt="" /></span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    Frank 和 Alice的 password 已经出来~ &nbsp;&nbsp;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    大致的算了一下 john 破解NTMLv2的速度大致一秒钟100多万条吧</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    所以说 跑个一个小时也没有结果建议网上解密,<a href="http://www.cmd5.com" target="_blank">cmd5</a> 就是不错的网站</span></p><p><span style="font-size: 15px;">&nbsp;</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">  上面倒腾了一大堆,看着也够麻烦的,要是你瞟到了这里说明你赚了 &nbsp; :)</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    如果正常进入本机的话可以直接提取hash的,神器<strong>PwDump7</strong>在这,直接运行.exe就可以,地址贴在后面</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    如果拿到SYSTEM和SAM文件,在Windows下也有获取hash的工具 <strong>SAMInside</strong>,导入文件即可</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    如果进不了也可以在CMD模式下COPY文件到U盘然后,取出hash破解</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    当然,在这篇文件里写的都是破解登录密码,而非清除(重置)</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    因为清除重置什么的和砸破窗户跳进去有什么区别呢 :)</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">    </span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">工具下载:</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">  PwDump7   百度网盘&nbsp;&nbsp;http://pan.baidu.com/s/1D7jUu 密码: 91ud</span></p><p><span style="font-family: 'comic sans ms', sans-serif; font-size: 15px;">  SANInside  &nbsp;百度网盘&nbsp;&nbsp;http://pan.baidu.com/s/1kT9RcjX 密码: bb1s</span></p><p><span style="font-size: 15px;">&nbsp;</span></p><p>&nbsp;</p><img src="http://counter.cnblogs.com/blog/rss/4050850" width="1" height="1" alt=""/><br/><p>本文链接:<a href="http://www.cnblogs.com/anka9080/p/winloginpojie.html" target="_blank">『电脑技巧』破解Win7/Win8登录密码</a>,转载请注明。</p>

高级...
微信扫一扫
关注无线梦工厂
返回主页 手机网推广 加入Timewe 关于我们 加入收藏

触屏版,3G,Wap,手机网站,浏览器,pc版,在线,嵌入式,Wap浏览器,电脑上的Wap浏览器 各主流搜索引擎收录Timewe
(R)2009-2019 Timewe 时维网络科技
简体/繁体