chenming142's Blog for github

实践|思考|总结|分享

在Java中日期时间类型的相互转换

在上篇《Java中Map与TO自动转换》中的存在一个难点,就是如何把Map(一般是String类型,但不一定保证都是)中的数据,转换为To带类型的属性,接下来我们将解决这个问题。

使用java.beanutil包中ConvertUtil类,进行基本类型的转换

ConvertUtil工具类职责是在字符串和指定类型的实例之间进行转换。目前支持的类型有:

java.lang.BigDecimal;java.lang.BigInteger   
java.lang.Class

byte;java.lang.Byte
char;java.lang.Character
short;java.lang.Short
int;java.lang.Integer
long;java.lang.Long
boolean;java.lang.Boolean
float;java.lang.Float
double;java.lang.Double

java.lang.String
java.io.File
java.net.URL

java.sql.Time
java.sql.Timestamp

总体提供两大类功能:
1. 将字符串转换为指定类型
2. 注册、注销和查询类型转换器

通用定时器|倒计时

在一年之前我同事尚谦写了一个倒计时,那个倒计时其实功能上已经很完善了,而且在项目中实际应用效果也不错;今天拿出来整理一下,只为再练练手而已。

TODO : 修复两个错误1)isdebug方法错误2)倒计时|计时器的间隔不为1s时的,时分秒的减|加的间隔错误

调用API

JavaScript Syntax MDN Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
   var _cfg = {'allTimes' : 120, renderTo : 'timer'};
  var timer = new EasyTimer(_cfg);
  timer.start();

  _cfg ={'allTimes' : 40, renderTo : 'timer1', format : '剩余{s}秒'};
      new EasyTimer(_cfg).start();

  _cfg ={'allTimes' : 10, renderTo : 'timer2', format : '剩余{s}秒', ok : function(){alert('我是timer2,我执行完毕了!');}};
      new EasyTimer(_cfg).start();

  _cfg = {'allTimes' : 5, renderTo : 'timer3', immediate: true};
  new EasyTimer(_cfg);

  _cfg = {'allTimes' : 125, renderTo : 'timer4', direction : 1, immediate: true};
  new EasyTimer(_cfg);

构造函数及参数说明

EasyTimer(_cfg) : 构造一个倒计时|定时器
_cfg = {
    allTimes : 0,  
    defaultFormat :  '{d}天{h}时{m}分{s}秒',
    renderTo : '',
    direction : ''
    immediate : false,
    ok : fn,
    callback : fn
} 
allTimes      :定时器|倒计时的时间总秒数,默认为0
defaultFormat :时间显示的格式,不传即显示上述默认格式
renderTo      :时间显示的位置元素,必传参数
direction     :定时器与倒计时类型区分{0 : 倒计时,1 : 定时器}
immediate     :定时器与倒计时初始化后,是否自动执行
ok            :定时器与倒计时完成后,调用函数
callback      :定时器与倒计时间隔调用函数
isdebug       :针对当前定时器与倒计时打印调试信息

Java中Map与TO自动转换

在JAVA开发过程中需要经常使用到TO,TO能方便的对对象成员变量的存取与持久化;但是业务流程开发过程中,我们通常使用Map来进行参数的获取和临时保存,所以在Map与TO之间进行自动转换是非常必要地。

  • 使用Java反射机制来转换 在Java运行时环境中,对于任意一个类,根据反射机制都能知道该类包含的属性和方法;对于该类的任意对象都能调用属于它的方法即能动态获取该类的信息及动态调用对象的方法
    Java反射机制主要提供以下功能:
      在运行时判断任意一个对象所属的类
      在运行时构造任意一个类的对象
      在运行时判断任意一个类所具有的属性和方法
      在运行时调用任意一个对象的方法
    
    在JDK中,主要由以下类来实现Java反射机制,这些类位于java.lang.reflect包中:
      Class类      :代表一个实体类
      Field类      :代表实体类的成员变量即类的属性
      Method类    :代表实体类的方法
      Constructor类:代表实体类的构造方法
      Array类      :提供了动态创建数组,以及访问数组的元素的静态方法
    

    通过Class类获取成员变量、成员方法、接口、超类和构造方法等

Java的类与面向对象特性

在面向对象的编程语言中,类是编程的核心;对于类,我们可以理解它是定义了一个新的数据类型;一旦定义后,就可以使用这个新类型创建该类型的对象.

类是对象的模板,而对象就是类的实例.

什么是类?

类是描述对象的”基本原型”,它定义一种对象所能拥有的数据和能完成的操作,在面向对象的程序设计中,类是程序的基本单元,它是由一组结构化的数据和在其上的一组操作构成.

在Java中,存在类的概念,定义类时使用class关键字即可.

Java Syntax MDN Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 package com.oo;

  class Clazz {
      public Clazz(){
          System.out.println("----->name:"+name);             //[1]
          this.name = "parent constructor clazz!";
          System.out.println("---> 父类构造器代码块被执行 <---");
          System.out.println("----->name:"+name);             //[2]
      }
      public Clazz(String name){
          this.name = name;
      }
      public String getName(){
          return this.name;
      }
                                                              //[3]
      private String name = "parent initialize clazz!";
  }

  public class Clazzer extends Clazz{
      /**
      * 静态代码块 - 类变量(静态变量)可以向前引用(即:先引用,再定义)
      */
      static {
          info = "fancydeepin";
          System.out.println("---> 子类静态代码块被执行   <---");
      }
      /**
      * 类变量(静态变量)在类的初始化之前初始化,无论类的实例将被创建多少个
      *  -都将只在初始化时候在栈内存上分配一次空间
      *  -凡 static 修饰的,都将按位置被顺序执行,name 的值最终输出 fancy 而不是上面的 fancydeepin
      */
      public static String info = "fancy";
      //                                                         //[1]
      /**
      * 实例变量(非静态变量),定义时指定初始值,会比在构造器赋予值更早执行
      */
      private String name = "subclass initialize Clazzer";
      public Clazzer(){
          System.out.println("----->name:"+name);             //[2]
          this.name = "subclass constructor Clazzer";
          System.out.println("---> 子类构造器代码块被执行 <---");
          System.out.println("----->name:"+name);             //[3]
      }
      public Clazzer(String name){super(name);}
      
      public static void main(String[] args){
          Clazzer c = new Clazzer();
      }
  }

jQuery 数据类型详解

ECMAScript中有5种基本数据类型:Undefined,Null,Boolean,Number和String.还有一种复杂数据类型——Object,Object本质上是由一组无序的名值对组成的.

typeof 操作符

对一个值使用typeof操作符可能返回下列某个字符串:
“undefined” —— 如果这个值未定义
“boolean” —— 如果这个值是布尔值
“string” —— 如果这个值是字符串
“number” —— 如果这个值是数值
“object” —— 如果这个值是对象或null
“function” —— 如果这个值是函数

注:typeof 操作符的操作数可以是变量,也可以是数值字面量.typeof是操作符而非函数.

Jquery Unique 详解

最近在工作中使用到了jquery.unique函数,用的过程中出现了很多偏差,所以就查看了jquery源码现在总结一下.

先看看jQuery.unique(array)api是:

删除数组中重复元素.只处理删除DOM元素数组,而不能处理字符串或者数字数组.

再来看看jquery.unique的测试结果:
jquery-1.4 [jquey-1.4]
jquery-1.7 [jquey-1.7.2]

从测试结果看,1.4版本虽未能够完美实现去除重复元素,但是某些情况(即数组是有序的)下也是能处理数值和字符型数值数组的;而1.7.2版已能完美支持了.

去除重复元素的实现方法

Javascript Array Syntax MDN Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
   $ = function() {
      return {
          unique1: function(elems) {
              for (var i = 0; i < elems.length; ++i) {         // 外层++i
                  for (var j = i + 1; j < elems.length; ++j) { // 内层j = i +1
                      if (elems[i] === elems[j]) {             // 判断是否重复的
                          elems.splice(i--, 1);                 // 如果重复,就去掉
                          break;                               // i-- 与break,保证外层始终从0开始
                      }
                  }
              }
              return elems;
          },
          unique2: function(elemsWithId) {
              var obj = {};
              for (var i = 0; i < elemsWithId.length; ++i) {
                  var elem = elemsWithId[i];
                  obj[elem.getAttribute('id')] = obj[elem.getAttribute('id')] || elem;
              }
              elemsWithId.length = 0;
              for (var id in obj) {
                  elemsWithId.push(obj[id])
              }
              return elemsWithId;
          }
      }
  }();

方法一使用了两重循环,算法复杂度为O(n^2).实现思路比较直观,即遍历数组,看每个元素是否与后面的元素重复,有重复则移除;但是DOM Element数量较多时性能较差,而jQuery中对大量元素进行去除重复的操作很普遍.
方法二将Objct当做HashMap/HashSet来使用,算法复杂度为O(n);遗憾的是JavaScript中无法直接用DOM Element作为Object的key,因此只能将id作为key,然而并非所有的 DOM Element 都是有id 的,所以这种方法并不通用。

Spring Test整合JUnit 4

JUnit 框架原本就能用来进行单元测试,但是在使用了Spring之后测试就变得复杂了,但是幸运的是Spring提供了Spring-test,可以用来整合JUnit,使测试变得简单.

加入依赖包

使用Spring整合JUnit来测试需要加入以下依赖包:
1. JUnit 4
2. Spring Test(Spring 框架中的test包)
3. Spring 相关的其他依赖包及其配置

创建测试源目录和包结构

推荐创建一个和src平级的源test目录,因为src中的内都是以后需要打包的应用类,而test中的类仅仅只用来测试.test目录下的包名称和结构也建议与src中的保持一致,这样既不会产生冲突也容易识别,方便检索.
目录及包结构

创建测试框架抽象类

Spring的测试机制是基于JUnit的扩展,在org.springframework.test包下,可以看到6个从 TestCase基础上扩展出来的抽象类,分别是:
1. ConditionalTestCase - 可以有选择地关闭掉一些测试方法,不让它们在测试用例中执行,而无需将这些方法注释掉
2. AbstractSpringContextTests - 运行多个测试用例和测试方法时,Spirng上下文只需创建一次
3. AbstractSingleSpringContextTests - 方便手工执行Spring配置文件,手工设定Spring容器是否需要重新加载
4. AbstractDependencyInjectSpringContextTests - 自动装配\依赖检查\自动注入
5. AbstractTransactionalSpringContextTests - 自动恢复数据库现场即自动回滚
6. AbstractTransactionalDataSourceSpringContextTests - 通过JDBC访问数据库,检查数据库操作正确性

上述抽象类按照先后顺序逐步加强了每个抽象类的功能,并且按照逐步继承的关系,使得子抽象类具有父抽象类的所有特性,因此最终的AbstractTransactionalDataSourceSpringContextTests抽象类具有其所有祖先抽象类的特性以及其自身的特性,实际应用中可以根据需要选择需要使用的抽象基类进行扩展.

简明 Vim 练级攻略

原文地址:http://coolshell.cn/articles/5426.html

你想以最快的速度学习人类史上最好的文本编辑器VIM吗?你先得懂得如何在VIM幸存下来,然后一点一点地学习各种戏法。
Vim the Six Billion Dollar editor

Better, Stronger, Faster.

学习 vim 并且其会成为你最后一个使用的文本编辑器。没有比这个更好的文本编辑器了,非常地难学,但是却不可思议地好用。我建议下面这四个步骤:

1. 存活   
2. 感觉良好  
3. 觉得更好,更强,更快  
4. 使用 VIM 的超能力  

当你走完这篇文章,你会成为一个vim的 superstar。

在开始学习以前,我需要给你一些警告:

1. 学习vim在开始时是痛苦的。  
2. 需要时间  
3. 需要不断地练习,就像你学习一个乐器一样。  
4. 不要期望你能在3天内把vim练得比别的编辑器更有效率。   
5. 事实上,你需要2周时间的苦练,而不是3天。  

第一级 - 存活

  1. 安装 VIM
  2. 启动 VIM
  3. 什么也别干!请先阅读 当你安装好一个编辑器后,你一定会想在其中输入点什么东西,然后看看这个编辑器是什么样子。但vim不是这样的,请按照下面的命令操作:
  4. 启 动Vim后,vim在 Normal 模式下。
  5. 让我们进入 Insert 模式,请按下键 i 。(陈皓注:你会看到vim左下角有一个–insert–字样,表示,你可以以插入的方式输入了)
  6. 此时,你可以输入文本了,就像你用“记事本”一样。
  7. 如果你想返回 Normal 模式,请按 ESC 键。

现在,你知道如何在 InsertNormal 模式下切换了。
下面是一些命令,可以让你在 Normal 模式下幸存下来: i → Insert 模式,按 ESC 回到 Normal 模式.
x → 删当前光标所在的一个字符。
:wq → 存盘 + 退出 (:w 存盘, :q 退出) (陈皓注::w 后可以跟文件名)
dd → 删除当前行,并把删除的行存到剪贴板里
p → 粘贴剪贴板
推荐:
hjkl (强例推荐使用其移动光标,但不必需) →你也可以使用光标键 (←↓↑→). 注: j 就像下箭头。 :help <command> → 显示相关命令的帮助。你也可以就输入 :help 而不跟命令。(陈皓注:退出帮助需要输入:q)

你能在vim幸存下来只需要上述的那5个命令,你就可以编辑文本了,你一定要把这些命令练成一种下意识的状态。于是你就可以开始进阶到第二级了。

但是,在你进入第二级时,需要再说一下 Normal 模式。在一般的编辑器下,当你需要copy一段文字的时候,你需要使用 Ctrl 键,比如:Ctrl-C。也就是说,Ctrl键就好像功能键一样,当你按下了功能键Ctrl后,C就不在是C了,而且就是一个命令或是一个快键键了,在VIM的Normal模式下,所有的键就是功能键了。这个你需要知道。

标记: 下面的文字中,如果是 Ctrl-λ我会写成 <C-λ>. : 开始的命令你需要输入 回车,例如:如果我写成 :q 也就是说你要输入 :q<enter>.

UML 建模之时序图(Sequence Diagram)

原文:http://www.cnblogs.com/ywqu

一、时序图简介(Brief introduction)
二、时序图元素(Sequence Diagram Elements)

  • 角色(Actor)
  • 对象(Object)
  • 生命线(Lifeline)
  • 控制焦点(Focus of Control)
  • 消息(Message)
  • 自关联消息(Self-Message)
  • Combined Fragments

三、时序图实例分析(Sequece Diagram Example Analysis)

  • 时序图场景
  • 时序图实例
  • 时序图实例分析

四、总结(Summay)