Spring MVC之工作流程

  一直以来都是用Spring MVC做业务开发,却很少去了解内部的一些细节,虽然网上与天盖地的源码解读,然而却无多大印象,加上版本变化之快,不妨重读一次。这里以spring-webmvc 4.3.4为例,也正是花图所使用的版本,下面详细来看看。

  DispatcherServlet继承自FrameworkServlet,而FrameworkServlet又继承自HttpServletBean并实现了ApplicationContextAware,通过这样的一个分层结构,可以更清晰的知道处理流程。

  第一部分:初始化

  初始化分两个部分:一个是监听器部分:负责Root WebApplicationContext的初始化,包含通过XmlBeanDefinitionReader获取配置文件,进行加载,通过RequestMappingHandlerMapping扫描出带有RequestMapping注解的Controller,通过RequestMappingHandlerAdapter注册Controller,等等。

  另一部分是FrameworkServlet的初始化:抽象类HttpServletBean继承自HttpServlet,实现了父类的init()方法,获取init-param中的配置,对DispatcherServlet进行数据绑定。然后调用FrameworkServlet.initServletBean(),初始化webApplicationContext,并调用DispatcherServlet.onRefresh(),来完成初始化。

initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);

  从Bean中取出相应的Resolver,若没配置则取默认,默认的设置在DispatcherServlet.properties。

  第二部分:接收请求

  对于Java Web而言,都是通过web.xml中的Servlet来分配请求,一般的都会将”/”根请求配置为DispatcherServlet,这样所有的前端请求都会路由到Spring MVC。

  抽象类FrameworkServlet对Servlet的几个基本Http method方法进行了代理,统一通过processRequest()进行处理,并最终到达DispatcherServlet中的doDispatch()。

  doDispatch()中先检查request是否是multipart request,如果是,则用一个multipartResolver来包装request,判断依据是contentType是否是”multipart/”开头。

  找到HandlerExecutionChain用来处理当前的请求,方法是从已注册的mappingRegistry中找到最匹配请求URL路径的handlerMethod,这个即我们最熟悉的Controller,放在HandlerExecutionChain中。若HandlerExecutionChain为空,则没有匹配到任何处理流程,发送404响应,并报非常熟悉的一个日志:”No mapping found for HTTP request with URI XXX”。

  找到HandlerAdapter用来处理请求,从已加载的handlerAdapters中遍历出一个支持该Handler的HandlerAdapter,本例中的Handler即Controller。

  检查Http method是否为GET或者HEAD,如果是,进行last-modified验证,符合条件的发送304响应,并更新Last-Modified相关参数值。

  检查拦截器配置,遍历执行applyPreHandle(),并触发triggerAfterCompletion(),若有返回false的,则本次请求结束。

  一路顺利到此可以调用Controller中的方法了。

  对于Controller返回时ModelAndView没设置view的,给一个默认view。

  接着倒着遍历执行过滤器applyPostHandle(),执行完一个完整的拦截器链。

  接下来是进行ModelAndView的渲染,将ModelMap转化到request.setAttribute()中,并RequestDispatcher.include() or forward()到JSP中。

  最终完成本次请求。

在MacOS中使用AB测试工具

  一直以来都是用JMeter来做压力测试,GUI界面功能虽然强大,报表齐全,但有时候只是想简单测试下,启动JMeter过于繁琐,于是想到用ab来测试,一条命令搞定。MacOS自带了ab,却因版本问题无法正常使用,需要升级到最新版,本文简单记录下过程。

1,先下载httpd、apr、apr-util、pcre,若有已安装的可以忽略
http://httpd.apache.org/download.cgi
http://apr.apache.org/download.cgi
https://ftp.pcre.org/pub/pcre/

2,由于httpd依赖apr、pcre,所以先安装apr、apr-util、pcre

$ cd apr-1.5.2/
$ ./configure
$ make
$ make test
$ sudo make install

$ cd apr-util-1.5.4/
$ ./configure --with-apr=../apr-1.5.2/
$ make
$ sudo make install

$ cd pcre-8.40/
$ ./configure
$ make
$ sudo make install

$ cd ../httpd-2.4.25/
$ make
$ sudo make install

3,在恢复模式下替换系统ab,关闭MacOS Rootless,开机按住Cmd+R键,进入恢复模式,打开终端执行:

$ csrutil disable
Successfully disabled System Integrity Protection. Please restart the machine for the changes to take effect.

重启
$ reboot

4,备份并替换,以下路径是httpd默认安装位置

$ cd /usr/local/apache2/bin/
$ sudo mv /usr/sbin/ab /usr/sbin/ab.bak
$ sudo cp ab /usr/sbin/

5,重新进入恢复模式,开启Rootless

$ csrutil enable
Successfully enabled System Integrity Protection. Please restart the machine for the changes to take effect.

重启
$ reboot

  到此,工具算是准备好了,但MacOS对文件打开有限制,无法满足ab需求,通过以下命令临时调整:(重启后需重新执行)

$ sysctl kern.maxfiles
kern.maxfiles: 12288

$ sysctl kern.maxfilesperproc
kern.maxfilesperproc: 10240

$ sudo sysctl -w kern.maxfiles=1048600
kern.maxfiles: 12288 -> 1048600

$ sudo sysctl -w kern.maxfilesperproc=1048576
kern.maxfilesperproc: 10240 -> 1048576

$ ulimit -n
256

$ ulimit -n 1048576

$ ulimit -n
1048576

  搞定!

Java并发编程一些笔记

《Java并发编程》

  • 自旋锁与互斥锁

  两者非常类似,只是调度策略的不同。对于独占资源的访问,互斥锁在获得锁之前将一直处于休眠状态,自旋锁则是不断的自我循环来等待锁。对于线程切换没有损失,但消耗CPU,等待过长影响系统性能。

  • 并发包中的信号量与有界阻塞容器

  Semaphore用来控制对某种资源的访问数量,可以用来实现资源池化访问,也可以将任何一种容器变成有界阻塞容器。

  • 线程的关闭

  大多数时候使用原生线程都是等到运行结束而自动关闭,然而有时候也需要提前结束线程,比如用户取消了操作。但Java没有提供任何机制来安全地终止线程。仅提供了中断(Interruption),这是一种协作机制,能够使一个线程终止另一个线程(Thread.stop和suspend存在缺陷,避免使用)。

  解决方案有:非阻塞情况下使用volatile类型的变量来做标记,阻塞框架又存在可中断和不可中断,可中断调用阻塞框架中断方法,例如对阻塞队列的操作。处理好中断异常,保证数据完整性。不可中断的阻塞如IO的操作或者等待获得锁而阻塞,在取消方法中先关闭IO,或者调用Lock类的lockInterruptibly。

  • 线程饥饿死锁

  在线程池中,任务依赖其他任务,那么可能产生死锁。在单线程Executor中,一个任务将另一个任务提交到同一个Executor,并且等待这个被提交任务的结果,会死锁。

  • 线程池大小

  线程池过大,大量的线程将在相对很少的CPU和内存资源上发生竞争,导致更高的内存占用量。线程池过小导致处理器空闲,减低吞吐率。

  • synchronized与ReentrantLock

  两者jvm层语义一致,Java 6及更高版本两者效率差别已经不是很大,Lock具有公平与非公平两种选择,除本身特性之外,非公平锁吞吐率高于公平。其原因是恢复一个被挂起的线程与该线程真正开始运行之间存在较大延时。Lock具有定时锁等待,可中断锁等待,非结构化加锁。

DJI Mavic Pro短暂的体验

  对于一个喜爱摄影的人来说,上帝视角无不充满了诱惑,然而传统摄影方式确实难以触及。这不自从去年大疆创新发布了旗下首款便携无人机Mavic Pro之后就一直长草至今,在得知年前有一批货放出之际,迅速下单购之。然而在收到之后却极其失望,如同大多数国产数码产品,但凡冠以“智能”头衔之后,必然要出现无数的软件问题。(这里可以先卖个关子,有空要盘点下16年购置过的那些“智能(SB)”数码)

  Mavic Pro硬件方面到还不错,外壳衔接,各种接口虽然粗糙了点,但也还耐用。尤其难免会磕磕碰碰的情况下,机身还是很坚固的。三轴云台也是很赞,极其稳定。出现问题的主要还是摄像头,其设定的规格是比精灵系列要低不少,不仅视野少了,传感器尺寸也少了,输出的DNG画质中央暖色调,四周冷色调,JPG则要略好一点。引入的自动对焦也是惨不忍睹,稍微纹理不明显就无法合焦,有趣的是似乎对焦永提示远都是正常的绿色,以至于导出到电脑上才发现不够清晰,整体拍摄水准停留在千元安卓手机水平。App端的拍照和录像设定也是不太方便,录制过程中无法拍照,每次切换手动/自动模式都要重新设定参数,拍夜景简直就是折磨。

  介于这些“缺陷”,限制与定价,个人觉得Mavic Pro的设定应该是一款高端遥控飞行玩具。在DJI并不清晰的产品定位中,Mavic Pro也就入门款,即便下一代,可能不会有很大提升。

  参考:DJI Mavic Pro 官方社区

  照片:花图相册

TOGO Smart fortwo初体验

  “共享出行”这个新事物可以说是火遍了整个16年的下半年,仅深圳以摩拜,ofo为主的共享单车已是遍地开花,随处可见。以其低廉的价格,任意停放的策略还是很非常惠民的。这不最近一家做共享租车的公司又刷爆互联网,在深圳首批试点区域就设在所居住的南山区,提供的车型还是清一色的奔驰Smart fortwo,作为混迹互联网的人自然免不了要尝尝鲜了。

  说到初次下载TOGO App已经是一个月前了,那时候注册帐号还是看不到车的,却已早早提示支付1500的违章押金和驾照认证,不免让人怀疑会不会有跑路嫌疑。直到最近,发现还能偶尔刷出个一两台车,合作的停车场也越来越多,看来时机差不多了。周四提交驾照认证后第二天周五晚上就收到审核通过的短信了,还以为要等到下周一呢,看来效率还是不错的。周六早晨正好刷出一辆车,还是在附近一个停车点,意味着不需要支付上一个人驶入的停车费。早早点了预订,需要在15分钟之内打开车门,好像一天只有三次违约机会。收拾东西就过去了,找到车后发现是停在一个小角落里,旁边用雪糕筒围着,看的出来是临时划出一小片区域给TOGO的专属停车位了。到了附近手机自动显示了开锁,上车检查一番果然如网上所说标配的加油卡不存在,被租客拿走了还是根本没放,谁知道呢,毕竟试运营,行驶证齐全就ok了。钥匙被拴起来的,仅够插入发动车辆,出发~~

  由于并不是直接奔者目的地去的,开去朋友那转了几圈。发现这车真特么灵活,短小的车身,调头如同自行车,正常速度过弯离心力感受特别大,小排量起步也觉得动力充沛。由于没有后排,前排到还觉得挺宽敞的。座位后面凸起部分放拿小行李转身即可摸到,不像传统车,前排没地方放,后排够不着。至于停车,更是方便不解释。要说不足的地方,整车内饰还是low了点,到处塑料不说,挡把,手刹手感极差,塑料玩具似的。蓝牙也没有,没有搁置手机的地方,有一个USB插口,须自备数据线。滨海大道上70噪音就不能忍了。

  至于价格,本次体验差不多2个小时,40公里,车费100多一点,再加一个25的还车附加费,还是比较合理,介于滴滴和传统长租(神州,一嗨)之间,如果说单车是解决3公里出行需求,那TOGO就是解决3公里到50公里之间的一个选择,50公里以上还是长租更合适。

  这个模式投入还是比较大的,Smart fortwo价格大家都清楚,就看怎么拿这笔押金资本运作了,还是希望能壮大起来,方便持证摇号中的人。