这个标题应该会慢慢改成<EJB解决方案>,今天看到论坛前辈们谈论"j2ee without ejb"的书,讨论了关于EJB的一些缺陷,更让我有兴趣去EJB的世界瞅个究竟了..
瞅了一晚上,大致结论是:EJB2.X确实是个失败. EJB3.0放弃了从前的框架,重新设计,至于效果怎样,还没来得及瞅.
看到IBM DEVELOPER的文章,对JMS有个初步的了解.以后有时间再整理下文档..
JMS已经作为JAVA技术中关于企业级消息传递的规范了.先看看下面一段话:
JMS开发者提供了一套规范文档和API.在JAVA开发JMS应用级程序的时候需要遵循这套规范来做.这也是JMS的优点,以广泛的业界支持和开放标准为基础。
简单来说:JMS大致分为三种模型:
1,one to one: Client ---------->queue------------->Server
2,one to many: Client ---------->queue------------->Server1,Server2,....
2,many to many: Client1,Client2...---------->queue------------->Server1,Server2,...
JMS消息的结构相当直观。其中有一个部分(section)用于路由、寻址和消息识别;还有一个可选的部分,在这个部分中可以传递一些特定于应用(application-specific)的参数;第三个部分存放的是消息的有效负荷(文本 、字节、值映射(value map)、对象,等等)。这三个部分分别被称为头部、属性和主体.
根据企业的需要,可选用与JAVA的三种解决方案:简单JMS客户机,结合JMS使用的会话bean,以及消息驱动bean.
JNDI灵活了消息的目的地:
可达到以下效果:
JNDI作为一种技术,不仅仅解决目的地,而可以解决很多需要与供应商无关的事情.
如JMS其他的建立连接问题,不同供应商订阅主题通配符号的问题等.
而解决这些问题的基础实际上就是把这些不同供应商的不同配置信息写到.properties文件里,JAVA通过Properties类进行lookup查询.
文件传输JMS解决方案
构架图:
平台无关性:
通过JNDI
public final static String CONNECTION_FACTORY_LOOKUP_NAME_KEY = "CONNECTION_FACTORY_LOOKUP_NAME"; public final static String FILE_TRANSFER_QUEUE_LOOKUP_NAME_KEY = "FILE_TRANSFER_QUEUE_LOOKUP_NAME"; public final static String JMS_PROVIDER_CLASS_KEY = "JMS_PROVIDER_CLASS"; public void init() throws NamingException { InitialContext jndi = createInitialContext(); initConnectionFactory(jndi); initFileTransferQueue(jndi); } public QueueConnection createConnection() throws JMSException {return getConnectionFactory().createQueueConnection(getUserName(), getPassword()); } public void initConnectionFactory(InitialContext jndi) throws NamingException { setConnectionFactory((QueueConnectionFactory)jndi.lookup (getProperties().getProperty(CONNECTION_FACTORY_LOOKUP_NAME_KEY))); } public void initFileTransferQueue(InitialContext jndi) throws NamingException { setFileTransferQueue((Queue) jndi.lookup (getProperties().getProperty(FILE_TRANSFER_QUEUE_LOOKUP_NAME_KEY))); }
性能:
消息一旦确认已发到对方server,马上就进行数据传输.
public void sendMessage(byte[] payload, boolean persistent) throws SendFailedException { QueueSender sender = null; try { Message message = createMessage(payload); sender = createSender (persistent ? DeliveryMode.PERSISTENT : DeliveryMode.NON_PERSISTENT); sender.send(message); getClient().getLogService().logInfo(getName() + " sent message " + message.getJMSMessageID() + "."); } catch (JMSException exception) { getClient().getLogService().logError ("JMS exception processing " + getName(),exception); stop(); throw new SendFailedException("JMS Message Send Failed"); } try { sender.close(); } catch (JMSException ignore) { getClient().getLogService().logInfo(getName() + " failed to close sender. Processing will continue."); } }
Stateless Bean
实现类的命名规则是: 接口+Bean;
客户端执行规则:Stateless bean发布到EJB容器后,容器就会为他创建一个对象,并通过这个对象调用Bean的业务方法。
运行规则:远程进程共享这个Bean
Statefull Bean
实现类的命名规则是:Serial+接口+Bean
客户端执行规则:Staefull bean发布到EJB容器后,容器就会为他创建一个对象,并通过这个对象调用Bean的业务方法。JSP通过Session缓存来取每个用户对应的对象
运行规则:每个用户独立一个Bean
附:“有一个古老的计算机科学笑话:每个编程问题都可以仅仅用一个抽象层(或间接的)来解决。在 J2EE 中,JNDI 是把 J2EE 应用程序合在一起的粘合剂,但还没有紧到无法让人很容易地把它们分开并重新装配。JNDI 提供的间接寻址允许跨企业交付可伸缩的、功能强大且很灵活的应用程序。这是 J2EE 的承诺,而且经过一些计划和预先考虑,这个承诺是完全可以实现的。实际上,它要比许多人想像的容易得多。 ”