通过继承ActionSupport类来完成Action开发,ActionSupport类不仅对Action接口进行简单实现, 同时增加了验证、本地化等支持 。真实开发中自定义Action都需要继承该类。对用户登录添加表单验证功能

ActionSupport类的作用:

struts2不要求我们自己设计的action类继承任何的struts基类或struts接口,但是我们为了方便实现我们自己的action,大多数情况下都会继承com.opensymphony.xwork2.ActionSupport类,并重写此类里的public String execute() throws Exception方法。因为此类中实现了很多的实用借口,提供了很多默认方法,这些默认方法包括国际化信息的方法、默认的处理用户请求的方法等,这样可以大大的简化Acion的开发。 Struts2中通常直接使用Action来封装HTTP请求参数,因此,Action类里还应该包含与请求参数对应的属性,并且为属性提供对应的getter和setter方法。 

那么Action 接口和 ActionSupport类的区别是什么呢?

Action接口有:

    public static final String SUCCESS = "success";

    public static final String NONE = "none";

    public static final String ERROR = "error";

    public static final String LOGIN = "login";

    public String execute() throws Exception;

可以看到有五个静态常量和返回类型为String 的execute()

而Actionsupport这个工具类在实现了Action接口的基础上还定义了一个validate()方法,重写该方法,它会在execute()方法之前执行,如校验失败,会转入input处,必须在配置该Action时配置input属性。
另外,Actionsupport还提供了一个getText(String key)方法还实现国际化,该方法从资源文件上获取国际化信息.
这样在自定义标签时可以定义一个变量为new actionsupport对象实现国际化。

Actionsupport类有(源码):


public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable {
    protected static Logger LOG = LoggerFactory.getLogger(ActionSupport.class);
    private final ValidationAwareSupport validationAware = new ValidationAwareSupport();
    private transient TextProvider textProvider;
    private Container container;
    public void setActionErrors(Collection<String> errorMessages) {
        validationAware.setActionErrors(errorMessages);
    }
    public Collection<String> getActionErrors() {
        return validationAware.getActionErrors();
    }
    public void setActionMessages(Collection<String> messages) {
        validationAware.setActionMessages(messages);
    }
    public Collection<String> getActionMessages() {
        return validationAware.getActionMessages();
    }
    @Deprecated
    public Collection<String> getErrorMessages() {
        return getActionErrors();
    }
    @Deprecated
    public Map<String, List<String>> getErrors() {
        return getFieldErrors();
    }
    public void setFieldErrors(Map<String, List<String>> errorMap) {
        validationAware.setFieldErrors(errorMap);
    }
    public Map<String, List<String>> getFieldErrors() {
        return validationAware.getFieldErrors();
    }
    public Locale getLocale() {
        ActionContext ctx = ActionContext.getContext();
        if (ctx != null) {
            return ctx.getLocale();
        } else {
            if (LOG.isDebugEnabled()) {
            LOG.debug("Action context not initialized");
            }
            return null;
        }
    }
    public boolean hasKey(String key) {
        return getTextProvider().hasKey(key);
    }
    public String getText(String aTextName) {
        return getTextProvider().getText(aTextName);
    }
    public String getText(String aTextName, String defaultValue) {
        return getTextProvider().getText(aTextName, defaultValue);
    }
    public String getText(String aTextName, String defaultValue, String obj) {
        return getTextProvider().getText(aTextName, defaultValue, obj);
    }
    public String getText(String aTextName, List<?> args) {
        return getTextProvider().getText(aTextName, args);
    }
    public String getText(String key, String[] args) {
        return getTextProvider().getText(key, args);
    }
    public String getText(String aTextName, String defaultValue, List<?> args) {
        return getTextProvider().getText(aTextName, defaultValue, args);
    }
    public String getText(String key, String defaultValue, String[] args) {
        return getTextProvider().getText(key, defaultValue, args);
    }
    public String getText(String key, String defaultValue, List<?> args, ValueStack stack) {
        return getTextProvider().getText(key, defaultValue, args, stack);
    }
    public String getText(String key, String defaultValue, String[] args, ValueStack stack) {
        return getTextProvider().getText(key, defaultValue, args, stack);
    }
    public String getFormatted(String key, String expr) {
        Map<String, Object> conversionErrors = ActionContext.getContext().getConversionErrors();
        if (conversionErrors.containsKey(expr)) {
            String[] vals = (String[]) conversionErrors.get(expr);
            ];
        } else {
            final ValueStack valueStack = ActionContext.getContext().getValueStack();
            final Object val = valueStack.findValue(expr);
            return getText(key, Arrays.asList(val));
        }
    }
    public ResourceBundle getTexts() {
        return getTextProvider().getTexts();
    }
    public ResourceBundle getTexts(String aBundleName) {
        return getTextProvider().getTexts(aBundleName);
    }
    public void addActionError(String anErrorMessage) {
        validationAware.addActionError(anErrorMessage);
    }
    public void addActionMessage(String aMessage) {
        validationAware.addActionMessage(aMessage);
    }
    public void addFieldError(String fieldName, String errorMessage) {
        validationAware.addFieldError(fieldName, errorMessage);
    }
    public String input() throws Exception {
        return INPUT;
    }
    public String doDefault() throws Exception {
        return SUCCESS;
    }
    public String execute() throws Exception {
        return SUCCESS;
    }
    public boolean hasActionErrors() {
        return validationAware.hasActionErrors();
    }
    public boolean hasActionMessages() {
        return validationAware.hasActionMessages();
    }
    public boolean hasErrors() {
        return validationAware.hasErrors();
    }
    public boolean hasFieldErrors() {
        return validationAware.hasFieldErrors();
    }
    public void clearFieldErrors() {
        validationAware.clearFieldErrors();
    }
    public void clearActionErrors() {
        validationAware.clearActionErrors();
    }
    public void clearMessages() {
        validationAware.clearMessages();
    }
    public void clearErrors() {
        validationAware.clearErrors();
    }
    public void clearErrorsAndMessages() {
        validationAware.clearErrorsAndMessages();
    }
    public void validate() {
    }
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public void pause(String result) {
    }
    private TextProvider getTextProvider() {
        if (textProvider == null) {
            TextProviderFactory tpf = new TextProviderFactory();
            if (container != null) {
                container.inject(tpf);
            }
            textProvider = tpf.createInstance(getClass(), this);
        }
        return textProvider;
    }
    @Inject
    public void setContainer(Container container) {
        this.container = container;
    }

可以看到里面有很多的方法,但我们很明显看到有一个我们很了解的,validate(),数据校验的方法。通过这个方法,我们可以登录时,用户名和密码为空的提示,或其他··

现在举一个简单的例子:当用户名和密码为空,给客户一个友好提示。

下面通过两种方式来阐述Struts 2的数据校验功能。

1. 编码方式校验
  1) Action一定要继承自ActionSupport
  2) 针对某个要进行校验的请求处理方法编写一个 public void validateXxx()方法,在方法内部进行表单数据校验.
  3) 也可针对所有的请求处理方法编写public void validate()方法。
  4) 在校验方法中,可以通过addFieldError()方法来添加字段校验错误消息。
  5) 当校验失败时,Struts框架会自动跳转到name为input的Result页面。在校验失败页面中,可以使用<s:fielderror/>来显示错误消息
  6) 简单,灵活。但重用性不高

重写validate方法

1.我们编写的Action一般继承与ActionSupport,而ActionSupport不仅实现了Action接口,还实现了Validatable接口,提供了数据校验功能。在Validatable接口中定义一个validate方法,重写该方法,如果校验表单输入域出现错误,则将错误添加到ActionSupport类的fieldError域中,然后通过OGNL表达式输出。

下面是用户登录校验界面:
  <body>
  <%--输出校验信息--%>
  <%--想要单个提示 <s:fielderror fieldName="uname"/>--%>
  <%--<s:property value=""/>
  --%><div style="color:red"><s:fielderror/></div>
  <s:form name="form1" namespace="/" method="post" action="LoginValidateAction">

  <s:div>请输入用户名:<s:textfield name="user.uname" ></s:textfield></s:div>
 <s:div>请输入密码:<s:password name="user.upwd" ></s:password></s:div>

 <s:submit value="登录"></s:submit>
  </s:form>
  <%--debug --%>
  <s:debug></s:debug>
  </body>
用户输入数据后,提交到LoginValidateAction 中:
public class LoginValidateAction extends ActionSupport  implements Action {
 public User user;
 public Map<String, Object> map;
          //验证的方法,会对所有的Action起作用
        @Override
    public void validate() {
            if(user.getUname().length()==0){
                addFieldError("uname", "用户名不能为空!");

            }
            if(user.getUpwd().length()==0){
                addFieldError("upwd", "密码不能为空!");
            }        

        }
      //处理业务的方法
    public String execute() throws Exception {
          System.out.println(user.getUname());
        if(user.getUname().equals("admin")&&user.getUpwd().equals("admin")){
             //让Struts2注入 map集合
        map.put("uname", user.getUname());
            //如果登录成功,返回“ success”
            return SUCCESS;
        }
        else{
            //登录失败,返回 error
            return INPUT;  //此处一定是 input
        }
    }
    /**
     * @return the user
     */
    public User getUser() {
        return user;
    }
    /**
     * @param user the user to set
     */
    public void setUser(User user) {
        this.user = user;
    }

上面的LoginValidateAction类重写了validate方法,该方法会在执行excute方法之前执行,如果执行该方法之后,Action类的filedError中包含了数据校验错误,请求将被转发到input逻辑视图。

struts.xml配置如下:


<!-- 数据校验 -->
     <action name="LoginValidateAction" class="cn.struts2.action.LoginValidateAction">
        <!-- 结果为“success”时,跳转至success.jsp页面 -->
    <result name="success">success.jsp</result>
      <!-- 结果为"error"时,跳转至fail.jsp页面   或 还在登录界面 login.jsp-->
            <result name="input">LoginValidateAction.jsp</result>
             <result name="login">fail.jsp</result>
            <result name="error">fail.jsp</result>
    </action>

在客户端的效果:

 

但是大家注意没有呢,当提示错误的时候不太是我们想要的的效果显示。

这个不是我们所想要的,那么我们怎么改呢?其实这主要显示的struts2主题样式导致的,

再来看看:

 

它自动给我们添加了样式。struts2提供了三种主题,ajax, simple, xhtml,它默认的是xhtml主题,当然你可以写任意个你自己的主题,我们称之为自定义主题。可以通过设置解决以上问题

有两种方法可以解决:

1.简单的方法(也很实用,针对所有struts2标签),在Struts.xml中,加上下一行代码就可以了。

<constant name="struts.ui.theme" value="simple" />

代表所有的页面采用的都是 simple主题了,这时它输出的页面,不回添加任何多余的代码,比如 table tr td 等,我们就可以像其他编辑页面的方式编辑页面的风格。

现在再来看看,错误的提示格式

我们可以通过设置这样一个标签:

<s:property value="errors.uname[0]"/>

把这个标签注释掉:

 <div style="color:red"><s:fielderror/></div>  

但我们设置成 这样时,会出现这样的效果。

 

这种效果就有点想我们平常输入错误时的那个提示了,还有其他属性值,这里就不用一一列举了。

使用Struts2的校验框架

 
 XML配置方式校验。

在编码方式之前被执行。
  1) 针对要校验的Action类,在同包下编写一个名为:Action类名-validation.xml校验规则文件。
  2) 在校验规则文件中添加校验规则:具体的校验器名,参数可参看Struts2的reference或Struts2的API。
   a) Field校验:针对Action类中每个非自定义类型的Field进行校验的规则。
 

   <field name="要校验的Field名">
     <field-validator type="校验规则器名" short-circuit="是否要短路径校验(默认是false)">
         <param name="校验器要使用的参数名">值</param>
            <message>校验失败时的提示消息</message>
  </field-validator>
  <!-- 还可添加其它的校验规则 -->
 </field>
 


     b) 非Field校验:针对Action类的某些Field使用OGNL表达进行组合校验。
  

  <validator type="fieldexpression">
  <param name="fieldName">pwd</param>
     <param name="fieldName">pwd2</param>
     <param name="expression"><![CDATA[pwd==pwd2]]></param><!-- OGNL表达式 -->
     <message>确认密码和密码输入不一致</message>
 </validator>
 


     c) visitor校验:主要是用来校验Action类中的自定义类型Field。(针对使用模型驱动方式时)
       i) 在Action类的的校验规则文件中针对自定义类型Field使用visitor校验规则。
    <!-- 针对自定义Field使用visitor校验 -->

 <field name="user">
  <field-validator type="required" short-circuit="true">
            <message>用户的信息必填</message><!-- 消息前缀 -->
  </field-validator>
  <field-validator type="visitor"><!-- 指定为visitor校验规则 -->
   <param name="context">userContext</param><!-- 指定本visitor校验的上下文名 -->
            <param name="appendPrefix">true</param><!-- 是否要添加校验失败消息的前缀 -->
            <message>用户的</message><!-- 消息前缀 -->
  </field-validator>
 </field>


    ii) 针对visitor的Field编写一个校验规则文件.文件名为: visitor字段类型名[-visitor校验的上下文名]-validation.xml. 例如: 本例中的文件名为User-userContext-validation.xml
                  注意: 此文件要存放到visitor字段类型所在的包下.
    iii) 在visitor的Field校验规则文件中针对要校验的Field添加校验规则.

  我们还可以不重写validate方法,而通过增加校验配置文件来进行数据校验。这个校验配置文件通过使用Struts2已有的校验器来完成对表单域的校验,下面以requiredstring校验器为例,这个校验器是一个必填校验器,指定某个表单域必须输入。

 下面是这个校验配置文件LoginValidateAction-validation.xml的写法:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN"
  "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
  <validators>
  <field name="uname">
   <field-validator type="requiredstring">
   <message>用户名不能为空</message>
  </field-validator>
  </field>
  <field name="upwd">
    <field-validator type="requiredstring">
   <message>密码不能为空</message>
  </field-validator>
  <field-validator type="stringlength">
   <param name=</param>
   <param name=</param>
   <message>密码长度应该在${minLength}--${maxLength}位之间</message>
  </field-validator>
  </field>
  </validators>

 

注意:这个校验配置文件必须遵守下面两个规则:

  1、该文件命运格式必须是Action类名-validation.xml,例如本例中该文件名为:LoginValidateAction-validation.xml

  2、该文件必须与Action类的class文件位于同一路径下,本例中文件位于

LoginValidateAction类的代码还是一样:

public class LoginValidateAction extends ActionSupport  implements Action {
 public User user;
 public Map<String, Object> map;
          //验证的方法,会对所有的Action起作用
        @Override
    public void validate() {
            if(user.getUname().length()==0){
                addFieldError("uname", "用户名不能为空!");

            }
            if(user.getUpwd().length()==0){
                addFieldError("upwd", "密码不能为空!");
            }        

        }
      //处理业务的方法
    public String execute() throws Exception {
          System.out.println(user.getUname());
        if(user.getUname().equals("admin")&&user.getUpwd().equals("admin")){
             //让Struts2注入 map集合
        map.put("uname", user.getUname());
            //如果登录成功,返回“ success”
            return SUCCESS;
        }
        else{
            //登录失败,返回 error
            return INPUT;  //此处一定是 input
        }
    }
    /**
     * @return the user
     */
    public User getUser() {
        return user;
    }
    /**
     * @param user the user to set
     */
    public void setUser(User user) {
        this.user = user;
    }

这样就OK啦

Struts 2 数据校验要用到的类和两种校验方式以及一些校验问题的解决的更多相关文章

  1. Windows校验文件哈希hash的两种常用方式

    大家经常都到哪儿去下载软件和应用程序呢?有没想过下载回来的软件.应用程序或资源是否安全呢?在 Windows 10 和 Office 2016 发布当初,很多没权限的朋友都使用第三方网站去下载安装映像 ...

  2. SpringMVC提供两种校验机制

    本文不讲如何使用SpringMVC提供的两种校验机制,只是简单的说明一下其中的差别而已: 1.创建一个Bean,在Bean的属性中添加校验信息,通过配置LocalValidatorFactoryBea ...

  3. oracle删除表数据的两种的方式

    转自:https://blog.csdn.net/qq_37840993/article/details/82490787 平时写sql中我们都会用到删除语句,而平时删除表数据的时候我们经常会用到两种 ...

  4. Repeater 控件 当数据源没有数据的时候显示 暂无数据 的两种方式

    第一种:现在前台给Repeater控件外面的div加一个runat=”server”  然后在cs后台判断数据源是否为空, 是的话就修改这个前台div的InnerText或者是InnerHtml 即可 ...

  5. 1.11-1.12 Sqoop导入数据时两种增量方式导入及direct

    一.增量数据的导入 1.两种方式 ## query 有一个唯一标识符,通常这个表都有一个字段,类似于插入时间createtime where createtime => 201509240000 ...

  6. highcharts.js两种数据绑定方式和异步加载数据的使用

    一,我们先来看看异步加载数据的写法(这是使用MVC的例子) 1>js写法 <script src="~/Scripts/jquery-2.1.4.min.js"> ...

  7. mybatis 批量添加数据的两种实现方式

    做开发的这几年期间经常遇到类似处理这种形式数据的问题,也遇到很多刚刚入行的新同学,发现他们做处理这块,经验不够,今天特地整理了一下,大家都会遇到的几种情况,代码也都粘贴出来了,拿去不谢,有时间大家还是 ...

  8. java 读取文件——按照行取出(使用BufferedReader和一次将数据保存到内存两种实现方式)

    1.实现目标 读取文件,将文件中的数据一行行的取出. 2.代码实现 1).方式1: 通过BufferedReader的readLine()方法. /** * 功能:Java读取txt文件的内容 步骤: ...

  9. 日均数据量千万级,MySQL、TiDB两种存储方案的落地对比

    http://mp.weixin.qq.com/s?__biz=MzIzNjUxMzk2NQ==&mid=2247484743&idx=1&sn=04337e020d268a9 ...

随机推荐

  1. webix前端架构的项目应用

    webix框架兼容javascript.HTML.CSS,应用比较灵活,应用框架时,配合后台webAPI,整个web项目里面,App文件夹保存前台的多语言文件,图片文件,webix原代码js.css, ...

  2. H3 BPM:为石化企业提供一个不一样的全停大修平台

    H3 BPM大型炼化企业装置全停检修管理平台(简称"全停大修")结合国际化的流程管理理念.成熟的系统技术架构.优秀的行业解决方案,为石油化工行业全停大修提供了卓越的信息化管理方案, ...

  3. Android之文件数据存储

    一.文件保存数据介绍 Activity提供了openFileOutput()方法可以用于把数据输出到文件中,具体的实现过程与在J2SE环境中保存数据到文件中是一样的.文件可用来存放大量数据,如文本.图 ...

  4. MySQL常用命令

    数据库登陆命令: mysql -uroot -p 2.提示输入密码: 3.登陆成功: 4.数据库修改相关命令: 修改数据库的编码格式: 语法格式为:ALTER {DATABASE|SCHEMA}  [ ...

  5. Win10命令提示符(cmd)怎么复制粘贴

    在Win10系统里右键开始菜单,选择弹出菜单里的命令提示符,如下图所示: 然后复制要粘贴的文字,例如: echo hovertree.com 把上面的文字复制后,点击命令提示符窗口,然后在命令提示符窗 ...

  6. eclipse,myeclipse 误删文件,回滚历史文件操作

    昨天因为误操作把一个写了一上午的代码给删了,找到的这个,以前竟然还没发现有这个功能- -! 具体操作: 1.建立同路径同名的文件 2.文件上右键 --> Compare With --> ...

  7. 【流量劫持】沉默中的狂怒 —— Cookie 大喷发

    精简版:http://www.cnblogs.com/index-html/p/mitm-cookie-crack.html 前言 上一篇文章 讲解了如何借助前端技术,打造一个比 SSLStrip 更 ...

  8. Ubuntu14.04配置Mono+Jexus

    总所周知,ASP.NET是微软公司的一项技术,是一个网站服务端开发的一种技术,它可以在通过HTTP请求文档时再在Web服务器上动态创建它们,就是所谓动态网站开发,它依赖运行于 IIS 之中的程序 .但 ...

  9. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  10. Windows平台分布式架构实践 - 负载均衡(下)

    概述 我们在上一篇Windows平台分布式架构实践 - 负载均衡中讨论了Windows平台下通过NLB(Network Load Balancer) 来实现网站的负载均衡,并且通过压力测试演示了它的效 ...