什么是静态参数?
静态参数就是硬编码的,不可随意改变。javascript
例子:java
咱们首先建立一个Action类,里面有两个参数,用来封装请求参数 public class User extends ActionSupport { private String username; //用户名 private int age; //年龄 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String adduser(){ System.out.println(username+":"+age); return null; } }
咱们在struts.xml中配置静态参数 <package name="p1" extends="struts-default"> <action name="action1" class="com.cad.struts2.User" method="adduser"> <!--经过注入的方式封装静态参数--> <param name="username">张三</param> <param name="age">18</param> </action> </package>
咱们访问action1动做时,会输出 张三:18
咱们配置的静态参数怎么就被传递到动做类里呢?程序员
咱们在struts2的运行流程中提到过,咱们动做类的动做方法执行以前,会有一系列的拦截器帮咱们执行一些操做。 在struts-default.xml中,有不少拦截器,拦截器又分为不少拦截器栈,咱们默认是使用defaultStack的拦截器栈。 这个拦截器栈中有一个叫作staticParams的拦截器帮咱们完成静态参数的封装,将配置的静态方法经过action类中的set方法设置进去。
什么是动态参数?web
像咱们用表单提交的数据,就是动态数据。数据是可变的。
例子:正则表达式
第一步:咱们先建立一个添加用户的表单 <form action="${pageContext.request.contextPath }/action1" method="post"> 用户名:<input type="text" name="username"><br> 年 龄:<input type="text" name="age"><br> <input type="submit" value="提交"> </form>
第一种方式:数据参数和动做类写在一块儿 要求是表单中的name必须和咱们类中的set方法后面的名称一致,例如表单中的username对应类中的setUsername,和参数并无太大关系,和set方法有关系。 public class User extends ActionSupport { private String username; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String adduser(){ System.out.println(username+":"+age); return null; } }
配置struts.xml文件 <package name="p1" extends="struts-default"> <action name="action1" class="com.cad.struts2.User" method="adduser"> </action> </package>
咱们访问添加用户页面,添加数据,会输出咱们添加的数据。sql
这一系列操做是由拦截器栈中的名为params的拦截器帮咱们完成的数据库
上面这种方式将参数和动做类写在一块儿,看起来太过混乱,咱们能不能用一个JavaBean将参数给封装起来。 答案是能。express
第二种方式,将参数数据和动做类分开写 第一步,咱们建立一个javaBean,User类,用来封装请求参数 public class User implements Serializable{ private String username; private int age; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
第二步:建立一个添加用户的动做类,里面有一个user对象 public class AdduserAction extends ActionSupport { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String adduser(){ System.out.println(user.getUsername()+":"+user.getAge()); return null; } }
第三步:咱们得改变一些咱们的jsp页面的写法,由于表单的name要和类中的数据相对应,但类中只有一个user ,username去找动做类中的setUsername,确定找不到。 咱们这样写,他就会先找类中的user对象,而后去找user对象的username和age <body> <form action="${pageContext.request.contextPath }/action1" method="post"> 用户名:<input type="text" name="user.username"><br> 年 龄:<input type="text" name="user.age"><br> <input type="submit" value="提交"> </form> </body>
原理:apache
这一系列操做仍是拦截器params帮咱们完成。咱们在getUser和setUser里打印两句话来看看他究竟是怎么执行的 public User getUser() { System.out.println("getuser"); return user; } public void setUser(User user) { System.out.println("setuser"); this.user = user; } 输出 getuser :先判断对象是否存在 setuser :若是判断不存在,调用set方法,经过反射建立一个对象,而且设置给该类 getuser :而后再获取该对象,调用该对象的get和set方法对参数赋值
出于结构清晰的考虑,应该采用单独的Model实例来封装请求参数和处理结果,这就是所谓的模型驱动, 所谓模型驱动,就是使用单独的JavaBean来贯穿整个MVC流程。 所谓属性驱动,就是使用属性来做为贯穿MVC流程的信息携带者,固然属性必须依附于对象,这个对象就是Action实例。 简单说,模型驱动就是使用单独的javaBean封装请求参数。 属性驱动就是把属性写在Action类中。
咱们发现上面的jsp中的name必须前面得加 user.username。。太过麻烦。咱们使用模型驱动来解决这个问题。实际开发中使用这种方式数组
模型驱动的要求: 1.动做类实现ModelDriven接口 2.实现接口中的getModel方法,返回咱们的数据对象 3.数据模型对象必须由咱们实例化。 咱们改进动做类 public class AdduserAction extends ActionSupport implements ModelDriven<User>{ //数据模型对象由咱们实例化 private User user=new User(); public User getUser() { System.out.println("getuser"); return user; } public void setUser(User user) { System.out.println("setuser"); this.user = user; } public String adduser(){ System.out.println(user.getUsername()+":"+user.getAge()); return null; } //实现接口方法,返回咱们的数据模型对象 public User getModel() { // TODO Auto-generated method stub return user; } }
咱们在jsp上就能像之前那样 ,name只用咱们的参数相同便可 <body> <form action="${pageContext.request.contextPath }/action1" method="post"> 用户名:<input type="text" name="username"><br> 年 龄:<input type="text" name="age"><br> <input type="submit" value="提交"> </form> </body>
原理:
其实这时候表单的name已经不只仅是一个简单的字符串了。 这一系列的操做是由ModelDriven和params拦截器帮咱们作的 。 params拦截器负责提取请求参数,若是是属性驱动模式,则还负责将请求参数传给Action类的属性 模型驱动的话就只提取请求参数。 ModelDriven拦截器会先判断咱们的动做类是否属于ModelDriven类型 属于的话,就调用咱们实现的getModel方法,获取咱们传入的对象 而后将咱们的对象给压入栈中
第一步:咱们先建立数据库表 create database demo; use demo; create table user( username varchar(100) primary key, password varchar(100), birthday date, hobby varchar(255), married boolean );
第二步:在domain包建立咱们的user实体类 public class User { private String username;//用户名 private String password;//密码 private Date birthday; //生日 private String hobby; //爱好 private boolean married; //是否结婚 public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public String getHobby() { return hobby; } public void setHobby(String hobby) { this.hobby = hobby; } public boolean isMarried() { return married; } public void setMarried(boolean married) { this.married = married; } }
第三步:完成数据层,咱们在Dao层处理数据 public class UserDao { QueryRunner qr=new QueryRunner(JdbcUtils.getDataSource()); //根据名字查找用户 public User findUserByUsername(String username){ try { String sql="select * from user where username=?"; return qr.query(sql, new BeanHandler<User>(User.class),username); } catch (Exception e) { throw new RuntimeException(e); } } //添加用户 public int addUser(User user){ String sql="insert into user values(?,?,?,?,?)"; Object []params={user.getUsername(),user.getPassword(),user.getBirthday(),user.getHobby(),user.isMarried()}; try { return qr.update(sql,params); } catch (SQLException e) { throw new RuntimeException(e); } } }
第四步:完成业务逻辑层的编写,service层 public class UserService { private UserDao userdao=new UserDao(); //注册 public int regist(User user){ return userdao.addUser(user); } //经过用户名查找用户 public User findByUsername(String username){ return userdao.findUserByUsername(username); } }
第五步:建立web层,咱们建立web层动做类 public class UserAction extends ActionSupport implements ModelDriven{ private User user=new User(); private UserService userservice=new UserService(); //注册方法 public String regist(){ User _user=userservice.findByUsername(user.getUsername()); //判断用户是否存在,存在返回exists字符串 if(_user!=null){ return "exists"; } //获取注册成功更新的行数 int count=userservice.regist(user); //若是>0,返回success if(count>0){ return SUCCESS; } return null; } public Object getModel() { // TODO Auto-generated method stub return user; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
第六步:咱们编写注册的jsp页面 <body> <form action="${pageContext.request.contextPath }/regist.action" method="post"> 用户名:<input type="text" name="username"><br> 密 码:<input type="password" name="password"><br> 生 日:<input type="text" name="birthday"><br> 爱好:<input type="checkbox" name="hobby" value="篮球">篮球 <input type="checkbox" name="hobby" value="足球">足球 <input type="checkbox" name="hobby" value="写代码">写代码<br> 已婚:<input type="checkbox" name="married" value="true"><br> <input type="submit" name="注册"><br> </form> </body>
第七步:配置 struts.xml <package name="p1" extends="struts-default"> <action name="regist" class="com.cad.web.action.UserAction" method="regist"> <result name="success">/success.jsp</result> <result name="exists">/msg.jsp</result> </action> </package>
成熟的MVC框架应该提供成熟的异常处理机制。固然能够在方法中手动捕捉异常,当捕捉到特定异常时,返回特定逻辑视图名。
这种方式很是繁琐,须要在方法中写大量try catch块,最大的缺点仍是一旦须要改变异常处理方法时,须要修改代码。
最好的方式是经过声明式的方式管理异常处理。struts2提供了一种声明式的异常处理方式。
咱们看Action接口中的execute方法声明。 public String execute() throws Exception 这就意味着咱们重写该方法时,无需进行任何异常处理,而是把异常抛给struts2框架处理. struts2框架接收到Action抛出的异常后,根据struts.xml文件配置的异常映射,转入指定的视图资源。 异常映射功能是由 exception的拦截器帮咱们作的。 struts2的异常处理机制是经过在struts.xml中配置<exception-mapping..../>元素完成。 属性: exception:异常类型 result:出现该异常时,系统转入result指定的结果
全局异常映射对全部的Action都有效,但局部异常映射只对该异常映射所在的Action有效。
若是全局异常映射和局部异常映射配置了同一个异常类型,在该Action内,局部覆盖全局。
局部异常映射:将<exception-mapping..../>元素做为<action.../>的子元素配置 全局异常映射:将<exception-mapping..../>元素做为<global-exception-mappings>元素的子元素配置
咱们作一个简单的登录应用 第一步:咱们编写咱们的Action类 public class LoginAction implements Action{ private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute()throws Exception{ //当用户名为monster时,抛出咱们的自定义异常 if(getUsername().equals("monster")){ throw new MyException("自定义异常"); } //当用户名为sql时,抛出sql异常 if(getUsername().equalsIgnoreCase("sql")){ throw new SQLException("用户名不能为sql"); } if(getUsername().equals("cad")&&getPassword().equals("123456")){ return "success"; }else { return "error"; } } }
第二步:咱们编写咱们的登录jsp页面 <body> <form action="${pageContext.request.contextPath }/login" method="post"> 用户名:<input type="text" name="username"><br> 密 码:<input type="password" name="password"><br> <input type="submit" value="提交"> </form> </body>
第三步:咱们编写咱们的配置文件struts.xml <package name="p2" extends="struts-default"> //全局结果视图定义 <global-results> <result name="sql">/exception.jsp</result> </global-results> //全局异常定义 <global-exception-mappings> //出现sql异常,就转入到视图名为sql的视图结果 <exception-mapping result="sql" exception="java.sql.Exception"></exception-mapping> </global-exception-mappings> <action name="login" class="com.cad.struts2.LoginAction" > //局部异常定义 <exception-mapping result="my" exception="conm.cad.struts2.MyException"></exception-mapping> <result name="my">/exception.jsp</result> <result name="success">/welcome.jsp</result> <result name="error">/error.jsp</result> </action> </package>
从struts2.1开始,struts2增长了未知处理器。 当用户请求未知Action,或指定Action里的未知方法,或Action处理结束后返回一个未知的result。struts2容许使用未知处理器来处理这些状况。 未知处理器须要实现UnknownHandler接口,该接口包含三个方法 -handleUnknownAction:用户请求未知Action时,该方法会被回调 -handleUnknownActionMethod:用户请求指定Action的未知方法时,该方法会被回调 -handleUnknownResult:Action处理结束后返回一个未知Result时,该方法会被回调 一旦实现了自定义的未知处理器,就能够在struts.xml中经过<bean../>元素来配置未知处理器 例如 <bean name="myHandler" class="com.cad.struts2.MyUnknownHandler" type="com.opensymphony.xwork2.UnknownHandler"></bean>
第一步:咱们实现咱们简单的未知处理器 public class MyUnknownHandler implements UnknownHandler { public ActionConfig handleUnknownAction(String namespace, String actionName) throws XWorkException { System.out.println(actionName+"不存在"); return null; } public Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode) throws XWorkException { System.out.println(resultCode+"不存在"); return null; } public Object handleUnknownActionMethod(Object action, String methodName) throws NoSuchMethodException { System.out.println(methodName+"不存在"); return null; } }
第二步:在struts.xml中配置未知处理器 //定义咱们的未知处理器 <bean name="myHandler" class="com.cad.struts2.MyUnknownHandler" type="com.opensymphony.xwork2.UnknownHandler"></bean> <package name="p3" extends="struts-default"> <action name="myAction"></action> </package> //定义未知处理器栈 <unknown-handler-stack> <unknown-handler-ref name="myHandler"></unknown-handler-ref> </unknown-handler-stack>
而后咱们访问myAction,会输出success不存在。 是由于不指定action的class属性时,默认使用ActioSupport 通常未知处理器主要处理Action返回未知result时有用。 了解便可。
全部的MVC框架,都属于表现层的解决方案,都须要负责收集用户请求参数,并将请求参数传给应用的控制器组件。
这时问题出现了,全部的请求参数都是字符串类型数据,所以MVC框架必须具有将这些字符串请求参数转换成相应的数据类型。
struts2提供了很是强大的类型转换机制,struts2的类型转换是基于OGNL表达式。
struts2提供了很好的扩展性,开发者能够开发出本身的类型转换器。完成字符串到自定义类型之间的转换。
若是类型转换中出现未知异常,开发者无须关心异常处理,struts2的conversionError拦截器会自动处理该异常,而且在页面上生成提示信息。
表单中提交的全部数据都是字符串类型
例如咱们有一个User类,name为String类型,age为int类型,birthday为Date类型,咱们必须在servlet中获取表单传入的参数,而后将其进行类型转换,而后封装到User对象中。
上述须要程序员本身进行类型转换操做,比较繁琐。
对于一个MVC框架而言,同样须要将请求参数封装成对象,也必须将请求参数转换成对象属性的数据类型,这就是类型转换的意义。
struts内建的类型转换器能自动将咱们的表单数据(字符串)转换成对应的数据类型。
完成字符串和日期类型之间的转换时,日期格式必须使用请求用户本地的格式。通常是yyyy-MM-dd,若是输入的日期格式不是本地的日期格式,例如咱们输入1996/01/31,就会出现错误,类型转换失败。
需求:
当咱们在表单中输入的日期格式不是本地的格式时,就会出现类型转换错误,咱们也常常须要将字符串转换成其余的格式,例如字符串转换成对象之类的操做,这时咱们就须要自定义类型转换器。 struts2的类型转换器其实是基于OGNL实现的。xwork集成了OGNL。 实现类型转换器必须实现TypeConverter接口。这个接口的方法太过复杂,因此还提供了一个该接口的实现类DefaultTypeConverter。 咱们重写DefaultTypeConverter类的convertValue方法便可。 咱们基于DefaultTypeConverter类实现类型转换器时,将字符串转换成咱们须要的类型经过convertValue方法实现,将咱们的类型转换成字符串也是经过convertValue方法实现,所以咱们必须判断转换的类型来实现不一样的逻辑。 为了简化类型转换器的实现,struts2提供了一个StrutsTypeConverter抽象类,这个类是DefaultTypeConverter类的子类。 咱们看下这个类的源码 :
继承DefaultTypeConverter public abstract class StrutsTypeConverter extends DefaultTypeConverter { //重写DefaultTypeConverter类的convertValue方法 public Object convertValue(Map context, Object o, Class toClass) { //若是要转换的类型是字符串类型,也就是把咱们的类型转换成字符串,调用convertToString方法 if (toClass.equals(String.class)) { return convertToString(context, o); } //若是参数是字符串数组,也就是将字符串转换成咱们须要的类型,调用convertFromString方法 else if (o instanceof String[]) { return convertFromString(context, (String[]) o, toClass); } //若是参数是字符串,也就是将字符串转换成咱们须要的类型,调用convertFromString方法 else if (o instanceof String) { return convertFromString(context, new String[]{(String) o}, toClass); } else { return performFallbackConversion(context, o, toClass); } } protected Object performFallbackConversion(Map context, Object o, Class toClass) { return super.convertValue(context, o, toClass); } //将字符串转换成咱们须要的类型的方法 public abstract Object convertFromString(Map context, String[] values, Class toClass); //将咱们的类型转换成字符串的方法 public abstract String convertToString(Map context, Object o); } 三个参数 : Map context:OGNL的上下文。暂时还没学,后面会学到,暂时不用管。 value:须要转换的参数。 toClass:转换后的类型
需求:咱们将咱们前面的注册案例中的生日改为 yyyy/MM/dd类型 第一步:建立自定义类型转换器 public class MyConverter extends StrutsTypeConverter { //日期转换器,转换成指定的类型 private DateFormat format=new SimpleDateFormat("yyyy/MM/dd"); //将字符串转换成日期类型 public Object convertFromString(Map context, String[] values, Class toClass) { //判断参数是否为空 if(values==null||values.length==0){ return null; } //咱们只有一个参数,就是表单的birthday String date=values[0]; //判断目标类型是不是Date if(toClass==java.util.Date.class){ try { //进行转换 return format.parse(date); } catch (ParseException e) { e.printStackTrace(); } } return null; } //将日期类型转换成字符串 public String convertToString(Map context, Object o) { //判断当前参数是不是日期类型 if(o instanceof java.util.Date){ return format.format(o); } return null; } }
第二步:注册类型转换器 局部类型转换器 按照属性来注册 若是属性都在action中,那么应该建立一个文件 Action名字-conversion.properties ,例如LoginAction-conversion.properties 若是属性放到了javaBean中,那么建立一个文件 javaBean名称-conversion.properties 例如 User-conversion.properties 文件由键值对组成。 键为须要转换的属性名字,值为本身实现的类型转换器全类名。 咱们建立 User-conversion.properties 内容 birthday=com.cad.web.convert.MyConverter 这时咱们注册时使用 1996/01/24这种格式进行注册就不会出现类型转换错误。 用户提交请求时,请求中的birthday参数会先被该类型转换器处理。 全局类型转换器 全部的Action都能用。咱们须要在src目录下建立一个 xwork-conversion.properties 的文件 由于是全局的,就不存在只对birthday这个属性进行转换。 这里的键是要转换的类型,值仍是类型转换器类。 咱们建立 xwork-conversion.properties 内容 java.util.Date=com.cad.web.convert.MyConverter 这样当咱们输入日期的表单时,就可使用咱们自定义的日期格式。
struts2提供了一个名为conversionError的拦截器,这个拦截器被注册在默认拦截器栈中。
当类型转换器执行类型转换出现错误时,该拦截器负责将对应错误封装成表单域错误(fieldError),并将错误信息放入ActionContext中。
当拦截器对转换异常进行处理后,系统会跳转到名为input的逻辑视图。
咱们在struts.xml中配置 <result name="input">/regist.jsp</result> 当类型转换失败后,再跳转到注册页面 跳转到input视图之后,咱们发现没有任何错误提示信息。咱们前面讲过conversionError拦截器会将转换错误封装成fieldError,并放在ActionContext中。 为了在页面中输出错误信息,咱们须要使用struts的标签。咱们先使用一些,后面会详细介绍。 咱们在页面添加<s:fielderror></s:fielderror>标签 当咱们类型转换失败后,就会输出错误信息。 咱们发现输出的错误信息是英文的,咱们但愿能变为中文的提示信息。 咱们只须要在建立一个properties文件 文件名为 javabean名称.properties 键为invalid.fieldvalue.属性名称 例如 :invalid.fieldvalue.birthday 值为要输出的内容 例如 invalid.fieldvalue.birthday=生日格式不正确
输入校验是web应用必须处理的问题,要防止用户的误输入和恶意非法输入。struts2给咱们提供了很是强大的输入校验体系。 输入校验分为客户端校验和服务器端校验。通常开发中二者都用,可是服务端校验必须使用。 客户端校验是经过javascript在表单页面进行初步过滤。客户端校验并不安全,攻击者有不少方法能够绕过客户端校验,因此服务端校验是必不可少的。 可是客户端校验必不可少,由于大多数浏览者都是正经常使用户,能够阻止一些误操做,下降了服务器的负载。 服务端校验: 咱们之前在servlet中增长校验。是经过获取参数,而后判断参数是否为空和长度等等来进行校验。 在servlet中使用硬编码进行输入校验乏味而又繁琐,struts2提供了基于校验框架的输入校验,只须要指定简单的配置文件便可。
声明式验证:经过xml配置文件进行验证
-校验规则文件与Action类放在同一目录下 -校验配置文件名称为 ActionClassName-validation.xml 例如 :UserAction-validation.xml 增长校验文件后,系统会自动加载该文件。当用户提交请求时,struts2会根据该文件对用户数据进行校验
基于表单字段的配置风格
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd"> //校验文件的根元素 <validators> //被校验表单项名称 <field name="username"> //指定校验器,struts2有不少内建校验器,requiredstring是校验数据是否为空并去除两端空格 <field-validator type="requiredstring"> //校验失败后的提示信息 <message>用户名不能为空</message> </field-validator> </field> </validators>
校验失败后,struts2会返回名为input的逻辑视图名,所以咱们还须要添加一个<result> 这个配置文件是全局验证。也就是这个Action中的全部动做都会被验证,咱们Action有的方法并不须要验证,加入验证甚至会出错。 咱们有两种方式可让不须要验证的方法跳过验证: 第一种:在不须要验证的方法前面添加注解@SkipValidation 第二种:针对动做类中的某个方法进行验证,建立的XML文件名为 ActionClassName-ActionName-validation.xml ,这里的ActionName不是方法名,而是配置的action名字 ,例如 :UserAction-regist-validation.xml
非字段配置风格(基于验证器的配置风格)
<validators> //验证器类型 <validator type="requiredstring"> //要校验的参数名字 <param name="fieldName">password</param> //校验失败后返回的信息 <message>密码不能为空</message> </validator> </validators>
校验配置文件的<field-validator>和<validator>元素能够指定一个可选的short-circuit属性,指定该校验器是不是短路校验器,默认是false。 短路校验器的做用是若是一个字段内有多个校验器,若是一个校验器校验失败,其余校验器根本不会继续校验。 校验器的执行顺序 -全部基于验证器的配置风格的校验器优先于字段风格的校验器 -全部的基于验证器风格的校验器,排在前面的先执行 -全部的基于字段风格的校验器,排在前面的先执行。 校验器的短路原则 -全部的非字段校验器最早执行,若是某个非字段校验器校验失败,则该字段上的全部字段校验器都不会执行 -非字段校验器校验失败,不会阻止其余非字段校验器的执行 -若是某个字段校验器校验失败,则该字段下的后面的字段校验器都不会执行 -字段校验器永远都不会阻止非字段校验器的执行
required:必填验证器,要求指定的字段必须有值。使用非字段风格的配置时,能够配置fieldName属性来设置要校验的表单项名称。 requiredstring:必填字符串验证器。 int、long、short:整数校验器。要求字段的整数值必须在指定范围内。参数:min指定该属性最小值,不指定不检查最小值。max指定该属性最大值,不指定不检查最大值。 date:日期校验器。要求字段的日期值必须在指定范围内。参数:min最小日期 ,max最大日期 expression:表达式校验器,它只能被非字段风格配置。参数:expression指定一个逻辑表达式。 fieldexpression:字段表达式校验器。要求字段知足一个逻辑表达式。 email:邮件校验器。要求被检查字段非空,而且必须是合法的邮箱地址,底层是正则表达式。 url:网址校验器。要求被检查字段非空而且是个发的url地址,底层是正则表达式。 stringlength:字符串长度校验器。要求字段长度必须在指定的范围内。参数:manLength 最大长度 minLength最小长度 regex:正则表达式校验器。 等等。
struts2内建的校验器能够完成大部分输入校验。可是有时候没法知足一些特殊的要求,struts2容许经过手动方式完成自定义校验。 继承ActionSupport,重写validate方法 public void validate() { if(user.getUsername()==null||user.getUsername().isEmpty()){ addFieldError("username", "用户名不能为空!!!"); } } 重写validate方法会检验action类里的全部方法,咱们不须要校验某些方法,有两种方法。 第一种:在不须要校验的方法前加上注解@SkipValidation 第二种:重写validateXxx方法,Xxx即为要验证的方法名 public void validateRegist() { if(user.getUsername()==null||user.getUsername().isEmpty()){ addFieldError("username", "用户名不能为空!!!"); } }
1.对字符串类型的请求参数进行类型转换,而且设置给JavaBean的属性 2.类型转换中可能出现异常,若是出现异常,将异常信息保存并封装 3.调用struts2的输入校验规则进行输入校验(根据各类vatidate.xml文件里定义的校验规则) 4.经过反射调用validateXxx方法进行校验 5.调用validate方法校验 6.上面的校验出现错误,转到input对应的视图资源。没错误,调用action中的处理方法。