<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Mvc on ZRJ | 学习笔记</title>
        <link>https://blog.zrj.me/tags/mvc/</link>
        <description>Recent content in Mvc on ZRJ | 学习笔记</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-CN</language>
        <lastBuildDate>Wed, 17 Feb 2016 22:24:04 +0800</lastBuildDate><atom:link href="https://blog.zrj.me/tags/mvc/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>spring mvc 的 controller 函数的参数</title>
        <link>https://blog.zrj.me/posts/2016-02-17-spring-mvc-%E7%9A%84-controller-%E5%87%BD%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0/</link>
        <pubDate>Wed, 17 Feb 2016 22:24:04 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2016-02-17-spring-mvc-%E7%9A%84-controller-%E5%87%BD%E6%95%B0%E7%9A%84%E5%8F%82%E6%95%B0/</guid>
        <description>&lt;p&gt;学习 spring mvc 的过程中，发现他的 controller 的函数的入参很是神奇，变化多端，捉摸不定，查了一下，这里有说：&lt;a class=&#34;link&#34; href=&#34;http://stackoverflow.com/questions/8372957/how-does-spring-mvc-controller-method-parameter-work&#34;  title=&#34;http://stackoverflow.com/questions/8372957/how-does-spring-mvc-controller-method-parameter-work&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://stackoverflow.com/questions/8372957/how-does-spring-mvc-controller-method-parameter-work&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The general answer is &amp;ldquo;Spring magic&amp;rdquo;; however, &amp;ldquo;Supported handler method arguments and return types&amp;rdquo; in the MVC chapter of the Spring reference guide has the exact answers to your questions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;在这里 &lt;a class=&#34;link&#34; href=&#34;http://stackoverflow.com/questions/12696222/spring-mvc-controller-method-signatures&#34;  title=&#34;http://stackoverflow.com/questions/12696222/spring-mvc-controller-method-signatures&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://stackoverflow.com/questions/12696222/spring-mvc-controller-method-signatures&lt;/a&gt; 和这里 &lt;a class=&#34;link&#34; href=&#34;http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-arguments&#34;  title=&#34;http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-arguments&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-arguments&lt;/a&gt; 可以看到更详细的说明&lt;/p&gt;
</description>
        </item>
        <item>
        <title>从点击到呈现 — 详解一次HTTP请求（3）</title>
        <link>https://blog.zrj.me/posts/2012-09-30-%E4%BB%8E%E7%82%B9%E5%87%BB%E5%88%B0%E5%91%88%E7%8E%B0-%E8%AF%A6%E8%A7%A3%E4%B8%80%E6%AC%A1http%E8%AF%B7%E6%B1%823/</link>
        <pubDate>Sun, 30 Sep 2012 23:15:53 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2012-09-30-%E4%BB%8E%E7%82%B9%E5%87%BB%E5%88%B0%E5%91%88%E7%8E%B0-%E8%AF%A6%E8%A7%A3%E4%B8%80%E6%AC%A1http%E8%AF%B7%E6%B1%823/</guid>
        <description>&lt;p&gt;请求进入服务器之后，服务器上的的 http 监听进程会得到这个请求，然后一般情况下会启动一个新的子进程去处理这个请求，同时父进程继续监听。http 服务器首先会查看重写规则，然后如果是文件真实存在，例如一些图片，或者 css js 等的静态文件，就会直接把这个文件返回，如果是一个动态的请求，那么会根据 url 重写模块的规则，把这个请求重写到一个 rest 风格的 url 上，然后根据动态语言的脚本，来决定调用什么类型的动态文件脚本解释器来处理这个请求。&lt;/p&gt;
&lt;p&gt;我们以 php 语言为例来说的话，请求到达一个 php 的 mvc 框架之后，框架首先应该会初始化一些环境的参数，例如远端 ip，请求参数等等，然后根据请求的 url 送到一个路由器类里面去匹配路由，路由由上到下逐条匹配，一旦遇到 url 能够匹配的上，而且请求的方法也能够命中的话，那么请求就会由这个路由所定义的处理方法去处理。&lt;/p&gt;
&lt;p&gt;请求进入处理函数之后，如果客户端所请求需要浏览的内容是一个动态的内容，那么处理函数会相应的从数据源里面取出数据，这个地方一般会有一个缓存，例如 memcached 来减小 db 的压力，如果引入了 orm 框架的话，那么处理函数直接向 orm 框架索要数据就可以了，由 orm 框架来决定是使用内存里面的缓存还是从 db 去取数据，一般缓存都会有一个过期的时间，而 orm 框架也会在取到数据回来之后，把数据存一份在内存缓存中的。&lt;/p&gt;
&lt;p&gt;orm 框架负责把面向对象的请求翻译成标准的 sql 语句，然后送到后端的 db 去执行，db 这里以 mysql 为例的话，那么一条 sql 进来之后，db 本身也是有缓存的，不过 db 的缓存一般是用 sql 语言 hash 来存取的，也就是说，想要缓存能够命中，除了查询的字段和方法要一样以外，查询的参数也要完全一模一样才能够使用 db 本身的查询缓存，sql 经过查询缓存器，然后就会到达查询分析器，在这里，db 会根据被搜索的数据表的索引建立情况，和 sql 语言本身的特点，来决定使用哪一个字段的索引，值得一提的是，即使一个数据表同时在多个字段建立了索引，但是对于一条 sql 语句来说，还是只能使用一个索引，所以这里就需要分析使用哪个索引效率最高了，一般来说，sql 优化在这个点上也是很重要的一个方面。&lt;/p&gt;
&lt;p&gt;sql 由 db 返回结果集后，再由 orm 框架把结果转换成模型对象，然后由 orm 框架进行一些逻辑处理，把准备好的数据，送到视图层的渲染引擎去渲染，渲染引擎负责模板的管理，字段的友好显示，也包括负责一些多国语言之类的任务。对于一条请求在 mvc 中的生命周期，可以参考这里，&lt;a class=&#34;link&#34; href=&#34;http://zrj.me/archives/404&#34;  title=&#34;临摹了一个 PHP MVC 框架&#34;
     target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;临摹了一个 PHP MVC 框架&lt;/a&gt;，在视图层把页面准备好后，再从动态脚本解释器送回到 http 服务器，由 http 服务器把这些正文加上一个响应头，封装成一个标准的 http 响应包，再通过 tcp ip 协议，送回到客户机浏览器。&lt;/p&gt;
</description>
        </item>
        <item>
        <title>临摹了一个 PHP MVC 框架</title>
        <link>https://blog.zrj.me/posts/2012-08-31-%E4%B8%B4%E6%91%B9%E4%BA%86%E4%B8%80%E4%B8%AA-php-mvc-%E6%A1%86%E6%9E%B6/</link>
        <pubDate>Fri, 31 Aug 2012 13:29:24 +0800</pubDate>
        
        <guid>https://blog.zrj.me/posts/2012-08-31-%E4%B8%B4%E6%91%B9%E4%BA%86%E4%B8%80%E4%B8%AA-php-mvc-%E6%A1%86%E6%9E%B6/</guid>
        <description>&lt;p&gt;框架是 slim，&lt;a class=&#34;link&#34; href=&#34;https://github.com/codeguy/Slim&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/codeguy/Slim&lt;/a&gt;，人如其名，真的很 slim，用起来也很简单，就这么几行就可以跑起来了&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;require&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Slim/Slim.php&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Slim&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;/:name&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;需要配合这个 apache 重写规则&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;RewriteEngine On

# Some hosts may require you to use the `RewriteBase` directive.
# If you need to use the `RewriteBase` directive, it should be the
# absolute physical path to the directory that contains this htaccess file.
#
# RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;运行效果如图&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;http://zrj.me/wp-content/uploads/2012/08/Unnamed-QQ-Screenshot20120831125336.png&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://blog.zrj.me/images/Unnamed-QQ-Screenshot20120831125336.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;跟着源码临摹了一个，现在已经可以跑上面那个例程了，临摹的方法就是顺着函数调用栈，用到哪个就去抄哪个函数过来，呵呵，这么搞现在应该是最简的能跑的了吧&lt;/p&gt;
&lt;p&gt;附上现在源码 &lt;a class=&#34;link&#34; href=&#34;http://zrj.me/wp-content/uploads/2012/08/slim2.zip&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;slim2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;调用也是一样的&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-php&#34; data-lang=&#34;php&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;?&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;php&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;require&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Slim2/Slim2.php&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$app&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Slim2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;get&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;/:name&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;	&lt;span class=&#34;k&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Hello, &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;$name&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;});&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$app&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;运行效果也是一样的&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;http://zrj.me/wp-content/uploads/2012/08/Unnamed-QQ-Screenshot20120831125201.png&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;&lt;img src=&#34;https://blog.zrj.me/images/Unnamed-QQ-Screenshot20120831125201.png&#34;
	
	
	
	loading=&#34;lazy&#34;
	
	
&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;现在只是实现了最简的&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一个环境资源类&lt;/li&gt;
&lt;li&gt;一个封装了请求的类&lt;/li&gt;
&lt;li&gt;一个路由器类&lt;/li&gt;
&lt;li&gt;一个路由规则类&lt;/li&gt;
&lt;li&gt;还有把他们结合在一起的核心类&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;目前没有实现中间件&lt;/p&gt;
&lt;p&gt;在这个框架中，一次请求其实这么来实现的&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;请求从 index.php 这个统一入口进来&lt;/li&gt;
&lt;li&gt;index.php 构造一个 slim 的实例对象&lt;/li&gt;
&lt;li&gt;slim 对象在初始化的时候构造运行环境类（environment），还有请求类（request），以及一个回应类（response），和一个路由器类（router）&lt;/li&gt;
&lt;li&gt;环境类顾名思义负责收集和整合运行环境的信息，包括请求方法，远端 IP，请求路径，运行的服务器名，服务器端口等等&lt;/li&gt;
&lt;li&gt;请求类其实跟环境的内容有稍稍重复，不过他更是明确职责一些，封装的内容也就是请求方法，请求路径等&lt;/li&gt;
&lt;li&gt;回应类主要负责响应的 http header，还有 set get cookie，还有就是响应正文了&lt;/li&gt;
&lt;li&gt;路由器类管理众多的路由规则，每个路由规则对应一个路由类的实例，同时负责匹配路由的选取（是选取，他不负责具体的匹配计算，匹配计算由每个路由类的实例自己完成）&lt;/li&gt;
&lt;li&gt;路由类负责解析请求的字符串，把他们正则匹配解析到变量中，以备响应函数的使用&lt;/li&gt;
&lt;li&gt;然后就是总揽全局的调用类了，（虽然我没有实现中间件类，但是这个框架却把自己这个调用者本身也当作一个中间件），这个总管的 call 函数负责把请求送到路由器中，让他去求得命中的路由，然后调用该路由的 callable 函数，然后送到响应类去输出&lt;/li&gt;
&lt;li&gt;后面应该还要实现一些模版，渲染引擎之类的东西，现在还没做&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;=============================================================&lt;/p&gt;
&lt;p&gt;2012-08-31 15:26:59 update 发现了框架作者自己写的一篇文章讲一个请求的生命周期的，比我这清晰多了，&lt;a class=&#34;link&#34; href=&#34;http://www.slimframework.com/read/slim-framework-application-lifecycle&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://www.slimframework.com/read/slim-framework-application-lifecycle&lt;/a&gt;，另外买一送一附送一篇，&lt;a class=&#34;link&#34; href=&#34;http://www.slimframework.com/read/how-to-organize-a-large-slim-framework-application&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;http://www.slimframework.com/read/how-to-organize-a-large-slim-framework-application&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;历史评论&#34;&gt;历史评论
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;从点击到呈现 — 详解一次HTTP请求（3） | ZRJ&lt;/strong&gt; (2012-10-05 08:29:55):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[&amp;hellip;] mvc 中的生命周期，可以参考这里，临摹了一个 PHP MVC 框架，在视图层把页面准备好后，再从动态脚本解释器送回到 http 服务器，由 [&amp;hellip;]&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        </item>
        
    </channel>
</rss>
