我正在使用Java服务,其中表A中的数据进入表B。该服务将POST请求发送到REST服务器,并为复制的每一行创建一个位置标头作为响应,确认已创建新资源并向新创建的资源发出GET请求时,将POJO作为JSON返回。这是处理POST请求的资源方法。
@POST
@Produces({MediaType.APPLICATION_JSON})
public Response migrateToMinio(@Context UriInfo uriInfo) throws Exception {
tiedostoService = new TiedostoService();
attachmentService = new AttachmentService();
List<Tiedosto> tiedostoList = tiedostoService.getAllFiles();
List<String> responseList = new ArrayList<>();
Response r;
Integer newRow;
String responseData = null;
int i=1;
for (Tiedosto tiedosto : tiedostoList) {
Attachment attachment = new Attachment();
attachment.setCustomerId(tiedosto.getCustomerId());
attachment.setSize(tiedosto.getFileSize());
newRow = attachmentService.createNew(attachment);
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
if (newRow == 1) {
builder.path(Integer.toString(i));
r = Response.created(builder.build()).build();
responseData = r.getLocation().toString();
i++;
}
responseList.add(responseData);
}
String jsonString = new Gson().toJson(responseList);
return Response.status(Response.Status.OK).entity(jsonString).build();
}
tiedostoService
和attachmentService
是两个表的服务类。 tiedostoList
具有tiedosto
表中的所有行,并已在for循环内进行迭代,以便为tiedostoList
中的每个项目在附件表中创建新行。当我将POST请求发送到/rest/attachments
时,需要花费几秒钟的时间来处理并返回状态200以及所创建资源的列表,如下所示:现在,我的问题是,是否有一种方法可以实现它,以便新创建的资源位置在创建后立即返回(也许是创建的201),而不必等待最终状态200?
最佳答案
这种解决方案将假定您保存附件的服务(AttachmentService
)将能够在保存之前计算位置。例如,服务应该能够知道,如果最后一个附件存储的ID为10
,则下一个附件存储的ID为11
(或者随后的ID将被计算),因此具有位置的http://localhost:8080/rest/attachments/11
。
假设您的服务中存在逻辑,您可以创建一个收据对象,其中包含创建资源的位置以及代表已保存资源的 future 。该收据对象可以由服务而不是附件本身返回。这样的收据对象的实现可能类似于以下内容:
public class CreationReceipt<T> {
private final String location;
private final Future<T> attachment;
public CreationReceipt(String location, Future<T> attachment) {
this.location = location;
this.attachment = attachment;
}
public String getLocation() {
return location;
}
public Future<T> getAttachment() {
return attachment;
}
}
在
AttachmentService
中,将存在一种存储新Attachment
并返回CreationReceipt<Attachment>
的方法:public class AttachmentService {
public CreationReceipt<Attachment> createNew(Attachment attachment) {
String location = computeLocationFor(attachment);
Future<Attachment> savedAttachment = saveAsynchronously(attachment);
return new CreationReceipt<>(location, savedAttachment);
}
private Future<Attachment> saveAsynchronously(Attachment attachment) { ... }
private String computeLocationFor(Attachment attachment) { ... }
}
预先计算
Attachment
的位置的逻辑将取决于您的应用程序的具体情况(我将对它进行打桩以便添加逻辑),但是用于异步保存Attachment
的逻辑可以遵循一种通用模式。使用ExecutorService
,可以使用于保存Attachment
(您的应用程序已使用)的同步逻辑异步。为此,将同步逻辑提交到ExecutorService
(使用submit
方法),并且Future
返回ExecutorService
,该Attachment
包装已保存的Attachment
,并在成功保存Attachment
后完成。一个示例(尽管不完整)实现类似于:
public class AttachmentService {
private final ExecutorService executor = Executors.newSingleThreadExecutor();
public CreationReceipt<Attachment> createNew(Attachment attachment) {
String location = computeLocationFor(attachment);
Future<Attachment> savedAttachment = saveAsynchronously(attachment);
return new CreationReceipt<>(location, savedAttachment);
}
private Future<Attachment> saveAsynchronously(Attachment attachment) {
return executor.submit(() -> save(attachment));
}
private Attachment save(Attachment attachment) { ... }
private String computeLocationFor(Attachment attachment) { ... }
}
请注意,此实现一次只允许保存一个
Executors.newSingleThreadExecutor()
(根据使用executor
的性质),但是可以通过定义ExecutorService
来使用其他save
实现来更改逻辑。要完成此实现,只需为Attachment
方法添加一个实现,该实现可同步保存一个新的createNew
对象(该同步逻辑应该在您现有的AttachmentService
方法中的Attachment
中找到)。从这一点来看,保存
saveLocations
的逻辑将是:List<String> savedLocations = new ArrayList<>();
for (Tiedosto tiedosto : tiedostoList) {
Attachment attachment = new Attachment();
attachment.setCustomerId(tiedosto.getCustomerId());
attachment.setSize(tiedosto.getFileSize());
CreationReceipt<Attachment> receipt = attachmentService.createNew(attachmentToSave);
savedLocations.add(receipt.getLocation());
}
// Do something with savedLocations
这是一个不完整的实现,但应演示将要使用的基本结构。循环完成后,您可以将
201 Created
包含为响应的主体,并将响应状态代码设置为ojit_code。关于java - 如何在Java中以正确的方式将List <>项目作为POST数据发送?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51653357/