Struts2 - JSON

Struts2中使用JSON作數據的get/post,方法有不少種,這裏有一篇文章比較詳細的列舉出了JSON在Struts和Servlet中如何GET:html

http://yshjava.iteye.com/blog/1333104java

 

Servlet的不寫了,也就是how to use HttpRequest和HttpResponse。主要是在Struts2身上。apache

以文章所描述的方法彷佛老是差了那麼點東西:能夠不使用那麼多配置嗎?json

因而研究了些時間,能夠這麼玩:瀏覽器

1)Eclipse引用Struts2的JSON plug-in和Convertion plug-in。緩存

2)struts.xml這麼寫:服務器

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <!-- 把它設置爲開發模式,發佈時要設置爲false -->
    <constant name="struts.devMode" value="true" />
    <!-- 設置在class被修改時是否熱加載,發佈時要設置爲false -->
    <constant name="struts.convention.classes.reload" value="true"/>
    <!-- 自動動態方法的調用,使用這個設置後能夠這樣調用:action!method -->
    <constant name="struts.enable.DynamicMethodInvocation" value="true" />
    <!-- 指定jsp文件所在的目錄地址 -->
    <constant name="struts.convention.result.path" value="/WEB-INF/content/" />
    <!-- 用於配置包名後綴。默認爲action、actions、struts-->
    <!-- <constant name="struts.convention.package.locators" value="controller" /> -->
    <constant name="struts.convention.action.packages" value="com.my.controller"></constant>
    <!-- 用於配置類名後綴,默認爲Action,設置後,Struts2只會去找這種後綴名的類作映射 -->
    <constant name="struts.convention.action.suffix" value="Controller"/>
    <!-- 設置即便沒有@Action註釋,依然建立Action映射。默認值是false。由於Convention-Plugin是約定優於配置的風格,
        能夠不經過註解根據預先的定義就能訪問相應Action中的方法 -->
    <constant name="struts.convention.action.mapAllMatches" value="true"/>
    <!-- 自定義jsp文件命名的分隔符 -->
    <constant name="struts.convention.action.name.separator" value="-" />
    <!-- 國際化資源文件名稱 -->
    <constant name="struts.custom.i18n.resources" value="i18n" />
    <!-- 是否自動加載國際化資源文件  -->
    <constant name="struts.i18n.reload" value="true" />
    <!-- 瀏覽器是否緩存靜態內容 -->
    <constant name="struts.serve.static.browserCache" value="false" />
     <!-- 上傳文件大小限制設置 -->
    <constant name="struts.multipart.maxSize" value="-1" />
    <!-- 主題,將值設置爲simple,即不使用UI模板。這將不會生成額外的html標籤 -->
    <constant name="struts.ui.theme" value="simple" />
    <!-- 編碼格式 -->
    <constant name="struts.i18n.encoding" value="UTF-8" />
    <!-- 設置默認package -->
    <constant name="struts.convention.default.parent.package" value="default"></constant>

    <package name="default" namespace="/" extends="json-default">
        <interceptors>
            <interceptor name="cacheInterceptor" class="com.my.interceptor.CacheInterceptor" />
            <interceptor-stack name="cacheStack">
                <interceptor-ref name="defaultStack"></interceptor-ref>
                <interceptor-ref name="paramsPrepareParamsStack"></interceptor-ref>
                <interceptor-ref name="cacheInterceptor"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <default-interceptor-ref name="cacheStack"></default-interceptor-ref>
        <default-action-ref name="index" />
        <global-results>
            <!-- <result name="error">/error.jsp</result> -->
            <result name="json" type="json">
                <!-- 是否包括父類的屬性輸出,默認true. -->
                <!-- <param name="ignoreHierarchy">false</param> -->
                <!-- 是否輸出null值的屬性,默認false -->
                <!-- <param name="excludeNullProperties">true</param> -->
            </result>
        </global-results>
        <global-exception-mappings>
            <exception-mapping exception="java.lang.Exception" result="error"/>
        </global-exception-mappings>
    </package>

</struts>

上面有兩個<param/>註釋了,使用方法已經有寫在裏頭,若是須要,能夠加上或在類中加入@Results。restful

關鍵點在於把<package />中的 extends設置爲json-default,以及在global-results中的這個json result。app

 

3)加入一個UserControl.javajsp

package com.my.controller;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import net.sf.json.JSONObject;

import com.my.beans.User;
import com.opensymphony.xwork2.ActionSupport;

@SuppressWarnings("serial")
public class UserController extends ActionSupport {
    
    private User user = new User();
    public User getUser() {
        return user;
    }

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

    private String json;
    public String getJson() {
        return json;
    }

    public void setJson(String json) {
        this.json = json;
    }
    
    private List<User> users = new ArrayList<User>();
    public List<User> getUsers() {
        return users;
    }

    public void setUsers(List<User> users) {
        this.users = users;
    }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }

    public String loadModel() throws IOException {
        System.out.println("json=" + getJson());
        System.out.println("user=" + getUser().getUsername());
        System.out.println("users=" + getUsers().size());
        User userBean = new User();
        userBean.setUsername("robin");
        users.add(userBean);
        this.setJson(JSONObject.fromObject(userBean).toString());
        return "json";
    }
    
}

這裏沒有什麼特別的東西,就是一些getter/setter,以及一個loadModel() action

 

4)JS對JSON的提交:

var url = "user!loadModel";
var params = {
    "json": "json string",
    "user.username" : "zhang",
    "users[0].username" : "zhang1",
    "users[0].password" : "1",
    "users[1].username" : "zhang2",
    "users[1].password" : "2",
};
$.post(url, params, function callback(data) {
    console.log(data)
});

這裏是重點。

能夠看到這段JS裏的params有:json/user.username/users[X].username

其中:

a) json

對應的就是上頁java中的getJson/setJson,這個東東列出來是能夠用於在頁面與服務器之間傳遞JSON字符串用的。若是你須要在action中輸出或提交json的字符串,它有很大做用,直接到位。可是缺點是要本身去將對象轉化爲json string以及json string轉化爲對象。

 

b) user.username

這樣的寫法能夠在後臺java中直接轉化成了對象。user.username中的user就是java中的user object。

 

c) users[0].username

這能夠直接轉化成後臺java中的List<user>對象users。

 

能夠看出,Struts2是能夠完成將json直接轉化成java object的。不過這樣的寫法,不是好的。由於這個JS的JSON只能稱做是一個字符串拼接,不是一個JSON object

 


 

 

還有一種方法,使用ModelDriven:

package com.my.controller;

import com.my.beans.User;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

@SuppressWarnings("serial")
public class UserModelController extends ActionSupport implements
        ModelDriven<Object> {

    private User user = new User();

    @Override
    public Object getModel() {
        return user;
    }

    @Override
    public String execute() throws Exception {
        return SUCCESS;
    }

    public String load() {
        return "json";
    }

}

 

使用ModelDriven,能夠JS直接提交JSON了:

var url = "user-model!load";
var params = {
    "username": "zhang1",
    "password": "123456"
};
$.post(url, params, function callback(data) {
    console.log(data)
});

這個params纔是真正的JSON object,它會被ModelDriven直接轉成user model。

可是:它彷佛不能提交List object。至今寫文時也沒有找到在ModelDriven中能夠提交JSON array to List的方法。

若是須要提交複雜的JSON到服務器,若是你用的是Struts,使用第一種方法的json的getter/setter吧。

 


 

 

我的Struts2研究了些日子對它的總結:

1)若是是使用MVC開發的,它是個很是好的選擇。由於它提供了很是豐富的可配置的功能及標籤。可是也正是由於這些複雜的配置,會使用得開發及維護上帶來不少詬病,好比速度上、發佈上、後期清理上的問題。既然MVC的理想是約定優於配置,那爲何還須要這麼複雜的配置呢?

2)它的Action在URL上的表現上讓人看着不舒服,由於太不restful了,同時它的restful plug-in彷佛沒太多的可擴展性。說白了,若是要作rest,理應不選擇它。

3)struts它合適於使用普通的form提交開發當中(即MVC)。不合適於MVVM模式的開發。若是想使用MVVM,那麼建議使用SpringMVC,而不是Struts。

 

沉思:

若是MVVM是將來的主流設計,那麼struts將會有天淡去在這個舞臺。

相關文章
相關標籤/搜索