例如,我有以下代码:
<jsp:useBean id="dog" class="Dog" scope="application"> <jsp:setProperty name="dog" property="breed" value="House Dog !!!"/> </jsp:useBean>
我知道它是如何工作的。但是,有时,我会在其中更改一些代码,例如:将“ dog”更改为“ newDog”,我会遇到错误或毫无根据的结果。
请给我上面的代码如何生成到Java中。(也许只是一个主意)
谢谢 :)
JSP最终生成为.java类,这些类被编译为Servlet。检查服务器的工作文件夹。对于Tomcat,/test.jsp将/org/apache/jsp/test_jsp.java在Tomcat的/work文件夹中生成一个文件。
.java
/test.jsp
/org/apache/jsp/test_jsp.java
/work
以下几行
<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()最终实现此目的:
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用于通过获取bean信息和属性BeanInfo#getPropertyDescriptors()。所需的<jsp:setProperty>方法如获得java.lang.reflect.Method通过PropertyDescriptor#getWriteMethod()。最后,它使用Reflection API调用该方法。
java.beans.Introspector
BeanInfo#getPropertyDescriptors()
<jsp:setProperty>
java.lang.reflect.Method
PropertyDescriptor#getWriteMethod()