让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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,800评论 25 707
  • 参考Android网络请求心路历程Android Http接地气网络请求(HttpURLConnection) 一...
    合肥黑阅读 21,260评论 7 63
  • 听说今天九号线堵了。不过这也是常有的事,每一个屏蔽门前都排着十几号人,该来的地铁迟迟未出现,排的人越来越多。前段时...
    橘子是怪兽阅读 346评论 0 0
  • 感赏刘先生很及时地购买了孩子出行的票,这样为孩子节省了不少时间。感赏自己和辅导老师反复沟通,为孩子的夏令营...
    立春暖阳阅读 196评论 0 1