关于javax.servlet.ServletContextset/getAttribute线程安全吗?和servlet线程安全问题的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Http
关于javax.servlet.ServletContext set / getAttribute线程安全吗?和servlet线程安全问题的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于HttpServletRequest.getContextPath()和ServletContext.getContextPath()、java web Servlet 使用 Application/ServletContext、java – ServletContext对象的线程安全性、java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String;等相关知识的信息别忘了在本站进行查找喔。
本文目录一览:- javax.servlet.ServletContext set / getAttribute线程安全吗?(servlet线程安全问题)
- HttpServletRequest.getContextPath()和ServletContext.getContextPath()
- java web Servlet 使用 Application/ServletContext
- java – ServletContext对象的线程安全性
- java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String;
javax.servlet.ServletContext set / getAttribute线程安全吗?(servlet线程安全问题)
必须使用setAttribute()
和getAttribute(String)
中的javax.servlet.ServletContext
,我无法通过并发访问找到有关预期行为的任何信息。但是,这些操作很可能由不同的线程调用。
该servlet规范3.0的状态:
Servlet可以按名称将对象属性绑定到上下文中。绑定到上下文中的任何属性都可用于属于同一Web应用程序的任何其他servlet。
但是,没有有关这些操作的并发行为的信息。通过查看Apache Tomcat
的源代码,可以发现它是作为ConcurrentHashMap实现的,从而使其具有有效的线程安全性。
我的问题是,我应该始终将这些操作视为不是线程安全的,并让应用程序处理同步,还是我缺少一些信息?
答案1
小编典典您可以放心地假设您可以调用getAttribute和setAttribute而不对任何内容进行同步,但是您应该使在那里存储的对象成为线程安全的(最简单的方法是存储不可变的东西)。注释中链接的问题是关于在ServletContext中存储一个可变对象,在这种情况下,使用该对象的线程需要首先获取其锁(已接受的答案对此进行了解释)。
没有明确的要求。《 Java并发实践 》第4.5.1节解释模糊文档中对此进行了介绍:
您将不得不猜测。提高您的猜测质量的一种方法是从将要实施该规范的人员(例如容器或数据库供应商)的角度来解释该规范,而不是仅仅使用它的人员。Servlet总是从容器管理的线程中调用,可以安全地假设,如果有多个这样的线程,则容器知道这一点。Servlet容器使某些为多个Servlet提供服务的对象可用,例如HttpSession或ServletContext。因此,servlet容器应该期望并发地访问这些对象,因为它创建了多个线程并从它们中调用了诸如Servlet.service之类的方法,可以合理地期望它们访问ServletContext。
由于无法想象在这些对象中有用的单线程上下文,因此即使规范没有明确要求它们也必须假定它们已成为线程安全的。此外,如果他们需要客户端锁定,则客户端代码应在什么锁定上同步?该文档没有说,而且似乎很荒谬。规范和官方教程中的示例进一步支持了这种“合理的假设”,这些示例显示了如何访问ServletContext或HttpSession而不使用任何客户端同步。
另一方面,通过setAttribute放置在ServletContext或HttpSession中的对象归Web应用程序所有,而不是Servlet容器。Servlet规范没有建议任何机制来协调对共享属性的并发访问。因此,容器代表Web应用程序存储的属性应该是线程安全的或有效不变的。如果容器所做的全部工作都是代表Web应用程序存储这些属性,则另一种选择是确保从Servlet应用程序代码访问它们时,它们始终受到锁的保护。但是,由于容器可能想要序列化HttpSession中的对象以进行复制或钝化,并且servlet容器可能无法知道您的锁定协议,因此应使它们成为线程安全的。
HttpServletRequest.getContextPath()和ServletContext.getContextPath()
看了一下api,没弄懂两者之前的区别是什么,大多数情况下我发现两者得到的结果是一样的,api这样说:
It is possible that a servlet container may match a context by more than one context path. In such cases the HttpServletRequest.getContextPath() will return the actual context path used by the request and it may differ from the path returned by this method. The context path returned by this method should be considered as the prime or preferred context path of the application.字面上了解了,但是具体有什么不同还是不知道,那么哥可以说下什么情况下两者返回的是不同的呢?
java web Servlet 使用 Application/ServletContext
本文介绍 怎么在Servlet Web应用 中 初始化 全局变量(ServletContext)
ServletContext 也就是 java Servlet Web应用 里面的全局变量,当我们有时要做一些初始化配置是通常也是存在ServletContext里面
怎么初始化呢?有2个办法,一是监听器(listener)来初始化,二是通过设置servlet的load-on-startup=1,让servlert在web应用在启动时就加载这servlert来实现
我们这里主要讲第一个,也就是通过监听器(listener)来实现
首先我们要准备一个实现了ServletContextListener监听器接口的类
public class ContextLoaderListener implements ServletContextListener{
//实现全局上下文初始化方法
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//获得全局变量
ServletContext servletContext = servletContextEvent.getServletContext();
//设置全局变量属性
servletContext.setAttribute("test","test1");
}
//实现全局上下文销毁函数
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//实现
}
}
接下来在web.xml里面配置监听器的配置,在web.xml添加以下配置
<listener>
<listener-class>listener.ContextLoaderListener</listener-class>
</listener>
接下来你就可以在
servlet中取到
全局变量里面test变量的值,代码如下
public class HelloOut extends HttpServlet {
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException {
PrintWriter writer = response.getWriter();
writer.println("Hello Word For Test");
//获取全局变量
ServletContext servletContext = getServletContext();
//输出test变量
writer.println(servletContext.getAttribute("test"));
writer.close();
}
}
PS:扩展,你还可以在listener实现一个计数器,每次运行contextInitialized方法计数+1,然后存到全局变量里去,在servlet中查看计数的值,你就验证contextInitialized 这个方法是否只运行了一次
下一篇文章是在servlet中使用EhCache
java – ServletContext对象的线程安全性
但是多个请求线程正在读取和修改此HashMap.
因为我相信ServletContext对象是在请求线程之间共享的,我是否需要同步对此HashMap的访问?或者还有其他更好的方法来实现同样的目标吗?
解决方法
进入上下文可用于属于同一Web的任何其他servlet
应用.(…).
(原因:使对象可用于其他servlet也意味着它们可供其他线程使用.这是唯一可能的,如果使用正确的同步,则ServletContext#setAttribute必须同步).
因此,通过ServletContext#getAttribute读取已发布的属性也是如此.
但是当然如果像HashMap这样的对象在不同的线程之间共享,开发人员必须确保以适当的线程安全的方式访问这个共享对象本身!如您在问题的其他答案中所述,使用ConcurrentHashMap是一种可能的解决方案,但在初始化属性时无法解决竞争条件,因为null检查不是原子的:
ConcurrentMap<String,Object> shared = (...)servletContext.getAttribute("sharedData"); if (shared == null) { shared = new ConcurrentHashMap<>(); servletContext.setAttribute("sharedData",shared); }
因此,servletcontextlistener可用于在Web应用程序启动时初始化上下文!
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String;
问题描述:在eclipse3.7中启动tomcat6时一直出现这个错误,
java.lang.NoSuchMethodError: javax.servlet.ServletContext.getcontextpath()Ljava/lang/String;
网上搜了好久,众说纷纭,最终才找到解决办法,参照此方法我的问题解决了。
解决方案:找到jdk安装目录进入jre\lib\ext,看是否有servlet-api.jar(我的没有),如果没有将tomcat中的servlet-api.jar复制到jre\lib\ext中
重启tomcat错误就没有出现。
如果你的jre\lib\ext下有这个架包,还是有错,可以尝试用tomcat中的servlet-api.jar替换jre\lib\ext下的servlet-api.jar,重启tomcat
2020年2月14日更新:
启动 dubbo项目的时候报错:
Exception in thread "NettyClientWorkerThread_4" java.lang.NoClassDefFoundError: com/aliyun/openservices/shade/io/netty/util/concurrent/DefaultPromise$1
at com.aliyun.openservices.shade.io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:435)
at com.aliyun.openservices.shade.io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:102)
at com.aliyun.openservices.shade.io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:179)
at java.lang.Thread.run(Thread.java:745)
一看是java.lang.NoClassDefFoundError,自然而然以为是类加载过程中找不到这个类的问题。
继而从jar包查起,后来发现是在 ons-client-1.8.0.Final.jar中。
com/aliyun/openservices/ons-client/1.8.0.Final
ons-client-1.8.0.Final.jar
实际项目 执行mvn package 之后,有这个jar,为啥还会出错呢。继续翻日志,发现最上面出现了依赖加载出问题了。
原来是 dubbo:reference 配置的有问题, group="@dubbo.someservice.group@"
这里的dubbo reference 的group中占位符对应的配置忘记加载properties配置文件中了。
明明是依赖的问题,却报错java.lang.NoClassDefFoundError,坑爹啊。
关于javax.servlet.ServletContext set / getAttribute线程安全吗?和servlet线程安全问题的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于HttpServletRequest.getContextPath()和ServletContext.getContextPath()、java web Servlet 使用 Application/ServletContext、java – ServletContext对象的线程安全性、java.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String;的相关信息,请在本站寻找。
本文标签: