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;
-
- }
-
-
- 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);
-
-
- 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和转换类型等操作的,具体实现:
这段实现的前半部分是关于上传的代码,因为咱们这个实例不和上传有关,所以直接忽略,直接到
- 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);
-
- }
-
-
-
-
-
- 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) {
-
-
-
-
-
-
-
-
-
- ((ActionForm) bean).setMultipartRequestHandler(multipartHandler);
-
- }
-
- }
这个方法会遍历ActionForm的值的类型,并且讲Map中的值的类型改为和ActionForm对应的类型。