Explication détaillée de 5 méthodes de traitement asynchrone dans SpringMVC

Cet article présente principalement 5 méthodes de traitement asynchrone SpringMVC. Cet article vous présente en détail à travers l'exemple de code, qui a une certaine valeur de référence pour l'étude ou le travail de chacun. Les amis qui en ont besoin peuvent se référer à

Il y a quelque temps, j'ai étudié le principe du diamant.Un des points de connaissance importants est la réalisation de connexion longue, qui utilise le traitement asynchrone de servlet. Le plus grand avantage du traitement asynchrone est qu'il peut augmenter la quantité de concurrence sans bloquer le thread actuel. En fait, Spring MVC prend également en charge le traitement asynchrone. Cet article enregistre les points techniques pertinents.

Démo de traitement asynchrone

Si vous souhaitez activer le retour asynchrone, vous devez activer @EnableAsync. Dans le code suivant, DeferredResult est utilisé pour le traitement asynchrone.

Une fois la demande reçue, créez d'abord l'objet DeferredResult et définissez le délai d'expiration sur 60 secondes. Spécifiez ensuite le rappel de DeferredResult lors de l'exécution asynchrone et du délai d'attente. Le traitement synchrone doit uniquement créer un traitement asynchrone, puis renvoyer DeferredResult. De cette façon, une fois que Spring MVC a traité la demande, il ne retournera pas immédiatement la réponse au client et attendra la fin du DeferredResult. Si le DeferredResult n'est pas traité dans les 60 secondes, un délai d'expiration sera déclenché, puis une réponse sera renvoyée au client.

@RequestMapping(value = "/async/demo")
public DeferredResult<String> async(){
 // 创建 DeferredResult,设置超时时间 60s
 DeferredResult<String> deferredResult = new DeferredResult<>((long)60 * 1000);

 String uuid = UUID.randomUUID().toString();
 Runnable callback = () -> manager.remove(deferredResult, uuid);
 // 设置完成和超时的回调
 deferredResult.onCompletion(callback);
 deferredResult.onTimeout(callback);

 // 创建异步任务
 manager.addAsyncTask(deferredResult, uuid);

 // 同步返回 DeferredResult
 return deferredResult;
}

Pour les tâches asynchrones, l'objet DeferredResult doit être conservé. À la fin du traitement asynchrone, vous devez appeler manuellement DeferredResult.setResult pour terminer la sortie. Lors de l'appel de setResult, la sortie de données est écrite sur le client, puis l'événement d'achèvement asynchrone est déclenché pour exécuter le rappel.

task.getDeferredResult().setResult(ConfigJsonUtils.toJsonString(map));

Utiliser DeferredResult pour le traitement asynchrone

DeferredResult Cette classe représente un résultat retardé. DeferredResult peut être utilisé dans des tâches asynchrones, et d'autres threads peuvent obtenir DeferredResult et définir les données de retour de DeferredResult. Habituellement, vous pouvez utiliser des pools de threads, des files d'attente, etc. pour coopérer avec DeferredResult afin de réaliser un traitement asynchrone.

Selon la description officielle, le flux de traitement Spring MVC est le suivant:

1. Enregistrez le DeferredResult retourné par le contrôleur dans une file d'attente ou une collection de mémoire;
2. Spring MVC appelle request.startAsync () pour activer asynchrone;
3. DispatcherServlet et tous les filtres quittent le thread de demande actuel;
4. Les applications métier sont définies dans le thread asynchrone Pour la valeur de retour de DeferredResult, Spring MVC enverra à
nouveau la demande: 5. DispatcherServlet est appelé à nouveau et la valeur de retour de DeferredResult est utilisée;

Utiliser Callable pour le traitement asynchrone

L'utilisation de Callable pour le traitement asynchrone est similaire à DeferredResult. La différence est que Callable sera remis au TaskExecutor spécifié par le système pour exécution.

Selon la description officielle, le flux de traitement Spring MVC est le suivant:

1. Le contrôleur renvoie le Callable;
2. Spring MVC appelle request.startAsync () pour activer asynchrone et soumet le Callable à un pool de threads de tâches;
3. DispatcherServlet et tous les filtres quittent le thread de demande actuel;
4. L'application métier renvoie la valeur dans le thread asynchrone, Spring MVC enverra à nouveau la demande
5. DispatcherServlet est appelé à nouveau et la valeur de retour de Callable est utilisée;

@RequestMapping(value = "/async/demo")
public Callable<String> async(){
 Callable<String> callable = () -> String.valueOf(System.currentTimeMillis());
 // 同步返回
 return callable;
}

Utilisez ListenableFuture pour le traitement asynchrone

ListenableFuture comme valeur de retour, similaire à DeferredResult. Les utilisateurs doivent également gérer les threads asynchrones par eux-mêmes, mais les délais d'expiration et les rappels d'achèvement ne sont pas pris en charge et doivent être gérés par eux-mêmes.

@RequestMapping(value = "/async/demo")
public ListenableFuture<String> async(){
 ListenableFutureTask<String> ListenableFuture= new ListenableFutureTask<>(() -> {
  return String.valueOf(System.currentTimeMillis());
 });
 Executors.newSingleThreadExecutor().submit(ListenableFuture);
 return ListenableFuture;
}

Utilisez ResponseBodyEmitter pour le traitement asynchrone

DeferredResult et Callable ne peuvent renvoyer qu'une valeur asynchrone. Si vous devez renvoyer plusieurs objets, utilisez ResponseBodyEmitter. Chaque objet retourné sera traité par HttpMessageConverter et réécrit dans le flux de sortie. Si vous souhaitez définir plus de données de retour, telles que l'en-tête, l'état, etc., vous pouvez renvoyer ResponseBodyEmitter en tant que données d'entité de ResponseEntity.

@RequestMapping("/async/responseBodyEmitter")
public ResponseBodyEmitter responseBodyEmitter(){
 ResponseBodyEmitter responseBodyEmitter=new ResponseBodyEmitter();

 Executors.newSingleThreadExecutor().submit(() -> {
  try {
   responseBodyEmitter.send("demo");
   responseBodyEmitter.send("test");
   responseBodyEmitter.complete();
  } catch (Exception ignore) {}
 });

 return responseBodyEmitter;
}

Utilisez StreamingResponseBody pour le traitement asynchrone

Si vous souhaitez ignorer la conversion automatique de la valeur de retour et écrire le flux de sortie directement dans OutputStream, vous pouvez utiliser StreamingResponseBody. Il peut également être renvoyé en tant que données d'entité de ResponseEntity.

@RequestMapping("/async/streamingResponseBody")
public StreamingResponseBody streamingResponseBody(){
 StreamingResponseBody streamingResponseBody = outputStream -> {
  Executors.newSingleThreadExecutor().submit(() -> {
   try {
    outputStream.write("<html>streamingResponseBody</html>".getBytes());
   } catch (IOException ignore) {}
  });
 };
 return streamingResponseBody;
}

Comparaison de différentes méthodes de traitement

image.png

Les dernières questions d'entretien à haute fréquence collectées en 2021 (toutes organisées en documents), il y a beaucoup de produits secs, y compris mysql, netty, spring, thread, spring cloud, jvm, code source, algorithme et autres explications détaillées. également des plans d'apprentissage détaillés et des entretiens. Questions, etc., amis qui ont besoin d'obtenir ce contenu, veuillez ajouter Q Junyang: 547998459

Je suppose que tu aimes

Origine blog.csdn.net/p1830095583/article/details/114880822
conseillé
Classement