gpt4 book ai didi

java - 同步访问 REST Web 服务

转载 作者:塔克拉玛干 更新时间:2023-11-02 07:51:15 26 4
gpt4 key购买 nike

我在使用这段代码的简单 REST 服务上遇到了麻烦:

@GET
@Path("next/{uuid}")
@Produces({"application/xml", "application/json"})
public synchronized Links nextLink(@PathParam("uuid") String uuid) {
Links link = null;
try {
link = super.next();
if (link != null) {
link.setStatusCode(5);
link.setProcessUUID(uuid);
getEntityManager().flush();
Logger.getLogger("Glassfish Rest Service").log(Level.INFO, "Process {0} request url : {1} #id {2} at {3} #", new Object[]{uuid, link.getLinkTxt(), link.getLinkID(), Calendar.getInstance().getTimeInMillis()});
}
} catch (NoResultException ex) {
} catch (IllegalArgumentException ex) {
}
return link;
}

这应该提供一个链接对象,并将其标记为已使用 (setStatusCode(5)) 以防止下次访问服务时发送相同的对象。问题是,当有很多快速客户端访问 Web 服务时,这一个向不同客户端提供 2 或 3 倍的相同链接对象。我该如何解决这个问题??

这是使用 to 的请求: @NamedQuery(name = "Links.getNext", query = "SELECT l FROM Links l WHERE l.statusCode = 2")

和 super.next() 方法:

public T next() {

javax.persistence.Query q = getEntityManager().createNamedQuery("Links.getNext");
q.setMaxResults(1);
T res = (T) q.getSingleResult();
return res;
}

谢谢

最佳答案

(根)JAX-RS 资源的生命周期是每个请求,所以(否则是正确的)synchronized nextLink 上的关键字遗憾的是,该方法无效。

您需要的是同步访问/更新的方法。这可以通过多种方式完成:

I) 您可以同步外部对象,由框架注入(inject)(例如:注入(inject)@ApplicationScoped 的 CDI),如下所示:

@ApplicationScoped
public class SyncLink{
private ReentrantLock lock = new ReentrantLock();
public Lock getLock(){
return lock;
}
}
....
public class MyResource{
@Inject SyncLink sync;

@GET
@Path("next/{uuid}")
@Produces({"application/xml", "application/json"})
public Links nextLink(@PathParam("uuid") String uuid) {
sync.getLock().lock();
try{
Links link = null;
try {
link = super.next();
if (link != null) {
link.setStatusCode(5);
link.setProcessUUID(uuid);
getEntityManager().flush();
Logger.getLogger("Glassfish Rest Service").log(Level.INFO, "Process {0} request url : {1} #id {2} at {3} #", new Object[]{uuid, link.getLinkTxt(), link.getLinkID(), Calendar.getInstance().getTimeInMillis()});
}
} catch (NoResultException ex) {
} catch (IllegalArgumentException ex) {
}
return link;
}finally{
sync.getLock().unlock();
}
}
}

II)你可以偷懒,在类里面保持同步

public class MyResource{
@Inject SyncLink sync;

@GET
@Path("next/{uuid}")
@Produces({"application/xml", "application/json"})
public Links nextLink(@PathParam("uuid") String uuid) {
Links link = null;
synchronized(MyResource.class){
try {
link = super.next();
if (link != null) {
link.setStatusCode(5);
link.setProcessUUID(uuid);
getEntityManager().flush();
Logger.getLogger("Glassfish Rest Service").log(Level.INFO, "Process {0} request url : {1} #id {2} at {3} #", new Object[]{uuid, link.getLinkTxt(), link.getLinkID(), Calendar.getInstance().getTimeInMillis()});
}
} catch (NoResultException ex) {
} catch (IllegalArgumentException ex) {
}

}
return link;
}
}

III) 您可以使用数据库进行同步。在那种情况下,您将研究 JPA2 中可用的悲观 锁定。

关于java - 同步访问 REST Web 服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14684849/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com