草之戒_
posts - 2,comments - 14,trackbacks - 0
      在这里我不说struts2的验证原理以及语法,我只讲一下关于struts2验证返回input视图的解决办法。
      当然如果你是使用一个方法对一个类,则不存在上面的问题,当然一个方法对应一个类,这种方式虽然可读性很高但是实际开发确实不可取,因为他会使类极具增加。如果你是使用一个类对应多个方法,你肯定碰到过这样一个问题,那就是验证时返回input视图,struts2默认验证失败返回input视图,但是我们在写程序中经常会有多个方法需要验证,打个比方如:create、update这两个操作一般情况下都会验证,但是我们把它写在一个类中,我们如果区分验证失败后,到底是create失败了还是update失败了呢?这个时候有没有怀疑过struts2,呵呵。
      当然struts2其时已经给了我们解决办法,如果你是一个细心的人读过struts2源码便过发现struts2是如何解决问题的,在这里我也简单的分析一下struts2的源码,大家请看下面这个类。
package com.opensymphony.xwork2.interceptor;

import com.opensymphony.xwork2.Action;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ValidationAware;
import com.opensymphony.xwork2.interceptor.annotations.InputConfig;
import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

import java.lang.reflect.Method;

public class DefaultWorkflowInterceptor extends MethodFilterInterceptor {

    
private static final long serialVersionUID = 7563014655616490865L;

    
private static final Logger LOG = LoggerFactory.getLogger(DefaultWorkflowInterceptor.class);

    
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];

    
//默认返回input视图,是在这里定义的
    private String inputResultName = Action.INPUT;
    
    
//可以在这里更改,一般没有人会这么做
    public void setInputResultName(String inputResultName) {
        
this.inputResultName = inputResultName;
    }

    @Override
    
protected String doIntercept(ActionInvocation invocation) throws Exception {
        Object action 
= invocation.getAction();

        
if (action instanceof ValidationAware) {
            ValidationAware validationAwareAction 
= (ValidationAware) action;

            
if (validationAwareAction.hasErrors()) {
                
if (LOG.isDebugEnabled()) {
                    LOG.debug(
"Errors on action " + validationAwareAction + ", returning result name 'input'");
                }
                
//one
                String resultName = inputResultName;
                
/*
                在这里大家读一下源码即可明白,当前处理的Action如果是一个ValidationWorkflowAware类型的,
                则调用他的getInputResultName作用返回值
                为了方便我直接把ValidationWorkflowAware放在下面的注释中,大家看他是一个接口,
                也就是说如果我们的Action实现了ValidationWorkflowAware接口
                他则会调用getInputResultName方法返回的值,而非input,而默认的ActionSupport没有实现这个接口,我们需要手动实现

                
*/
                
//package com.opensymphony.xwork2.interceptor;
                
//public interface ValidationWorkflowAware {
                    
// String getInputResultName();
                
//}

                
if (action instanceof ValidationWorkflowAware) {
                    resultName 
= ((ValidationWorkflowAware) action).getInputResultName();
                }
                
//这里不做讲述
                InputConfig annotation = action.getClass().getMethod(invocation.getProxy().getMethod(), EMPTY_CLASS_ARRAY).getAnnotation(InputConfig.class);
                
if (annotation != null) {
                    
if (!annotation.methodName().equals("")) {
                        Method method 
= action.getClass().getMethod(annotation.methodName());
                        resultName 
= (String) method.invoke(action);
                    } 
else {
                        resultName 
= annotation.resultName();
                    }
                }
                
return resultName;
            }
        }

        
return invocation.invoke();
    }

}
      大家看到上面是不是已经恍然大悟了,呵呵,是的我们实现了ValidationWorkflowAware接口之后,只需要定义一个inputResultName属性生成了对应的get、set方法是不是就对应有了getInputResultName,而这个属性的值我们可以动态传入一个值进来,呵呵,大家看下面这个实例。


public abstract class ActionSupport extends
        com.opensymphony.xwork2.ActionSupport 
implements Result,
        ValidationWorkflowAware {

    
private static final long serialVersionUID = 799075559195465128L;

    
public static final int ERROR_MSG = -1;
    
public static final int WARN_MSG = 0;
    
public static final int SUCCESS_MSG = 1;

    
public static long getSerialversionuid() {
        
return serialVersionUID;
    }

    
private ActionContext actionContext;
    
private Object id;
    
private Pagination pagn = new Pagination();
    
private QueryResult<?> results;
    
private String inputResultName;

    
/**
     * 初始化ActionContext对象
     
*/
    
public ActionSupport() {
        actionContext 
= ActionContext.getContext();
    }

    
/**
     * 
     * 
@return ActionContext对象
     
*/
    
public ActionContext getActionContext() {
        
return actionContext;
    }

    
/**
     * 
     * 
@return Struts封装后的ServletContext对象。
     
*/
    
public Map<String, Object> getApplication() {
        
return actionContext.getApplication();
    }

    
/**
     * 
     * 
@return 取得标识。
     
*/
    
public Object getId() {
        
return id;
    }

    
/**
     * 取得指定类型的标识。
     * 
     * 
@param <E>
     * 
@param c
     * 
@return
     
*/
    @SuppressWarnings(
"unchecked")
    
public <E> E getId(Class<E> c) {
        
return (E) id;
    }

    
/**
     * 
     * 
@return 输出对象。
     * 
@throws IOException
     
*/
    
public PrintWriter getOut() throws IOException {
        
return getResponse().getWriter();
    }

    
/**
     * 
     * 
@return 分页参数对象。
     
*/
    
public Pagination getPagn() {
        
return pagn;
    }

    
/**
     * 
     * 
@return HttpServletRequest对象。
     
*/
    
public HttpServletRequest getRequest() {
        
return ServletActionContext.getRequest();
    }

    
/**
     * 
     * 
@return HttpServletResponse对象。
     
*/
    
public HttpServletResponse getResponse() {
        
return ServletActionContext.getResponse();
    }

    
/**
     * 
     * 
@return 查询结果集。
     
*/
    
public QueryResult<?> getResults() {
        
return results;
    }

    
/**
     * 
     * 
@return ServletContext对象。
     
*/
    
public ServletContext getServletContext() {
        
return (ServletContext) this.actionContext
                .get(StrutsStatics.SERVLET_CONTEXT);
    }

    
/**
     * 
     * 
@return Struts封装后的HttpSession对象。
     
*/
    
public Map<String, Object> getSession() {
        
return actionContext.getSession();
    }

    
/**
     * 
     * 
@return Struts的ValueStack对象。
     
*/
    
public ValueStack getValueStack() {
        
return ServletActionContext.getValueStack(getRequest());
    }

    
/**
     * 向ActionContext中添加一个信息,此信息会保存到HttpServletRequest中。
     * 
     * 
@param key
     *            键。
     * 
@param value
     *            值。
     
*/
    
public void put(String key, Object value) {
        actionContext.put(key, value);
    }

    
public void setActionContext(ActionContext actionContext) {
        
this.actionContext = actionContext;
    }

    
/**
     * 
     * 
@param id
     *            设置标识。
     
*/
    
public void setId(Object id) {
        
this.id = id;
    }

    
/**
     * 
     * 
@param pagn
     *            设置分页参数对象。
     
*/
    
public void setPagn(Pagination pagn) {
        
this.pagn = pagn;
    }

    
/**
     * 
     * 
@param results
     *            设置返回的结果集。
     
*/
    
protected void setResults(QueryResult<?> results) {
        
this.results = results;
    }

    
public String getInputResultName() {
        
return inputResultName;
    }

    
public void setInputResultName(String inputResultName) {
        
this.inputResultName = inputResultName;
    }

    
public abstract String show() throws Exception;

    
public abstract String edit() throws EditFailureException;

    
public abstract String destroy() throws DestroyFailureException;

    
public abstract String create() throws CreateFailureException;

    
public abstract String deleteConfirm() throws DeleteFailureException;

    
public abstract String index() throws Exception;

    
public abstract String update() throws UpdateFailureException;

    
public abstract String editNew() throws EditFailureException;
}
      上面是我自定义一个ActionSupport类,该类实现了ValidationWorkflowAware,并重写了getInputResultName方法。然后我再定义一个Action继承了该类。
@Namespace(value = "/test")
@Action(params 
= { "actionName""demo" })
@Results( {
        @Result(name 
= "xx", type = "redirect", location = "http://www.google.com"),
        @Result(name 
= "hello", type = "redirect", location = "http://www.baidu.com") })
@SuppressWarnings(
"serial")
public class DownloadController extends ActionSupport {

    
public String index() {
        System.out.println(
"-------index-----------");
        
return "xx";
    }

    
public void validateIndex() {
        addFieldError(
"hell"".my hello.");
        System.out.println(
"ok");
    }
    
//..省略了其它无关方法
}
      在上面我就只是做了一个简单了模拟验证然后跳转到指定的页面。这里你可以这样请求,测试一个最终struts2是否调用了getInputResultName方法并使用其返回值,作为返回视图的名称:http://地址:端口/project/test/demo!index.action?inputResultName=hello,大家测试如果跳转到了baidu就说明成功了。
      至此,有问题可以留言。


转载时请注明转载地址,onlyeffort.QQ:501276913
posted on 2010-06-08 20:13 Aidan 阅读(6109) 评论(7)  编辑  收藏

FeedBack:
# re: Struts2-疑难杂症之Validator返回input视图
2010-06-08 23:15 | 18傲骨中文
收藏慢慢看~~  回复  更多评论
  
# re: Struts2-疑难杂症之Validator返回input视图
2010-06-09 08:17 | quaff
请使用@InputConfig

public class DownloadController extends ActionSupport {

@InputConfig(methodName="inputIndex")
//@InputConfig(resultName="input")
public String index() {
System.out.println("-------index-----------");
return "xx";
}

public void validateIndex() {
addFieldError("hell", ".my hello.");
System.out.println("ok");
}

public string inputIndex() {
return "input";
}
}  回复  更多评论
  
# re: Struts2-疑难杂症之Validator返回input视图
2010-06-09 08:46 | 雪山飞鹄
通常都是自己在validator方法中做判断,没研究过  回复  更多评论
  
# re: Struts2-疑难杂症之Validator返回input视图
2010-06-09 11:34 | Aidan
@quaff
Thank you.使用@InputConfig能更简单的完成任务,而且可读性更高。  回复  更多评论
  
# re: Struts2-疑难杂症之Validator返回input视图
2010-06-09 23:04 | aaaaaa
struts2早提供了每个方法一个validate,就是会执行validateXXX方法,比如业务方法update,那么会执行validateUpdate.  回复  更多评论
  
# re: Struts2-疑难杂症之Validator返回input视图
2010-06-10 08:39 | Aidan
@aaaaaa
不好意思,我们讨论的不是一个话题。  回复  更多评论
  
# re: Struts2-疑难杂症之Validator返回input视图
2010-06-10 08:50 | quaff
@Aidan
这是我提交给xwork的,看你的需求就知道这个功能就是为这个打造的  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
编程部落   qq群:37996359(上限500人,一起关注java、讨论技术,互相学习,共同进步)