Java Servlet&JSP Web开发

最近几周读了《Head First Servlets&JSP》一书,有一些想法,所以想记录下来。
因为自己主要擅长PHP开发,所以会与PHP做对比。

其实Servlet的doPost和doGet等方法非常符合REST这种设计理念,这点不得不佩服Servlet当初的设计者。
Servlet应该叫做应用控制器(application controller),因此没有前端控制器(front controller)。
对比PHP,PHP在非框架开发也是通过应用控制器这种模式进行开发的,与Servlet颇为类似。
但是与PHP不同的是,PHP根本没有REST思想,想怎么命名应用控制器都可以。
Servlet如果设计得当,就会得到符合REST风格的应用控制器。
但是可能性比较小,估计至少90%的项目都和PHP差不多,命名乱成一团。

然后再来看路由,相比于非框架的PHP,访问的地址就是文件名,Servlet的路由和现代框架风格比较相似。
Servlet用了路由来决定URL地址对应的Servlet,在当时确实是一种很现代的思想。
路由只是Servlet配置的一部分,除了路由以外,Servlet的还有很多配置项也都是配置在web.xml文件里面的。
因为毕竟编译语言,写在xml文件里面就免除了重新编译的麻烦。
书中还介绍了一种使用配置文件的数据生成全局对象的方法,但是这种方法产生的对象因为多线程共享,所以可能会有线程安全问题,值得注意。

再来说一下Servlet的官方视图JSP。请牢记,JSP就是一个Servlet,它会执行时编译成Servlet。
本质上来说Servlet采用的这种JSP的方式是这样的:
本来Servlet有一个函数比如叫做render(HttpServletReqeust req, HttpServletResponse res){}。
这个函数里面写了各种out.println("")之类的输出语句,用来构成一个网页。
但是大家有没有发现,这个render函数无法被多个Servlet重用,那么为了视图的重用,怎么办呢?
于是这个函数就被分离出来,形成一个单独的视图Servlet,这个函数内有一个函数类似render函数。
然后控制器Servlet在执行完了之后会把数据添加到req的属性中去,并把req和res传递给视图Servlet。
视图Servlet收到req和res后,就会从req获取数据渲染并传递给res,就是我们看到的网页。
但是视图Servlet写起来太麻烦了,写一个网页相比单纯的HTML要花费太多功夫,怎么办呢?
jSP的设计中想到的方法很简单,那就是先写HTML风格的页面脚本,然后把这个页面脚本编译成Servlet。
一次请求Servlet的处理过程是这样的:
系统会根据你的请求的URL通过路由找到对应的控制器Servlet;
控制器Servlet处理完成后,会把数据设置为Request的属性,然后把请求转发给视图Servlet;
如果视图Servlet没有找到,只有JSP文件,那么就会把JSP编译成视图Servlet;
视图Servlet会根据请求信息和控制器保存的属性信息渲染页面,形成我们看到的网页。

除此以外,Servlet还有一个非常特殊的特性叫做监听器,它会监听系统中的多种事件,满足我们在事件前后执行的需求。
当然,监听器用的比较少,不过有机会还是会用得上的。

工作流引擎的实现

如何看待工作流引擎?近日在研究工作流引擎Activiti的数据库设计。
一个完整的工作流引擎有哪些部分?一个用户和组系统,一个流程定义文件,N个外置表单。
就拿最简单的请假流程举例:

  • 员工1点击申请按钮。
  • 系统启动一个流程实例。
  • 流程实例启动了一个表单1。
  • 员工1填写了表单1后提交。
  • 系统接收到员工1填写的内容,将其保存为变量。
  • 系统创建了签收任务,并分配给领导组。
  • 领导1签收这个申请。
  • 系统创建了批准任务,并分配给领导1。
  • 领导1点击办理按钮。
  • 系统启动了表单2.
  • 领导1填写了表单2并提交。
  • 系统接收到领导1填写的内容,并将其保存为变量。
  • 系统创建了签收任务,并分配给HR组。
  • HR1签收了这个申请。
  • 系统创建了批准任务,并分配给HR1.
  • HR1点击办理按钮。
  • 系统启动了表单3。
  • HR1填写了表单3并提交。
  • 系统接收到HR1填写的内容,并将其保存为变量。
  • 系统创建了销假任务,并分配给用户1。
  • 用户1点击销假按钮。
  • 系统启动了表单4。
  • 用户1填写了表单4并提交。
  • 系统接收到用户1填写的内容,并将其保存为变量。
  • 流程实例结束。

stackoverflow上关于Java的TOP10问题

1、Why is it faster to process a sorted array than an unsorted array?
概述:为什么处理一个排序数组比一个未排序数组更快?
点评:答案是分支预测,重点在于了解分支预测的原理。

2、Why is subtracting these two times (in 1927) giving a strange result?
概述:为什么有特定的两个时间相差一秒,但是计算得出的结果却不是一秒。
点评:时区变化导致了很多问题,包括这一例,所以可能比较奇怪。只要保持时间问题上的敏感性就好。

3、Is Java “pass-by-reference” or “pass-by-value”?
概述:Java是值传递还是引用传递?
点评:虽然答案很清楚,但是回答里面还是可以学习到一些东西的。

4、Java's +=, -=, *=, /= compound assignment operators
概述:Java的+=, -=, *=, /=等运算符的执行原理?
点评:这些运算符运算完之后都会被格式化一遍,所以可能和想象中有所出入。

5、Avoiding != null statements
概述:如何避免使用 !=null 表达式?
点评:答案中提供了很多方案,这边就不赘述了。

6、Proper use cases for Android UserManager.isUserAGoat()?
概述:征求Android中UserManager.isUserAGoat的合适使用场景。
点评:对Android不了解就不点评了。

7、Differences between HashMap and Hashtable?
概述: HashMap和Hashtable之间的区别。
点评:需要对HashMap和Hashtable等数据格式有比较深入的了解。

8、Read/convert an InputStream to a String
概述: 询问如何把InputStream类型的数据变成一个字符串。
点评:涉及到InputStream和String两种格式之间的转换。

9、Why is char[] preferred over String for passwords in Java?
概述:为什么Java Swing中的密码优先使用chare[]而不是字符串?
点评:因为String是immutable,所以为了提前释放password这种敏感信息,所以使用字符数组。

10、Create ArrayList from array
概述:询问如何把array格式数据变成ArrayList格式数据。
点评:涉及到array和ArrayList两种格式之间的转换。

形参和实参,值传递和引用传递?

虽然接受了一定的编程科班教育,但是一直在搞Web,连形参和实参,值传递和引用传递的概念都搞模糊了。
正好趁自己不理解,把这几个概念都了解一下,免得以后搞个大笑话。

首先是形参和实参,这两个概念和值传递引用传递的概念搞混,但是现在了解了一下,完全不是一回事。
比如有个函数:
function test($a, $b, $c) {
print_r($a + $b + $c);
}
然后有个调用:
test($one, $two, $three);
那么$one, $two, $three就叫做实参,$a, $b, $c就叫做形参,形参只有在函数被调用时短暂存在。

然后再说值传递和引用传递
传参有两种效果,一种传递了以后,修改形参不影响实参;一种传递了之后,修改实参会影响形参。
值传递就是修改形参不影响实参的方式。
引用传递就是修改实参会影响形参的方式。

还得说一个特别一点的传递方式,对象类型引用变量的传参。
对象类型引用变量无论是值传递还是引用传递,最后都能修改被引用的对象的数据,这点需要牢记。
怎么说呢?整个过程是这样的:

  • 变量(地址)->地址指向的数据(引用)->引用指向的数据(对象)。

作为对比,普通类型变量的过程是这样的:

  • 变量(地址)->地址指向的数据(数据)。

以后的博客该怎么写?

最近,博客写的比较少,因为一直在思考编程思想,而这些思想都不太成熟,所以博客写的比较少。
但是,最近关于前后端知识体系的整理也比较熟悉了,所以也开始思考写博客的意义了。

除了编程思想以外,就数编程经验最重要了,而编程经验的获取,不外乎熟能生巧。比如许多互联网企业面试都考察算法一样,个人觉得,如果把算法当成高考科目来教育,没准我国的高中毕业生的整体水平能完爆那些面试前刷了几个月面试题的程序员。为啥,如果成为高考科目,分分钟出现几十种教辅资料把基础算法讲解的透彻务必,每天一张卷子做得高考生怀疑人生,即使死记硬背也能牢牢记住。就像大家高中锻炼出来的哑巴英语,在大学两年没使用,拿出来还能过个六级什么的。

有的时候,还会怀念高中时代的充实。当然,那是最适合娱乐的年纪却没有娱乐的时光,但是那种方向明确,有人引领的感觉是进了大学到现在都难以体会的。大学里面学习的东西比较脱离市场,未来不知所措;工作后学的东西乱七八糟,独自摸索。

到了现在,无论承不承认,以后自己的发展就围绕Web方向了,或许还有机会扩展到其他相关领域,比如大数据,客户端等。那么现在最重要的就是要熟能生巧,要多去熟练前后端各种框架技术的用法,总结规律,提高效率,不能光去学习思想而不去实践。古人说过:纸上得来终觉浅,绝知此事要躬行。

从今日开始,依据现有的分类,把每种语言,每种框架使用中遇到的问题,如何解决的,有了哪些新的想法都要记录下来。
除此以外,时常总结经验,明确自己发展方向,走错一步就落后一步,及早总结发现自己的错误。