Java实战之01Struts203属性封装、类型转换、数据验证

九、封装请求正文到对象中

1、静态参数封装

struts.xml配置文件中,给动作类注入值。调用的是setter方法。

原因:是由一个staticParams的拦截器完成注入的。

2、动态参数封装:开发时用到的

通过用户的表单封装请求正文参数。

2.1、动作类作为实体模型

实体模型:Entity,对应数据库中表的记录(注意类对应的是表结构,而对象对应的是一条记录)

 1 public class Demo1Action extends ActionSupport {
 2 
 3     private String name;
 4     private int age;
 5         
 6     public String demo1(){
 7         System.out.println(name);
 8         System.out.println(age);
 9         return SUCCESS;
10     }
11 
12     public String getName() {
13         return name;
14     }
15     public void setName(String name) {
16         this.name = name;
17     }
18     public int getAge() {
19         return age;
20     }
21     public void setAge(int age) {
22         this.age = age;
23     }
24 }
1 <!-- 动态参数封装:使用表单提交数据,第一种方式 -->
2         <action name="action2" class="cn.itcast.web.action.Demo2Action" method="demo2">
3             <result name="success">/success.jsp</result>
4         </action>
1 <form action="${pageContext.request.contextPath}/action2" method="POST">
2      用户名:<input type="text" name="name"/><br/>
3      年龄:<input type="text" name="age"><br/>
4      <input type="submit" value="提交"/>
5 </form>

原因:是由params拦截器完成的。

2.2、动作类和实体模型分开

问题:

由于我们没有初始化user对象,默认为null,一调用setUser方法,就空指针异常了。但是框架却封装进去值了。

原因:

通过执行过程:

 1 public class Demo3Action extends ActionSupport {
 2 
 3     private User user = new User();
 4     
 5     public String demo3(){
 6         System.out.println(user.getName());
 7         System.out.println(user.getAge());
 8         return SUCCESS;
 9     }
10 
11     public User getUser() {
12         System.out.println("getUser");
13         return user;
14     }
15     public void setUser(User user) {
16         System.out.println("setUser");
17         this.user = user;
18     }    
19 }

2.3、模型驱动:建立动作类和模型分开的前提下(开发中采用的方式)

此处的学习目标:目前先记住怎么写,要想理解,必须等讲完OGNL表达式之后。

 1 public class Demo4Action extends ActionSupport implements ModelDriven<User>{
 2 
 3     private User user = new User();
 4 
 5     public User getModel() {
 6         return user;
 7     }
 8         
 9     public String demo4(){
10         System.out.println(user.getName());
11         System.out.println(user.getAge());
12         return SUCCESS;
13     }
14 }

原因:是由modelDriven拦截器和params拦截器配合做的。

十、数据类型的转换(明白原理,实际开发中几乎不用)

1、开发中的情况:

实际开发中用户通过浏览器输入的数据都是String或者String[]

String/String[]————填充模型(set方法)————>POJO(plain old java object)  pojo中有java的数据类型。

POJO————————获取(get方法)————>页面展示:String

2、类型转换情况

写数据:(增,删,改)都是StringString[]数组转换为其他类型。

读数据:(查)其他类型转换为String

3Struts2提供的常用类型转换

a.基本数据类型自动转换。

b.日期类型:默认按照本地日期格式转换(yyyy-MM-dd)。

c.字符串数组:默认用逗号+空格,连接成一个字符串。

4、自定义类型转换器(知道)

示例:把日期格式按照 MM/dd/yyyy的格式转换

4.1Struts2中的类型转换器结构:

4.2、编写类型转换器(编写一个类继承StrutsTypeConverter,实现抽象方法)

 1 public class MyTypeConverter extends StrutsTypeConverter {
 2     
 3     private DateFormat format = new SimpleDateFormat("MM/dd/yyyy");
 4 
 5     public Object convertFromString(Map context, String[] values, Class toClass) {
 6         if(values == null || values.length == 0){
 7             return null;
 8         }
 9         String date = values[0];
10         if(java.util.Date.class == toClass){
11             try {
12                 return format.parse(date);
13             } catch (ParseException e) {
14                 e.printStackTrace();
15             }
16         }
17         return null;
18     }
19     public String convertToString(Map context, Object o) {
20         if(o instanceof Date){
21             Date date = (Date)o;
22             return format.format(date);
23         }
24         return null;
25     }
26 }

4.3、注册类型转换器

局部类型转换器:只能指定javabean中的属性用

按照属性来注册。在属性所属的javabean的包下建立一个.properties文件。文件名称:javabean名称-conversion.properties

全局类型转换器:(推荐)

按照要转换的数据类型来注册。

at the top op classpath,建立一个固定名称xwork-conversion.properties的属性文件。

5、转换失败后的处理(需要掌握)

当转换失败后,页面提示:

解决办法:配置回显结果视图

十一、数据验证

用户的输入验证,必须做,且工作量巨大。

1、验证的方式

客户端验证:javascript

服务端验证:逻辑验证(我们的代码)

注意:如果客户端和服务端二选一的话,服务器端的不能省。

实际开发中:客户端+服务端

2Struts2的服务端验证

2.1、编程式验证

前提:

动作类必须继承ActionSupport

在代码中编写验证规则。

a、针对动作类中的所有动作方法进行验证:

在动作类中覆盖public void validate()方法。

 1 public class StudentAction extends ActionSupport implements ModelDriven<Student> {
 2 
 3     private Student student = new Student();
 4 
 5     public Student getModel() {
 6         return student;
 7     }
 8     public void validate(){
 9         if(StringUtils.isBlank(student.getUsername())){
10             addFieldError("username", "用户名不能为空");
11         }
12     }
13     public void validateRegist(){
14         if(StringUtils.isBlank(student.getUsername())){
15             addFieldError("username", "用户名不能为空");
16         }
17     } 
18 
19     public String regist(){
20         System.out.println("用户名不能为空");
21         return SUCCESS;
22     }
23     
24     public String update(){
25         System.out.println("用户名不能为空“);
26         return SUCCESS;
27     }
28 
29     @SkipValidation
30     public String findAll(){
31         return SUCCESS;
32     }
33 }

由此可知,该验证方法会对动作类中的所有动作方法进行验证。

b、针对动作类中的某个动作方法进行验证

针对上面的问题,解决办法1:给不需要验证的动作方法添加一个@SkipValidation注解。

解决办法1和解决办法2的使用时机:需要验证的动作方法少,用解决办法2。需要验证的方法多,用解决方式1。(简单一点:挑少的写)

 所有编程式验证的弊端:硬编码。

2.2、声明式验证(推荐)

通过编写验证规则的xml文件。需要验证时,编写xml文件,不要验证,就不写。

优势:解决了2.1编程式验证的弊端

a、针对动作类中的所有动作进行验证:在动作类所在的包中,建立一个ActionClassName-validation.xml的文件,内容如下:

注意:它是针对动作类中的所有动作方法。

b、针对动作类中的某个动作进行验证:在动作类所在的包中建立一个xml文件,名称为ActionClassName-ActionName-validation.xml。内容如下:

2.3Struts2内置的常用声明式验证器

2.3.1位置:

xwork-core-2.3.15.3.jar\com\opensymphony\xwork2\validator\validator\default.xml

2.3.2、验证器注入参数

例如:我们使用requiredstring,默认是去空格,当我们不想去空格时,就可以给验证器注入参数。

基于字段的:

基于验证器的:

3、常用验证器示例

 1 public class Student implements Serializable {
 2 
 3     private String username;
 4     private String password;
 5     private Date birthday;
 6     private String hobby;
 7     private boolean married;
 8     
 9     public String getUsername() {
10         return username;
11     }
12     public void setUsername(String username) {
13         this.username = username;
14     }
15     public String getPassword() {
16         return password;
17     }
18     public void setPassword(String password) {
19         this.password = password;
20     }
21     public Date getBirthday() {
22         return birthday;
23     }
24     public void setBirthday(Date birthday) {
25         this.birthday = birthday;
26     }
27     public String getHobby() {
28         return hobby;
29     }
30     public void setHobby(String hobby) {
31         this.hobby = hobby;
32     }
33     public boolean isMarried() {
34         return married;
35     }
36     public void setMarried(boolean married) {
37         this.married = married;
38     }
39 }
 1 <body>
 2       <s:actionerror/>
 3      <s:form action="saveUser">
 4         <s:textfield name="username" label="用户名"/>
 5         <s:textfield name="age" label="年龄"/>
 6         <s:textfield name="email" label="邮箱"/>
 7         <s:textfield name="password" label="密码" />
 8         <s:textfield name="repassword" label="确认密码"/>
 9         <s:textfield name="score" label="成绩" />
10         <s:textfield name="url" label="个人主页"/>
11         <%-- list中的内容:
12                 相当于创建一个新的List集合
13         --%>
14         <s:radio list="{'男','女'}" name="gender" label="性别"/>
15         <%--
16             <input type="radio" name="gender" value=""/>17             <input type="radio" name="gender" value=""/>18          --%>
19         <s:submit value="注册"></s:submit>
20     </s:form>
21   </body>
原文地址:https://www.cnblogs.com/minihouseCoder/p/5579140.html