如何解决为什么我不能在没有 <jsp:useBean> 的情况下使用 <jsp:getProperty>?
override func layoutSubviews() {
let gradientLayer = CAGradientLayer()
gradientLayer.type = .axial
gradientLayer.colors = [UIColor.clear.cgColor,UIColor.black.cgColor]
gradientLayer.frame = bounds
gradientLayer.startPoint = CGPoint(x: 0,y: 0.5)
gradientLayer.endPoint = .init(x: 0,y: 1)
gradientLayer.zPosition = 1
gradientLayer.opacity = 0.5
layer.addSublayer(gradientLayer)
}
,转到 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);
}
以打印给定的名称 (Evan)。这是它的外观图片(来源 Head First Servlets 和 JSP):
我知道 result.jsp
通过调用 <jsp:useBean>
返回相同的 Person 对象 - 因为它们在相同的请求范围。而在另一边,getAttribute()
将调用 <jsp:getProperty>
从字面上尝试查找值“person”的属性..并最终打印 Evan。
但如果我不使用 findAttribute()
呢?这是否意味着我无法在 request 范围内访问“person”属性?我的意思是它仍然存在,即使我没有使用 <jsp:useBean>
那么为什么我必须在两个 id 中具有相同的 value("person") <jsp:useBean>.
和 name 在 <jsp:useBean>
中?简单地删除 <jsp:getProperty>
会破坏我的程序。
知道 <jsp:useBean>
调用 <jsp:getProperty>
,如果有一个单独的属性(如 attribute-name),将用作一个属性不是更合乎逻辑吗?在 page>request>session>application 范围内查找属性的参数?为什么我必须“绑定”这两个标签:findAttribute()
和 <jsp:useBean>
?
解决方法
你觉得下面的代码怎么样?
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
存在。
TL;DR:您应该记住,您需要将 <jsp:getProperty>
与 <jsp:useBean>
一起使用,因为规范是这样说的。 <jsp:useBean>
需要将 bean 引入 JSP 处理器,然后 <jsp:getProperty>
才能使用它。
更长的解释:
为什么我不能在没有 <jsp:getProperty>
的情况下使用 <jsp:useBean>
?
因为它们“在某种程度上”旨在协同工作。我不知道为什么会这样决定(只有 JSP 规范的设计者可以回答这个问题),但是 optional chaining 本身对 <jsp:getProperty>
有这样的说法:
由名称命名的对象必须已使用 jsp:useBean 操作或具有与此名称相关联的 VariableInfo 条目的自定义操作“引入”到 JSP 处理器。如果对象不是以这种方式引入的,则建议(但不是必需)容器实现引发翻译错误,因为页面实现违反了规范。
我说“有点”旨在协同工作,因为在某些情况下,您可以使用 <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>
将 bean 引入 JSP 处理器,以便当处理器看到 <jsp:getProperty>
时,它知道它在处理什么。所以基本上,<jsp:useBean>
定义它,然后 <jsp:getProperty>
使用它。如果您不调用 <jsp:useBean>
,<jsp:getProperty>
将尝试使用未定义的内容,JSP 处理器会抱怨,您将返回以下异常:
jsp:getProperty 用于名为“person”的 bean。以前没有按照 JSP.5.3 引入名称
但是如果您阅读规范,它会说:
[...] 建议(但不是必需)容器实现引发翻译错误 [...]
例如,如果您使用 Tomcat,则有一个 org.apache.jasper.compiler.Generator.STRICT_GET_PROPERTY
系统属性可以控制将 <jsp:getProperty>
中使用的对象预先“引入”到 JSP 处理器的要求(基本上,强制执行或不是 JSP.5.3 规则)。例如,请参阅此 the spec。
因此,如果我使用以下系统变量启动 Tomcat 服务器:
-Dorg.apache.jasper.compiler.Generator.STRICT_GET_PROPERTY=false
然后我可以在没有 <jsp:getProperty>
的情况下使用 <jsp:useBean>
,前提是我以其他方式在 SCOPE 中引入了 person
Bean(例如从带有 request.setAttribute()
的 servlet,{{1 }} 或 session.setAttribute()
以便 application.setAttribute()
可以执行 <jsp:getProperty>
并查找名为 pageContext.findAttribute()
的 bean 并找到它。
如果您使用该系统属性,则 person
标记生成的输出会发生变化。它不再依赖于 <jsp:getProperty>
并且演员表被移除:
<jsp:useBean>
如果有人对所有这些混乱如何展开感兴趣,那么要查看的类(对于 Tomcat 服务器)是: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");
和 org.apache.jasper.compiler.Validator
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。