ITKeyword,专注技术干货聚合推荐

注册 | 登录

Dubbo教程持续集成篇--SonarQube代码质量管理平台的配置与使用

whs_321 分享于 2016-06-04

推荐:SonarQube代码质量管理平台安装与使用

Sonar简介 Sonar是一个用于代码质量管理的开源平台,用于管理源代码的质量,可以从七个维度检测代码质量 通过插件形式,可以支持包括 java,C#,C/C++,PL/SQL,Cobo

up vote 1 down vote favorite 1

Servlets runs in several threads, so my question is:

If I have a lot of servlets which call some utility class (DbUtils, for example

Connection c = DbUtils.getConnection();
//....some action with db here

should I assume additional actions for synchronization inside DbUtils?

Actually I'd like to inherit HttpServlet into something like DatabaseInvokerServlet:

public abstract class DatabaseInvokerServlet extends HttpServlet

with methods:

public abstract void getResultSets(Connection connection) throws SQLException;
private AbstractUser currentUser;
private HttpServletRequest request;
private HttpServletResponse response;
protected void processData() {}
protected void afterRequestProcessed() throws ServletException, IOException {}
protected void beforeRequestProcessed() throws ServletException, IOException {}

protected void execute() {
    Connection c = null;
    try {
        c = DbUtils.getConnection();
        getResultSets(c);
        processData();
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        try {
            if (c != null) {
                c.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

public HttpServletRequest getRequest() {
    return request;
}

public HttpServletResponse getResponse() {
    return response;
}

public AbstractUser getCurrentUser() {
    return currentUser;
}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=UTF-8");
    response.setCharacterEncoding("UTF-8");


    this.request = request;
    this.response = response;
    this.currentUser = (AbstractUser) request.getSession().getAttribute("currentUser");

}

Then I'd just inherit my DatabaseInvokerServlet to new servlets to do custom stuff. The reason is not to copy-paste database invoke block with try-catch-finally in a lot of places.

But as I can see such approach won't work because of synchronization issues. Am I right?

java servlets jdbc synchronization share | improve this question edited Mar 18 '11 at 12:06 BalusC 722k 234 2663 2844 asked Mar 18 '11 at 7:00 Kerb 676 1 12 29      Please post the code of DbUtils.getConnection(); –  Hendrik Brummermann Mar 18 '11 at 7:22 add a comment  | 

4 Answers 4

active oldest votes up vote 3 down vote accepted

If the DbUtils creates the connection in the same thread, like as:

public static Connection getConnection() throws SQLException {
    return DriverManager.getConnection(url, username, password);
}

Then it's threadsafe.

But if the connection is a class variable, like as:

private static Connection connection = DriverManager.getConnection(url, username, password);

public static Connection getConnection() throws SQLException {
    return connection;
}

Then it is definitely not threadsafe because the same connection will be shared among all threads. Also when it's closed in a thread, all subsequent threads won't be able to use the connection because it's not open anymore. Also when it's never closed, the DB will timeout the connection sooner or later, usually after a few hours, and your application won't work anymore because the connection is not open anymore.

As to the servlet,

public abstract class DatabaseInvokerServlet extends HttpServlet {
    private AbstractUser currentUser;
    private HttpServletRequest request;
    private HttpServletResponse response;
    // ...
}

it's definitely not threadsafe. You're assigning the current user, request and response as instance variables. From each servlet class, there is only one instance during the application's lifetime. This instance is shared among all visitors/sessions throughout the entire application's lifetime. Each HTTP request operates in a separate thread and uses the same instance.

Imagine two simultaneous visitors: visitor A will set the current user, request and response. The DB process however takes a long time. Before the response of visitor A has returned, visitor B calls the same servlet and thus the current user, request and response will be overriden. Then, the query of visitor A finishes and wants to write to the response, it is instead writing to the response of visitor B! Visitor B sees the result of the query of visitor A and visitor A sees nothing on his screen!

You should never assign request/session-specific data as instance variable of the servlet. You should keep them method (thread) local.

public abstract class DatabaseInvokerServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        AbstractUser currentUser = request.getSession().getAttribute("user");
        // Keep the variables in the method block! 
        // Do not assign them as instance variable!
    }
}

As to the complete picture, this approach is clumsy. The database access layer should have nothing to do with servlets. It should operate in its own standalone classes which you could just construct/invoke in every other Java class, any servlet class, or a normal application with main(), or whatever. You should not have any single line of java.sql.* imports in your servlet classes (expect of maybe SQLException if it is not abstracted away). You should not have any single line of javax.servlet.* imports in your database classes.

See also:

share | improve this answer answered Mar 18 '11 at 12:05 BalusC 722k 234 2663 2844 add a comment  |  up vote 1 down vote

If the utility class has state (example: class or instance variables) most probably yes.

share | improve this answer answered Mar 18 '11 at 7:02 Riccardo Cossu 1,998 1 18 36 add a comment  |  up vote 1 down vote

If I guess right the DBUtils is returning new instance for each call of getConnection(). And as the DBUtils class is a utility class so it shouldn't be maintaining any state. In this scenario no you dont need any addition efforts for synchronization.

share | improve this answer answered Mar 18 '11 at 7:06 Amit 173 5 15 add a comment  |  up vote 1 down vote

Servlets runs in several threads.

The J2EE spec says there is only one instance per servlet class running in one web container for non single thread servlet. 

Servlet 2.3 specs

A servlet container may send concurrent requests through the service method of the servlet. To handle the requests the developer of the servlet must make adequate provisions for concurrent processing with multiple threads in the service method.

Synchronisation in servlet.

Never have an member variable in a servlet, it is not thread safe.
share | improve this answer answered Mar 18 '11 at 7:07 Dead Programmer 7,720 15 61 102 add a comment  | 

Your Answer

  draft saved draft discarded

Sign up or log in

Sign up using Google

Sign up using Facebook

Sign up using Email and Password

Post as a guest

Name Email

Post as a guest

Name Email discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged java servlets jdbc synchronization or ask your own question.

推荐:SonarQube代码质量管理平台搭建手册(集成jenkins进行自动化代码审查)

SonarQube代码质量管理平台搭建手册(集成jenkins进行自动化代码审查) 1.安装SonarQube 1.1 步骤1 准备好java环境(本次测试系统为windows,linux环境下可参照w

up vote 1 down vote favorite 1 Servlets runs in several threads, so my question is: If I have a lot of servlets which call some utility class (DbUtils, for example Connection c = D

相关阅读排行


用户评论

游客

相关内容推荐

最新文章

×

×

请激活账号

为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。

您的注册邮箱: 修改

重新发送激活邮件 进入我的邮箱

如果您没有收到激活邮件,请注意检查垃圾箱。