Netbeans 6.7 中的 Link-in-Editor 功能

Eclipse 和 Netbeans 两大 IDE 我都用过,当然,主要还是 Eclipse 为主。在熟悉了 Eclipse 的快捷键后,开发起来有一种很顺手的感觉。

然而,转换到 Netbeans 之后一直很郁闷,也很纳闷,为什么 Netbeans 没有类似 Eclipse 的 link-in-editor 功能呢? 在切换文件的同时,左侧的项目浏览器或文件浏览器也能够同时切换。

今天偶然发现,其实 Netbeans 也有这样的功能,只是自己缺少耐心,缺乏探索。在 Netbeans 的 视图 菜单中,选择 将编辑器与视图同步,即可达到这种效果。

By javafuns on October 23, 2009 at 10:59 · Views: 262 · Permalink · RSS · Leave a comment
Categorized in: Java · Tagged with: , ,

Tutorial of SOAP with Attachments API for Java

随着web 服务、SOA 概念的兴起,和诸多 SOA 应用的实践,Java 阵营也审时度势,趁势推出相应的 API 以应对这一变化。SOAP 是 Java web 服务栈中很基础的一项技术,web 服务间以 SOAP 消息来互相通信。
SOAP with Attachments API for Java(简称 SAAJ) 就是 Java 阵营为访问 web 服务所提供的基础设施,它简化了对 SOAP 的处理。
SAAJ 包含 2 部分 APIs,其一用于创建消息,添加消息内容,其二则用于建立连接,发送 SOAP 消息。

一. 创建 SOAP 消息

SOAP 消息的 XML 文档结构在前一篇文章中已有图示。其中,SAAJ APIs 中的 SOAPMessage 类表示一个 SOAP 消息,SOAPPart 类表示 SOAP part,SOAPEnvelope 接口表示 SOAP envelope,等等。很多 SAAJ APIs 的接口都继承了 DOM 接口。
当创建一个 SOAPMessage 时,该 SOAPMessage 会自动创建并包含 SOAP 消息所必须的部分:一个新的 SOAPMessage 对象会包含一个 SOAPPart 对象,这个 SOAPPart 则包含有一个 SOAPEnvelope 对象,该 SOAPEnvelope 对象会包含一个空的SOAPHeader 对象,紧接着是一个空的 SOAPBody 对象。SOAPHeader 在 SOAP 消息中是可选的,这里之所以自动创建它,是因为我们在 SOAP 消息中经常会使用到它。
Read more »

By javafuns on October 21, 2009 at 15:42 · Views: 240 · Permalink · RSS · Leave a comment
Categorized in: SOA · Tagged with: , , ,

Structures of SOAP with Attachments

还是图形看起来更直观:

SOAP Message with No Attachments

SOAP Message with No Attachments

—-

SOAP Message with Attachments

SOAP Message with Attachments

By javafuns on October 15, 2009 at 22:28 · Views: 200 · Permalink · RSS · Leave a comment
Categorized in: SOA · Tagged with: ,

一个简单的 POJO factory 实现

很简单,看看代码就明白了,不比 “hello,world” 复杂 :) 。 主入口类 ServiceFactory 类似于 spring 的 BeanFactory:

/**
 *
 * @author javafuns
 */
public class ServiceFactory {

    private static Map beansMap = Configuration.getInstance().getAllServices();

    private ServiceFactory() {
    }

    public static   T getService(Class superClaz) throws XxxException {
        String serviceClazShortName = BeanUtil.getClassShortName(superClaz);
        String impl = beansMap.get(serviceClazShortName);
        if (isBlank(impl)) {
            throw new XxxException();
        }

        try {
            return (T) Class.forName(impl, true, ServiceFactory.class.getClass().getClassLoader()).newInstance();
        } catch (InstantiationException e) {
            throw new XxxException("xxxx", e);
        } catch (IllegalAccessException e) {
            throw new XxxException("xxxx",  e);
        } catch (ClassNotFoundException e) {
            throw new XxxException("xxxx",  e);
        }
    }

    private static boolean isBlank(String s) {
        return (s == null || "".equals(s.trim()));
    }

    public static void main(String[] args) {
        try {
            Map map = ServiceFactory.getService(Map.class);
            map.put("key", "value");
            System.out.println(map.get("key"));
            List list = ServiceFactory.getService(List.class);
            list.add("hello");
            list.add("world");
            for (String s : list) {
                System.out.println(s);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

使用Configuration类读取(属性)配置文件:

/**
 *
 * @author javafuns
 */
class Configuration {

    private static Configuration instance = new Configuration();
    private Map serviceMap = new HashMap();

    private Configuration(String filename) {
        try {
            Properties properties = new Properties();
            properties.load(getClass().getResourceAsStream("/" + filename));
            String services = properties.getProperty("services", "");
            extractService(services);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected Configuration() {
        this("config.properties");
    }

    public static Configuration getInstance() {
        return instance;
    }

    /**
     * extract all services definitions from configuration.properties.
     * @param services
     */
    private void extractService(String serviceDefs) {
        if (serviceDefs != null) {
            serviceDefs = serviceDefs.trim();
            if (serviceDefs.startsWith("{") && serviceDefs.endsWith("}")) {
                String[] services = serviceDefs.substring(1, serviceDefs.length() - 1).split(",");
                for (String service : services) {
                    String[] kv = service.split(":");
                    if (kv.length == 2) {
                        this.serviceMap.put(kv[0].trim(), kv[1].trim());
                    }
                }
            }
        }
    }

    public String getService(String superClaz) {
        return this.serviceMap.get(superClaz);
    }

    public Map getAllServices() {
        return Collections.unmodifiableMap(this.serviceMap);
    }
}

BeanUtil只有一个类方法,用于获取类名:

/**
 *
 * @author javafuns
 */
public class BeanUtil {

    private BeanUtil() {
    }

    public static String getClassShortName(Class clazz) {
        String className = clazz.getName();
        return className.substring(className.lastIndexOf('.') + 1);
    }
}

最后来看一下属性文件是如何定义的:

services={\
Map:java.util.HashMap,\
List:java.util.ArrayList,\
Set:java.util.HashSet\
}
test= test
By javafuns on September 25, 2009 at 14:07 · Views: 326 · Permalink · RSS · Leave a comment
Categorized in: Design Patterns, Java · Tagged with: , ,

打算卖掉笔记本

妈的,心里还有点舍不得,毕竟用了4年了,有点感情了,另外,难道是恋旧心理作怪?

By javafuns on September 12, 2009 at 22:30 · Views: 289 · Permalink · RSS · Leave a comment
Categorized in: My Life · Tagged with: 

Groovy 学习笔记 (五)

  1. (1..10).each{ log += it } 等价于 (1..10).each({ log += it })
  2. Closure声明方式之一是: reference.& (其中receiver是对象)
  3. closuredeclared
  4. def adder = { x, y -> return x+y } 等价于 adder(4, 3) 或 adder.call(2, 6)
  5. 文件读写更加简单:
    1. def file = new File(‘myFileName.txt’)
    2. for (line in file) println line
  6. 方法的最后一个语句得到的值作为返回值,所以return语句是可选的
  7. 异常不强制要求捕获
  8. for (it in aaa) 中,变量 aaa 可以是字符串,可以是对象,等等
  9. def file = new File(‘myFileName.txt’)
    for (line in file) println def file = new File(‘myFileName.txt’)
    for (line in file) println line
By javafuns on September 9, 2009 at 21:50 · Views: 387 · Permalink · RSS · Leave a comment
Categorized in: Scripts · Tagged with: , ,

31天重构指南

本文源自:31天重构指南

本文源自 infoQ 上的一篇文章,发现该篇文章非常实用,便记录于此。

该文列出了Sean Chambers在博客中编写的一系列描述重构方式的文章。Sean指出,这些重构方式主要来源于Martin的重构资源站点、代码大全(第二版)以及平时由他自己收集的互联网资源,他的目的是为各种重构方式提供了一些额外的描述及相关的讨论。

以下是这31篇文章列表:

  1. 封装集合
  2. 移动方法
  3. 提升(pull up)方法层级
  4. 降低(push down)方法
  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. 使用多态代替条件判断

第1天. 封装集合

某些场景下,我们并不希望直接将集合暴露给客户类,这时我们可以将集合进行封装,例如只提供对集合的增加/删除:

public class Order {
    private List _orderLines;

    public Iterator orderLines() {
        return _orderLines.iterator();
    }

    public void addOrderLine(OrderLine orderLine) {
        _orderLines.add(orderLine);
    }

    public void removeOrderLine(OrderLine orderLine) {
         _orderLines.remove(orderLine);
    }
}

第2天. 移动方法

如果一个方法在某个类中所使用的次数要远远多于它本身所在的类,那么很可能该方法应隶属于前一个类。

第3天. 提升方法层级

当多个子类都需要某个方法时,那么需要将这个方法从各子类级别提升到该继承体系中的上一级。

第4天. 降低方法层级

与第3天重构相反,当只有个别子类需要某方法时,不妨将该方法从父类中移至该子类。

第5天. 提升字段

与提升方法层级类似,这里需要提升的是字段。

第6天. 降低字段

与降低方法层级类似,这里需要降低的是字段。

第7天. 改名(方法,类,参数)

当方法名,类名,或参数名称不具有描述性,没有含义,或表达不恰当时,需要对这些名称进行重构。

第8天. 使用委派代替继承

这是老生常谈了,has-a is better than is-a。继承打破了类之间的封装性,某些情况下,基类的改变将导致子类行为异常(<Effective Java)。据说,James Gosling对于他所设计的Java语言最后悔的一件事就是允许继承。所以,只有真正是 is-a 的关系时,方可使用继承。

第9天. 提取接口

当不止一个类使用同一个类的方法集合时,那么最好为后者提取出一个接口,以实现解耦。

第10天. 提取方法

简单地来讲,就是一个方法只做一件事,不要在一个方法中糅合多个逻辑。

第11天. 使用策略模式代替switch

如果 switch-case 中的 case 条件经常发生变动(如增加或移除),那么不妨使用策略模式代替之。详见 Switch to Strategy

第12天. 分解依赖

引入中间类分解依赖。

第13天. 提取方法对象

与提取方法类似,只不过要把这些方法放在适合它们的类中。

第14天. 分离职责

单一责任原则,即一个类只做它该做的事情。如果该类所提供的各接口之间不相关,那么把这些不相关的接口分离出去。

第15天. 移除重复内容

一段类似代码多次重复出现,那么最好将它们整合到一个方法中,实现代码共享。

第16天. 封装条件

如果一个条件检查涉及到多个判断,那么最好将这个条件检查提取出来成为一个属性或一个方法,这样有利于程序阅读。

第17天. 提取父类

与第3天的<提升方法层级>类似,区别是在本重构中父类尚不存在,这时需新建父类,然后将方法提升级别至这个父类,以便于父类的其它子类也能共享这些方法。

第18天. 使用条件判断代替异常

本重构是指不要滥用异常处理来控制程序流。

第19天. 提取工厂类

抽象工厂或工厂方法。

第20天. 提取子类

与第4天<降低方法层级>类似,区别是将方法降低到的低级别子类尚不存在,需新建。

第21天. 合并继承

今日重构方法是指,当子类功能其实是可以合并到父类中,那么何必还要多出一个子类呢?

第22天. 分解方法

将一个大方法分成若干小方法进行调用,而不是将逻辑都放在一个大方法里,难以阅读。

第23天. 引入参数对象

当参数个数太多时,是非常不利于客户使用该 API 的,因为这样的方法难以阅读和理解。重构办法是,引入参数对象,将参数组织成适当的对象作为方法参数。

第24天. 分解嵌套条件判断

典型的嵌套条件判断是多层的 if-else 判断,这使得程序不那么易读。典型场景是在方法开始时检查参数,只有所有参数都符合需求时,才开始执行方法功能。不妨逐个检查参数,不符合要求时,马上退出方法。

第25天. 引入契约式设计

Design By Contract or DBC。本条重构个人觉得纯属扯蛋,不能称之为重构。

第26天. 避免双重否定

双重否定难以理解,比如

if ( !customer.IsNotFlagged ) {
...
}

改为

if (customer.IsFlagged) {
...
}

更易于理解

第27天. 去除上帝类

上帝类是指那些融合了各种功能的类,往往造成该类职责不清,该有的有,不该有的也有。典型的如以manager,util 结尾的类。重构方法是,将这些方法分解到适合它们的类中。

第28天. 为布尔方法重命名

还是见原文吧。

第29天. 去除中间人对象

中间人对象是指某对象只是简单的将方法调用转发给目标对象,而其本身并没有做任何工作,留之纯属多余,干脆去掉。

第30天. 尽快返回

与第24天<分解嵌套条件判断>类似,条件不符合则马上返回结果。

第31天. 使用多态代替条件判断

如果需要根据对象所属类型进而做某些工作,那么最好改用多态。

By javafuns on September 7, 2009 at 22:55 · Views: 328 · Permalink · RSS · Leave a comment
Categorized in: Java · Tagged with: ,

关于Arrays.asList()

Arrays.asList()所返回的结果是Arrays的一个静态内部类,该静态内部类只override了AbstractList的有限的几个方法,且对该结果的修改将直接反应到原数组上。

比如,今天我在将数组通过Arrays.asList()转化为list后企图对该list进行remove(index),结果导致UnsupportedOperationException。原因就在于这个静态内部类并没有override父类AbstractList的remove(index)方法。

By javafuns on August 31, 2009 at 13:55 · Views: 563 · Permalink · RSS · Leave a comment
Categorized in: Java · Tagged with: 
  • Highest Rated

  • My PicasaPhotos

    IMG_0696.JPG

    IMG_0664.JPG

    c5bed429f00441ed98250ac3.jpg

  • RSS My del.icio.us

  • My RSS