从Web应用程序使用Cassandra驱动程序的正确方法是什么? [英] What is the right way to use Cassandra driver from a web application

查看:143
本文介绍了从Web应用程序使用Cassandra驱动程序的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Java和Cassandra 2.x(在Jersey框架上)构建一个RESTful API。我是两个技术的新手,所以我想问你是正确的方式来集成和共享Cassandra驱动程序。

I want to build a RESTful API with Java and Cassandra 2.x (on Jersey framework). I'm new to both technologies so I would like to ask you is that the correct way to integrate and share Cassandra driver.

0。通过Maven获取驱动程序

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

1。使用Client类封装驱动程序的功能:

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。我在ContextListener中祈祷客户端并通过上下文属性共享它

2. I insatiate the client in ContextListener and share it though context attribute

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。现在我从servlet的上下文中获取客户端并使用它。

3. Now I get the client from servlet's context and use it

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") + "|";
}

这是正确的方式视图)?

Is that the correct way to do it (both from performance and architectural point of view)?

提供完整范例: https://github.com/lukaszkujawa/ jersey-cassandra

推荐答案

我刚刚开发了你要开发的东西。你写的工作,但它不是我最喜欢的方法。我宁愿创建一个Singleton(因为一个会话足够一个应用程序)。以下是Joshua Bloch枚举的单例模式这里是我做的

I just developed what you are going to develop. What you wrote works but it's not my favourite approach. I'd rather create a Singleton (since 1 session is enough for an application). Following Joshua Bloch enum's singleton's pattern here is what I did

    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;
        }
}

在上下文监听器中,我调用connect或shutdown。
由于新驱动程序中的所有异常都未选中,因此我的提示是创建自己的Jersey ExceptionMapper映射DriverException的实现。还有一件事,想想使用PreparedStatements而不是字符串,以便Cassandra只解析查询一次。在我的应用程序中,我也遵循上述模式的查询(枚举单例,准备语句加载第一次,然后公开方法使用这些语句)。

And in the context listener I call connect or shutdown. Since all exceptions in new driver are unchecked my tip for you is to create your own implementation of the Jersey ExceptionMapper mapping DriverException. One more thing, think about working with PreparedStatements rather than Strings so that Cassandra parse the query only once. In my application I followed the above patterns also for the queries (an enum singleton that prepare statements when loaded first time and then expose methods to use these statements).

HTH,
Carlo

HTH, Carlo

这篇关于从Web应用程序使用Cassandra驱动程序的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆