开发

Laravel框架 – 容器、绑定与依赖注入

laravel框架的核心概念就是容器,打开laravel的入口文件public/index.php,一路追寻,会发现laravel框架在初始化时会新建一个Illuminate\Foundation\Application实例对象赋值给$app这个全局变量。这个Application实例就是我们的laravel容器(Application是Container的子类),是整个laravel程序的基础:   一、容器 容器,就是用来装东西的,对吧。现实中的容器可以用来装水、装米,但编程世界中的容器装的则是一个个实例对象。举个例子,在程序运行过程中,我们可能需要一个Mailer实例来发送邮件,通常直观的做法是在需要的时候才创建这个Mailer实例,但我们也可以在程序初始化的时候先行创建一个Mailer实例,并在容器中注册该实例(laravel中叫做binding),随后在程序中任何需要用到Mailer的地方,就可以直接向容器申请这个实例(laravel叫做resolving)或者由容器进行自动依赖注入。 实际上laravel容器的绑定并不是真的绑定一个实例,而是绑定一个闭包函数,该闭包负责生成要绑定的实例对象。同时在绑定的时候定义是否为单例绑定(laravel中把单例绑定叫做shared)。然后直到程序向容器申请该实例的时候,才真正执行这个闭包函数去生成一个实例。对于非单例绑定,每次resolving都会生成一个新的实例;对于单例绑定,只在第一次resolving的时候生成实例,然后将该实例放入容器的instances数组中(Illuminate\Container\Container->instances),后面在申请时直接从该数组中返回实例。 (如果你有java的spring框架基础的话,那么就很好理解了。laravel容器就相当于spring容器,容器中绑定的实例对象相当于spring bean的概念,他们的目的都是为了依赖注入。另外,laravel的中间件也有点类似spring中切面的概念。推荐可以看一下Craig Walls写的《Spring实战》这本书,对于容器与依赖注入的概念描述得很棒。) (或者,关于容器与依赖注入的概念,还可以参考这篇博文:https://www.insp.top/article/learn-laravel-container) 1. 打印Laravel容器 https://www.hawu.me/coding/1132 2. binding 绑定操作通常在ServiceProvider的register()方法中定义,然后通过写入/config/app.php文件中的providers数组让laravel框架在初始化时自动加载。(当然,你也可以在程序其他地方直接调用bind()与singleton()方法进行绑定) 绑定的作用其实是告诉容器,在解析绑定时候如何生成需要的实例对象。如果一个类不依赖于任何其他类(即构造方法无参)或者它的构造器依赖可以被laravel解析,那么这个类就无需绑定到容器。容器不需要被告知如何生成这样的类对象,因为容器可以通过php的反射机制自动解析出具体对象。 However, there is no […]

Laravel框架 – 命令行工具artisan

说在前面的话: laravel算是近几年最火的php web开发框架了,在github的php项目中稳居第一(Most Popular PHP Project at Github)。star数量甚至是我先前挚爱codeigniter的两倍。这几天抽空看了下laravel的文档与入门视频(laracasts.com),惊讶于现在的php居然已经能写成这样了,laravel简直就是php届的spring。容器、依赖注入、中间件。。。跟朴实无华的codeigniter相比简直就是在炫技,当然这也成了laravel反对派们的口实——“将追求简单直接的php写成了晦涩臃肿的java”。我试了一下laravel与codeigniter渲染一个index页面的性能,laravel平均耗时80ms,而ci只需要8ms,=。=#  but!who care!“当你需要考虑性能的时候,性能早已不是问题了。” balabala吹完laravel,该说正题了。除了laravel本身的框架之外,laravel还提供了一个屌炸天命令行工具artisan,简直就是开发神器。这篇文章就是想记录下平时常用的命令,免得一段时间不写全忘光光。 一、启动服务 $ php artisan serve 使用这个命令,直接在8000端口启动web服务,而不需要在配置nginx,这对于开发环境特别方便。   二、路由相关 1.

php通过fsockopen异步发送邮件

不考虑pthreads拓展的话,原生php是不支持多线程的。如果想要在web项目中异步发送邮件或者执行其他php脚本,就可以考虑使用fsockopen的方法:发送一个socket连接请求目标脚本,不需要等待目标脚本执行结果直接关闭socket连接,接着执行后续任务,同时目标脚本由于收到请求,开始响应并执行。这就实现了php的“伪异步”。 $url = YOUR_WEB_PATH . "/send_email";  // 异步执行的目标脚本 $post_data = array();     /** * 构造$post_data */     trigger_async_request($url, $post_data); //

关于CSRF攻击

今天在某个技术群里有网友聊起CSRF攻击,就想起了以前写汤圆网时用到的“盐值”(unique_salt)与token。 一、什么是CSRF攻击及CSRF的防御 可以参考这篇文章:http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html 对于用户提交的涉及到修改数据的请求,最好都要考虑下防御CSRF。 二、加盐再散列(salt md5) 参考wiki:https://zh.wikipedia.org/wiki/%E7%9B%90_%28%E5%AF%86%E7%A0%81%E5%AD%A6%29 三、我曾经的解决方案 我也记不得我这个解决方法是哪里学来的了。=。=# 大概思路是这样: 1. 首先定义一个系统全局的salt值: $config[‘salt’] = ‘abcd1234’; 2. 然后在生成前端页面时,生成timestamp与token: $timestamp = time();

spring mvc给freemarker传全局的值

通常spring mvc通过model给freemarker view传值,这是一个局部的概念,针对的是每个页面。有时候,我们会想给整个freemarker传一些全局的值。比如网站的url前缀,比如静态资源的路径,这些值在每个页面几乎都会需要用到,但我们不可能在每个model中传递这些值。 我们可以通过FreeMarkerViewResolver来给freemarker模板设置全局的值。 <beans:bean id="freemarkerResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <!– 省略 –> <!– 传值给${request} –> <beans:property name="requestContextAttribute" value="request"/> <beans:property name="attributes"> <beans:props> <!–

在spring框架中发送邮件

spring封装了一个邮件发送类:org.springframework.mail.javamail.JavaMailSender,这个JavaMailSender底层实现依赖的是公开的JavaMail API。所以要让spring的JavaMailSender正常工作,就必须先导入JavaMail API的实现类,比如com.sun.mail:javax.mail。 发送的邮件有两种类型,一种是简单文本邮件,不支持html,即使邮件内容中出现html标签,对方邮箱收到邮件后显示的仍是原始文本;一种是富文本邮件,支持html,对方邮箱收到邮件后会解析html标签并渲染。 一、配置JavaMailSender <bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <property name="host" value="smtp.exmail.qq.com"/> <property name="port" value="25"/> <property name="username" value="your exmail name" />

spring中Constructor、@Autowired、@PostConstruct的顺序

其实从依赖注入的字面意思就可以知道,要将对象p注入到对象a,那么首先就必须得生成对象p与对象a,才能执行注入。所以,如果一个类A中有个成员变量p被@Autowired注解,那么@Autowired注入是发生在A的构造方法执行完之后的。 如果想在生成对象时候完成某些初始化操作,而偏偏这些初始化操作又依赖于依赖注入,那么就无法在构造函数中实现。为此,可以使用@PostConstruct注解一个方法来完成初始化,@PostConstruct注解的方法将会在依赖注入完成后被自动调用。 Constructor >> @Autowired >> @PostConstruct 举个例子: public Class AAA { @Autowired private BBB b; public AAA() { System.out.println("此时b还未被注入:

关于三层架构及事务的异常处理

我的个人理解,在三层架构的开发模式中。 dao层 负责对数据库进行增删查改基本操作。比如新建一个用户信息,更新一个用户信息。 每个dao层的方法都必须是单元操作,即不允许多次读写数据库,因此无需在dao层加事务处理。 在dao层无需手动去处理异常,异常由系统自动抛出,在service层捕获。 service层 负责组合dao层方法来处理业务逻辑。比如处理用户A转账给用户B,就需要两次调用dao层方法,一次是减少用户A的账户、一个是增加用户B的账户,这种业务逻辑就必须放在service层。 service层负责捕获dao层的异常,并判断是否向上抛出异常,是否回滚事务,或者还是在service层就处理掉异常,给上层返回处理结果。 通常,对于简单的业务逻辑,可以在service捕获并处理异常,然后给上层action层返回处理结果(成功or失败)即可。如果涉及到的业务复杂,并且涉及到多次的dao层写入操作,就必须回滚事务。注意,使用spring的aop事务的话,要么是在service层抛出异常触发aop事务回滚,要么就得手动回滚事务。如果异常在service层被捕获并处理掉,是不会触发事务回滚的。 action层 复杂调用service层方法,并捕获service层的异常,给用户输出可读的信息。 无需事务处理。

关于http代理与端口扫描

写爬虫总会有用到http代理的时候,通常的做法都是直接去代理网站(比如快代理,米扑代理)找代理ip来用,但是这些http代理的原理是什么?代理网站是怎么扫描到这么多代理ip的?这两个问题一直困扰着我,可能以前也查过相关资料,但没记住=。=# 今天还是把这个记下来吧,好记性不如烂笔头不是嘛。 一、http代理原理 参考:https://imququ.com/post/web-proxy.html python实现简单的http代理:https://github.com/abhinavsingh/proxy.py 著名的开源http代理程序有:squid、harproxy、varnish。关于squid的用法可以参考我的下一篇文章《使用squid搭建代理服务器》 从知乎上摘抄了一份对比图,对比了这些开源代理的特性,可以了解一下。 二、端口扫描 代理网站如何扫描到那些可用的代理ip,最直接的方法就是使用暴力穷举: 扫描所有ipv4公网地址(ipv4地址数量有255*255*255*255大概42亿个,其中公网ip大概占20多亿个); 对每个公网ip进行端口扫描(最常用的是TCP SYN扫描),确认该ip下有哪些端口号对外开放(一台主机的端口数量是65535个); 然后再对这几个端口分别进行http代理测试,确认是否可用。 端口扫描的原理其实就是对该[ip: port]尝试进行TCP三次握手,参考:http://zenoh.iteye.com/blog/1264915 下面是一段python实现的最简单的端口扫描脚本: #!/usr/bin/env python from socket

Spring的@Autowired与自动代理

我想Spring框架的优点,第一条应该就是Spring的依赖注入了吧。尤其@Autowired这个注解,甚至可以直接注解在私有成员变量上而不用去写setter方法。之前看《Spring实战》这书的时候,里面说autowired自动注入是byType的,当时一直以为就是byClass,就是根据变量的类类型,去Spring context中找这样类型的bean。但当我写Dao层、Service层代码的时候,发现情况根本不是这样的。 比如说我现有有一个BookmakerDao接口,以及接口的实现类BookmakerDaoHibernate,并用@Repository注解将实现类注解为Spring bean。 public interface BookmakerDao { /** * */ } @Repository public class BookmakerDaoHibernate implements BookmakerDao { /**

Scroll to Top