Donc, je travaille sur cette application Spring MVC à l'aide de Spring Security. J'ai frappé un problème de performance dans certains cas où mon contrôleur prend beaucoup trop de temps pour répondre. Cela est dû à une méthode de traitement pouvant prendre une énorme quantité de données pour traiter, sur la base de certaines saisies de l'utilisateur.
Maintenant, j'ai modifié le code un peu dans et autour de cette méthode de traitement avec mon équipe et je ne pense pas que nous puissions obtenir une meilleure performance de cela sans le couper et exécuter chaque tranche de manière asynchrone. P>
Le problème est que j'essaie de le trancher et de distribuer le travail aux filets enfants, en utilisant un threadpool de Java.Util.ConCurrent, je reçois des messages d'erreur sur le contexte de sécurité lorsque ceux-ci sont exécutés. P>
Voici un extrait de StackTrace: P>
Exception in thread "pool-1-thread-3" org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342) at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254) at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63) Exception in thread "pool-1-thread-4" at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at $Proxy63.batchSaveCampaignpayment(Unknown Source) at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595) org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342) at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254) at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at $Proxy63.batchSaveCampaignPayment(Unknown Source) at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595) Exception in thread "pool-1-thread-5" org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342) at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254) at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) at $Proxy63.batchSaveCampaignPayment(Unknown Source) at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) at java.lang.Thread.run(Thread.java:595)
4 Réponses :
Nous faisons généralement ce qui suit: Dans le fil initial géré à ressort
LocaleContextHolder.setLocale( locale, true); RequestContextHolder.setRequestAttributes( ra, true);
J'ai essayé exactement ce code. fait la finale de 2 variables afin que je puisse les utiliser avec le threadpool. Toujours eu les mêmes erreurs. Je me suis assuré en imprimant le contenu des variables qu'ils ont correctement passés aux fils de l'enfant.
Peut-être que vous pourriez utiliser quelque chose comme inheritablethreadlocalsecurityContexTholderstrategy? Je pense que ce qu'il fait est de copier le contexte de sécurité du fil de courant sur les threads que vous créez dans P>
J'ai trouvé deux solutions lorsque j'avais un problème similaire:
Vous pouvez le faire de cette manière P> <beans:bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<beans:property name="targetClass"
value="org.springframework.security.core.context.SecurityContextHolder"/>
<beans:property name="targetMethod" value="setStrategyName"/>
<beans:property name="arguments" value="MODE_INHERITABLETHREADLOCAL"/>
</beans:bean>
Deux solutions de travail - mais quand utiliser quelle solution? Plus d'infos sur MODE_INHERITABLETHREADLOCAL B> peut être trouvé dans Stackoverflow.com/questions/31967886/...
Comme autre mentionné, dans le Documentation Il y a un exemple soigné. Ce qui pourrait être amélioré en utilisant des fonctions Lambda. @Async("contextPropagatedExecutor")
public void doSomething(){}
En supposant que vous utilisez un
TASKEXECUT CODE> Vous pouvez l'envelopper dans un
DélégatingsecurityContexttaskexecuteur code> qui prend soin de tout cela. Tout ce qui est expliqué dans le Guide de référence a>.