分类 Web后端 下的文章

粗浅了解了一下Velocity模板引擎的原理

今天阅读了一篇文章,关于Velocity模板引擎原理的,很有收获,所以简单的概括一下。

其实,一直在思考Velocity这种模板引擎和JSP的区别,今天才恍然大悟。
其实Velocity可以称得上是半个语言了,所有的Velocity模板都会被分解成语法抽象树(AST)。如果对语法抽象树没有概念的话,可以了解一下《自制编程语言》一书(其实我也没有看过这本书)。
但是如何将Java的Context和Velocity最后分解出的语法抽象树匹配起来,这个才是问题所在。

这边可以对照一下JSP,JSP作为纯正的Java,自然不用担心变量的匹配的问题,所有通过Request的Attributes转发到JSP的对象都可以恢复原来格式的对象来调用。
但是Velocity中分解出的语法抽象树却需要通过反射等功能来获取Java变量的值,替换语法抽象树中的节点。

Servelt如何判断用户首次访问站点是否需要进行URL重写?

看到《Head First Servlet&JSP》的URL重写的时候,对这边就有疑问了。

Servlet如何判断客户端不支持Cookie而进行URL重写呢?毕竟用户的第一次访问站点都是不可能带Cookie的,那么如何判断这个是用户首次访问站点还是因为用户的浏览器不支持Cookie?

然后,找到了一篇文章:http://dk05408.iteye.com/blog/2103257,发现这个问题Servlet处理的太简单了。简单的来说,就是不处理,所有的用户第一次访问站点的情况都当成不支持Cookie处理,进行URL重写。等到下次访问的时候,就能正确判断支持不支持Cookie了。

这样的话,那么Servlet就会对每一个不支持Cookie的请求都会尝试设置Cookie,这也是一种没办法的办法。

SlimPHP框架运行原理

SlimPHP主要有两个大的部分,路由(Router)部分和中间件(Middleware)部分。
首先,我们需要了解的是路由部分。
其实路由部分没什么难度,Route对象主要存储的是来自map()方法的内容。
Router是一个控制器,所有对Route的操作都要经手Router,职责有创建Route对象和dispatch(Request)到匹配的Route。
匹配的Route将会被放到Request里面,Route中的Closure(其中有业务逻辑代码)在中间件部分执行。

然后,我们来了解一下中间件部分。
所有中间件会形成一个栈(stack)结构,从最外层的中间件到最里层的中间件依次执行。
当然,最里层的中间件会继续调用$next,那么这个$next是何方神圣呢?
其实这个$next就是App对象,在PHP中,有一个魔术方法__invoke()可以把一个对象当成函数来用。
这边的App类就有一个__invoke()方法,当调用到最里层的中间件的时候,就相当于会调用$app($request, $response)。
在这个__invoke()方法里面,将会调用路由部分存储在Request中的Route中携带的Closure业务逻辑。
具体怎么执行的,请查看相关代码。

差不多就这些内容。

PHP的页面控制器和前端控制器

读过《企业应用架构模式》(一本归纳总结了企业应用开发中的架构和模式的书)的读者都会知道书中提到过两种对立的模式,页面控制器和前端控制器模式,那么这两种模式有什么区别呢?

页面控制器和前端控制器模式的区别在于前端请求的地址不同,前端控制器是只有一个请求地址,而页面控制器是请求多个地址。而这造成了两种模式的本质区别,那就是需不需要路由。

在PHP中,我们初学这门语言的时候,大多是从页面脚本入门,这时候使用的就是PHP的页面控制器模式。而在框架中,我们需要切换到前端控制器模式,理解路由的概念。

在前端控制器模式中,路径参数有url字符串,url参数,request method。
而在页面控制器中,不同文件本身就是一种路径参数,当然除此之外可以叠加上诉的url字符串等其他参数。

所以,前端控制器模式中,路由分发实现是由一个路由分发器来进行dispatch。
而在页面控制器中,路由分发实现不仅通过用户请求不同文件,而且需要在文件中进行进一步的分发来实现。

后面,我会改造Slimphp框架成为页面控制器模式的版本,未完待续。

安装php-fpm和nginx

以前一直用Apache Httpd和mod_php的组合的,现在来了解一下nginx+php-fpm的组合。

安装参考了这个网页:https://www.sitepoint.com/setting-up-php-behind-nginx-with-fastcgi/

除了存在默认的localhost的站点外,我还新建了一个站点,贴一下diff(diff sites-enabled/nginx.zhudekui.com sites-enabled/default)的内容。

< listen 80;
< #listen [::]:80 default_server ipv6only=on;


  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;

24c24
< root /var/www/html;


  root /usr/share/nginx/html;

28c28
< server_name nginx.zhudekui.com;


  server_name localhost;

54,55c54,55
< location ~ .php$ {
< fastcgi_split_path_info ^(.+.php)(/.+)$;


  #location ~ \.php$ {
  #       fastcgi_split_path_info ^(.+\.php)(/.+)$;

61,64c61,64
< fastcgi_pass unix:/var/run/php5-fpm.sock;
< fastcgi_index index.php;
< include fastcgi_params;
< }


  #       fastcgi_pass unix:/var/run/php5-fpm.sock;
  #       fastcgi_index index.php;
  #       include fastcgi_params;
  #}

此外,还了解了一下FastCGI:
在CGI的时代,每个请求都是由CGI创建一个process(进程),而且会在完成后销毁。
要知道,虽然*nix的创建销process的开销比Windows好很多,但是还是比较weight,这导致网站并发量很难提高。
而FastCGI,有点类似于进程池的概念,FastCGI将多个线程不断重用,基本没有了创建销毁process的开销。