使JavaServlet线程安全
我从网页上得到了关于API执行的混合响应 回溯一点,发现Angular的启动方式是正确的,但是API对并发请求的响应是混合的 搜索互联网发现Javaservlet中的全局变量可能触发异常行为,因为一个线程可能访问另一个变量当前正在处理的变量 因此,说到这里,我意识到,使JavaServlet线程安全,java,multithreading,servlets,Java,Multithreading,Servlets,我从网页上得到了关于API执行的混合响应 回溯一点,发现Angular的启动方式是正确的,但是API对并发请求的响应是混合的 搜索互联网发现Javaservlet中的全局变量可能触发异常行为,因为一个线程可能访问另一个变量当前正在处理的变量 因此,说到这里,我意识到,PrintWriter正在制造一个问题。但我遇到的困难是如何摆脱这个问题 而且也可能是目前的问题根本与我的结论无关。 请纠正我错误推导出的任何错误 @WebServlet(name = "WorkSpaceDetails", url
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";
}
}
@WebServlet(name=“WorkSpaceDetails”,urlPatterns={”/WorkSpaceDetails})
公共类WorkSpaceDetails扩展了HttpServlet{
打印输出;
私有静态最终长serialVersionUID=1L;
私有void processRequest(HttpServletRequest请求、HttpServletResponse响应)
抛出ServletException、IOException、Exception{
字符串wid=request.getParameter(“id”);
试一试{
id=Integer.parseInt(wid);
setContentType(“应用程序/json”);
响应。setCharacterEncoding(“utf-8”);
out=response.getWriter();
连接conn=null;
PreparedStatement prx=null;
PreparedStatement pry=null;
结果集=null;
结果元数据;
字符串查询;
JSONObject obj=新的JSONObject();
字符串工作空间类型;
List completeData=new ArrayList();
列表列名称=新的ArrayList();
列表数据=新的ArrayList();
试一试{
query=“-”;
conn=boneCPConnectionPool.getConnection();
prx=连接准备状态(查询);
prx.setInt(1,id);
set=prx.executeQuery();
while(set.next()){
WorkSpaceType=set.getString(“WorkSpaceType”);
System.out.println(“工作空间类型:“+WorkSpaceType”);
if(WorkSpaceType.equalsIgnoreCase(“1”)){
系统输出打印项次(“+1”);
query=“-”;
}否则{
系统输出打印项次(“+0”);
query=“-”;
}
conn=boneCPConnectionPool.getConnection();
pry=conn.prepareStatement(查询);
撬动装置(1,id);
set=pry.executeQuery();
metaData=set.getMetaData();
int count=metaData.getColumnCount();
对于(int i=1;i而不是将PrintWriter out;
声明为类成员,而是将其作为processRequest()
中的局部变量,就像您在doGet()
和doPost()
中已经做的那样。这样,可以同时访问servlet的多个线程就不会相互干扰
更新
似乎只有从doPost()
调用了processRequest()
,因此我建议您:
- 摆脱
PrintWriter out
类成员
- 在
doGet()中声明本地PrintWriter输出
- 在
doPost()中声明本地PrintWriter输出
- 将
作为参数传递给processRequest()
,其签名可以是:
private void processRequest(
HttpServletRequest请求、HttpServletResponse响应、PrintWriter输出);
更新
- 将
作为参数传递给generateJson()
- 将
out
作为参数传递给调用processRequest()处的'generateJson'方法
private void generateJson(列表数据,打印输出);
generateJson(completeData,out);
不要将PrintWriter out;
声明为类成员,而是将其作为processRequest()
中的局部变量,就像您在doGet()
和doPost()中已经做的那样
。这样,可以同时访问servlet的多个线程就不会相互干扰
更新
似乎只有从doPost()
调用了processRequest()
,因此我建议您:
- 摆脱
PrintWriter out
类成员
- 在
doGet()中声明本地PrintWriter输出
- 在
doPost()中声明本地PrintWriter输出
- 将
作为参数传递给processRequest()
,其签名可以是:
private void processRequest(
HttpServletRequest请求、HttpServletResponse响应、PrintWriter输出);
更新
- 将
作为参数传递给generateJson()
- 将
out
作为参数传递给调用processRequest()处的'generateJson'方法
private void generateJson(列表数据,打印输出);
generateJson(completeData,out);
解决此问题的两个选项如下:
将PrintWriter
移动到需要它的方法中的局部变量
如果必须将其作为实例/类变量,则使用ThreadLocal
变量。使用ThreadLocal
将允许访问servlet
的每个线程都有自己的PrintWriter
实例
希望这有帮助!解决此问题的两个选项如下:
将PrintWriter
移动到需要它的方法中的局部变量