Java EE-webservice中的线程安全
阅读: “在WAR中部署的带有@WebService注释的POJO..不是线程安全的” 实际上,“EJB(注释为@webservice)在默认情况下是线程安全的” 我有一个疑问,我的公司使用pojo注释的@Webservice(打包在战争中),它使用@EJB组件(打包在JAR中),所有组件都包装在一个EE应用程序“.ear”中 所有逻辑都在ejb组件内,但是存储在ejb内的类变量是线程安全的吗 我必须实现一个代理Web服务,它并行调用其他Web服务并收集所有响应,对它们进行排序并返回给调用方 我该如何认识到这一点?我将在代理服务器中使用线程安全的hashmap来收集以异步方式调用其他web服务的临时响应(例如,使用jax-ws回调机制) 这条路对吗 编辑: @WebService(serviceName=“ProxyWS”) 公共类代理{Java EE-webservice中的线程安全,java,multithreading,web-services,Java,Multithreading,Web Services,阅读: “在WAR中部署的带有@WebService注释的POJO..不是线程安全的” 实际上,“EJB(注释为@webservice)在默认情况下是线程安全的” 我有一个疑问,我的公司使用pojo注释的@Webservice(打包在战争中),它使用@EJB组件(打包在JAR中),所有组件都包装在一个EE应用程序“.ear”中 所有逻辑都在ejb组件内,但是存储在ejb内的类变量是线程安全的吗 我必须实现一个代理Web服务,它并行调用其他Web服务并收集所有响应,对它们进行排序并返回给调用方 我
@EJB
private ProxyBeanLocal proxyBean;
@WebMethod(operationName = "hello")
public String hello(@WebParam(name = "name") String txt) {
return proxyBean.businessMethod();
}
}
@无状态
公共类ProxyBean实现ProxyBeanLocal{
专用最终字符串适配器_1_URL=“”;
专用最终字符串适配器_2_URL=“”;
并行映射m;
@凌驾
公共字符串businessMethod(){
试一试{
m=新的ConcurrentHashMap();
适配器服务适配器=新适配器服务(新URL(适配器1 URL));
AdapterWSAdapter=serviceAdapter.getAdapterSport();
helloAsync(“,this);//调用异步并对此进行回调
serviceAdapter=新适配器服务(新URL(适配器2\U URL));
adapter=serviceAdapter.getAdapterSport();
adapter.helloAsync(“,this”);
}捕获(格式错误){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}
return null;//所有响应到达后返回记录集(使用阻塞队列?)
}
@凌驾
公共无效处理响应(响应res){
试一试{
m、 put(res.get().getReturn(),res.get().getReturn());
}捕获(中断异常例外){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}捕获(ExecutionException ex){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}
}
}可以从不同的线程调用用
@WebService
注释的端点实现。以下是报告的相关部分:
通常会调用端点来服务并发请求,因此
它的实现程序应该编写为支持多线程。
synchronized关键字可以像往常一样用于控制对
代码的关键部分
如果您想要一个类型为ConcurrentMap
的类变量,那么如果预期映射应该包含来自客户端的一个特定调用的处理结果,那么这可能不适用于您。原因是,如果同时处理两个调用,那么来自这两个调用的数据将进入该映射。即使这不会破坏底层映射的结构,返回的数据也很可能是不一致的(比如来自两个请求的数据的混合)
您需要将数据与正在运行的其他请求隔离开来。而类变量并没有做到这一点。堆栈变量或线程本地应该这样做。还可能存在如何从WebService1…WebServiceN获取数据的问题。如果这是在其他线程中完成的,那么您需要同步对该原因映射的访问,但这不是并发问题的一部分
想想如果两个客户端同时调用hello
端点和businessMethod
会发生什么。来自服务的响应将放在handleResponse
中相同的ConcurrentHashMap
克服此问题的一种方法是创建asynchHandler
,它将引用为处理特定请求而创建的映射,如下所示:
public static ResponsesCollector implements AsyncHandler<HelloResponse> {
private Map<String, String> responses = new ConcurrentHashMap<>();
@Override
public void handleResponse(Response<HelloResponse> res) {
responses.put(res.get().getReturn(), res.get().getReturn());
}
public Map<String, String> getResponses() {
return responses;
}
}
@Override
public String businessMethod() {
try {
ResponsesCollector responsesCollector = new ResponsesCollector()
AdapterWS_Service serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_1_URL));
AdapterWS adapter = serviceAdapter.getAdapterWSPort();
adapter.helloAsync("", responsesCollector);
serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_2_URL));
adapter = serviceAdapter.getAdapterWSPort();
adapter.helloAsync("", responsesCollector);
} catch (MalformedURLException ex) {
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE, null, ex);
}
// ideally here you need return control to container
// and resume processing inside responseCollector
// when the last response is gotten. The problem is that JAX-WS does not
// specify how to do async processing on server side (similar to Async Servlets in Servlets specification 3.x).
// I know only one implementation that has an extension for async WebMethod -
// JEUS, see https://technet.tmaxsoft.com/upload/download/online/jeus/pver-20160610-000001/web-service/chapter_jaxws_async_operation.html
// So the only portable option here is to wait (using container thread).
//
return null; //return recordset once all responses arrived (using blocking queue?)
}
公共静态响应Collector实现AsyncHandler{
私有映射响应=新的ConcurrentHashMap();
@凌驾
公共无效处理响应(响应res){
responses.put(res.get().getReturn(),res.get().getReturn());
}
公共映射getResponses(){
回应;
}
}
@凌驾
公共字符串businessMethod(){
试一试{
ResponseCollector ResponseCollector=新的ResponseCollector()
适配器服务适配器=新适配器服务(新URL(适配器1 URL));
AdapterWSAdapter=serviceAdapter.getAdapterSport();
adapter.helloAsync(“,ResponseCollector);
serviceAdapter=新适配器服务(新URL(适配器2\U URL));
adapter=serviceAdapter.getAdapterSport();
adapter.helloAsync(“,ResponseCollector);
}捕获(格式错误){
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE,null,ex);
}
//理想情况下,您需要对容器进行返回控制
//并在responseCollector内恢复处理
//问题是JAX-WS没有
//指定如何在服务器端执行异步处理(类似于servlet规范3.x中的异步servlet)。
//我只知道一个实现具有异步WebMethod的扩展-
//杰斯,看https://technet.tmaxsoft.com/upload/download/online/jeus/pver-20160610-000001/web-service/chapter_jaxws_async_operation.html
//所以这里唯一的可移植选项是等待(使用容器线程)。
//
return null;//所有响应到达后返回记录集(使用阻塞队列?)
}
谢谢,我添加了一个示例以更好地理解我将要做的事情。你认为这会导致不一致吗?是的,这个实现有我在回答中描述的问题。我已经添加了一个如何解决这个问题的想法的草图@FrancescoUmani
public static ResponsesCollector implements AsyncHandler<HelloResponse> {
private Map<String, String> responses = new ConcurrentHashMap<>();
@Override
public void handleResponse(Response<HelloResponse> res) {
responses.put(res.get().getReturn(), res.get().getReturn());
}
public Map<String, String> getResponses() {
return responses;
}
}
@Override
public String businessMethod() {
try {
ResponsesCollector responsesCollector = new ResponsesCollector()
AdapterWS_Service serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_1_URL));
AdapterWS adapter = serviceAdapter.getAdapterWSPort();
adapter.helloAsync("", responsesCollector);
serviceAdapter = new AdapterWS_Service(new URL(ADAPTER_2_URL));
adapter = serviceAdapter.getAdapterWSPort();
adapter.helloAsync("", responsesCollector);
} catch (MalformedURLException ex) {
Logger.getLogger(ProxyBean.class.getName()).log(Level.SEVERE, null, ex);
}
// ideally here you need return control to container
// and resume processing inside responseCollector
// when the last response is gotten. The problem is that JAX-WS does not
// specify how to do async processing on server side (similar to Async Servlets in Servlets specification 3.x).
// I know only one implementation that has an extension for async WebMethod -
// JEUS, see https://technet.tmaxsoft.com/upload/download/online/jeus/pver-20160610-000001/web-service/chapter_jaxws_async_operation.html
// So the only portable option here is to wait (using container thread).
//
return null; //return recordset once all responses arrived (using blocking queue?)
}