Confusion regarding the behaviour of the request o

2019-01-28 11:49发布

问题:

I've been messing around with servlets and JSPs and I am a bit confused at something:

  1. I've made a servlet (controller) which would dispatch the request to a JSP

  2. I've set some attributes to the request object using setAttribute() method in my servlet.

  3. I can access the request object's parameters and attributes within the JSP without any
    problem.

  4. Now I've stored the request object as an attribute in the session object using
    session.setAttribute("test", request).

  5. I've written a second JSP (navigating to it from the first JSP would be through
    Javascript when I click a particular button- by using the window.location function and
    giving the address of the second JSP as the value)

  6. In the second JSP, when I retrieve the request object from the session object, I get a
    null value from all the attributes of the retrieved request object.
  7. I can access the parameters of the retrieved request object BUT only if I had retrieved
    the parameters atleast once in my first JSP using request.getParameter() method
    otherwise they return null in my second JSP.

I am really new to this stuff and am confused about this behaviour. Why were my request object's attributes being 'erased' while the parameters remain intact (as long I had accessed the parameters in my first JSP; which is even more bewildering to me as it does not make sense IMO)

Any explanation would be appreciated! Thanking you in advance.

回答1:

This is just an educated guess, but I think the problem is that request objects in your container of choice might be lazy about its parameters: when you ask it for a parameter it reaches out to some external context and pulls the required data, at the same time caching it.

Nevertheless, the reason of the strange behavior is not really important. The problem should be solved by not saving requests in session. A request object is only your handle to the current request, not a data store by itself. It might be using any mechanism underneath, for all we know the attributes may be stored in threadlocals. There is absolutely no contract that would make a request act as an archive of any sort. For example: what would it mean if I asked such a stored request for the security principal? Would I mean "the current principal of the session"? Would I mean "the principal as of the moment when the request was created"?

EDIT:

Out of pure curiosity I just took a peek at Tomcat's implementation (I have no idea which container you are using) and found that it supports my claims: not only most of the data is gathered lazily, but the request object is recycled! So if you try store it in a session and then use, you might find that you are using someone's else request.



回答2:

There are 4 scopes in Java EE 5. In both Java EE 6 and Java EE 7 there are 5 scopes. The most used are:

  • Request scope
  • Session scope
  • Application scope (Web Context)

You can store some data in all the above scopes by setting the appropriate attribute.

Here is a quote from the Java EE API docs related to ServletRequest.setAttribute(String, Object) method in regard to request scope:

void setAttribute(java.lang.String name,
                  java.lang.Object o)

Stores an attribute in this request. Attributes are reset between requests. This method is most often used in conjunction with RequestDispatcher.
...

So with every new request the previous attributes you have set in request will be lost. After you have set an attribute in a request, you must forward the request to the desired page. If you redirect, this will be a totally NEW request, thus the attributes previously set will be lost. (If you still want use redirection read this: Servlet Redirection to same page with error message)

Those attributes that are set in a HttpSession (in the session scope) will live as long as the session lives and, of course, will be available to only the user to which session belongs.

As for the context attributes they are meant to be available to the whole web application (application scope) and for ALL users, plus they live as long as the web application lives.


As a conclusion, if you have previously set an attribute in the session it will be available to the same user as long as the session is alive.

Hope this will help you.

P.S.
Maybe this article will also be useful for you: How Java EE 6 Scopes Affect User Interactions
The only thing that this article uses Annotations for scoping, but you'll get the idea.