2010-01-28 9 views
0

J'ai un tag personnalisé qui effectue un traitement, puis définit un cookie. Cependant, le cookie n'était pas réglé, et je ne pouvais pas comprendre pourquoi. Un autre développeur a fait remarquer que parce que nous utilisons un système de gabarit, le point auquel l'étiquette évalue, l'en-tête de réponse a déjà été vidé en tant que partie d'un include. Puisque l'en-tête a été envoyé, il ne semble pas possible d'ajouter le cookie (cependant, aucune exception d'état n'est levée lorsque j'essaie de le faire). Y a-t-il un moyen de contourner ceci? Est-ce que cela semble être le problème?Ajouter un cookie à la réponse en Java après que l'en-tête a été vidé?

Répondre

1

Comme d'autres l'ont dit, vous voulez vraiment éviter d'avoir à le faire en premier lieu. Vous aimeriez peut-être avoir un joli type de modèle MVC où vous avez quelques servlets qui font votre travail lourd comme la base de données et les cookies et tout ça, et ensuite passez le contrôle à un JSP qui restitue la réponse. Étant donné que le JSP n'est pas appelé pour générer du code HTML tant que vos servlets ne sont pas terminés, vous ne devriez pas courir dans cette situation.

Il est un peu boiteux que setCookie ne vous dise pas quand il échoue, mais il est également logique que vous ne voulez probablement pas qu'il casse toute votre page. ServletResponse.isCommitted() vous dira si les en-têtes sont déjà écrits, et par conséquent si votre appel setCookie() échouera.

Si vous êtes dans une situation désespérée et que vous devez absolument pouvoir le faire (alors que vous cherchez une meilleure solution), vous pouvez créer un filtre de servlet pour mettre en mémoire tampon la réponse jusqu'à ce que votre cookie soit activé. Le modèle serait quelque chose comme ceci:

doFilter(request, response, chain) 
{ 
    BufferedResponse bufferedResponse = new BufferedResponse(response); 
    try 
    { 
    // pass control to the next filter or to the JSP/servlet servicing the request 
    chain.doFilter(request, bufferedResponse); 
    } 
    finally 
    { 
    bufferedResponse.flush(); 
    } 
} 

BufferedResponse aurait besoin de mettre en œuvre et maintenir HttpServletResponse essentiellement tout en mémoire jusqu'à ce que vous rincer explicitement. À ce stade, il écrirait les en-têtes, les cookies et le corps de la réponse tamponnée.

Cela fonctionnera totalement, mais votre serveur Web utilisera beaucoup de mémoire supplémentaire puisqu'il doit mettre en mémoire tampon le corps entier de la réponse en mémoire pour chaque requête. En outre, vos pages se chargeront plus lentement puisque le serveur ne peut pas commencer à envoyer quoi que ce soit au navigateur client tant que votre page n'est pas complètement terminée. Mauvais juju mon ami.

+0

J'ai fini par utiliser un filtre de servlet, mais je l'ai utilisé pour effectuer le travail de configuration du cookie au lieu de gérer la réponse comme dans l'exemple ci-dessus. Merci pour la perspicacité! –

+0

J'ai soulevé une question similaire ici - http://stackoverflow.com/q/12155879/374556 – bloodcell

0

Eh bien, un cookie HTTP fait partie de l'en-tête HTTP, ce qui serait définitivement votre problème. Et pour cette raison, vous ne pouvez tout simplement pas écrire un cookie après avoir vidé les en-têtes HTTP.

Une raison spécifique pour laquelle vous roulez et n'utilisez pas la mémoire tampon de réponse? Vous pouvez également essayer de vous assurer de modifier l'en-tête et d'ajouter le cookie avant qu'il ne soit vidé.

0

Je suppose qu'une solution de contournement possible serait d'émettre du JavaScript pour définir le cookie. Il y a bien sûr des problèmes évidents avec cette méthode. Une astuce similaire serait d'inclure un webbug de 1x1 pixel qui définit un cookie lorsqu'il est chargé.

Je suggère de garder JSP (et similaire) concernés seulement avec la création de la page vue. Et aussi garder très peu d'état de session.

0

HTTP sait également que les pieds de page sont ajoutés après que le corps soit géré comme des en-têtes (même format). Malheureusement, HttpServletResponse n'a pas de méthode addFooter (l'API Resin a, par exemple). Sans un api ça serait dur. Aucune chance de l'ajouter simplement au corps - qui sera analysé comme corps, pas pied de page. Pardon.

Si vous écrivez html pour un navigateur, peut-être vous pouvez inclure un morceau de javascript à la fin de la page (avant </html>) pour placer le cookie.