动态JDBC凭据

时间:2013-09-02 11:01:45

标签: java-ee jdbc datasource

我正在开发一个Java EE Web应用程序。我希望Web应用程序使用JDBC连接池。

在应用程序服务器中定义DataSource非常简单。我的问题是所有数据库连接都是使用相同的凭据(用户/密码)创建的,我需要的是,根据访问Web应用程序的用户,应用程序获得与用户凭据的数据库连接已经加入了Web应用程序。

我正在使用JBoss应用程序服务器和Oracle数据库。

1 个答案:

答案 0 :(得分:1)

我不知道开箱即用的解决方案(仅限配置)以及数据源。

但你可以实现它,看看这些方法:

  • 基于每个请求使用普通JDBC打开数据库连接。您可以在javax.servlet.Filter中打开和关闭连接,以确保没有泄漏连接。例如,使用HttpServletRequest.setAttribute()将连接放入请求范围。这对某些数据库来说足够快,但对其他数据库来说可能太慢了。

  • 如果没有资源(连接数等),您也可以在每个会话的基础上处理它。使用HttpSession.setAttribute()将连接放入会话范围。在这种情况下,还要对过滤器进行额外检查,以确保连接仍然有效(这会处理超时,关闭的套接字等)。如果会话无效,请关闭连接(您可以在HttpSessionListener中执行此操作。)

这些都是简单的方法。您可以优化第一个:在请求之间保持连接打开,在一段时间不活动后关闭。

至于第一个选项,一些代码:

过滤器:

@WebFilter("/pages/public/web/filter/dbconn/*")
public class DbConnectionFilter implements Filter {
    private final static Db db = new Db();

    public void init(FilterConfig fc) throws ServletException {
    }

    public void doFilter(ServletRequest req, ServletResponse resp,
            FilterChain chain) throws IOException, ServletException {

        final HttpServletRequest request = (HttpServletRequest) req;

        try {
            final Connection conn = db.getConnection(
                    request.getParameter("user"),
                    request.getParameter("password"));
            try {
                request.setAttribute("dbConnection", conn);
                chain.doFilter(req, resp);
            } finally {
                request.removeAttribute("dbConnection");
                conn.close();
            }
        } catch (SQLException e) {
            throw new ServletException(e);
        }
    }

    public void destroy() {
    }
}

使用小型实用程序类:

class Db {
    private final String jdbcDriver = "org.postgresql.Driver";
    private final String jdbcUrl = "jdbc:postgresql://localhost/sandbox";

    public Db() {
        try {
            final Class<?> cls = Class.forName(this.jdbcDriver);
            final Driver driver = (Driver) cls.newInstance();
            DriverManager.registerDriver(driver);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    public Connection getConnection(final String jdbcUser,
            final String jdbcPassword) throws SQLException {
        return DriverManager
                .getConnection(this.jdbcUrl, jdbcUser, jdbcPassword);
    }
}

并在您的servlet中,例如:

final Connection conn = (Connection) request.getAttribute("dbConnection");

此代码仅供参考(您应使用request.getRemoteUser(),密码应存储在其他地方,...)

我使用PostgreSQL测试过它:在这种情况下,它足够快,可以在请求的基础上进行测试。