[英]Making Java Servlet Thread safe
I've been getting mixed up responses on the execution of my API from webpage. 我对网页执行API的反应一直很混乱。
Backtracked a little and found out, Angular was firing it the right way, but the API responded with mixed responses for concurrent requests. 回溯了一点,发现了,Angular正确地触发了它,但是API响应了并发请求的混合响应。
Searched the internet found out Global variables in Java servlet may trigger the abnormal behavior as one thread might access the variable currently being processed by another variable. 在互联网上搜索发现Java servlet中的全局变量可能会触发异常行为,因为一个线程可能会访问另一变量当前正在处理的变量。
So coming to the point I realized PrintWriter
is creating a problem here. 因此,我意识到
PrintWriter
在这里造成了问题。 But what I'm experiencing a difficulty with is how to get out of the problem. 但是我遇到的困难是如何解决这个问题。
And also may be the current problem is not at all related to my conclusions. 也可能是当前的问题与我的结论根本无关。 Please correct me wherever I've wrongly derived anything wrong.
如果我错误地得出任何错误,请纠正我。
@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";
}
}
Instead of declaring PrintWriter out;
而不是声明
PrintWriter out;
as a class member, do it as a local variable inside processRequest()
, like you're already doing in doGet()
and doPost()
. 作为类成员,请将其作为
processRequest()
的局部变量进行,就像您已经在doGet()
和doPost()
所做的那样。 This way, the multiple threads that may access the servlet concurrently won't interfere with each other. 这样,可以同时访问servlet的多个线程不会互相干扰。
It seems that processRequest()
is only called from doPost()
, so I suggest you to: 看来
processRequest()
仅从doPost()
调用,所以我建议您:
PrintWriter out
class member PrintWriter out
类成员 PrintWriter out
in doGet()
doGet()
声明本地PrintWriter out
PrintWriter out
in doPost()
doPost()
声明一个本地PrintWriter out
out
as a parameter to processRequest()
, whose signature may be: out
作为参数processRequest()
其签名可能是: private void processRequest(
HttpServletRequest request, HttpServletResponse response, PrintWriter out);
out
as a parameter to generateJson()
out
作为参数传递给generateJson()
out
as a parameter to call made to 'generateJson' method at processRequest()
out
,以在processRequest()
对“ generateJson”方法进行调用 private void generateJson(List<HashMap> data, PrintWriter out);
generateJson(completeData, out);
Two of the options you have to fix this issue are as follows: 您必须解决此问题的两个选项如下:
Move PrintWriter
to local variables inside methods that need it. 将
PrintWriter
移到需要它的方法内的局部变量。
If you absolutely have to have it as an instance/class variable then use a ThreadLocal
variable. 如果您绝对必须将其作为实例/类变量,请使用
ThreadLocal
变量。 Using ThreadLocal
would allow each thread accessing your servlet
to have its own PrintWriter
instance. 使用
ThreadLocal
将允许每个访问您的servlet
线程拥有自己的PrintWriter
实例。
Hope this helps! 希望这可以帮助!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.