![](/img/trans.png)
[英]Should I avoid use of filters in servlets to check whether user is logged in
[英]Why should I avoid using InheritableThreadLocal in servlets?
我在Servlet
類中使用了InheritableThreadLocal
。 因此它可以從它的子線程中獲得。 在線程池執行程序中使用InheritableThreadLocal
是邪惡的嗎? 。 比如servlet線程池。
我的問題。
1)為什么我們要避免在servlets中使用InheritableThreadLocals
?
2)在InheritableThreadLocal
是否可以進行內存泄漏?
3) InheritableThreadLocal
還有其他選擇嗎?
4)如果線程將被重用會發生什么, threadlocal
存儲的值將不會被清除?
我的實時場景
public class UserAccessFilter implements javax.servlet.Filter {
static final InheritableThreadLocal<String> currentRequestURI = new InheritableThreadLocal<String>();
public void doFilter(ServletRequest req, ServletResponse resp , FilterChain fc) throws IOException, ServletException{
String uri = request.getRequestURI();
fc.doFilter(request, response);
}
}
public class MailServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String mailCount = req.getParameter("mailCount");
if(mailCount != null && !"".equals(mailCount) && mailCount.matches("[0-9]+")){
MailThread mailThread = new MailThread("xxx@gmail.com", generateToAddress(Integer.parseInt(mailCount))); //NO I18N
Thread t = new Thread(mailThread);
t.start();
}
resp.getWriter().println("Mail Servlet.............."); //NO I18N
}
}
class MailThread implements Runnable{
private String from;
private String to;
public MailThread(String from , String to){
this.from = from;
this.to = to;
}
@Override
public void run() {
sendMail();
}
public void sendMail(){
//I want this uri from child threads. I can't pass this value to this constructor.
String uri = currentRequestURI.get();
//Do Mail Operations
}
}
過濾器 - > Servlet A - >子線程--->郵件線程(這里我得到過濾器中設置的值)。
為什么我們要避免在servlet中使用InheritableThreadLocals?
它們代表了將信息從一個請求泄漏到另一個請求的潛在途徑。 “問題”是請求由線程池處理。 當請求完成時,線程處理的下一個請求可能是針對不同的用戶。 但是如果你在完成第一個請求時忘記清除線程本地狀態,那么第二個請求可能會使用它。
InheritableThreadLocal中是否存在內存泄漏?
是的......有點兒。 如果我們假設工作池是有界的,則任何線程的線程本地狀態都可能被覆蓋,從而清除內存泄漏。 在最壞的情況下,問題是有限的內存泄漏......受池中線程數量的限制。
信息泄漏問題更令人擔憂。
是否有任何替代InheritableThreadLocal?
在請求或響應對象中設置屬性更好。
如果線程將被重用會發生什么,threadlocal中存儲的值將不會被清除。
它不會被清除。 那就是問題所在!
您的示例有效, MailThread
在創建時繼承 currentRequestURI
的值。
但UserAccessFilter
和java.lang.InheritableThreadLocal
只是混淆了代碼試圖做的事情,這是邪惡的部分。
更改MailThread
的構造函數有什么問題,以便您可以從MailServlet
傳遞請求URI,如下所示:
MailThread mailThread = new MailThread("xxx@gmail.com", generateToAddress(Integer.parseInt(mailCount)), req.getRequestURI());
那么你不需要本地的線程,你不需要過濾器,代碼更清晰。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.