Struts中在使用DispatchAction时使用多个input,以及屏蔽不需要进行Form验证的方法

来源:互联网 发布:李滨 驻韩大使知乎 编辑:程序博客网 时间:2024/06/04 18:05

    最近参与一个项目,使用Struts作为web层框架。在开发过程中,有大量比如CRUD之类的业务,使用相同的ActionForm,因此在处理这些业务时使用DispatchAction是非常方便的,而且代码也集中在一个类中被多个方法分割。因此,比较容易进行修改和维护。
    但是当同时结合Apache的Validation框架使用时,就会出现问题。如果在配置Action时没有关闭Validation那么所有的form在构造或重新利用时都将进行验证,比如:在显示增加界面是不需要进行Form验证,在提交增加时不需要进行Form验证。另外,增加时和编辑时的Input是不同,但是Action配置时只能提供一个Input元素。
     针对以上问题我的处理方法是扩展Struts,首先我想做的是让Struts根据配置来进行验证,也就是说对需要进行Form验证的方法使用验证,在验证不成功时根据每个方法的配置返回不同的Input。对不需要进行Form的方法不使用验证。打开Struts(1.2.9)的代码,在RequestProcessor类中有这样一个方法: 

 

 protected boolean processValidate(HttpServletRequest request,
                                                         HttpServletResponse response,
                                                         ActionForm form,
                                                         ActionMapping mapping)

这个方法是在创建(或者从新利用)Form之后进行Form验证的方法,我们可以复写这个方法,对于需要进行验证的DispatchAction中的方法我们不进行处理,由RequestProcessor进行处理,对于不需要进行Form验证的方法我们默认返回验证成功。以下是我继承RequestProcessor后的新类:

package haixing.struts;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.InvalidCancelException;
import org.apache.struts.action.RequestProcessor;

/** *//**
 * 
@author haixing 2006-9-25
 * 
 * 您可以任意使用和修改这些代码.
 
*/

public class DispatchRequestProcessor extends RequestProcessor ...{

    
protected boolean processValidate(HttpServletRequest request,
                      HttpServletResponse response,
                      ActionForm form,
                      ActionMapping mapping) 
     
throws IOException, ServletException, InvalidCancelException ...{
        
        DispatchActionMapping bam 
= null;
        
if (mapping instanceof DispatchActionMapping) ...{
            bam 
= (DispatchActionMapping)mapping;
        }

        
else ...
            
return super.processValidate(request, response, form, mapping);
        }

        
        
if (mapping.getParameter() == null...{
            
return super.processValidate(request, response, form, mapping);
        }

        
        String parameter 
= request.getParameter(mapping.getParameter());
        
        
        
if (parameter == null...{
            
return super.processValidate(request, response, form, bam);
        }

        
        parameter 
= parameter.trim().toLowerCase();
        
if (bam.containsIgnore(parameter)) ...{
            
return true;
        }

        
else ...{
            bam.setNoIgnore(parameter);
        }

        
        
return super.processValidate(request, response, form, bam);
        
    }

    
}

这里使用到了一个DispatchActionMapping类,这个类是作为配置支持的,大家知道ActionMapping(也就是后续版本中的ActionConfig)是用来配置Action的,因此,为了达到我的目的需要扩展ActionMapping:

package haixing.struts;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.StringTokenizer;

import org.apache.struts.action.ActionMapping;

/** *//**
 * 
@author haixing 2006-9-25
 * 
 * 您可以任意使用和修改这些代码.
 *
 * Struts的ActionMapping的扩展,主要是为BaseAction服务(BaseAction继承了org.apache.struts.actions.DispatchAction)
 * 所以这个类也可以用在DispathAction上。
 * 
 * 作用:
 *         1. 可以指定不需要进行Form验证的Action方法 (通过DispatchAction的paratement指定的参数)
 *         2. 可以指定需要进行Form验证的Action方法以及对应的Input
 * 
 * 配置方法(struts-config.xml):
 *         1. <action-mappings type="haixing.BaseActionMapping">
 *         2. <action classname="haixing.BaseActionMapping">
 * 
 * 这个类需要配合使用BaseRequestProcessor,那么就需要在配置文件(struts-config.xml)中进行如下配置:
 *         <controller processorClass="haixing.BaseRequestProcessor"/>
 * 
 * Action的写法:
 *         <action path="/news"
 *                name="newsForm"
 *                type="haixing.NewsAction"
 *                input="/default_input"
 *                scope="request">
 *            <set-property property="ignores" value="addShow,delete,modifyShow"/>
 *            <set-property property="inputs" value="add=/news/addNews.jsp, modify=/news/modifyNews.jsp"/>
 *            <forward name="list" path="/news/listNewsForManagement.do"/>
 *            <forward name="addShow" path="/news/addNews.jsp"/>
 *            <forward name="modifyShow" path="/news/modifyNews.jsp"/>
 *            <forward name="list" path="/news/listNewsForManagement.do"/>
 *       </action>
 *   
 *    <set-property property="ignores" value="addShow,delete,modifyShow"/>
 *     这个配置指定:addShow, delete, modifyShow时不需要进行Form验证,那么其他的所有方法都将进新Form验证。
 *     
 *     <set-property property="inputs" value="add=/news/addNews.jsp, modify=/news/modifyNews.jsp"/>
 *    指定add方法的input是/news/addNews.jsp,modify方法的Input是/news/modifyNews.jsp。如果在Action中的其他方法没有在这里指
 *    定,那么都将默认返回action中的input。
 *
 *    action标签中的input为默认的input,不知道为什么ActionMapping是默认保存在Session中
 *
 
*/

public class DispatchActionMapping extends ActionMapping ...{
    
    
private static final long serialVersionUID = -4695833433866065225L;
    
    
/** *//**
     * 不需要进行Form验证的方法名称列表
     
*/

    
private ArrayList ignores = new ArrayList();
    
    
/** *//**
     * 需要进行Form验证的方法名称以及Input的map
     
*/

    
private HashMap inputs = new HashMap();
    
    
/** *//**
     * 当前需要验证的方法名
     
*/

    
private String currentNoIgnore = null;
    
    
/** *//**
     * 设置当前需要验证的方法名
     * 
     * 
@param parameter
     
*/

    
public void setNoIgnore(String parameter) ...{
        
        currentNoIgnore 
= parameter;
        
    }

    
    
/** *//**
     * 设置需要验证的方法名以及Input
     * 各个名称之间以","分割,名称与input之间以"="分割
     * 
     * 
@param inputs
     
*/

    
public void setInputs(String inputs) ...{
        
        StringTokenizer st 
= new StringTokenizer(inputs, ",");
        
while (st.hasMoreTokens()) ...{
            String input 
= st.nextToken().trim();
            
//如果去掉空格后字符串长度为0,那么跳过
            if (input.length() > 0)
                parseInput(input);
        }

        
    }

    
    
/** *//**
     * 解析方法名及input,以"="分割
     * 
@param input
     
*/

    
protected void parseInput(String input) ...{
        
        StringTokenizer st 
= new StringTokenizer(input, "=");
        
        
//方法名,默认为null
        String key = null;
        
//名称默认为null
        String forward = null;
        
        
//因为传递过来的字符窜长度大于0,所以这个方法不会失效
        key = st.nextToken().toLowerCase();
        
        
//如果没有写input,那么input为null
        if (st.hasMoreElements())
            forward 
= st.nextToken().trim();
        
        inputs.put(key, forward);
        
    }

    
    
/** *//**
     * 设置需要忽略的方法名
     * 
@param ignores
     
*/

    
public void setIgnores(String ignores) ...{
        
        StringTokenizer st 
= new StringTokenizer(ignores, ",");
        
while (st.hasMoreTokens()) ...{
            String ignore 
= st.nextToken().trim().toLowerCase();
            
if (ignore.length() > 0)
                
this.ignores.add(ignore);
        }

        
    }

    
    
/** *//**
     * 当前请求参数中是否包含要被忽略的方法名
     * 
     * 
@param ignore
     * 
@return
     
*/

    
public boolean containsIgnore(String ignore) ...{
        
        
return ignores.contains(ignore);
        
    }

    
    
/** *//**
     * 返回input的名称
     * 
@see org.apache.struts.config.ActionConfig#getInput()
     
*/

    
public String getInput() ...{
        
        
//如果没有传递参数,那么返回默认的input
        if (currentNoIgnore == null)
            
return super.getInput();
        
        Object input 
= inputs.get(currentNoIgnore);
        
if (input != null)
            
return (String)input;
        
else
            
return super.getInput();
        
    }

}

具体的我就不多说了,请看上面代码的注释。这样扩展后使得在使用DispathAction是可以配置多个Input,并且可以指定不需要进行验证的方法。上面的代码可能写得不够完善,留待日后再做吧。

原创粉丝点击