在上篇博客SSH框架之Struts(3)――Struts的运行流程之核心方法,我们提到RequestProcessor中的processPopulate()是用来为为ActionForm 填充数据,它是怎样实现将表单数据放入到1个ActionForm中的呢?――第3方工具,BeanUtils,相对来讲,这是1个非常重要的用来操作javaBean的服务。
public static void populate(
Object bean,
String prefix,
String suffix,
HttpServletRequest request)
throws ServletException {
// Build a list of relevant request parameters from this request
HashMap properties = new HashMap();
// Iterator of parameter names
Enumeration names = null;
// Map for multipart parameters
Map multipartParameters = null;
String contentType = request.getContentType();
String method = request.getMethod();
boolean isMultipart = false;
if (bean instanceof ActionForm) {
((ActionForm) bean).setMultipartRequestHandler(null);
}
MultipartRequestHandler multipartHandler = null;
if ((contentType != null)
&& (contentType.startsWith("multipart/form-data"))
&& (method.equalsIgnoreCase("POST"))) {
// Get the ActionServletWrapper from the form bean
ActionServletWrapper servlet;
if (bean instanceof ActionForm) {
servlet = ((ActionForm) bean).getServletWrapper();
} else {
throw new ServletException(
"bean that's supposed to be "
+ "populated from a multipart request is not of type "
+ ""org.apache.struts.action.ActionForm", but type "
+ """
+ bean.getClass().getName()
+ """);
}
// Obtain a MultipartRequestHandler
multipartHandler = getMultipartHandler(request);
if (multipartHandler != null) {
isMultipart = true;
// Set servlet and mapping info
servlet.setServletFor(multipartHandler);
multipartHandler.setMapping(
(ActionMapping) request.getAttribute(Globals.MAPPING_KEY));
// Initialize multipart request class handler
multipartHandler.handleRequest(request);
//stop here if the maximum length has been exceeded
Boolean maxLengthExceeded =
(Boolean) request.getAttribute(
MultipartRequestHandler.ATTRIBUTE_MAX_LENGTH_EXCEEDED);
if ((maxLengthExceeded != null) && (maxLengthExceeded.booleanValue())) {
((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
return;
}
//retrieve form values and put into properties
multipartParameters = getAllParametersForMultipartRequest(
request, multipartHandler);
names = Collections.enumeration(multipartParameters.keySet());
}
}
if (!isMultipart) {
names = request.getParameterNames();
}
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String stripped = name;
if (prefix != null) {
if (!stripped.startsWith(prefix)) {
continue;
}
stripped = stripped.substring(prefix.length());
}
if (suffix != null) {
if (!stripped.endsWith(suffix)) {
continue;
}
stripped = stripped.substring(0, stripped.length() - suffix.length());
}
Object parameterValue = null;
if (isMultipart) {
parameterValue = multipartParameters.get(name);
} else {
parameterValue = request.getParameterValues(name);
}
// Populate parameters, except "standard" struts attributes
// such as 'org.apache.struts.action.CANCEL'
if (!(stripped.startsWith("org.apache.struts."))) {
properties.put(stripped, parameterValue);
}
}
// Set the corresponding properties of our bean
try {
BeanUtils.populate(bean, properties);
} catch(Exception e) {
throw new ServletException("BeanUtils.populate", e);
} finally {
if (multipartHandler != null) {
// Set the multipart request handler for our ActionForm.
// If the bean isn't an ActionForm, an exception would have been
// thrown earlier, so it's safe to assume that our bean is
// in fact an ActionForm.
((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
}
}
}
这段实现的前半部份是关于上传的代码,如果用到上传功能的可以仔细浏览以下前边部份的代码,我们这里不做解释,可以往下看。
if (!isMultipart) {
names = request.getParameterNames();
}
这是用来获得到表单所有的名称,进而为属性值的Copy和转换做准备
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String stripped = name;
if (prefix != null) {
if (!stripped.startsWith(prefix)) {
continue;
}
stripped = stripped.substring(prefix.length());
}
if (suffix != null) {
if (!stripped.endsWith(suffix)) {
continue;
}
stripped = stripped.substring(0, stripped.length() - suffix.length());
}
Object parameterValue = null;
if (isMultipart) {
parameterValue = multipartParameters.get(name);
} else {
parameterValue = request.getParameterValues(name);
}
}
// Populate parameters, except "standard" struts attributes
// such as 'org.apache.struts.action.CANCEL'
if (!(stripped.startsWith("org.apache.struts."))) {
properties.put(stripped, parameterValue);
}
遍历表单所有的名称,并通过parameterValue = request.getParameterValues(name);取得名称对应的value值。以后就是通过properties.put(stripped, parameterValue);将名称作为key,名称对应的值作为value放入到map中。
// Set the corresponding properties of our bean
try {
BeanUtils.populate(bean, properties);
} catch(Exception e) {
throw new ServletException("BeanUtils.populate", e);
} finally {
if (multipartHandler != null) {
// Set the multipart request handler for our ActionForm.
// If the bean isn't an ActionForm, an exception would have been
// thrown earlier, so it's safe to assume that our bean is
// in fact an ActionForm.
((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
}
}
}
在这里,主要是调用第3方服务BeanUtils来实现属性值的转换和赋值。这个方法会遍历ActionForm的值的类型,并且讲Map中的值的类型改成和ActionForm对应的类型。到这里processPopulate的方法就实现终了。BeanUtils的populate方法是将从form表单取到的名称和值映照到对应的ActionForm中,源码以下
public static void populate(Object bean, Map properties)
throws IllegalAccessException, InvocationTargetException {
// Do nothing unless both arguments have been specified
if ((bean == null) || (properties == null)) {
return;
}
if (log.isDebugEnabled()) {
log.debug("BeanUtils.populate(" + bean + ", " +
properties + ")");
}
// Loop through the property name/value pairs to be set
Iterator names = properties.keySet().iterator();
while (names.hasNext()) {
// Identify the property name and value(s) to be assigned
String name = (String) names.next();
if (name == null) {
continue;
}
Object value = properties.get(name);
// Perform the assignment for this property
setProperty(bean, name, value);
}
}
BeanUtils.populate(bean, properties);履行完,至此,完成了form表单数据到ActionForm的映照。
BeanUtils作为1个操作javaBean的第3方服务,这里引出BeanUtils,下篇通过实例来了解和学习BeanUtils。