JAVA学习笔记Day25——动态接口的实现

来源:互联网 发布:影响网络吞吐量的原因 编辑:程序博客网 时间:2024/06/05 16:51

动态接口的实现有很多好处,今天以HTTP协议解析json字符串为例。

基本知识

1、JAVA中我们有时候想要传递一个方法,在C/C++中有方法指针,而在JAVA中,我们可以使用的唯一方法就是接口。所以我们一个接口来传递其中的方法。
2、我们今天是想要从网上获取一个json字符串,然后再用Gson方式去解析得到想要的对象。选择使用动态接口的方式去解决是为了节省代码,不必要在不同的地址去获取json串时还需要去写HTTP协议那一套的连接下载。

2、下载具体步骤

1、首先我们需要建立json串对应的相关对象。在这里,我们需要为每个对象添加注解,因为在fastJson、Gson中不加注解容易混淆。
2、我们是解析这个地址的相关信息。http://www.tngou.net/api/top/list

// TnGou类package net.xiaohong.proxy;import com.google.gson.annotations.SerializedName;import java.util.List;public class TnGou {    @SerializedName("status")    private boolean status;    @SerializedName("total")    private int total;    @SerializedName("tngou")    private List<News> data;// 为了节省空间,大家需要自行解决getter、setter,嘿嘿  }
// News类package net.xiaohong.proxy;import com.google.gson.annotations.SerializedName;import java.util.Calendar;/** * Created HTTP_Work. * By XIAOHONG . * On 2016/8/18. */public class News {    @SerializedName("count")    private int count;    @SerializedName("description")    private String description;    @SerializedName("fCount")    private int fCount;    @SerializedName("fromName")    private String fromName;    @SerializedName("fromURL")    private String fromURL;    @SerializedName("id")    private int id;    @SerializedName("img")    private String img;    @SerializedName("keyWords")    private String keyWords;    @SerializedName("rCount")    private int rCount;    // 毫秒值,做转换      @SerializedName("time")    @JsonAdapter(CalendarAdapter.class)    private Calendar time;    @SerializedName("title")    private String title;    @SerializedName("topClass")    private int topClass;    // 为了节省空间,大家需要自行解决getter、setter,嘿嘿}

类型适配器,在gson解析中如果拿不到想要的类型,可以对其进行类型适配,比如时间

// 时间类型比配。会返回一个时间类package com.xiaohong.proxy;import com.google.gson.TypeAdapter;import com.google.gson.stream.JsonReader;import com.google.gson.stream.JsonWriter;import java.io.IOException;import java.util.Calendar;public class CalendarAdapter extends TypeAdapter<Calendar> {// 写Calendar ->json    @Override    public void write(JsonWriter jsonWriter, Calendar calendar) throws IOException {        if (calendar == null) {            jsonWriter.nullValue();        } else {            jsonWriter.value(calendar.getTimeInMillis());        }    }// 读,将json->Calendar     @Override    public Calendar read(JsonReader jsonReader) throws IOException {        if (jsonReader.hasNext()) {            long l = jsonReader.nextLong();            Calendar calendar = Calendar.getInstance();            calendar.setTimeInMillis(l);            return calendar;        }        return null;    }}

要实现动态接口,需要把自己想要的方法定义在接口中。

package net.xiaohong.proxy;public interface HttpInter {    @GET("http://www.tngou.net/api/top/list?page=%d&rows=%d&id=%d")    TnGou getList(int page, int rows, int id);}

在这里,我使用到了注解,通过注解来获取想要的方式(GET、POST)

package net.xiaohong.proxy;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface GET {    String value();}

往下需要一个工具类去实现动态接口的方式,我们需要将HttpInter 作为参数,通过这个接口拿到这里面的方法,进而,我们再去执行相关的下载操作。

// 动态接口实现类package net.xiaohong.proxy;import com.google.gson.Gson;import java.io.ByteArrayOutputStream;import java.io.InputStream;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.net.HttpURLConnection;import java.net.URL;public class Utils {    public static<T> T getInstance(Class<T> type) {        Object o = Proxy.newProxyInstance(type.getClassLoader(),                new Class[]{type},                new MyHandler());        return (T) o;    }    private static class MyHandler implements InvocationHandler {        @Override        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        // 拿到方法的注解类型,因为在这里我默认就让他使用GET了            GET get = method.getAnnotation(GET.class);            //              if (get != null) {            String url = String.format(get.value(), args);            Class<?> type = method.getReturnType();            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();            connection.setRequestMethod("GET");            int code = connection.getResponseCode();            if (code == 200) {                int length;                byte[] buffer = new byte[102400];                InputStream is = connection.getInputStream();                ByteArrayOutputStream baos = new ByteArrayOutputStream();                while ((length = is.read(buffer)) != -1) {                    baos.write(buffer, 0, length);                }                Gson gson = new Gson();                return gson.fromJson(baos.toString("UTF-8"), type);            }            }            return null;    }}}
// 测试类package net.xiaohong.proxy;import java.util.List;public class HttpTest {    public static void main(String[] args) {        HttpInter instance = Utils.getInstance(HttpInter.class);        TnGou list = instance.getList(1, 5, 0);//        News show = instance.getShow(2);        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");        List<News> data = list.getData();        for (News news : data) {            System.out.print(format.format(news.getTime().getTime()) + ": ");            System.out.println(news.getTitle());        }    }}

运行结果:
这里写图片描述

到这里整个项目就实现了。这样使用动态接口的好处:我们可以在对不同的地址获取不同的json进行解析成对象。集体方法:

1、我们需要在HttpInter接口中添加我们想要的方法:比如我们想要获取这样的数据:
@GET("http://www.tngou.net/api/top/show?id=%d")
News getShow(long id);
}

此时我们需要在News类中添加一个属性:
@SerializedName("message")
private String message;

测试类中:
News show = instance.getShow(2);
System.out.println(show.getMessage());

运行结果:
这里写图片描述

0 0
原创粉丝点击