为什么我不能使用< jsp:getproperty>没有< jsp:usebean>?

luaexgnf  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(430)

假设有一个servlet有代码:

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    foo.Person p = new foo.Person("Evan");
    req.setAttribute("person", p);

    RequestDispatcher view = req.getRequestDispatcher("/result.jsp");
    view.forward(req, resp);
}

,这是 result.jsp 打印名字(埃文)。下面是它的外观(sourceheadfirstservlet和jsp):

我知道 <jsp:useBean> 通过调用 getAttribute() -因为它们在相同的请求范围内。在另一边, <jsp:getProperty> 将呼叫 findAttribute() 从字面上试图找到“人”的价值属性。。最终印出埃文。
但如果我没用呢 <jsp:useBean> ? 这是否意味着我无法在范围请求中访问“person”属性?我的意思是即使我不使用 <jsp:useBean>. 所以为什么我必须在两个id中都有相同的值(“person”) <jsp:useBean> 里面的名字 <jsp:getProperty> ? 简单的删除 <jsp:useBean> 破坏了我的程序。
知道吗 <jsp:getProperty> 电话 findAttribute() ,如果有一个单独的属性(如属性名)将用作参数来查找作用域页>请求>会话>应用程序中的属性,这不是更符合逻辑吗?为什么我必须“绑”这两个标签: <jsp:useBean> 以及 <jsp:getProperty> ?

s1ag04yj

s1ag04yj1#

你觉得下面的代码怎么样?

public class Main {
    public static void main(String[] args) {
        System.out.println(person);
    }
}

您一定已经正确地猜到它不会被成功编译。
下面的代码呢?

public class Main {
    public static void main(String[] args) {
        Person person = new Person();// Declaring person
        System.out.println(person);
    }
}

当然,它将被成功编译1,因为现在编译器明白 person 是。
同样,使用

<jsp:getProperty name="person" property="name">

没有声明 person 作为

<!-- Declaring person -->
<jsp:useBean id="person" class="foo.Person" scope="request" />

无法成功编译。
1假设 Person.class 有。

3zwjbxry

3zwjbxry2#

热释光;医生:你应该记住你需要 <jsp:getProperty><jsp:useBean> 因为说明书上这么说。 <jsp:useBean> 需要将bean引入jsp处理器,然后 <jsp:getProperty> 我可以用它。
更详细的解释:
为什么我不能用 <jsp:getProperty> 没有 <jsp:useBean> ?
因为他们“有点”是为了一起工作。我不知道为什么会这样决定(只有jsp规范的设计者才能回答这个问题),但是规范本身有这样的说法 <jsp:getProperty> :
以名称命名的对象必须使用jsp:usebean action 或具有此名称的关联variableinfo项的自定义操作。如果对象不是以这种方式引入的,则建议(但不是必需的)容器实现引发转换错误,因为页面实现违反了规范。
我说“有点”是为了协同工作,因为在某些情况下你可以使用 <jsp:getProperty> 没有 <jsp:useBean> ,但您必须将jsp处理器配置为忽略jsp.5.3规范规则(对于允许该规则的服务器)。
这不是很清楚,所以让我们看看一些代码会发生什么。
我有以下jsp:

-------------------------------------------------------------------
<jsp:useBean id="person" class="test.Person" scope="application" />
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
<jsp:getProperty name="person" property="name" />
-------------------------------------------------------------------

我使用了这些分隔符,以便以后可以在jsp生成的servlet中找到它们,在这里它们生成以下代码:

out.write("\t\t-------------------------------------------------------------------\r\n");
  out.write("\t\t");
  test.Person person = null;
  synchronized (application) {
    person = (test.Person) _jspx_page_context.getAttribute("person", javax.servlet.jsp.PageContext.APPLICATION_SCOPE);
    if (person == null){
      person = new test.Person();
      _jspx_page_context.setAttribute("person", person, javax.servlet.jsp.PageContext.APPLICATION_SCOPE);
    }
  }
  out.write("\r\n");
  out.write("\t\t+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");
  out.write("\t\t");
  out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString((((test.Person)_jspx_page_context.findAttribute("person")).getName())));
  out.write("\r\n");
  out.write("\t\t-------------------------------------------------------------------\r\n");

如果你看看 <jsp:getProperty> 你可以看到它对 test.Person :

org.apache.jasper.runtime.JspRuntimeLibrary.toString((((test.Person)_jspx_page_context.findAttribute("person")).getName()))

但那是从哪里来的呢?在你的 <jsp:getProperty> 指定bean名称( person )和属性名( name ),但没有课。所以这些属性只会导致 findAttribute("person") 然后在 getName() . 这门课是从哪里来的?答案是,前一个电话 <jsp:useBean> 在jsp处理器中引入了这一点。
所以你必须打电话 <jsp:useBean> 在jsp处理器中引入bean,以便当处理器看到 <jsp:getProperty> 它知道自己在处理什么。所以基本上, <jsp:useBean> 定义它,然后 <jsp:getProperty> 使用它。如果你不打电话 <jsp:useBean> ,的 <jsp:getProperty> 会尝试使用未定义的内容,jsp处理器会抱怨,您会得到一个异常:
jsp:getproperty for 名为“person”的bean。名称以前没有按照jsp.5.3引入
但如果你看了说明书,上面写着:
[…]建议容器实现(但不是必需的)引发转换错误[…]
例如,如果您使用tomcat,那么 org.apache.jasper.compiler.Generator.STRICT_GET_PROPERTY 控制在中使用对象的要求的系统属性 <jsp:getProperty> 以前“引入”到jsp处理器(基本上是强制执行或不执行jsp.5.3规则)。例如,请参阅tomcat文档页。
因此,如果我用系统变量启动tomcat服务器:

-Dorg.apache.jasper.compiler.Generator.STRICT_GET_PROPERTY=false

那我可以用 <jsp:getProperty> 没有 <jsp:useBean> ,前提是我介绍 person 以其他方式(比如从具有 request.setAttribute() , session.setAttribute() 或者 application.setAttribute() 以便 <jsp:getProperty> 我可以做一个 pageContext.findAttribute() 找一个叫 person 找到它。
如果使用该系统属性,则 <jsp:getProperty> 标记更改。这不再取决于 <jsp:useBean> 演员被移除:

out.write("\t\t+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r\n");
      out.write("\t\t");
      out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString(org.apache.jasper.runtime.JspRuntimeLibrary.handleGetProperty(_jspx_page_context.findAttribute("person"), "name")));
      out.write("\r\n");
      out.write("\t\t-------------------------------------------------------------------\r\n");

如果有人对所有这些乱七八糟的事情是如何展开的感兴趣,那么(对于tomcat服务器)应该关注的类有: org.apache.jasper.compiler.Validator 以及 org.apache.jasper.compiler.Generator .

相关问题