zoukankan      html  css  js  c++  java
  • [Struts2学习笔记] -- 自定义类型转换

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'index.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
          <h3>输入坐标值,格式为x,y,x和y的类型是int类型</h3>
        <s:form method="post" action="point" namespace="/">
            <!-- 输入坐标值,格式为x,y,x和y的类型是int类型 -->
            <s:textfield label="point" name="point"></s:textfield>
            <s:submit value="submit"></s:submit>
        </s:form>
      </body>
    </html>
    index.jsp代码

      Struts2的自定义类型转换可以通过重写继承DefaultTypeConverter类来完成,也可以通过Struts2提供的模版重写方法来完成。并且有局部类型转换和全局类型转换两种,首先来看一下通过继承DefaultTypeConverter类来实现类型转换的方法。建立一个页面,其中有一个文本框,需要输入坐标值,用','来分割x和y,如图:

      代码如下:

    index.jsp代码

      接着,编写一个Point类,有x和y两个字段,用int表示,代码如下:

    package cn.net.bysoft.lesson3;
    
    public class Point {
        public Point() {
        }
    
        public Point(int x, int y) {
            super();
            this.x = x;
            this.y = y;
        }
    
        public int getX() {
            return x;
        }
    
        public void setX(int x) {
            this.x = x;
        }
    
        public int getY() {
            return y;
        }
    
        public void setY(int y) {
            this.y = y;
        }
    
        private int x;
        private int y;
    }
    Point类

      然后开始编写继承DefaultTypeConverter类的转换类,这里命名为PointConverter.java,代码如下:

    package cn.net.bysoft.lesson3;
    
    import java.util.Map;
    
    import ognl.DefaultTypeConverter;
    
    public class PointConverter extends DefaultTypeConverter {
    
        @Override
        public Object convertValue(Map context, Object value, Class toType) {
            if (Point.class == toType) {
                // 用实体的类型与toType比较,等于客户端传递到服务端数据。
                Point point = new Point();
                // 客户端传递过来的数据为String数组,因为控件的(比如input空间)name可以有多个。
                // 此处其实和HttpServletRequest.getParameterValues(String name)方法效果相同。
                String[] strArray = (String[]) value;
                // 解析字符串。
                String[] paramValues = strArray[0].split(",");
                int x = Integer.parseInt(paramValues[0]);
                int y = Integer.parseInt(paramValues[1]);
                point.setX(x);
                point.setY(y);
    
                return point;
            }
    
            if (String.class == toType) {
                // 用String类型与toType比较,等于服务器发送到客户端数据。
                Point point = (Point) value;
                int x = point.getX();
                int y = point.getY();
                StringBuffer sb = new StringBuffer();
                sb.append("[x = ");
                sb.append(x);
                sb.append(", y = ");
                sb.append(y);
                sb.append("]");
    
                return sb.toString();
            }
    
            return null;
        }
    
    }
    PointConverter

      其中重写convertValue方法进行类型转换,这个方法参数,toType类型若等于"某某类名".class则代表要将Object value转换成Java实体类,也就是客户端传递到服务端的数据需要进行类型转换。假如toType类型等于String.class则等于服务器像客户端发送数据,需要将对象转换成字符串。具体的转换方法可根据实际情况编写。

      接下来可以创建一个Action用于控制服务端与客户端的请求了,代码与配置如下:

    package cn.net.bysoft.lesson3;
    
    import com.opensymphony.xwork2.ActionSupport;
    
    public class PointAction extends ActionSupport {
        /**
         * 
         */
        private static final long serialVersionUID = -2035413550978816228L;
    
        @Override
        public String execute() throws Exception {
            return SUCCESS;
        }
    
        public Point getPoint() {
            return point;
        }
    
        public void setPoint(Point point) {
            this.point = point;
        }
    
        private Point point;
    }
    PointAction代码
    <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd">
    <struts>
        <package name="struts2_3_24_1" extends="struts-default">
            <action name="helloWorld" class="cn.net.bysoft.lesson1.HelloWorldAction">
                <result>lesson1/hello.jsp</result>
            </action>
            <action name="login" class="cn.net.bysoft.lesson2.LoginAction">
                <result name="success">/lesson2/success.jsp</result>
                <result name="input">/lesson2/login.jsp</result>
            </action>
            <action name="point" class="cn.net.bysoft.lesson3.PointAction">
                <result name="success">/lesson3/output.jsp</result>
                <result name="input">/lesson3/index.jsp</result>
            </action>
        </package>
    </struts>
    PointAction的struts.xml配置

      最后,最关键的是要编写一个配置文件来声明转换的信息,使用局部转换需要在Action的包下建立一个同名的加-conversion.properties属性文件,如PointAction-conversion.properties。内容如下:

    point=cn.net.bysoft.lesson3.PointConverter

      等号左侧是Action中的字段名称,右侧是使用我们的PointConverter类进行转换。以上工作完成后,可以进行类型转换,编写一个输出页面测试类型转换,代码如下:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <%@ taglib prefix="s" uri="/struts-tags" %>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>My JSP 'output.jsp' starting page</title>
        
        <meta http-equiv="pragma" content="no-cache">
        <meta http-equiv="cache-control" content="no-cache">
        <meta http-equiv="expires" content="0">    
        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
        <meta http-equiv="description" content="This is my page">
        <!--
        <link rel="stylesheet" type="text/css" href="styles.css">
        -->
    
      </head>
      
      <body>
        point:<s:property value="point"/>
      </body>
    </html>
    output.jsp代码

      有一点需要注意的是,在PointConverter.java类中,在客户端向服务端请求类型转换时,参数Object value是一个字符串数组(String[]),因为页面中控件的name属性可以有多个,一次向服务端发送多个Point对象存放到数组中,请看如下代码:

    <h3>输入坐标值,格式为x,y,x和y的类型是int类型</h3>
        <s:form method="post" action="point" namespace="/">
            <!-- 输入坐标值,格式为x,y,x和y的类型是int类型 -->
            <s:textfield label="point" name="point"></s:textfield>
            <s:textfield label="point" name="point"></s:textfield>
            <s:textfield label="point" name="point"></s:textfield>
            <s:submit value="submit"></s:submit>
        </s:form>

      所以,在处理类型转换时,可以一次进行多个对象的类型转换,新创建一个局部类型转换类,实现转换客户端传递过来多个Point并放到集合中,代码如下:

    package cn.net.bysoft.lesson3;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    import ognl.DefaultTypeConverter;
    
    public class PointConverter2 extends DefaultTypeConverter {
    
        @Override
        public Object convertValue(Map context, Object value, Class toType) {
            if (List.class == toType) {
                // 用实体的类型与toType比较,等于客户端传递到服务端数据。
                List<Point> points = new ArrayList<Point>();
                // 客户端传递过来的数据为String数组,因为控件的(比如input空间)name可以有多个。
                String[] strArray = (String[]) value;
                for (String str : strArray) {
                    // 解析字符串。
                    String[] paramValues = str.split(",");
                    int x = Integer.parseInt(paramValues[0]);
                    int y = Integer.parseInt(paramValues[1]);
                    Point point = new Point();
                    point.setX(x);
                    point.setY(y);
                    points.add(point);
                }
                return points;
            }
    
            if (String.class == toType) {
                // 用String类型与toType比较,等于服务器发送到客户端数据。
                List<Point> points = (List<Point>) value;
                int count = 0;
                StringBuffer sb = new StringBuffer();
                sb.append("[");
                for (Point point : points) {
                    count++;
                    int x = point.getX();
                    int y = point.getY();
    
                    sb.append("point").append(count).append(":").append("{x = ")
                            .append(x).append(", y=").append(y).append("}");
                }
                sb.append("]");
                return sb.toString();
            }
    
            return null;
        }
    }
    PointConverter2.java的代码

      在Struts2中添加相关字段和get/set方法,并配置属性文件:

        public List<Point> getPoints() {
            return points;
        }
    
        public void setPoints(List<Point> points) {
            this.points = points;
        }
        
        private List<Point> points;
    points=cn.net.bysoft.lesson3.PointConverter2

      结果如下:

      如果有很多Action中都有一个Poin,那局部转换就麻烦,因为要为每一个Action都编写一个属性文件,Struts2提供了全局的转换方 式,可以编写全局属性文件实现效果。属性文件命名为固定的xwork- conversion.properties,属性值等号左侧是实体类的全名,右侧是制定的转换类。例如:

    cn.net.bysoft.lesson3.Point=cn.net.bysoft.lesson3.PointConverter

      Struts2还提供了内置的转换类StrutsTypeConverter,他是一个抽象类,提供了两个抽象方法让我们重写:

      继承这个抽象类,并重写convertFormString方法和convertToString方法,顾名思义,convertFromString是将客户端请求传递过来的字符串转换成服务端对象,而convertToString是将服务端对象转换成字符串以备发送到客户端。具体代码如下:

    package cn.net.bysoft.lesson3;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.struts2.util.StrutsTypeConverter;
    
    public class PointConverter3 extends StrutsTypeConverter {
    
        @Override
        public Object convertFromString(Map arg0, String[] values, Class toClass) {
            // 用实体的类型与toType比较,等于客户端传递到服务端数据。
            List<Point> list = new ArrayList<Point>();
            System.out.println(list.getClass());
            // 客户端传递过来的数据为String数组,因为控件的(比如input空间)name可以有多个。
            for (String value : values) {
                // 解析字符串。
                Point point = new Point();
                String[] paramValues = value.split(",");
                int x = Integer.parseInt(paramValues[0]);
                int y = Integer.parseInt(paramValues[1]);
                
                point.setX(x);
                point.setY(y);
                list.add(point);
            }
            return list;
        }
    
        @Override
        public String convertToString(Map arg0, Object o) {
            // 用String类型与toType比较,等于服务器发送到客户端数据。
            List<Point> points = (List<Point>) o;
            int count = 0;
            StringBuffer sb = new StringBuffer();
            sb.append("[");
            for (Point point : points) {
                count++;
                int x = point.getX();
                int y = point.getY();
    
                sb.append("point").append(count).append(":").append("{x = ")
                        .append(x).append(", y=").append(y).append("}");
            }
            sb.append("]");
            return sb.toString();
        }
    
    }
    PointConverter3.java的代码

      这段代码相对于之前的代码,将两个if判断拆分成两个方法,更加优雅,并且由Starts来判断我们是从字符串转换成对象,还是从对象转换成字符串,使得代码更加健壮。

  • 相关阅读:
    (办公)写代码的任务完成后,编写接口文档
    (办公)eclipse连接github cannot open git-upload-pack(git-receive-pack)
    (办公)Spring boot(系列)的返回json封装类
    (办公)重新选择一个开发工具Eclipse
    (办公)项目结构
    (生活)整理电脑文件夹.
    (后台)jxl.read.biff.BiffException: Unable to recognize OLE stream
    (其他)导入密钥
    (后端)根据查询语句修改的update语句
    考研打卡_Day017
  • 原文地址:https://www.cnblogs.com/DeadGardens/p/5152592.html
Copyright © 2011-2022 走看看