《Head First Servlets & JSP》笔记

第一章:
P17 content-type(内容类型)响应首部的值成为MIME类型。
P21 端口是一个16位数,标识服务器硬件上一个特定的软件程序。TCP端口只是一个数字而已。

第二章:
P37 Servlet也需要帮助。请求到来时,必须有人实例化servlet,或者至少要建一个新的线程处理这个请求,必须有人调用Servlet的doPost()或doGet()方法。
P41 容器提供的功能:通信支持、生命周期管理、多线程支持、声明方式实现安全、JSP支持。
P44 在Servlet从容器中得到的响应对象中,可以拿到一个PrintWriter。使用这个PrintWriter能够将HTML文本输出到响应对象。
P49 除了把URL映射到实际的Servlet,还可以使用部署描述文件对Web应用的其他方面进行定制,包括安全角色、错误页面、标记库、初始配置信息等。
P49 实际上,容器使用了一组很复杂的规则来寻找匹配的servlet,它会根据客户请求提供的URL查找位于服务器某个位置的一个具体Java类。
P65 一个完全兼容的J2EE应用服务器必须有一个Web容器和一个EJB容器(以及其他一些部件,包括JNDI和JMS实现)。Tomcat是一个Web容器,而不是完整的J2EE应用服务器,因为Tomcat没有EJB容器。

第三章:
P80 要记住,最后servlet要从请求接受一个参数,在模型上调用一个方法,把信息保存在JSP能找到的一个位置上,再把请求转发给JSP。
P86 servlet把请求转发给JSP。然后,JSP从请求对象得到数据。
P88 容器提供了一种称为“请求分派”的机制 ,允许容器管理的一个组件调用另一个组件。
P89 RequestDispatcher view = request.getReqeustDispatcher("result.jsp");view.forward(request, response);

第四章:
P95 容器根据请求中的URL查找正确的servlet,为这个请求创建或分配一个线程,并调用servlet的service()方法(确定调用哪个Servlet方法)。
P96 service()方法结束,所以线程要么撤销,要么返回到容器管理的一个线程池。
P97 你可能听过别人这么说,“servlet的每个实例……”。但这种说法是错误的。任何servlet类都不会有多个实例,只有一种特殊情况除外。
P104 每个Servlet都有一个ServletConfig对象,每个Web应用有一个ServletContext对象。
P108 对,除了GET和POST之外,确实还有其他一些HTTP 1.1方法,包括HEAD、TRACE、OPTIONS、PUT、DELETE和CONNECT。
P118 如果没有在表单中之处method="POST",就会默认为HTTP GET请求。
P119 单个参数可以有多个值!这说明需要一个返回数组的getParameterValues(), 而不是返回String的getParameter()。
P123 还有可能创建一个servlet来处理计算机驱动的请求,其中请求体包含要处理的文本或二进制内容。
P123 既然客户对服务器是远程的,所以getRemotePort()是指“得到客户的端口“。getLocalPort()和getServerPort()的差别很微妙,getServerPort() 是”请求原来发送到哪个端口“,getLocalPort()是指”请求最后发送到哪个端口“。
P126 使用响应对象向客服发回数据会对响应调用两个方法:setContentType()和getWriter(),在此之后,只需要完成I/O将HTML写至流。
P132 不过ServletResponse接口只提供了两个流可供选择: ServletOutputStream用于输出字节,PrintWriter用于输出字符数据。
P132 PrintWriter实际上”包装“了ServletOutputStream,也就是说,PrintWriter有ServletOutputStream的一个引用,而且会把调用委托给ServletOutputStream。
P133 setHeader()会覆盖现有的值;addHeader()会增加另外一个值。

P157 上下文初始化参数与servlet初始化参数很类似,只不过上下文参数对整个Web应用可用,而不是针对一个servlet。
P165 她想监听一个上下文初始化事件,这样就能得到上下文初始化参数,并在应用为客户提供服务之前运行一些代码。

P236 禁用cookie的用户会忽略"Set-Cookie"响应首部。
P238 此时,容器并不知道cookie是否工作,所以向客户返回第一个响应时,它会同时尝试cookie和URL重写这两种做法。
P239 根本就不能对静态页面完成URL重写!使用URL重写只有一种可能,这就是作为会话一部分的所有页面都是动态生成的!
P253 但是不存在setCookie()方法。只有一个addCookie()方法!

依赖注入的存在是为了解决什么问题?

最近喜欢上问自己问题:某某技术的存在是为了解决什么问题?因为只有了解这个技术的产生缘由后,才会对这个技术的理解更加深刻。
那么,今天尝试着来问自己这么一个问题:依赖注入解决了什么问题?之所以会产生这个疑问呢,还是得归咎于了解了Node.js的express框架后,发现相比其他语言的框架(Spring,Laravel),缺少依赖注入这个特色。但是实际使用上,其实还是相当给力的,那么依赖注入的存在是否就无关紧要呢?
那么,首先我们来了解一下依赖注入的定义是什么?

依赖注入(Dependency
Injection),是这样一个过程:由于某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。

嗯,是不是觉得非常深奥和玄乎?什么接口,注入,具体服务类,上下文等名词搞晕了我们大脑,这也就是为什么学习技术是一件痛苦的事情了,类似《Head first》之类的书籍简直是神器。

这么玄奥的话我们是不懂的啦,那么我们来尝试依赖注入产生的动机。

首先,没有依赖注入,我们会频繁的制造创建对象的代码,比如我们要发送邮件:

use AppBundle\Mailer;

$mailer = new Mailer('sendmail');
$mailer->send('ryan@example.com', ...);

比如这种代码,我们可能在很多地方去重复制造。
重复制造有什么问题呢?
个人觉得其实也没有什么问题,大家刚开始编程的时候不都这么写的么。。。哈哈

但是可能有人觉得重复制造不好,比如有可能在一次调用过程中会制造出多个mailer对象,其实明明创建一个就可以了是不?
那么我们在最开始的时候初始化一个对象好不好呢?
比如在每次请求过程开始的时候,初始化一个mailer对象,然后在后面就可以任意次数进行调用了。

但是也有问题,万一这个项目的代码中需要用到成百上千个这样的对象(纯属假设),那我们岂不是要在请求开始的时候创建这么多个对象了。
那么,有更好的解决办法么?
我们可以假设系统中存在一个容器,容器内部放置了这么多个对象,容器内的对象可以直接用来调用。其实容器内被调用的对象都不存在,只有在第一次被调用的时候才会被系统初始化,保存在容器内部。
但是对我们这些调用者来说,容器就相当于存在成百上千个对象等待我们去调用。

这样就大概是依赖注入被制造出来的原因了,只是关于重复制造存在的问题,我还需要思考思考该怎么表述。

给个Node.js依赖注入的例子:http://www.infoq.com/cn/articles/ioc-meet-nodejs

安装Shadowsocks教程

一直以来都是使用ssh来翻墙的,翻墙速度一般,毕竟单线程。
但是最近防火墙又抽风了,真是防不胜防。
真是没有办法,于是动起了安装Shadowsocks的想法。

我直接在fedora主机上搜索shodowsocks,搜出来一个python-shadowsocks直接就装上了。
但是查了一下发现这个软件貌似是服务器端的(此处应有伏笔),我就没有理会。
先安装一个ss客户端吧,找了半天,都是windows端和osx端的客户端。
唯一找到的Linux下客户端是一个名为shadowsocks-qt5的软件,然而qt5程序需要安装qt支持。
然后发现根本不要这么麻烦,其实python-shadowsocks自带了一个sslocal的命令,这个就是客户端。
这就再好不过了,按照教程写了config.json文件。

{
        "server": ,
        "server_port": ,
        "local_port": ,
        "password": ,
        "timeout": ,
        "method": 
}

恩,尝试了一下sslocal -c config.json命令,至少没有报错。

然后搭建linux端的ss服务器了,直接找到了官网教程
先安装python的pip包管理器,然后使用pip命令安装shadowsocks。
因为已经在安装docker-compose的时候安装过pip了,所以直接安装了shadowsocks。
通过教程知道了可以通过这样的命令来启动ss服务器:

ssserver -p 443 -k password -m rc4-md5

输入命令,成功启动了ss服务。
然后把本地的配置文件和自己启动ss服务的参数对应起来,启动客户端程序就可以使用ss了。

Docker命令分类整理

程序自身:
version 查看版本
help 查看帮助

后台服务:
daemon 启动后台服务

全局信息:
info 查看信息
events 查看所有事件日志
networks 查看所有网络管理器
images 查看所有镜像
ps 查看所有容器
volume 查看所有卷
stats 查看所有容器状态

Registry:
login 登录Docker HUB
logout 登出Docker HUB
search 查询镜像
pull 拉取镜像
push 推送镜像

镜像信息:
build 根据Dockerfile创建镜像
commit 根据容器创建镜像
rmi 移除镜像
history 查看镜像历史
tag 给镜像打上标签


容器管理相关:
create 创建容器
run 创建并运行容器
rm 移除容器

容器查询和更新:
inspect 查看容器详细信息
port 查看容器端口信息
rename 重命名容器
update 更新容器的分配资源

容器查询内部信息:
logs 查看容器log信息
ps 查看容器内部ps信息
top 查看容器内部top信息
diff 查看容器比起原始镜像更新了哪些文件

容器更新内部:
attach 重新附加到容器原始命令上去
exec 使容器执行一个命令
cp 在容器和本地之间复制文件

容器的开启和关闭:
stop
start
restart
kill
pause 暂停
uppause 取消暂停
wait

容器的导入导出:
import
export
save 保存容器
load 加载容器

安装Gogs真的很简单

1、安装好Ubuntu虚拟机,桥接网卡模式,分配独立内网IP(比如IP为192.168.1.115)。
2、安装好Git程序。
3、找到Gogs二进制安装包的下载链接:https://gogs.io/docs/installation/install_from_binary.html
4、下载Gogs二进制安装包,比如是v0.8.10版本,使用命令:wget http://7d9nal.com2.z0.glb.qiniucdn.com/gogs_v0.8.10_linux_amd64.tar.gz
5、解压下载的安装包,使用命令:tar -xf gogs_v0.8.10_linux_amd64.tar.gz
6、进入当前目录的gogs文件夹,启动goes:./gogs web
7、按照提示的地址,比如0.0.0.0:3000地址,其实代表虚拟机IP的3000端口,访问该网页地址:192.168.1.115:300。
8、按照提示进行安装,需要注意的是需要设置SMTP邮件服务器,并勾选邮件提示等选项;其他的选择数据库之类的,选择sqlite3最简单了,但是sqlite3估计在并发多的情况下可能会有性能问题。
9、点击安装,如果有错误提示请修正。配置域名信息的话,如果你有配置网站的相关经验的话,其实非常简单。
10、访问你配置的域名,就可以使用Gogs了。