最近关注OSGI,是因为听说OSGI的class load机制有别于双亲委托,是网状搜索。所以可以实现组件的动态替换
于是找了个成熟的OSGI框架 – Felix http://felix.apache.org/site/index.html
看了看Felix的Sample,发现大量的在讲消费者生产者解耦。恩,如果你都解耦了,变成用http/tcp协议通信了,那确实都是可插拔替换的了。
但是,但是这样和RMI或者WebService有什么区别吗?
上网搜OSGI的好处,通篇都是讲OSGI可以适用于SOA。
那么,如何适用呢?如何部署呢?一个Bundle公开注册成一个service?一组service部署在一台物理机器上?同一台物理机器上的service如何通信?也通过BundleContext? BundleContext如何部署?部署在单独物理机器上?要不要做双机热备?
苍天啊!!谁来解答我的问题?
附上一个Felix的Sample
首先是被调用者,用来在嵌入式DB中生成数据,查询数据。被Activator注册到BundleContext上。
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.developers.blog.osgi.basic.persistence;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
/**
*
* @author rafsob
*/
public class Activator implements BundleActivator {
private ServiceRegistration serviceRegistration;
public void start(BundleContext bundleContext) throws Exception {
PersistenceService persistenceService =
new PersistenceService();
serviceRegistration =
bundleContext.registerService(
PersistenceService.class.getName(), persistenceService, null
);
}
public void stop(BundleContext bundleContext) throws Exception {
serviceRegistration.unregister();
}
}
package org.developers.blog.osgi.basic.persistence;
import org.developers.blog.osgi.basic.persistence.vo.Customer;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.developers.blog.osgi.basic.persistence.internal.DerbyManager;
/**
* Hello world!
*
*/
public class PersistenceService
{
private DerbyManager derbyManager;
public PersistenceService() throws Exception {
this.derbyManager = new DerbyManager();
}
public List<Customer> getCustomers() throws PersistenceException {
Statement stmt = null;
ResultSet rs = null;
List<Customer> customers = new ArrayList<Customer>();
try {
Connection connection = derbyManager.getConnection();
stmt = connection.createStatement();
rs = stmt.executeQuery("SELECT * FROM CUSTOMER");
while (rs.next()) {
customers.add(
new Customer(
rs.getString("firstName"),
rs.getString("secondName"),
rs.getString("address"),
rs.getString("city"),
rs.getString("country"),
rs.getString("email")));
}
} catch (Exception ex) {
throw new PersistenceException("DB query failed", ex);
} finally {
try {
rs.close();
} catch (SQLException ex) {
throw new PersistenceException("DB closing failed", ex);
}
try {
stmt.close();
} catch (SQLException ex) {
throw new PersistenceException("DB closing failed", ex);
}
}
return customers;
}
}
嵌入式DB管理的小类
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.developers.blog.osgi.basic.persistence.internal;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
/**
*
* @author rafsob
*/
public class DerbyManager {
private final static String DERBY_DRIVER =
"org.apache.derby.jdbc.EmbeddedDriver";
private final static String DATABASE_NAME = "persistenceDB";
private Connection connection = null;
public DerbyManager() throws Exception {
init();
}
public void init() throws Exception {
Class.forName(DERBY_DRIVER).newInstance();
String property = "java.io.tmpdir";
String tempDir = System.getProperty(property);
String jdbcURL = "jdbc:derby:" + tempDir + "/" + DATABASE_NAME + ";create=true";
System.out.println(jdbcURL);
connection = DriverManager.getConnection(jdbcURL);
generateDummyCustomers();
}
public Connection getConnection() {
return this.connection;
}
public void destroy() throws Exception {
connection.close();
DriverManager.getConnection("jdbc:derby:;shutdown=true");
}
public void generateDummyCustomers() throws Exception {
Statement stmt = null;
try {
stmt = connection.createStatement();
stmt.executeUpdate("DROP TABLE customer");
stmt.close();
} catch (Exception ex) {}
String createTable = "CREATE TABLE customer (" +
"id INT NOT NULL GENERATED ALWAYS AS IDENTITY," +
"firstName VARCHAR(128)," +
"secondName VARCHAR(128)," +
"address VARCHAR(128)," +
"city VARCHAR(128)," +
"country VARCHAR(128)," +
"email VARCHAR(128))";
stmt = connection.createStatement();
stmt.executeUpdate(createTable);
stmt.close();
String insert = "INSERT INTO customer " +
"(firstName, secondName, address, city, country, email) VALUES " +
"('Rafael','Sobek','Kaiseralle','Karlsruhe','Germany','info@developers-blog.org')";
stmt = connection.createStatement();
stmt.executeUpdate(insert);
stmt.close();
}
}
最后是消费者,通过Felix的whiteboard pattern公开成servlet,调用注册过的PersistenceService实现对DB数据的查询