struts2自定義類型轉換器


首先,何為struts2的類型轉換器?

類型轉換器的作用是將請求中的字符串或字符串數組參數與action中的對象進行相互轉換。

一、大部分時候,使用struts2提供的類型轉換器以及OGNL類型轉換機制即可滿足大部分類型轉換需求。如:

類User.java

package models;

public class User {
    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;
    }

}

類LoginAction

package actions;

import java.util.List;

import models.User;

import com.opensymphony.xwork2.ActionSupport;

public class LoginAction extends ActionSupport {

    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String execute() throws Exception {
        if (getUser().getUsername().equals("yangys")
                && getUser().getPassword().equals("123")) {
            return SUCCESS;
        }
        return ERROR;
    }

}

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><s:text name="login page"></s:text></title>
</head>
<body>
    <s:form action="login">
        <s:textfield name="user.username" key="username" />
        <s:password name="user.password" key="password" />
        <s:submit value="login" />
    </s:form>
</body>
</html>

不用做任何處理,表單中的user.username和user.password即可映射到LoginAction中的user對象上。

注:需提供相關的getter與setter

 

二、在特殊情況下,這種類型轉換滿足不了需求,比如需要把一個復雜字符串轉換為一個對象。

如用戶輸入"huaihaizi,123"需要將huaihaizi映射到username,把123映射到password。則需要提供自定義類型轉換器並將其注冊到struts2中,供系統調用並完成類型轉換。

 為了模擬此需求,將login.jsp改為如下,通過一個user輸入框輸入用戶名密碼,以逗號分隔。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><s:text name="login page"></s:text></title>
</head>
<body>
    <s:form action="login">
        <s:textfield name="user" key="user" />
        <s:submit value="login" />
    </s:form>
</body>
</html>

User.java與LoginAction.java保持不變。此時為了達到user輸入框中的內容映射到user對象的username和password上,需要編寫一個自定義轉換器類。在OGNL項目中有一個TypeConvert接口,這個借口就是自定義類型轉換器必須實現的接口,該接口定義如下。

public interface TypeConverter {
    public Object convertValue(Map context, Object target, Member member,
            String propertyName, Object value, Class toType);
}

實現自定義類型轉換器必須實現上面的接口,但是該接口過於復雜,所以OGNL提供了實現類DefaultTypeConverter,通常都采用繼承並重寫DefaultTypeConverter的convertValue()方法來實現自定義類型轉換器,如上需求,需要編寫UserConverter.java,代碼如下:

package converters;

import java.util.Map;

import models.User;
import ognl.DefaultTypeConverter;

public class UserConverter extends DefaultTypeConverter {

    @Override
    public Object convertValue(Map context, Object value, Class toType) {
        if (toType == User.class) {
            String[] params = (String[]) value;
            User user = new User();
            user.setUsername(params[0].split(",")[0]);
            user.setPassword(params[0].split(",")[1]);
            return user;
        } else if (toType == String.class) {
            User user = (User) value;
            String userString = "<" + user.getUsername() + ","
                    + user.getPassword() + ">";
            return userString;
        }
        return null;
    }
}

這里,convertValue方法就是執行類型轉換邏輯的,參數value是轉換前的值,toType是轉換目標類型,通過判斷toType來執行轉換方向的邏輯代碼。如此例中,toType==User.class時,即為將頁面字符串轉換成User類的對象,由於適應頁面控件參數的通用性,頁面參數統一包裝成了字符串數組,如果是一個字符串,則為長度1的字符串數組。比如此例中,輸入為"huaihaizi,123",則把huaihaizi賦值給user對象的username,把123賦值給user對象的password,並將此user返回即可。反之則把user對象的username和password拼接成字符串返回。

三、struts2提供了一個StrutsTypeConverter抽象類,這個類是DefaultTypeConverter的子類,將convertValue的兩個轉換方向拆分成了兩個方法,

convertFromString(Map context,String[] values,Class toClass)

convertToString(Map context ,Object o)

邏輯更為清楚,用法與DefaultTypeConverter一致。

三、然后通過在struts2項目中注冊此自定義類型轉換器即可,注冊此自定義類型轉換器有三種方式。

1.注冊局部類型轉換器,局部類型轉換器僅僅對某個Action的屬性起作用

局部類型轉換器則是在該Action同一目錄下添加ActionName-convertion.properties,並在內部添加一行映射關系<propName>=<ConverterClass>。本例子中在LgoinAction.java所在包下添加LoginAction-convertion.properties文件,並在文件中添加user=converters.UserConverter即可。

2.注冊全局類型轉換器,全局類型轉換器對所有Action的特定類型的屬性都會生效

在源代碼根路徑下提供xwork-convertion.properties文件。並在文件中添加<propType>=<ConverterClass>。本例子中在src目錄下添加xwork-convertion.properties文件,並在文件中添加models.User=converters.UserConverter即可。

3.使用JDK1.5的注解來注冊類型轉換器。

 

局部類型轉換器與全局類型轉換器的區別:局部類型轉換器只針對局部變量進行一次性轉換,比如該局部變量是個List<User>,也是在局部類型轉換器中對該變量進行一次轉換。如果用全局類型轉換器,則該List中的每一個User都將進行一次轉換。

四、處理Set集合屬性的類型轉換,一般情況下不建議在Action中使用Set集合屬性,因為Set集合里元素是無序的,所以Struts2不能准確的將參數轉換成Set集合里的元素,也不能准確的讀取Set集合里的元素。除非Set集合的每個元素都有一個唯一標示,比如對於上面的User類來講,將username做為標識,則在Action的Set<User>中不能存在兩個User對象的username相同,需要重寫User的equals和hashCode方法。

 

@Override
public int hashCode() {
    // TODO Auto-generated method stub
    return getUsername().hashCode();
}

@Override
public boolean equals(Object obj) {
    if (this == obj) {
        return true;
    } else if (obj != null && obj.getClass() == User.class) {
        User objUser = (User) obj;
        if (objUser.getUsername().equals(this.getUsername())) {
            return true;
        }
    }
    return false;
}

 

然后在局部類型轉換器注冊文件中指定該Set集合元素的標識。如該Set集合為users,則上面講過在LoginAction-conversion.properties中添加users=converters.UserConverter 即可注冊該局部類型轉換器,現在此行下面添加KeyProperty_users=username則可以制定users變量的唯一標識屬性是username。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM