【问题标题】:Java Bean: how <jsp:setProperty> in <jsp:useBean> is generated into Java CodeJava Bean:如何将 <jsp:useBean> 中的 <jsp:setProperty> 生成到 Java 代码中
【发布时间】:2012-04-23 17:23:47
【问题描述】:

例如,我有这样的代码:

<jsp:useBean id="dog" class="Dog" scope="application">
     <jsp:setProperty name="dog" property="breed" value="House Dog !!!"/>
</jsp:useBean>

我知道它是如何工作的。但是,有时,我会在其中更改一些代码,例如:“dog” 到“newDog”,我会遇到错误或 unguested-result (with me)。

请告诉我上面的代码是如何生成Java的。 (也许只是一个主要想法)

谢谢:)

【问题讨论】:

    标签: java jsp javabeans


    【解决方案1】:

    JSP 最终生成为.java 类,这些类被编译为 servlet。检查服务器的工作文件夹。对于 Tomcat,/test.jsp 在 Tomcat 的 /work 文件夹中生成为 /org/apache/jsp/test_jsp.java 文件。

    以下几行

    <jsp:useBean id="dog" class="com.example.Dog" scope="application">
         <jsp:setProperty name="dog" property="breed" value="House Dog !!!"/>
    </jsp:useBean>
    

    (我所做的唯一更改是添加一个包;无包类是 Bad™)

    生成为

      com.example.Dog dog = null;
      synchronized (application) {
        dog = (com.example.Dog) _jspx_page_context.getAttribute("dog", javax.servlet.jsp.PageContext.APPLICATION_SCOPE);
        if (dog == null){
          dog = new com.example.Dog();
          _jspx_page_context.setAttribute("dog", dog, javax.servlet.jsp.PageContext.APPLICATION_SCOPE);
          out.write("\n");
          out.write("     ");
          org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper(_jspx_page_context.findAttribute("dog"), "breed", "House Dog !!!", null, null, false);
          out.write('\n');
        }
      }
    

    Tomcat 是开源的,根据其源代码,JspRuntimeLibrary#introspecthelper() 方法委托给 internalIntrospecthelper(),它最终会这样做:

    Method method = null;
    Class<?> type = null;
    Class<?> propertyEditorClass = null;
    try {
        java.beans.BeanInfo info
            = java.beans.Introspector.getBeanInfo(bean.getClass());
        if ( info != null ) {
            java.beans.PropertyDescriptor pd[]
                = info.getPropertyDescriptors();
            for (int i = 0 ; i < pd.length ; i++) {
                if ( pd[i].getName().equals(prop) ) {
                    method = pd[i].getWriteMethod();
                    type   = pd[i].getPropertyType();
                    propertyEditorClass = pd[i].getPropertyEditorClass();
                    break;
                }
            }
        }
        if ( method != null ) {
            if (type.isArray()) {
                if (request == null) {
                    throw new JasperException(
                        Localizer.getMessage("jsp.error.beans.setproperty.noindexset"));
                }
                Class<?> t = type.getComponentType();
                String[] values = request.getParameterValues(param);
                //XXX Please check.
                if(values == null) return;
                if(t.equals(String.class)) {
                    method.invoke(bean, new Object[] { values });
                } else {
                    createTypedArray (prop, bean, method, values, t,
                                      propertyEditorClass); 
                }
            } else {
                if(value == null || (param != null && value.equals(""))) return;
                Object oval = convert(prop, value, type, propertyEditorClass);
                if ( oval != null )
                    method.invoke(bean, new Object[] { oval });
            }
        }
    } catch (Exception ex) {
        Throwable thr = ExceptionUtils.unwrapInvocationTargetException(ex);
        ExceptionUtils.handleThrowable(thr);
        throw new JasperException(ex);
    }
    

    你看,它使用java.beans.Introspector 来获取BeanInfo#getPropertyDescriptors() 的bean 信息和属性。所需的&lt;jsp:setProperty&gt; 方法由PropertyDescriptor#getWriteMethod() 获得为java.lang.reflect.Method。最后它使用Reflection API 调用该方法。

    【讨论】:

      【解决方案2】:

      它是这样生成的:

      Dog dog = new Dog();
      dog.setBreed("House Dog !!!");
      

      setProperty 中的 dog 是对 useBean 的 Dog 类的引用。 希望你明白这一点

      【讨论】:

      • 没有。我知道您缺少很多代码行:) 我知道是因为我只是不明白 是如何真正生成的。
      • 您会看到这是如何工作的: 1. use bean 有一个 id、class 和 scope 属性。 id 是将用于实例化您传递给类属性的类(FQCN)的名称或变量。 2.所以setProperty方法使用name属性的值来定位Dog类的实例,一旦定位到这个类,它会使用反射来设置定位到的Dog类的breed属性值属性中提供的值的 setProperty。这就是为什么usebean的id属性和setProperty的name属性的值必须匹配的原因。
      猜你喜欢
      • 2011-06-27
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 2012-04-21
      • 2012-10-18
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      相关资源
      最近更新 更多