在Java中实现异步回调并将结果返回给前端,通常是在Web应用开发中处理耗时操作时所采用的技术手段,以避免阻塞HTTP请求线程并提高用户体验。以下是一个简单的例子,说明如何通过Spring WebFlux或者Servlet 3.0及以上标准的异步API配合JSON响应的方式实现这一目标。
- import org.springframework.web.bind.annotation.*;
- import reactor.core.publisher.Mono;
-
- @RestController
- public class AsyncController {
-
- @GetMapping("/asyncTask")
- public Mono<String> asyncTask(@RequestParam("taskId") String taskId) {
- return doAsyncTask(taskId).map(result -> {
- // 这里假设doAsyncTask返回Mono对象,当异步任务完成时会填充结果
- return ResponseEntity.ok().body(result);
- });
- }
-
- private Mono<YourResultType> doAsyncTask(String taskId) {
- return Mono.create(sink -> {
- // 创建一个异步任务,在完成后回调
- someService.doSomethingAsync(taskId, new SomeCallback(sink));
- });
- }
-
- class SomeCallback implements AsyncCallback<YourResultType> {
- private final MonoSink<YourResultType> sink;
-
- public SomeCallback(MonoSink<YourResultType> sink) {
- this.sink = sink;
- }
-
- @Override
- public void onResult(YourResultType result) {
- // 当异步任务完成时,通过sink.success()传递结果
- sink.success(result);
- }
-
- @Override
- public void onError(Throwable error) {
- // 如果发生错误,通过sink.error()传递异常
- sink.error(error);
- }
- }
- }
-
- // 假设`YourResultType`是你异步任务的结果类型
- import javax.servlet.AsyncContext;
- import javax.servlet.ServletException;
- import javax.servlet.annotation.WebServlet;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.IOException;
-
- @WebServlet(urlPatterns = "/asyncTask", asyncSupported = true)
- public class AsyncServlet extends HttpServlet {
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
-
- final AsyncContext asyncContext = request.startAsync();
- Thread taskRunner = new Thread(() -> {
- YourResultType result;
- try {
- // 执行异步任务
- result = someService.doSomethingAsync(request.getParameter("taskId"));
- } catch (Exception e) {
- handleError(asyncContext, e);
- return;
- }
-
- // 将结果写回响应并结束异步上下文
- writeResponse(asyncContext, result);
- });
-
- taskRunner.start();
- }
-
- private void writeResponse(AsyncContext asyncContext, YourResultType result) {
- HttpServletResponse response = (HttpServletResponse) asyncContext.getResponse();
- try {
- response.setContentType("application/json");
- response.getWriter().write(objectMapper.writeValueAsString(result));
- asyncContext.complete();
- } catch (IOException e) {
- handleError(asyncContext, e);
- }
- }
-
- private void handleError(AsyncContext asyncContext, Throwable error) {
- HttpServletResponse response = (HttpServletResponse) asyncContext.getResponse();
- try {
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- response.getWriter().write(error.getMessage());
- asyncContext.complete();
- } catch (IOException e) {
- // 处理写入错误...
- }
- }
- }
在这两个示例中,核心思想都是启动一个异步任务,然后在任务完成后通过某种机制(如Reactor的MonoSink或Servlet的AsyncContext)将结果返回给前端。前端可以通过AJAX请求获取异步任务的结果,并根据返回的状态进行相应的处理,如展示数据或更新UI。