servlet 过滤器中的 StringBuffer 与 StringBuilder
Posted
技术标签:
【中文标题】servlet 过滤器中的 StringBuffer 与 StringBuilder【英文标题】:StringBuffer vs StringBuilder in servlet filter 【发布时间】:2014-07-22 04:28:35 【问题描述】:我知道在 servlet 过滤器中我们应该注意我们的实例变量的线程安全,但是在下面的代码中,我使用了 stringBuilder 和 stringBuffer(一个线程安全,一个不安全)。
public class ValidationFilter implements Filter
//thread safe
// StringBuffer request=new StringBuffer();
//not thread safe--lets check if it works fine
StringBuilder request=new StringBuilder();
////NOTE!!!:even with large request lenght no interference was seen so what is the problem with NOT being thread safe??
@Override
public void init(FilterConfig config) throws ServletException
//
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException
//HERE WE PUT SOME CODE REGARDING TO FILTERING REQUESTS
//HERE WE SHOULD DEFINE A REGEX TO VALIDATE THE STRING IF IT IS NOT THE RIGHT STRING REDIRECT THE REQUEST TO A NEW ADDRESS!!
//String is immutable so we need to use string buffer or string builder
//StringBuffer is synchronized, StringBuilder is not. BUT as far as we know Servlet creates new thread for each request fo we
//need to be synchronised!!
request.append(req.getParameter("line"));
System.out.print(request);
if (request!=null)
Token.trim(request.toString());
res.getWriter().print(request);
else
res.getWriter().print("Error got Null from the client!");
@Override
public void destroy()
//
在这两种情况下,我都使用如下表单发送了一个非常长的请求(实际上通过使用此表单,我发送了两个非常长的请求输入),但我们得到了上述过滤器的输出,我看不到两者之间有任何干扰输出结果意味着这两个线程安全运行并且没有破坏 StringBuffer 或 StringBulder ,所以这意味着在这种情况下线程安全吗??
<!DOCTYPE html>
<html>
<head>
<title>a request page</title>
</head>
<body>
<form action="http://localhost:8080/Compute" method="POST">
Compute it: <input type="text" name="line"><p>
<input type="submit" value="Compute">
</form>
</body>
</html>
【问题讨论】:
为什么要在doFilter
方法中修改过滤器本身的状态根本?无论您使用哪种类型,这似乎都是个坏主意。 (甚至StringBuffer
在同步操作方面也只是“安全”的——这并不意味着您可以在多个独立操作之间有效地共享一个实例。)
您的整个代码毫无意义。 request
永远不会是 null
,因此您的支票已过时。如果你想测试req.getParameter("line")
的返回值对于null
你必须这样做;将其附加到StringBuilder
不会将StringBuilder
变为null
。此外,您仍然将不可变的String
传递给Token.trim(…)
,因此StringBuilder
的可变性在这里无关紧要。无论Token.trim(…)
做什么,都不会影响您的StringBuilder
。
【参考方案1】:
它们都在错误的上下文中使用。过滤器不应保持请求的状态。其他人已经提到的StringBuilder
上的操作不是线程安全的。同样正如 Jon 提到的那样,StringBuffer
上的操作仅在单个操作上是安全的,而不是在聚合操作上是安全的,例如。您最终可能会在同一个StringBuffer
对象上拥有来自多个线程的append(...)
。
【讨论】:
【参考方案2】:您在输出结果之间看不到任何干扰的唯一原因是 StringBuffer 已同步,StringBuilder 未同步。请注意,StringBuffer 和 StringBuilder 对象是可变的,这意味着存储在 String 对象中的值可以更改。
由于StringBuffer
是同步的,使用起来更安全。
【讨论】:
我也用过StringBuilder,发现输出结果之间没有干扰! @user3593084 这只是巧合。 看,两者都是可变的,所以你可能没有找到它,因为StringBuffer
是同步的,所以它可以安全使用。现在,您每秒处理的请求数可能会减少。考虑一下,如果每秒有很多请求,到那时你会目不转睛地看到干扰。以上是关于servlet 过滤器中的 StringBuffer 与 StringBuilder的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Jetty 中的 /* 上映射 servlet 过滤器?