Maison > Questions et réponses > le corps du texte
@Controller
public class AController{
@Autowire
HttpServletRequest request;
@RequestMapping("/test")
public Result test(){
System.out.println(request.toString());
request.getHeader("uid");
}
}
例如上述代码,
我使用Autowire
注入request
后,直接在controller
的方法中使用request
,
由于controller
默认是单例的,我在想是否会有线程安全问题。
因为我输出了request
的hashcode
发现每次请求hashcode
都是一样的。
那么后面的request
是否会覆盖当前request
导致信息失真?
·····························补充··························
1、我想在controller
的每个方法里都使用HttpServletRequest
,那么每次在方法里都要声明我觉得就比较麻烦了?不知道大家怎么解决这个问题?
2、我这样写的原因是,我想通过继承一个父类的方式,让request作为父类的一个成员变量,这样可以在方法里直接使用。
3、我通过楼下叉叉哥的方式(之前就是这样写的)
public Result test(HttpServletRequest request){
System.out.println(request.toString());
}
同样不断访问,或者用不同客户端访问。发现打印出来的每个请求的request的hashcode居然也是相同的,为什么?
巴扎黑2017-04-17 17:59:04
Merci pour vos réponses
Après mes tests et explorations.
La conclusion est que
l'injection de HttpServletRequest à l'aide de @autowire
est thread-safe.
J'ai écrit un blog sur le processus de vérification spécifique
Si vous êtes intéressé, vous pouvez y jeter un œil. S'il y a quelque chose qui ne va pas, veuillez le signaler.
Merci encore aux programmeurs à l'étage qui ont répondu avec enthousiasme à mes questions
Cliquez moi pour l'adresse du blog
ps : La discussion ci-dessus concerne uniquement le contrôleur en mode singleton
···
大家讲道理2017-04-17 17:59:04
Tout d'abord, en principe, Request ne peut pas être défini comme membre du Controller, car les cycles de vie des deux sont complètement déconnectés. Cela empêchera uniquement le Controller d'appeler le bon objet Request.
Deuxièmement, @Autowire est une mission ponctuelle et il existe d'innombrables objets Request, donc si vous l'écrivez comme ça, Spring ne saura pas quoi faire. Puisqu’il n’y a aucun objet Request au démarrage de l’application, cela devrait entraîner l’échec du démarrage.
PHP中文网2017-04-17 17:59:04
Euh, je me suis ridiculisé en me concentrant sur la résolution du mineur request
même problème à chaque fois et j'ai oublié le sujet.
Ajouter@ModelAttribute
C'est vrai que il y aura des problèmes de sécurité des threads !
...
Si vous souhaitez utiliser les attributs d'objet et gérer la sécurité des threads, il existe une méthode très simple, mais particulièrement grossière Utilisez-la directement @Scope("prototype")
pour laisser Spring MVC en générer un nouveau pour. chaque requête. Classe d'entité...
Mais pourquoi Spring MVC nécessite-t-il un singleton par défaut ? Naturellement, en raison des avantages en termes de performances et de coût des singletons,
et écrire @Scope("prototype")
signifie renoncer aux avantages des singletons.
Donc c'est effectivement une façon, mais ce n'est pas bon, je gêne tout le monde, désolé.
@Controller
// @Scope("prototype")
public class AController{
//@Autowired //如果采用非单例模式的话,用autowried也一样。
protected HttpServletRequest request;
protected HttpServletResponse response;
@ModelAttribute
public void bindRequestObject(HttpServletRequest request, HttpServletResponse response) {
this.request = request;
this.response = response;
}
@RequestMapping("/test")
public Result test(){
System.out.println(request.toString());
request.getHeader("uid");
}
}
迷茫2017-04-17 17:59:04
1. Une fois qu'Autowire aura injecté la requête, il y aura des problèmes de sécurité lors de l'utilisation des variables d'instance
2 Cela écrasera la requête
3 Le hashcode est toujours le même objet
Je pense qu'il est difficile d'écrire des paramètres dans la méthode, vous pouvez donc faire ceci :
@Controller
public class AControllre extends AbstractController {
@RequestMapping("/test")
public String test(){
//使用
String name = getRequest().getParameter("username");
return "";
}
}
class AbstractController {
protected HttpServletRequest getRequest() {
return ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest();
}
protected HttpServletResponse getResponse() {
return new ServletWebRequest(((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes()).getRequest()).getResponse();
}
}
PHPz2017-04-17 17:59:04
C'est la première fois que je vois cette façon d'écrire. Pourquoi ne pas l'écrire comme ça ?
@Controller
public class AController{
@RequestMapping("/test")
public Result test(HttpServletRequest request){
System.out.println(request.toString());
request.getHeader("uid");
}
}
En fait, dans la plupart des cas, la requête n'a pas besoin d'être passée en paramètre. Par exemple, si vous souhaitez récupérer l'uid dans l'en-tête de la requête, vous pouvez écrire comme ceci :
@Controller
public class AController{
@RequestMapping("/test")
public Result test(@RequestHeader("uid") String uid) {
System.out.println(uid); // 相当于request.getHeader("uid")
}
}
阿神2017-04-17 17:59:04
Si vous l'écrivez de cette façon, des problèmes de sécurité des threads se produiront certainement, car chaque contrôleur au printemps est singleton par défaut, donc votre demande sera partagée par d'autres threads, il est donc recommandé de l'écrire de la même manière que @ChaCha哥.
伊谢尔伦2017-04-17 17:59:04
Il y en aura. Dans Servlet, les paramètres d'attribut sont écrits dans la méthode afin qu'ils ne soient pas partagés
PHP中文网2017-04-17 17:59:04
Si vous écrivez comme ceci, il y aura certainement des problèmes de sécurité des threads, car le contrôleur est un singleton par défaut, ce qui signifie que plusieurs requêtes partageront un objet HttpServletRequest. Si vous ajoutez @Scope("prototype"), il y en aura. il n'y aura pas de problème
PHP中文网2017-04-17 17:59:04
Il y aura des problèmes de sécurité des threads, je vous suggère de lire cet articlehttp://www.xuebuyuan.com/1628190.html
巴扎黑2017-04-17 17:59:04
Toute variable d'instance de classe présente des risques potentiels pour la sécurité des threads. Le code doit garantir que la variable d'instance est en sécurité sous plusieurs threads, ou garantir que la classe est accessible par un seul thread à la fois.
Le problème du multi-thread dans votre exemple est inévitable. Vous devez suivre le didacticiel Spring et l'écrire de la manière standard. Faites les choses correctement et comprenez-les d'abord, puis faites les plus compliquées.