[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,如圖:css

  代碼以下:html

index.jsp代碼

  接着,編寫一個Point類,有x和y兩個字段,用int表示,代碼以下:java

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,代碼以下:apache

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。內容以下:app

point=cn.net.bysoft.lesson3.PointConverter

 

  等號左側是Action中的字段名稱,右側是使用咱們的PointConverter類進行轉換。以上工做完成後,能夠進行類型轉換,編寫一個輸出頁面測試類型轉換,代碼以下:less

<%@ 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對象存放到數組中,請看以下代碼:jsp

<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並放到集合中,代碼以下:ide

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來判斷咱們是從字符串轉換成對象,仍是從對象轉換成字符串,使得代碼更加健壯。

相關文章
相關標籤/搜索