Java servlet 和 JSP 访问同一个会话 bean
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2663079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java servlet and JSP accessing the same session bean
提问by Mykola Golubyev
Let's say I have a simple Login servlet that checks the passed name
and creates User
object and stores it in a session.
假设我有一个简单的 Login servlet,它检查传递的对象并name
创建User
对象并将其存储在会话中。
User user = new User();
user.setId(name);
request.getSession().setAttribute("user", user);
response.sendRedirect("index.jsp");
In the index.jsp
page I access the user object through jsp:useBean
在index.jsp
页面中,我通过访问用户对象jsp:useBean
<jsp:useBean id="user" scope="session"
class="package.name.User"/>
<div class="panel">
Welcome ${user.id}
</div>
It works so far.
到目前为止它有效。
From the jsp beans documentation
来自 jsp beans 文档
To locate or instantiate the Bean, takes the following steps, in this order:
- Attempts to locate a Bean with the scope and name you specify.
- Defines an object reference variable with the name you specify.
- If it finds the Bean, stores a reference to it in the variable. If you specified type, gives the Bean that type.
- If it does not find the Bean, instantiates it from the class you specify, storing a reference to it in the new variable. If the class name represents a serialized template, the Bean is instantiated by java.beans.Beans.instantiate.
- If has instantiated (rather than located) the Bean, and if it has body tags or elements (between and ), executes the body tags.
要定位或实例化 Bean,请按以下顺序执行以下步骤:
- 尝试使用您指定的范围和名称定位 Bean。
- 使用您指定的名称定义对象引用变量。
- 如果找到 Bean,则在变量中存储对它的引用。如果您指定类型,则为 Bean 提供该类型。
- 如果找不到 Bean,则从您指定的类中实例化它,并将对它的引用存储在新变量中。如果类名表示序列化模板,则 Bean 由 java.beans.Beans.instantiate 实例化。
- 如果已实例化(而不是定位)Bean,并且它具有主体标记或元素(介于 和 之间),则执行主体标记。
The questions:
问题:
Attempts to locate a Bean with the scope and name you specify
尝试使用您指定的范围和名称定位 Bean
It does not specify the "locate" process. Does it mean it will check HttpServletRequest.getSession()
or just check whether other pages already created this bean or not?
它没有指定“定位”过程。这是否意味着它会检查HttpServletRequest.getSession()
或只是检查其他页面是否已经创建了这个 bean?
If it does not find the Bean, instantiates it from the class you specify, storing a > reference to it in the new variable.
如果它没有找到 Bean,则从您指定的类中实例化它,在新变量中存储对它的 > 引用。
This actually means that Jsp can associate a newly created bean with session using jsp_internal_name_user. There is no word about how Jsp stores and finds beans in the session.
这实际上意味着 Jsp 可以使用jsp_internal_name_user将新创建的 bean 与会话相关联。没有关于 Jsp 如何在会话中存储和查找 bean 的消息。
There is an option to access session objects by using ${sessionScope.user}
and that will guarantee that "user" from the Java session object will be get. The same one I put into by myself.
有一个选项可以通过 using 访问会话对象${sessionScope.user}
,这将保证从 Java 会话对象中获取“用户”。和我自己放进去的一样。
Java EE 5 example "Book Store" access session objects using ${sessionScope.name}
approach.
Java EE 5 示例“书店”使用${sessionScope.name}
方法访问会话对象。
Using just ${user}
works. And this is what worries me. I would like to see a specific sentence in the specification about the locate
process and whether ${user}
must work or whether it is up to the JSP and/or JSTL reference implementation.
使用刚刚好${user}
。而这正是我所担心的。我想在规范中看到关于locate
流程的特定句子,以及是否${user}
必须工作或是否取决于 JSP 和/或 JSTL 参考实现。
采纳答案by BalusC
In case of a controller (servlet) which takes care about the model, the jsp:useBean
is only useful if the default instance (constructed with the no-arg constructor) exposes different behavior/state than a non-existing instance. E.g. if you would like to have a default user name "Unknown User", you would do:
对于负责模型的控制器 (servlet),jsp:useBean
仅当默认实例(使用无参数构造函数构造)公开与不存在的实例不同的行为/状态时才有用。例如,如果您想要一个默认用户名“未知用户”,您可以这样做:
public User {
this.id = "Unknown User";
}
Else the enduser may face a "Welcome" instead of "Welcome Unknown User" display. In your particular case, you can safely remove it. It's superfluous.
否则最终用户可能会看到“欢迎”而不是“欢迎未知用户”显示。在您的特定情况下,您可以安全地将其删除。这是多余的。
However, I've also seen the argument that it's useful for pure documentation. You could declare "useless" jsp:useBean
instances in top of JSP page so that you have an overview which models exactly are been used in the particular JSP page. Although I find it pretty smart, I myself have never had the need for this way of documenting the model in JSP. As per the comments, another argument is indeed that this way IDE's like IDEA and Eclipse are able to autocomplete bean properties in EL.
但是,我也看到了它对纯文档有用的论点。您可以jsp:useBean
在 JSP 页面的顶部声明“无用”实例,以便您了解在特定 JSP 页面中确切使用了哪些模型。虽然我觉得它很聪明,但我自己从来没有需要这种在 JSP 中记录模型的方式。根据评论,另一个论点确实是这样的 IDE 像 IDEA 和 Eclipse 一样能够在 EL 中自动完成 bean 属性。
Update: as to the locating, it uses PageContext#findAttribute()
for that and then uses reflection/javabean introspection to invoke getter methods on it. E.g.
更新:至于定位,它PageContext#findAttribute()
用于定位,然后使用反射/javabean 自省来调用它的 getter 方法。例如
${user.name}
roughly resolves to
大致解析为
out.print(pageContext.findAttribute("user").getName())
Also see the JSP specificationand the JSP EL specification.
Update 2: the <jsp:useBean>
certainlydoesn't use an internal name or so as session attribute prefix. Loop over all session attributes yourself to see the actual keys and values:
更新 2:<jsp:useBean>
当然不使用内部名称等作为会话属性前缀。自己遍历所有会话属性以查看实际的键和值:
<c:forEach items="${sessionScope}" var="entry">
${entry.key} = ${entry.value}<br>
</c:forEach>
or in a servlet
或在 servlet 中
for (String name : Collections.list(session.getAttributeNames())) {
System.out.println(name + " = " + session.getAttribute(name));
}
回答by lexicore
From the documentation:
从文档:
The
<jsp:useBean>
element locates or instantiates a JavaBeans component.<jsp:useBean>
first attempts to locate an instance of the Bean. If the Bean does not exist,<jsp:useBean>
instantiates it from a class or serialized template.
该
<jsp:useBean>
元素定位或实例化一个 JavaBeans 组件。<jsp:useBean>
首先尝试定位 Bean 的实例。如果 Bean 不存在,<jsp:useBean>
则从类或序列化模板中实例化它。
Since "locating" the bean is perfectly allright then we can assume that the bean may be made available by means other than instantiation via <jsp:useBean>
. For instance, by creating it in a servlet.
由于“定位” bean 完全没问题,那么我们可以假设 bean 可以通过实例化以外的方式使用<jsp:useBean>
。例如,通过在 servlet 中创建它。
回答by evnafets
Quoting the JSP spec JSP.5.1
引用 JSP 规范 JSP.5.1
The basic semantic tries to find an existing object using id and scope. If the object is not found it will attempt to create the object using the other attributes.
基本语义尝试使用 id 和范围查找现有对象。如果未找到对象,它将尝试使用其他属性创建对象。
In other words,
换句话说,
<jsp:useBean id="user" scope="session" class="package.name.User"/>
would translate roughly into java as:
将大致翻译成 java 为:
package.name.User user = (package.name.User)session.getAttribute("user");
if (user == null){
user = new package.name.User();
session.setAttribute("user", user);
}