2014-07-10 10 views
9

ich eine RESTful API mit Java und Cassandra 2.x bauen verwenden möchte (auf Jersey-Framework). Ich bin neu in beiden Technologien, also möchte ich Sie fragen, ist das der richtige Weg, Cassandra-Treiber zu integrieren und zu teilen.Was ist der richtige Weg Cassandra Treiber von einer Web-Anwendung

0. Holen Sie sich den Treiber obwohl Maven

<dependency> 
      <groupId>com.datastax.cassandra</groupId> 
      <artifactId>cassandra-driver-core</artifactId> 
      <version>2.0.3</version> 
</dependency> 

1. Funktionalität Wrap-Treiber mit einer Client-Klasse:

package com.example.cassandra; 

import com.datastax.driver.core.*; 

public class Client { 

    private Cluster cluster; 
    private Session session; 

    public Client(String node) { 
     connect(node); 
    } 

    private void connect(String node) { 
     cluster = Cluster.builder() 
      .addContactPoint(node) 
      .build(); 

     session = cluster.connect(); 
    } 

    public ResultSet execute(String cql3) { 
     return session.execute(cql3); 
    } 

    public void close() { 
     cluster.close(); 
    } 

} 

2. ich den Client in ContextListener insatiate und Aktie es aber Context-Attribut

package com.example.listener; 

import javax.servlet.ServletContext; 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 

import com.example.cassandra.Client; 

public class ExampleContextListener implements ServletContextListener { 

    Client cassandraClient; 

    public void contextInitialized(ServletContextEvent servletContextEvent) { 
     ServletContext ctx = servletContextEvent.getServletContext(); 

     cassandraClient = new Client(ctx.getInitParameter("DBHost")); 
     ctx.setAttribute("DB", cassandraClient); 
    } 

    public void contextDestroyed(ServletContextEvent servletContextEvent) { 
     cassandraClient.close(); 
    } 

} 

3. Nun habe ich den Client aus dem Kontext des Servlets und es verwenden,

Client client = (Client) context.getAttribute("DB"); 
client.execute("USE testspace;"); 

ResultSet rs = client.execute("SELECT * from users;"); 
for (Row row : rs) { 
    output += row.getString("lname") + "|"; 
} 

Ist das der richtige Weg, es (beide von Leistung und architektonischer Sicht) zu tun?

Voll Beispiel verfügbar auf: https://github.com/lukaszkujawa/jersey-cassandra

+0

Hallo, ich frage mich, wenn Sie mir die beste Art und Weise sagen könnte, die Sie in Ihrer Web-App angenommen? – niaomingjian

Antwort

9

ich gerade entwickelt, was Sie entwickeln werden. Was du geschrieben hast, funktioniert, aber es ist nicht mein Lieblingsansatz. Ich würde lieber ein Singleton erstellen (seit 1 Sitzung ist genug für eine Anwendung). Joshua Bloch Enum des Singletons folgendes Muster hier ist das, was ich tat

public enum Cassandra { 

     DB; 

     private Session session; 
     private Cluster cluster; 
     private static final Logger LOGGER = LoggerFactory.getLogger(Cassandra.class); 

     /** 
     * Connect to the cassandra database based on the connection configuration provided. 
     * Multiple call to this method will have no effects if a connection is already established 
     * @param conf the configuration for the connection 
     */ 
     public void connect(ConnectionCfg conf) { 
      if (cluster == null && session == null) { 
       cluster = Cluster.builder().withPort(conf.getPort()).withCredentials(conf.getUsername(), conf.getPassword()).addContactPoints(conf.getSeeds()).build(); 
       session = cluster.connect(conf.getKeyspace()); 
      } 
      Metadata metadata = cluster.getMetadata(); 
      LOGGER.info("Connected to cluster: " + metadata.getClusterName() + " with partitioner: " + metadata.getPartitioner()); 
      metadata.getAllHosts().stream().forEach((host) -> { 
       LOGGER.info("Cassandra datacenter: " + host.getDatacenter() + " | address: " + host.getAddress() + " | rack: " + host.getRack()); 
      }); 
     } 

     /** 
     * Invalidate and close the session and connection to the cassandra database 
     */ 
     public void shutdown() { 
      LOGGER.info("Shutting down the whole cassandra cluster"); 
      if (null != session) { 
       session.close(); 
      } 
      if (null != cluster) { 
       cluster.close(); 
      } 
     } 

     public Session getSession() { 
      if (session == null) { 
       throw new IllegalStateException("No connection initialized"); 
      } 
      return session; 
     } 
} 

Und im Kontext Zuhörer Ich verbinde oder Herunterfahren nennen. Da alle Ausnahmen in neuen Treiber deaktiviert sind, ist mein Tipp für Sie, Ihre eigene Implementierung der Jersey ExceptionMapper Mapping DriverException zu erstellen. Denken Sie darüber hinaus daran, mit PreparedStatements statt mit Strings zu arbeiten, damit Cassandra die Abfrage nur einmal analysieren kann. In meiner Anwendung befolgte ich die oben genannten Muster auch für die Abfragen (ein Enum Singleton, die Anweisungen vorbereiten, wenn sie das erste Mal geladen werden und dann Methoden zur Verwendung dieser Anweisungen verfügbar machen).

HTH, Carlo

+0

Danke nochmal Carlo. Wie Sie sehen können, gab ich PHP auf und wechselte zu Java. Es wird hier kein Problem mit den Fahrern geben;) –

+0

Definitiv kein Problem. Der neue Fahrer ist sehr gut gemacht und was Jersey für eine erholsame Auszeit bietet, ist einfach unglaublich. Sie werden Ihre Wahl nicht bereuen! Viel Spaß, Carlo –

+1

Hallo Carlo, Sie wollen sagen, dass nur ein Singleton Cassandra Session-Objekt für eine Webanwendung ausreicht. Wenn die Anzahl meiner Anwendungsanwender 1000 ist. Wird ein einzelnes Sitzungsobjekt mein Szenario erfüllen? Bitte klären Sie meine Anfrage. Danke – Gnana