`
lighter
  • 浏览: 495567 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

小心给servlet忽悠了

阅读更多
你真的会写线程安全的servlet吗?

很多人认为servlet随便怎样写可以的,反正是线程安全的,没有什么关系的.那我们来看看下面的这一个例子吧.
首先要看一下小段的servlet代码,如下:
public class Test extends HttpServlet {
   String name;

   protected void doPost (HttpServletRequest req,
                       HttpServletResponse res) {
     name = req.getParameter("name");
     ...
     out.println(name + ", thanks for visiting!");
   }
}


我相信不少人的代码在经意或不经意间都这样写过,然后自己一个跑一下程序,可以啦,然后就不再理会啦,上面的程序是有问题的,假如有两个用户同时用到这一段代码的程序的功能,就有可能会出现如下这种情况:

引用
Thread 1: assign "A" to name
Thread 2: assign "B" to name
Thread 1: print "B, thanks for visiting!"
Thread 2: print "B, thanks for visiting!"


怎样改写呢?其实也比较简单的,比较出名的找bug的工具Fortify推荐如下一种方式如下:
public class Test extends HttpServlet {

   protected void doPost (HttpServletRequest req, HttpServletResponse res) {
	RequestHandler handler = new RequestHandler();
	handler.handle(req, res);
   }
}

public class RequestHandler {

   String name;

   public void handle(HttpServletRequest req, HttpServletResponse res) {
     name = req.getParameter("name");
     ...
     out.println(name + ", thanks for visiting!");
   }
}


请记得这一句话:
引用
Do not use Servlet member fields for anything but constants. (i.e. make all member fields static final).


刚才今天我的一个同事也写了类似上面的有bug的那一个servlet程序,我也改造过来了;
不过是用了另一种方式实现的,用的是ThreadLocal这一个关键类,伪代码如下:
public class Test extends HttpServlet {
	private static final ThreadLocal parameterLocal = new ThreadLocal();  
	
	private static final ThreadLocal filesLocal = new ThreadLocal();      
	
	protected Map getFiles() {
		Map files = (HashMap)filesLocal.get();
		if(files==null){
			files = new HashMap();
			filesLocal.set(files);
		}
		return files;
	}

	protected  Map getParameters() {
		Map parameters = (HashMap)parameterLocal.get();
		if(parameters==null){
			parameters = new HashMap();
			parameterLocal.set(parameters);
		}
		return parameters;
	}

	public void doPost(HttpServletRequest request, HttpServletResponse response) {
			.....//可以通过getParameters()返回Map对象
			log.info(getParameters().get("possess"));
	
			Iterator iterator = getFiles().values().iterator(); //可以通过getFiles()返回Map对象
			FileItem item = (FileItem) iterator.next();
			.....
	}
}


分享到:
评论
2 楼 CherryRemind 2008-01-08  
Servlet 不用成员变量,变量放在method里面, 遇到过类似问题
1 楼 qiuriyuchen 2007-12-14  
晕,不知在搞什么,这样不就可以了吗  
public class Test extends HttpServlet { 
      
     
       protected void doPost (HttpServletRequest req, 
                           HttpServletResponse res) { 
        String  name = req.getParameter("name"); 
         ... 
         out.println(name + ", thanks for visiting!"); 
       } 
  } 

相关推荐

Global site tag (gtag.js) - Google Analytics