使Java Servlet线程安全

时间:2016-10-27 15:20:16

标签: java multithreading servlets

我一直在从网页上执行我的API获得混合回复。

稍微回溯并发现,Angular正在以正确的方式解雇它,但API对并发请求的响应采取了混合响应。

搜索互联网发现Java servlet中的全局变量可能会触发异常行为,因为一个线程可能会访问当前正由另一个变量处理的变量。

所以我意识到PrintWriter在这里创造了一个问题。但我遇到的困难是如何摆脱这个问题。

也可能是目前的问题与我的结论完全没有关系。 如果我错误地导出任何错误,请纠正我。

@WebServlet(name = "WorkSpaceDetails", urlPatterns = {"/WorkSpaceDetails"})
public class WorkSpaceDetails extends HttpServlet {

    PrintWriter out;
    private static final long serialVersionUID = 1L;


    private void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException, Exception {
        String wid = request.getParameter("id");

        try {

            id = Integer.parseInt(wid);
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            out = response.getWriter();
            Connection conn = null;
            PreparedStatement prx = null;
            PreparedStatement pry = null;
            ResultSet set = null;

            ResultSetMetaData metaData;
            String query;
            JSONObject obj = new JSONObject();
            String WorkSpaceType;
            List<HashMap> completeData = new ArrayList<HashMap>();
            List<String> ColoumnNames = new ArrayList<String>();
            List<String> Data = new ArrayList<String>();
            try {
                query = "-";
                conn = boneCPConnectionPool.getConnection();
                prx = conn.prepareStatement(query);
                prx.setInt(1, id);
                set = prx.executeQuery();
                while (set.next()) {
                    WorkSpaceType = set.getString("WorkSpaceType");
                    System.out.println("WorkSpaceType:" + WorkSpaceType);
                    if (WorkSpaceType.equalsIgnoreCase("1")) {
                        System.out.println("" + 1);
                        query = "-";
                    } else {
                        System.out.println("" + 0);
                        query = "-";
                    }
                    conn = boneCPConnectionPool.getConnection();
                    pry = conn.prepareStatement(query);
                    pry.setInt(1, id);
                    set = pry.executeQuery();
                    metaData = set.getMetaData();
                    int count = metaData.getColumnCount();
                    for (int i = 1; i <= count; i++) {
                        System.out.println("" + metaData.getColumnName(i));
                        ColoumnNames.add(metaData.getColumnName(i));
                    }
                    while (set.next()) {
                        HashMap tmp = new HashMap();
                        for (int i = 0; i < ColoumnNames.size(); i++) {

                            String cname = ColoumnNames.get(i);

                            tmp.put(cname, set.getString(cname));
                            tmp.put("WorkSpaceType", WorkSpaceType);
                        }
                        System.out.println("" + tmp);
                        completeData.add(tmp);
                        generateJson(completeData);
                    }


                }

            } catch (Exception e) {
                e.printStackTrace();
                out.println(e);
            } finally {

                if (conn != null) {
                    try {
                        conn.close();
                    } catch (Exception e) {
                    }
                }
                if (set != null) {
                    try {
                        set.close();
                    } catch (SQLException ignore) {
                    }
                }
                if (prx != null) {
                    try {
                        prx.close();
                    } catch (SQLException ignore) {
                    }
                }
                if (pry != null) {
                    try {
                        pry.close();
                    } catch (SQLException ignore) {
                    }
                }

            }
        } catch (Exception e) {

            JSONObject obj = new JSONObject();
            obj.put("Error", "BLANK ID");
            System.out.println(obj.toString());
            e.printStackTrace();
        }
    }

    private void generateJson(List<HashMap> data) {
        JSONObject obj = new JSONObject();
        try {
            for (HashMap map : data) {

                Iterator it = map.entrySet().iterator();

                while (it.hasNext()) {

                    Map.Entry pair = (Map.Entry) it.next();
                    String key = (String) pair.getKey();

                    String value = (String) pair.getValue();
                    if (value == null) {
                        value = "blank";
                    }
                    obj.put(key, value);
                }
            }

            out.println(obj.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        out = response.getWriter();
        JSONObject obj = new JSONObject();
        try {
            obj.put("Error", "API Protected Get Request");
        } catch (JSONException ex) {
            Logger.getLogger(WorkSpaceDetails.class.getName()).log(Level.SEVERE, null, ex);
        }
        out.println(obj.toString());
        out.close();
        System.out.println("API Protected:Get Request");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        out = response.getWriter();
        JSONObject obj = new JSONObject();
        try {
            processRequest(request, response);
        } catch (NumberFormatException ex) {
            try {
                obj.put("Error", "ID NULL");
            } catch (JSONException ex1) {
                Logger.getLogger(WorkSpaceDetails.class.getName()).log(Level.SEVERE, null, ex1);
            }
            out.println(obj.toString());
        } catch (Exception ex) {

            try {
                obj.put("Error", "TOKEN NULL");
            } catch (JSONException ex1) {
                Logger.getLogger(WorkSpaceDetails.class.getName()).log(Level.SEVERE, null, ex1);
            }
            out.println(obj.toString());
            out.close();

        }
    }

    @Override
    public String getServletInfo() {
        return "Servlet to get info of a Workspace";
    }

}

2 个答案:

答案 0 :(得分:3)

不要将$users->groupBy('country_id') 声明为类成员,而是将其作为PrintWriter out;内的局部变量,就像您在processRequest()doGet()中已经做过的那样。这样,可以同时访问servlet的多个线程不会相互干扰。

更新

doPost()似乎只从processRequest()调用,所以我建议您:

  • 摆脱doPost()班级成员
  • PrintWriter out
  • 中声明本地PrintWriter out
  • doGet()
  • 中声明本地PrintWriter out
  • doPost()作为参数传递给out,其签名可能是:
processRequest()

更新

  • private void processRequest( HttpServletRequest request, HttpServletResponse response, PrintWriter out); 作为参数传递给out
  • generateJson()作为参数传递给&#39; generateJson&#39; out
  • 的方法

processRequest()

private void generateJson(List<HashMap> data, PrintWriter out);

答案 1 :(得分:1)

您必须解决此问题的两个选项如下:

  1. PrintWriter移动到需要它的方法中的局部变量。

  2. 如果您必须将其作为实例/类变量,请使用ThreadLocal变量。使用ThreadLocal将允许访问servlet的每个帖子拥有自己的PrintWriter个实例。

  3. ThreadLocal

    希望这有帮助!