Leo Wang's Notepad

Blog

理解Spring中的DI和AOP

问题的提出

Spring中的依赖注入(DI)为何而生?

下面这篇日语文章提到,所有的Web应用都需要考虑到下面三个问题。

Spring MVCの概要を理解する

1)对象的生命周期问题。

假设你用Servlet来接收用户的访问请求,有一个用户需要访问一个页面,你就需要一个线程来负责处理这个请求,并调用某个业务逻辑(比如调用一个UserService的实例)。如果处理不当,每新增一个用户就实例化一个业务逻辑(new一个UserService的实例),随着访问用户的增多,就会给系统带来大量垃圾回收负担,以及内存消耗的问题。为了防止这种情况发生,就需要把业务逻辑的部分设计为Singleton的,这样就不会每次都新增一个实例。

2)松耦合问题。

为了实现Web程序中的松耦合,即让一个类与另一个类不是那么的紧密结合,通常需要接口(Interface)来实现。但是单存的利用Interface并不能实现松耦合。还需要利用一些技巧,比如Factory Method等设计模式。

3)技术细节的隐藏。

当你写一个User或者SalesOrder类的时候,你希望专注于自己的业务逻辑,比如创建用户,删除用户,创建订单,删除订单这些具体的业务。如果你在这些类中再加上访问记录(log)处理,就会明显的影响你程序的可读性。因为本质上log处理和你的业务逻辑没有什么联系,两者混杂在一起就会让人看起来比较头大。还有一些异常处理类的逻辑也会产生同样的问题。你怎样才能把这些和真正的业务逻辑无关的逻辑分离出去?

问题的回答

Spring给出的解决方案是这样的。

1)对象的生命周期问题。=>DI

2)松耦合问题。 => DI

3)技术细节的隐藏。=>AOP

首先Spring是怎么实现DI的呢,是通过DI Container来实现的。

在没有使用DI的Web应用中,Controller用到Service的时候,会生成(new)一个,Service用到DAO的时候,也是同样的生成(new)一个。

no DI

而使用了DI的Spring,则将实例化的工作全部交给了DI Container去做。

Controller中仅仅声明了Service接口的一个属性,具体的实现(new)没有去做,同样Service中也只是声明了一个DAO接口的一个属性,也没有去实现(new)。当需要实例的时候,就让DI Container根据配置去找到合适的类去实例化相应的接口属性。

DI

而用Spring写成的Web程序,其处理顺序可以用下图来表示

Spring Flow

  1. Dispatcher Servlet接收用户访问请求
  2. Dispatcher Servlet利用HandlerMapping取得URL所对应的Controller对象
  3. Controller来实行业务逻辑,调用Service对象和DAO对象得到业务数据,并把数据放到Model中。并返回一个View的名字,希望把数据显示到该View上。
  4. Dispatcher Servlet得到View的名字后,调用View Resolver来得到相应的View对象。
  5. Dispatcher Servlet把View对象生成为一个画面(View),画面包含Model对象中的数据,然后把这个View返回给用户(response)。用户的浏览器把这个画面呈献给用户。

 …

我对Javascript中的闭包Closure的理解

怎样理解 Javascript Closure 也就是闭包的概念,想必很多人在为此头疼。

笔者先后参考了下面这些资料

MDN Javascript Closure https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

阮一峰的博客 http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

Frank Fang的博客 http://www.cnblogs.com/frankfang/archive/2011/08/03/2125663.html

作者们都声称自己搞懂了闭包的概念,可自己还是看的云里雾里。

直到笔者看到下面这篇文章,才开始真正理解闭包的概念和应用场景。

Jonathan D. Johnson的博客 http://jondavidjohn.com/javascript-closure-explained-using-events/

下面我试着把这篇文章边翻译边把自己的理解写出来。

先看一下下面这段程序,

效果:在第3次按下button的时候显示”Third time’s the charm”的消息框。

在sap hybris的accelerator中添加hybris cms组件(hybris cms component)的方法

在hybris的accelerator中新建CMS组件(hybris cms component)的步骤包括:

*注意:hybris addon中的步骤有所不同,将在另一篇文章中记述。

  1. 自定义hybris item,在extension的items.xml文件中定义,类似于任何其他hybris item。
  2. 一个继承AbstractCMSComponentController的Spring MVC控制器,或使用DefaultCMSComponentController。
  3. 用于在页面上呈现组件的JSP,根据需要使用HTML,CSS和Tag Libraries。

可以通过XML配置为组件自定义hybris WCMS Cockpit:

  1. editorArea_typeName.xml:WCMS Cockpit编辑器区域的配置文件。
  2. contentEditor_typeName.xml:用于LiveEdit模式和联机编辑的配置文件
  3. wizardConfig_typeName.xml:如果通过向导对话框添加组件,则通过此文件进行向导配置。

在SAP hybris中实行单体测试(Unit Test)的注意事项

在SAP hybris的单体测试中,出现如下错误信息:

sap hybris在新建自定义cms component时的注意事项

在SAP hybris中添加自定义的CMS Component,需要注意以下几点:

参考链接: https://wiki.hybris.com/pages/viewpage.action?pageId=294094319

  1. 在addon中添加,可免去对accelerator的修改
  2. 在/<addon-name>/resources/<addon-name>/web/spring/<addon-name>-web-spring.xml中添加renderer和rendererMapping的定义
  3. 使用ant命令安装addon

<addon-name>-web-spring.xml的代码示例如下:

Sony 面经

Sony面试的一些问题记录一下。

 

时间:9月26日

地点:品川本社

面试官:4人

问题:

  • 自我介绍
  • 简历细节的确认
  • 离职的动机
  • 来日本工作的动机
  • 介绍一下迄今为止所经历的项目中的成功和失败经验
  • 你自己的卖点(Sales Point)是什么
  • 对这个岗位的理解
  • 业余时间做过什么项目
  • 有什么问题
    • 岗位具体的工作内容是什么
    • 同样年龄段的人都是怎样的工作风格
    • 该岗位对英语作了一些具体要求,实际工作中和海外的团队有何种交流合作

有了uwsgi为什么还需要nginx

在python的web开发中,我用flask框架写了一个小程序,部署的时候,我用到了uwsgi来做容器。

在学习uwsgi部署的过程中,另一个关键词nginx频繁的跳出来。这两者通常是成对出现的。

你有没有和我一样的困惑,为什么有了uwsgi我们还需要nginx?

我是说,既然uwsgi能够展现你想要的内容,那nginx存在的意义在哪里?

首先,nginx是一个HTTP 服务器。如果你是学Java出身的,说到HTTP服务器你应该会想到Apache。

类似的uwsgi可以比喻为tomcat。

nginx官方网站上给出的一张图片很好的揭示了nginx的角色。

architecture-nginx

我所理解的nginx的主要功能,有以下几个部分:

  • nginx处理静态内容请求更专业、快速
  • nginx可以缓存请求。如果让uwsgi来直接接受请求的话,uwsgi需要花费大量的时间来等待request,这本身对web应用所在的主机是很大的资源浪费。
  • 分发请求。假如你有好几个web应用,分布在不同的主机上,nginx可以把请求分发到各自的web应用来进行处理。这一特点是nginx可以用来做负载均衡器。
  • 相比web容器,nginx的漏洞更少更安全
  • nginx可以更好的处理HTTPS
  • nginx有网关(gateway)的作用,可以过滤访问IP。

 …

在Python中将datetime字符串转换为utc timestamp

在python中有很多方法将datetime的字符串转换为 utc timestamp

网上找了好多,看起来都纷繁复杂。本文就想简单的做好一件事,就是将datetime的字符串转换为utc timestamp。

理解这个转换的关键,在于理解python中所有的日期字符串都被python解读为local time。

也就是说,同样是’2015/10/27 00:00:00’这个字符串,虽然身处东京的我和身在伦敦的你看到的是同一个字符串,但他们本身被python解读为两个不同地方的日期和时间。

如果想让python不去理会时差,而只想要utc格式的时间戳的话,用calendar.timegm()函数即可实现。

现举例如下:

3招做好SSRS的分页

在使用SSRS,也就是SQL Server Report Service(SQL Server 报表)的过程中,如果你在寻找下面3个问题的答案,本文可能会帮到你。

  • 针对每个数据分组重新设定页码
  • 让表头在每个页面都能显示
  • 让数据在合理的位置分页

针对每个数据分组重新设定页码

在Details上设置属性,Group里面的ResetPageNumber设置为True,即可让每一个新的分组数据重新设定页码。

group

 

让表头在每个页面都能显示

在详细模式里面找到表头的Static,然后设置KeepWithGroup属性为After,RepeatOnNewPage为True。 如果表头之前还有上一层分组的Static,上一层分组的上述两个属性要分别设为Before和True。 在同一个分组的Static的RepeatOnNewPage不能设置为不同的值,所以同样设定为了True, 但是不希望在后续页面继续显示的部分,其KeepWithGroup只要设定为Before,就不会随后续数据分页而再次出现了。repeatonnewpage

让数据在合理的位置分页

在希望保持为一个整体的Group上设置KeepTogether为True,就会尽量让同一组的数据在同一页面显示。

keeptogether