深入浅出学习Struts框架(十二)-分析Struts框架实例7

上一篇博客主要是讲解ActionServlet中的一个方法processActionForm,当我们在截取字符串,再根据字符串取得ActionMapping之后,我们就要用利用ActionMapping来创建ActionForm,并且把ActionForm放到request或session中管理。获得ActionForm之后,我们就要将ActionForm中的数据放到Mapping中,以便实例化Action。在Struts中有一个方法是专门把ActionForm的数据放到Mapping的,这个方法就是processPopulate。今天我们就来详细来看看这个方法。

首先这个方法主要的功能是将表单数据放到Map中,并且将Map的值根据ActionForm类型转换好后设置到ActionForm中。

这个方法具体的流程是首先执行ActionForm中的reset方法进行重置,然后得到表单中所有输入域的name名称,再调用request.getParameterValues(),根据name名称得到相应的值,最后将表单中的数据全部放到一个map中,map的key为表单输入域的名称,map的value为表单输入域的值(字符串数组),接下来调用一个第三方组件BeanUtils,将Map中的值,根据ActionForm中的类型先转换好,再调用ActionForm中的setter方法设置到ActionForm上。

下面咱们来跟随源代码来看看这个方法的实现过程.首先还是和以前博客一样设置断点,进入process方法,找到processPopulate方法:

进入这个方法,看到这个方法的实现源代码:

protectedvoid processPopulate(HttpServletRequest request, HttpServletResponse response, ActionForm form, ActionMapping mapping) throws ServletException { if (form == null) { return; } // Populate the bean properties of this ActionForm instance if (log.isDebugEnabled()) { log.debug(" Populating bean properties from this request"); } form.setServlet(this.servlet); form.reset(mapping, request); if (mapping.getMultipartClass() != null) { request.setAttribute(Globals.MULTIPART_KEY, mapping.getMultipartClass()); } RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix(), request); // Set the cancellation request attribute if appropriate if ((request.getParameter(Constants.CANCEL_PROPERTY) != null) || (request.getParameter(Constants.CANCEL_PROPERTY_X) != null)) { request.setAttribute(Globals.CANCEL_KEY, Boolean.TRUE); } }

其中,form.reset(mapping, request);这个方法就是讲form重置,作用是使ActionForm中的值恢复初始状态。

下面RequestUtils.populate(form, mapping.getPrefix(), mapping.getSuffix()这个方法就是要完成填充map和转换类型等操作的,具体实现:

publicstaticvoid 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 { thrownew 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) { thrownew 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(); }

这段代码,这段代码主要是获得表单的所有名称,之后通过下面这段代码:

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值,之后通过

if (!(stripped.startsWith("org.apache.struts."))) { properties.put(stripped, parameterValue); }

将名称作为key值,讲名称的value值作为value值添加到map中,到此为止,我们就讲表单数据添加到了map中。

随后,调用第三方的组件来实现类型转换:

try { BeanUtils.populate(bean, properties); } catch(Exception e) { thrownew 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); } }

这个方法会遍历ActionForm的值的类型,并且讲Map中的值的类型改为和ActionForm对应的类型。

到这里processPopulate的方法就实现完毕,实现了这个方法有什么用处呢?敬请等待下一篇博文!

深入浅出STRUTS 2 Struts Ti却发现了二者在技术与开发人员这两个层面上的共同之处,不久之后,两个项目就在WebWork的技术基础上进行了合并2。 当我们说起WebWork的时候,我们实际上说的是两个项目——XWork和WebWork。XWork是一个通用的命令框架,它提供了很多核心的功能,例如actions,验证和拦截器,它可以完全独立于执行上下文运行,并提供了一个内部的依赖注入机制,用来做配置和工厂实现的管理。 而WebWork则是一个完全独立的上下文。它用Web应用中运行所需的上下文把XWork包装起来,并提供了可以简化Web开发的特定实现。 Struts2的目标很简单——使Web开发变得更加容易。为了达成这一目标,Struts2中提供了很多新特性,比如智能的默认设置、annotation的使用以及“惯例重于配置”原则的应用,而这一切都大大减少了XML配置。Struts2中的Action都是POJO,这一方面增强了Action本身的可测试性,另一方面也减小了框架内部的耦合度,而HTML表单中的输入项都被转换成了恰当的类型以供action使用。开发人员还可以通过拦截器(可以自定义拦截器或者使用Struts2提供的拦截器)来对请求进行预处理和后处理,这样一来,处理请求就变得更加模块化,从而进一步减小耦合度。模块化是一个通用的主题——可以通过插件机制来对框架进行扩展;开发人员可以使用自定义的实现来替换掉框架的关键类,从而获得框架本身所不具备的功能;可以用标签来渲染多种主题(包括自定义的主题);Action执行完毕以后,可以有多种结果类型——包括渲染JSP页面,Velocity和Freemarker模板,但并不仅限于这些。最后,依赖注入也成了Struts2王国中的一等公民,这项功能是通过Spring框架的插件和Plexus共同提供的,与PicoContainer的结合工作还正在进行中。 本书的目的,是为了帮助读者掌握Struts2框架,并能够对组成框架的功能部件和可用的配置项有深刻的理解。我在书中还将介绍一些可以提高生产力的方法——包括默认配置项和应当注意的实现特性,可用的多种配置选项和一些开发技术。本书还会就与第三方软件进行集成的话题展开讨论。 2 Don Brown, Struts Ti项目的领导,他在文章中详细介绍了Struts Ti的历史
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值