边城愚人

如果我不在边城,我一定是在前往边城的路上。

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  31 随笔 :: 0 文章 :: 96 评论 :: 0 Trackbacks

2007年4月8日 #

推酷是面向IT领域的个性化阅读产品(www.tuicool.com),关于产品的更多信息请参考网站的关于页面。 推酷目前加入到国外一家孵化机构的孵化计划,该孵化计划于8月到10月这3个月在大连进行集中开发(提供住宿), 之后会返回北京继续开发(亦解决住宿问题)。目前推酷正处于热烈的第二阶段开发中,预计今年11月初能正式上线推广。 为了把推酷各方面做得更好更专业,推动推酷更快的发展,现诚邀热爱技术的朋友加入。 推酷目前需要的技术主要有以下三方面: 1)前端开发,即html/css,少量的JS应用,会些简单的UI设计更好。功力方面,至少要比现在的页面做的更专业些。 2)Web开发,即Ruby on Rails开发,如果有其他语言的Web开发经验,有志转向ROR亦可。 3)Android开发,有扎实的Java经验亦可。 对于上述技能,擅长其中某一方面即可。你可以没有多年的开发经验,但还是需要有一定的项目经验基础, 并且能自我驱动学习,持续不断地提高自己的技术。在推酷,你可能会独立负责某一方面的开发, 这会使你在技术方面更快的成长。当然,我这个零号员工还是可以给予一些指导的。 因为是创业初期,目前推酷可以提供的月薪在3000-6000元(这个工资水平确实不够给力, 考虑到创业的机会与风险,如果想找个稳当些的工作,推酷就不太合适了)。 如果你有创业热情,并认同推酷的价值,作为初创成员会给予你丰厚的干股。 推酷也欢迎实习生加入,但要求能全职的实习4个月以上。 就组团理念来说,推酷希望能组成3-4人的技术型小团队,在个人技术发挥、工作时间安排等方面,都会更加的自由开放。 如果你有加入推酷的意愿,可以将个人简历发给我(不用太正式,就别写自己用过什么eclipse、svn等工具啦), 邮箱是kafka0102@163.com。 打造忒酷的个性化阅读产品的路上,我在等你。
posted @ 2012-07-16 13:36 kafka0102 阅读(406) | 评论 (0)编辑 收藏

     摘要: 继承是面向对象中很重要的概念。如果考虑到Java语言特性,继承分为两种:接口继承和实现继承。这只是技术层面的问题,即便C++中不存在接口的概念,但它的虚基类实际上也相当于接口。对于OO的初学者来说,他们很希望自己的程序中出现大量的继承,因为这样看起来很OO。但滥用继承会带来很多问题,尽管有时候我们又不得不使用继承解决问题。  阅读全文
posted @ 2007-09-03 10:08 kafka0102 阅读(2694) | 评论 (5)编辑 收藏

     摘要: 在结束了上一篇Spring 1.x中AOP的使用之后,我用马不停蹄的打开Eclipse,做着Spring2.X下了AOP的Sample。在上一篇文章中的配置过程中,由于对自动代理不是很熟,出现了循环引用的异常信息。当初在阅读PicoContainer源码时看到循环引用不以为然,后来在学习AspectJ时小有印象,这次在折腾了半个多小时后可加深了印象。  阅读全文
posted @ 2007-08-30 08:42 kafka0102 阅读(2285) | 评论 (2)编辑 收藏

     摘要: 本文通过一个“Hello World”级别的横切性功能介绍Spring1.X中AOP的使用,并结合Spring的经典的声明式事务管理给出Spring AOP配置中的经典方案。在Spring2出来以后,Spring1.X的AOP使用方式已经“不合时宜”了,因此如果你是在新项目中采用Spring AOP,建议使用Spring2中的AOP使用方式。关于Spring2.X中AOP的使用,参考该文的姊妹文章Spring2.X中AOP的使用。

一提到AOP的应用,人们就会本能地提起日志功能,它就像一门语言的“Hello World”一样被人们无数次提起。也许有人会疑问除了“不实用”的日志功能,AOP还能做些什么?可能在很多时候我们并不需要自己实现一个AOP功能,尤其是在拥有了很多优秀的AOP应用框架来解决通用的横切性问题的情况下(比如Spring的事务管理、比如Acegi的安全管理、比如WebWork的拦截功能)。但问题总是层出不穷的,总会有些问题可能需要我们自己AOP一下。  阅读全文
posted @ 2007-08-30 08:38 kafka0102 阅读(2348) | 评论 (1)编辑 收藏

     摘要: 1)MVC模式

当年做JSP生产实习时,印象最深也最困惑的模式就是MVC模式了。那时候Struts刚红,几乎每本Struts书中都会有大篇幅的MVC介绍。这个模式最早出现在GUI,后来在Web服务器端红火起来,先前在Ajax书中也看到Web客户端的MVC介绍。说实话,在我看了很多人的MVC解释后,我仍有些糊涂,这里说说我的理解。

有人提到MVC模式时说MVC代表了模型层、视图层、控制层,我觉得这是不对的。在经典的J2EE三层架构中,三层是分为Web层、业务层、持久化层;这个经典分层是基于分布式应用(EJB)的,也就说,Web层物理上是在Web服务器中,业务层和持久化层物理上是在应用服务器中。在这种情况下,MVC只是属于Web层这一层的,而不是分为三层。在这种分布式应用中,视图就是JSP(如果采用的话),控制器就是Servlet(如果采用的话),而模型就是就是调用业务层的在Web层中的桩子。假如我们采用轻量级的SSH技术架构,视图还是JSP,控制器是Struts,而模型就是Spring+Hibernate。这里最难理解的就是模型的概念。我觉得模型是有状  阅读全文
posted @ 2007-08-23 10:00 kafka0102 阅读(1584) | 评论 (0)编辑 收藏

     摘要: 今日发现一名为savage100的同学问我关于范型效率的问题的留言,抱着负责任的态度,想给那位仁兄做个回复,不成想未发现blogjava有回复功能,而且也未找到savage100的博客。唉!于“百忙之中”以此文作解,也算尽了我回复之责任。  阅读全文
posted @ 2007-08-21 22:47 kafka0102 阅读(689) | 评论 (0)编辑 收藏

     摘要: 最近在学Acegi,就试着运行一个小例子,不成想抛出下面的异常
org.apache.jasper.JasperException: Unable to compile class for JSP:

An error occurred at line: 23 in the generated java file
The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory

Stacktrace:  阅读全文
posted @ 2007-08-21 21:55 kafka0102 阅读(24574) | 评论 (15)编辑 收藏

     摘要: Hibernate提供客户化映射类型接口,使用户能以编程方式创建自定义的映射类型来将持久化类任意类型的属性映射到数据库中。使用客户化映射类型,需要实现org.hibernate.usertype.UserType接口。这是个强大的功能,也是Hibernate的最佳实践之一。我们经常提到 ORM中很困难的一点便是O的属性和R的属性不能一一映射,而Hibernate提供的UserType无疑给出了一个很好的解决方案。本文给出使用客户化映射类型的两个例子,算是对Hibernate初学者的抛砖。  阅读全文
posted @ 2007-08-15 10:32 kafka0102 阅读(1514) | 评论 (0)编辑 收藏

     摘要: Hibernate的检索策略包括类级别检索策略和关联级别检索策略。
类级别检索策略有立即检索和延迟检索,默认的检索策略是立即检索。在Hibernate映射文件中,通过在上配置lazy属性来确定检索策略。对于Session的检索方式,类级别检索策略仅适用于load方法;也就说,对于get、qurey检索,持久化对象都会被立即加载而不管lazy是false还是true。一般来说,我们检索对象就是要访问它,因此立即检索是通常的选择。由于load方法在检索不到对象时会抛出异常(立即检索的情况下),因此我个人并不建议使用load检索;而由于中的lazy属性还影响到多对一及一对一的检索策略,因此使用load方法就更没必要了。

关联级别检索策略有立即检索、延迟检索和迫切左外连接检索。对于关联级别检索,又可分为一对多和多对多、多对一和一对一两种情况讨论。  阅读全文
posted @ 2007-08-11 13:33 kafka0102 阅读(1030) | 评论 (0)编辑 收藏

     摘要: JDK内建的任务调度工具类有Timer和TimerTask类,对于简单的任务调度,JDK的Timer就能够胜任。一般来说,Timer应该随程序启动后一直运行。如果是web程序,可以通过listener加载Timer实例。对于普通的应用程序,需要将Timer设置成非后台线程才行。  阅读全文
posted @ 2007-07-19 09:50 kafka0102 阅读(2920) | 评论 (4)编辑 收藏

     摘要: 本文主要介绍如何使用简单的Spring邮件抽象层来实现邮件发送功能,对于JavaMail中的API并不做介绍。通过对比JavaMail的API和Spring的邮件抽象层,我觉得,Spring的邮件抽象层优点就是简化了代码量,并能充分利用IOC功能;缺点就是要使用部分Spring API,使程序与第三方框架耦合。关于这方面的内容,可以参考Spring的参考手册。  阅读全文
posted @ 2007-07-15 20:41 kafka0102 阅读(2686) | 评论 (1)编辑 收藏

     摘要: call和execution的指示符分别为call(Method-Signature)、execution(Method-Signature),匹配方法签名的方法或构造函数的执行。对于call来说,调用的连接点位于方法调用点的调用代码处;对于execution来说,执行的连接点位于方法执行的位置。也就是说,call和execution的重要区别在于它们传递了哪些类型给AspectJ编译器以用来与aspect进行链接。  阅读全文
posted @ 2007-07-12 09:50 kafka0102 阅读(4147) | 评论 (6)编辑 收藏

     摘要: target切入点格式如下:target([Type|Identifier])。Type指示对连接点处的对象类型提供一个静态编译时评估,并采用完全限定类名的形式(也就是说,Type不能是使用通配符的类型声明模式)。Identifier提供了一种方法,可通过它来评估连节点处的运行时对象的实际类型,而不仅仅是静态类型。 Identifier在运行时动态地赋予合适的对象。  阅读全文
posted @ 2007-07-09 09:17 kafka0102 阅读(2690) | 评论 (3)编辑 收藏

     摘要: 让我好好想想,AspectJ中最常用的切入点是什么?哦,也许是call(Method-Signature)吧。这是个相对简单的方法签名。实际上,方法签名的完整形式如下:

[modifiers] [returnTypePattern] [DeclaredTypePattern.]methodName([Parameters])[throws TypePattern],其中方括号中的签名组件是可选的。modifiers 为修饰符模式,returnTypePattern 为返回类型模式,DeclaredTypePattern 为类型声明模式,methodName 为方法名称,Parameters 为方法参数,throws TypePattern 为throw字句。该文仅仅介绍 DeclaredTypePattern,因为相比之下其它模式比较简单的多。

  阅读全文
posted @ 2007-07-07 14:54 kafka0102 阅读(1728) | 评论 (2)编辑 收藏

     摘要: 经常地,你必须遍历一个对象集合并基于一些条件(criteria)来过滤它们。JDK提供了有用的机制来排序集合,即Comparator接口。然而,JDK缺少过滤集合的机制。

这篇文章描述了一个仅由一个类和一个接口组成的简单机制,它允许你快速和灵活地过滤集合。当搜索一个集合时,该机制提供了与SQL中的select语句相同的功能。它的隐含的概念是,在遍历集合和过滤集合中的对象时,达到职责的分离。
这里提出的方法有下面的优点:
1、一个核心的过滤器组件的复用产生更清晰的代码。
2、通用过滤组件的复用产生更免于错误的代码。
3、从过滤逻辑中分离出迭代逻辑使你任意地增加和删除过滤器而不影响到其他代码。
4、对于大集合和多个criteria能够获得性能提高。  阅读全文
posted @ 2007-06-30 22:22 kafka0102 阅读(1330) | 评论 (1)编辑 收藏

     摘要: 对于没有使用过Calendar的程序员来说,再次处理日期时不妨使用Calendar而不仅仅是Date和SimpleDateFormat等类。这篇文章根据几个使用日期的场景来说明如何使用Calendar等类。
在数据库编程时,我们通常将java日期字段选作Date型的(一般是java.sql.Date,继承于java.util.Date,使用方法是类似的),当然也可以存储为字符串甚至是long型的time,但我们这里只讨论date型的。如果存储的时间是系统当前时间,我们可以使用Date d = new Date();就得到想要的时间;以前我编程时也指定存储日期的格式,但现在想来不是很有必要,完全可以在读出数据时指定格式。另一种可选的方法是使用 Calendar类,方法如下:  阅读全文
posted @ 2007-06-22 08:40 kafka0102 阅读(4067) | 评论 (0)编辑 收藏

     摘要: 最近在看一个程序,该程序的图形界面采用SWT编写。想要将程序运行起来首先需要做的就是将swt(jface)包放到类路径上,swt包可以从http://www.eclipse.org/swt下载(其中除了swt包还有和操作系统相关的文件),和swt开发相关的插件为VE。一切就绪,运行程序发现了“Exception in thread "main" java.lang.UnsatisfiedLinkError: no swt-pi-gtk-3232 in java.library.path ”的错误(我的操作系统为Ubuntu7.04)。解决方案有多种,这里只介绍我使用的一种方法。  阅读全文
posted @ 2007-06-21 09:11 kafka0102 阅读(13599) | 评论 (1)编辑 收藏

     摘要: 哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+ Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。可以证明哈夫曼树的WPL是最小的。
构造哈夫曼树的算法如下:
1)对给定的n个权值{W1,W2,W3,...,Wi,...,Wn}构成n棵二叉树的初始集合F={T1,T2,T3,...,Ti,..., Tn},其中每棵二叉树Ti中只有一个权值为Wi的根结点,它的左右子树均为空。
2)在F中选取两棵根结点权值最小的树作为新构造的二叉树的左右子树,新二叉树的根结点的权值为其左右子树的根结点的权值之和。
3)从F中删除这两棵树,并把这棵新的二叉树同样以升序排列加入到集合F中。
4)重  阅读全文
posted @ 2007-06-21 08:23 kafka0102 阅读(12236) | 评论 (7)编辑 收藏

     摘要: 设有主串s和子串t,子串t定位是指在主串s中找到一个与子串t相等的子串。通常把主串s称为目标串,把子串t称为模式串,因此定位也称作模式匹配。模式匹配成功是指在目标串s中找到一个模式串t。

传统的字符串模式匹配算法(也就是BF算法)就是对于主串和模式串双双自左向右,一个一个字符比较,如果不匹配,主串和模式串的位置指针都要回溯。这样的算法时间复杂度为O(n*m),其中n和m分别为串s和串t的长度。

KMP算法是由Knuth,Morris和Pratt等人共同提出的,所以成为Knuth-Morris-Pratt算法,简称KMP算法。KMP算法是字符串模式匹配中的经典算法。和BF算法相比,KMP算法的不同点是匹配过程中,主串的位置指针不会回溯,这样的结果使得算法时间复杂度只为O(n+m)。下面说说KMP算法的原理。  阅读全文
posted @ 2007-06-17 22:14 kafka0102 阅读(9676) | 评论 (6)编辑 收藏

     摘要: 做java企业级开发时,我们通常采用三层架构。特别地,如果我们要做的系统的业务逻辑不是很复杂时,我们要处理的不过是CRUD操作,这时我们可能将dao层与service层合并为一层,尽管很多人会这样做,但我仍倾向于将两层分开;因为service与dao不是一一对应的,从复用及逻辑清晰的角度考虑,应该将它们分开。在三层架构下,对于web层,service层,dao层我们都该怎么测试?这里我将介绍基于Spring,Hibernate和DbUnit的情况下我的测试方法。由于使用了Spring,事务管理就不在dao,因此要单独地测试dao可能要麻烦一些;另一方面,dao中的操作大多是简单的,也不是很值得测试。在使用了Hibernate和Spring的情况下,我们要测试的除了HQL,还有其配置文件,我觉得对数据持久化的测试最好定在service上。如果service业务逻辑复杂的话,与数据持久化无关的业务逻辑(应该写在领域对象中)可以单独测试,在保证与数据持久化无关的业务逻辑的正确性下,带上dao操作做集成(单元)测试。  阅读全文
posted @ 2007-06-14 09:18 kafka0102 阅读(1463) | 评论 (0)编辑 收藏

     摘要: 在做Java企业程序的时候,不可避免地要和外部资源打交道,比如数据库,Http请求等。对于这些外部资源的处理,我们可采取的操作或者是直接处理或者是模拟处理。当我们使用Webwork,Spring,Hibernate等框架时,我们要测试的并不仅仅是Java代码,我们还要测试依赖于这些框架的配置文件等等。因此,对于数据持久化的测试,Mock方法是行不通的,我们需要真实地测试数据库操作。对于持久化测试来说,重要的是创造出已知的“干净的”的准备数据。如果我们在测试一个持久化方法前不能确定数据库到底存着什么数据,我们只能通过反复地查看数据库数据来验证测试方法的正确性了(这就是我和大多数人以前使用的最“直接”的方法)。现在就让我们使用DbUnit,来更好的更自动化的测试持久化操作吧!

先介绍一下DbUnit。DbUnit是一个 JUnit扩展,适用于数据驱动的程序。使用DbUnit,可以在测试运行期间将数据库的数据处于已知状态,这样在测试时可以方便地写出测试断言,也能自动地完成对数据持久化方法的测试。在使用上,DbUnit也很简单, 它提供了大量的  阅读全文
posted @ 2007-06-14 09:03 kafka0102 阅读(2755) | 评论 (2)编辑 收藏

     摘要: 很早就知道Jetty,但直到最近才使用它作为Web服务器。Jetty是一个开放源码的HTTP服务器和Java serverlet容器,是完全使用Java语言实现的。作为嵌入的Web服务器,Jetty被广泛应用,比如DWR,JBoss,Geronimo,Tapestry中都使用了Jetty。相比于其他Web服务器,Jetty最大的有点就是小巧且启动速度快。当前的Jetty最新版本为6,相比以前的版本“重”了不少,“重”的原因自然是功能的增强。我使用myeclipse插件开发Web程序,Web服务器从Tomcat转换成Jetty只需改变一下程序部署的位置而已。  阅读全文
posted @ 2007-06-11 15:48 kafka0102 阅读(1864) | 评论 (1)编辑 收藏

     摘要: Web上最常用的两种Http请求就是Get请求和Post请求了。我们在做java web开发时,也总会在servlet中通过doGet和doPost方法来处理请求;更经常地,我们会在doGet方法的实现中调用doPost方法。尽管做了近两年的web开发,我对诸如Get请求和Post请求的基本概念仍不是十分了解。近日阅读《javascript高级程序设计》(很长时间没有看书了!),重新整理了一下Get请求和Post请求的概念,算是读书笔记吧。  阅读全文
posted @ 2007-05-22 22:30 kafka0102 阅读(3315) | 评论 (3)编辑 收藏

     摘要: 题按:做了几年的java程序,却很难说对基本的OO概念都有理解。即便每天都写的代码中,也很难说清楚其中到底运用了怎样的概念和思想。前日的考试中看到关于上溯造型与下溯造型的问题,就查了些资料,集中说一下吧。  阅读全文
posted @ 2007-05-21 22:34 kafka0102 阅读(3169) | 评论 (2)编辑 收藏

     摘要: 我们应该如何以及在哪里使用Mock对象呢?一般来说,对于目标对象中的合作者对象,在测试时如果其状态或行为的实现严重地依赖外部资源(比如数据持久化中的DAO,比如负责发送电子邮件的类),或者团队并行开发时,目标对象的合作者对象并没有实现(比如J2EE中,横向分工时,负责Action的调用Service,负责Service调用DAO时,相应的Service及DAO没有实现),这时我们就需要模仿这些类。其实,在做J2EE时,传统的N层架构中,我们都是面向接口编程的,我们定义了DAO接口,我们定义了Service接口,这样做的优点就是我们在测试时可以构造实现接口的Mock类。这里不得不提依赖注入,通过依赖注入,我们才能在测试时set Mock对象。这也说明,为了方便测试,我们不得不一步一步重构代码,而模式就在重构中自然地产生了。
  阅读全文
posted @ 2007-04-26 08:35 kafka0102 阅读(4035) | 评论 (1)编辑 收藏

     摘要: 你可以使用eclipse的重构工具方便的生成javabean的getter和setter方法,但在编写javabean时,你可能不得不手动编写枯燥单调的继承自Object的隐含的常用方法,如toString(),hashcode(),equals(Object),compareTo(Object)。当然也有省力的解决方法,那就是eclipse的插件Commonclipse。Commonclipse使用commons-lang包,自动生成上面的方法。你可以到其网站Commonclipse上下载插件感受一下。  阅读全文
posted @ 2007-04-22 12:36 kafka0102 阅读(3040) | 评论 (6)编辑 收藏

     摘要: 当你偶然路过这里时,我假定你已经很明白java中范型和DAO模式了。当然,我也会顺便唠叨几句范型和DAO模式,只是它们不会这篇随笔的重点。我早先在DW上看到一篇蛮不错的文章不要重复 DAO!Hibernate 和 Spring AOP 构建泛型类型安全的 DAO,它也促使我在一个实验工程中使用了范型化的DAO模式。前几天看到的另一篇文章Generic Data Access Objects使我重新想起了这档事。以前的代码不可追,索性就重做了一个sample实现范型化的DAO。坦白的讲,和上面的两篇文章相比,这篇随笔并没有太多新内容,如果你愿意的话,你可以只看上面的两篇文章而关掉这个页面。
  阅读全文
posted @ 2007-04-17 08:55 kafka0102 阅读(3587) | 评论 (7)编辑 收藏

    实现JavaScript继承的最简单的方式是call方法(或者apply方法)及原型链方法,但这两种方法都有缺陷,而其混合体就是很好的继承实现方式。下面举例说明:
function Animal(age){
    
this.age = age;
}

Animal.prototype.sayAge 
= function(){
    window.alert(
"My age is "+this.age+"!");
};

function Dog(age,name){
    Animal.call(
this,age);
    
this.name = name;
}
Dog.prototype 
= new Animal();
Dog.prototype.sayName 
= function(){
    window.alert(
"I am a "+this.name+"!");
};

var dog = new Dog(15,"dog");
dog.sayName();
dog.sayAge();
    对于类Animal来说,它有一个字段属性age及函数属性sayAge,sayAge方法的定义采用的是原型方式。Dog类要继承Animal,其字段属性除了age外还有name,通过Animal.call(this,age);可以实现Dog继承Animal的字段属性age并将其初始化了。call方法的第一个参数为继承的类的this指针,第二个参数为Animal类的构造函数的参数。实际上,只是通过call方法就可以实现继承,但唯一的要求是父类的函数属性要在构造函数中定义,这对于这里的函数属性使用原型方式定义来说就不适合了(采用原型方式定义函数属性比在构造函数内定义更直观一些)。要想继承Animal的原型方式定义的函数属性,需要的语句就是“Dog.prototype = new Animal();”。而Dog类中的sayName()函数则是其自身的函数属性了。
    除了这个最经典的实现继承的方式外,目前还有一些免费的库可供使用。但想到形形色色的库,头就大了,有时间有必要时再研究吧!
posted @ 2007-04-08 21:11 kafka0102 阅读(1476) | 评论 (0)编辑 收藏

     摘要: 最近在阅读《JavaScript高级程序设计》,未免遗忘读过的内容,就打算以博客的形式做些读书笔记。今天介绍的是JavaScript的三种构造对象的方法,除了这三种方法,还有工厂方法来构造对象,但考虑到其简单性及非正规性,这里就不做介绍。和Java这样的面向对象语言相比,JavaScript更像是函数式语言,其并没有类的概念,盖之以对象定义的概念,而具体创建的对象叫做对象的实例。  阅读全文
posted @ 2007-04-08 11:24 kafka0102 阅读(22143) | 评论 (8)编辑 收藏