讓SpringMVC接收JSON——WebServer(SpringMVC+fastjson)+Android(OkHttp)

目標:

(1)架設可以接收JSON的SpringMVC服務器
(2)使用Android客戶端向服務器發送JSON字符串

使用SpringMVC+fastjson框架接收JSON字符串

1. 這里使用阿里的fastjson

與同類其他json解析框架(jackson、gson)比,其在性能速度上有比較明顯的優勢。其主要功能是convert Java Objects to JSON String和convert JSON String to Java Objects。
官方網址:https://github.com/alibaba/fastjson

1.1 fastjson優勢:
  • 提供服務器端和android客戶端最好的性能
  • 提供最簡單的JSONString()和parseObject()方法去轉換Java Objects為JSON,反之亦然
  • 允許先前存在的不能修改的對象轉成JSON,以及從JSON轉成Object
  • 支持Java 泛型
  • 允許自定義對象的呈現方式
  • 支持復雜對象(繼承層次多且大量使用泛型的)
1.2 使用fastjson:

Maven 坐標:

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.38</version>
</dependency>

spring的bean配置:

<bean id="fastJsonConfig" class="com.alibaba.fastjson.support.config.FastJsonConfig">
        <!-- 自定義配置... -->
        <!-- Default charset -->
        <property name="charset" value="UTF-8" />
        <!-- Default dateFormat -->
        <property name="dateFormat" value="yyyy-MM-dd HH:mm:ss" />
        <!-- SerializerFeature -->
        <property name="serializerFeatures">
            <list>
                <value>WriteNullListAsEmpty</value>
            </list>
        </property>
  </bean>
  <mvc:annotation-driven>
        <mvc:message-converters register-defaults="true">
            <bean
                class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <value>application/json</value>
                    </list>
                </property>
                <property name="fastJsonConfig" ref="fastJsonConfig" />
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

這是fastjson在spring4中的配置,與spring3不同,在 <mvc:annotation-driven>中設置message-converters為FastJsonHttpMessageConverter,表示JSON轉換器設置為fastjson轉換器。supportedMediaTypes表示request數據類型為json類型。fastJsonConfig表示FastJsonHttpMessageConverter的配置。
其中dateFormat表示date類型字段輸出的格式,如果不添加該設置,輸出日期值為一個整型數據。
charset表示response數據類型為utf-8。

1.3 Controller中如何使用:

在Controller部分使用@RestController注解,表示輸出數據支持字符串

    @RequestMapping(value="")
    public ResultMessage user(){
        return  new ResultMessage("200","成功!",userService.get(1));
    }

當請求該url時,則返回JSON字符串。其中類到JSON的映射是由fastjson完成的。
JSON字符串如下:

{
    "code": "200",
    "data": {
        "alias": "張三",
        "id": 1,
        "name": "test",
        "password": "1",
        "reg_date": "2017-10-01 00:00:01",
        "state": 1,
        "type_id": 1
    },
    "msg": "成功!"
}

可見fastjson支持復雜類對象。

1.4 接收JSON請求數據

    @RequestMapping(value="",method=RequestMethod.POST,consumes = "application/json",produces={"application/json"})
    public ResultMessage user(@RequestBody User user){
        System.out.println(user);
        return  new ResultMessage("200","成功!",user);
    }

其中@RequestBody表示請求中包含JSON字符串數據,映射到當前user變量上,user類型為User實體。這里fastjson將請求數據自動轉換成User類型實例,注入到當前方法中。
在測試請求時,使用postman工具。需要設置:

  • 設置請求的header部分content-type為application/json


    設置請求的Header
  • 為了發送JSON字符串,設置Body部分,數據類型為raw,并設定數據為:
設置請求的Body
  • 發送請求后,得到:
發送JSON,收到JSON

2 在Android客戶端中使用OkHttp向服務器發送JSON請求

2.1 OkHttp簡介

官網:https://github.com/square/okhttp
https://square.github.io/okhttp/
OkHttp是一個支持http協議的客戶端,也是一個高效的客戶端。特點如下:
(1)支持HTTP1和2,允許多個針對相同主機的請求共享一個socket。
(2)使用連接池減少潛在的請求
(3)Transparent GZIP減少下載大小
(4)使用響應端緩存避免重復請求。
Gradle 坐標:

compile 'com.squareup.okhttp3:okhttp:3.9.0'

2.2 同步請求和異步請求

(1)同步請求

        OkHttpClient client=new OkHttpClient();
        MediaType JSON=MediaType.parse("application/json; charset=utf-8");
        RequestBody requestBody=RequestBody.create(JSON,jsonValue);
        Request request=new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        try {
            Response response=client.newCall(request).execute();
            if(response.isSuccessful()){
                callback.onResponse(response);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

其中client是請求的客戶端。JSON表示請求的數據類型。jsonValue表示請求的json字符串,例如:

 String json ="{\n" +
                                "\"alias\": \"張三***\",\n" +
                                "\"id\": 1,\n" +
                                "\"name\": \"test\",\n" +
                                "\"password\": \"1\",\n" +
                                "\"reg_date\": \"2017-10-01 00:00:01\",\n" +
                                "\"state\": 1,\n" +
                                "\"type_id\": 1\n" +
                                "}";

requestBody表示使用json字符串創建的請求數據體,然后使用requestBody初始化一個request。url是一個服務器請求的網址,類型為字符串,再使用client.newCall(request).execute()執行請求,這是一個同步請求。使用response.isSuccessful()判斷請求是否得到正確回應。

注意:由于是同步請求OkHttp并沒有提供線程去執行這個網絡請求,需要將上述代碼放到Thread中去執行。

(2)異步請求

try {
            client.newCall(request)
                    .enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            e.printStackTrace();
                        }

                        @Override
                        public void onResponse(Call call, final Response response) throws IOException {

                         handler.post(new Runnable() {
                             @Override
                             public void run() {
                                 if(callback!=null)
                                     callback.onResponse(response);
                             }
                         });

                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        }

request的創建過程同“同步請求”代碼。不同的是異步請求使用client.newCall(request).enqueue(new Callback(){})。其中enqueue表示這個請求將進入一個隊列中。逐個去執行,使用回調方法來做請求響應。onFailure表示請求失敗時響應的事件方法。onResponse表示請求有響應時執行的事件方法,其中注入了response可以用于獲取響應結果。

注意:OkHttp已經將異步代碼封裝到線程中執行,這里在執行異步請求時,無需在線程中執行。

2.3 進一步封裝OkHttp

public class UtilHttp {
    private static  OkHttpClient client=new OkHttpClient();
    private static Handler handler = new Handler(Looper.getMainLooper());

    public static final MediaType JSON=MediaType.parse("application/json; charset=utf-8");
    public static void execute(String url, String jsonKey, 
                               String jsonValue, 
                               final ResponseCallback callback){

        RequestBody requestBody=RequestBody.create(JSON,jsonValue);

        Request request=new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();
        try {
            client.newCall(request)
                    .enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            e.printStackTrace();
                        }

                        @Override
                        public void onResponse(Call call, 
                                               final Response response) throws IOException {

                         handler.post(new Runnable() {
                             @Override
                             public void run() {
                                 if(callback!=null)
                                     callback.onResponse(response);
                             }
                         });

                        }
                    });
        } catch (Exception e) {
            e.printStackTrace();
        }

//        try {
//            Response response=client.newCall(request).execute();
//            if(response.isSuccessful()){
//                callback.onResponse(response);
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }
    public  interface ResponseCallback{
        void onResponse(Response response);
    }
}

其中new Handler(Looper.getMainLooper())表示獲取主線程的Handler,用于網絡響應后直接進行UI操作,也可以不用在Activity中再次實例化Handler。
定義接口ResponseCallback實現回調方法的封裝,方便Activity傳遞回調方法實例。 handler.post(new Runnable() {})表示handler直接操作UI控件。所以ResponseCallback的回調方法中可以直接操作Acitivity中的UI。

   String json ="{\n" +
                "\"alias\": \"張三***\",\n" +
                "\"id\": 1,\n" +
                "\"name\": \"test\",\n" +
                "\"password\": \"1\",\n" +
                "\"reg_date\": \"2017-10-01 00:00:01\",\n" +
                "\"state\": 1,\n" +
                "\"type_id\": 1\n" +
                "}";

        UtilHttp.execute(url, "user", json,  new UtilHttp.ResponseCallback() {
            @Override
            public void onResponse(Response response) {

                String msg= null;
                try {
                    msg = response.body().string();
//                                    Log.i("TAG",msg);
                    Toast.makeText(MainActivity.this,msg,Toast.LENGTH_LONG).show();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        });

點擊按鈕,執行效果如:

發送JSON,收到JSON
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,992評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,558評論 25 708
  • 參考Android網絡請求心路歷程Android Http接地氣網絡請求(HttpURLConnection) 一...
    合肥黑閱讀 21,365評論 7 63
  • 聽說今天九號線堵了。不過這也是常有的事,每一個屏蔽門前都排著十幾號人,該來的地鐵遲遲未出現,排的人越來越多。前段時...
    橘子是怪獸閱讀 377評論 0 0
  • 感賞劉先生很及時地購買了孩子出行的票,這樣為孩子節省了不少時間。感賞自己和輔導老師反復溝通,為孩子的夏令營...
    立春暖陽閱讀 202評論 0 1