Spring4 Retrofit2 整合

Spring4 Retrofit2 整合

组件结构

开始spring实例化bean后实例化带有HttpService注解的类(实际为retrofit动态代理类)结束

实现

1.构造retrofit工厂用于创建服务

Retrofit LoggingInterceptor日期拦截器

public class LoggingInterceptor implements Interceptor {
    private static Logger logger = Logger.getLogger(LoggingInterceptor.class);

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        logger.info(String.format("发送请求:%s%n请求头:%s",
                request.url(), request.headers()));
        Response response = chain.proceed(request);
        return response;
    }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

Retrofit FastJson转换器

public class FastJsonConverterFactory extends Converter.Factory{
    public static FastJsonConverterFactory create() {
        return new FastJsonConverterFactory();
    }

    /** * 需要重写父类中responseBodyConverter,该方法用来转换服务器返回数据 */
    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new FastJsonResponseBodyConverter<>(type);
    }

    /** * 需要重写父类中responseBodyConverter,该方法用来转换发送给服务器的数据 */
    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return new FastJsonRequestBodyConverter<>();
    }
}

  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
public class FastJsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
    private final Type type;

    public FastJsonResponseBodyConverter(Type type) {
        this.type = type;
    }

    /* * 转换方法 */
    @Override
    public T convert(ResponseBody value) throws IOException {
        BufferedSource bufferedSource = Okio.buffer(value.source());
        String tempStr = bufferedSource.readUtf8();
        bufferedSource.close();
        try {
            return JSON.parseObject(tempStr, type);
        }catch (JSONException e){
            return (T) tempStr;
        }

    }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
public class FastJsonRequestBodyConverter<T> implements Converter<T, RequestBody> {
    private static final MediaType MEDIA_TYPE = MediaType.parse("application/json; charset=UTF-8");

    @Override
    public RequestBody convert(T value) throws IOException {
        return RequestBody.create(MEDIA_TYPE, JSON.toJSONBytes(value));
    }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

工厂生产的实体类

public class RetrofitBean {
    private Retrofit retrofit;
    private Map<Class,Object> service = new HashMap<>();

    public Retrofit getRetrofit() {
        return retrofit;
    }

    public void setRetrofit(Retrofit retrofit) {
        this.retrofit = retrofit;
    }

    public Map<Class, Object> getService() {
        return service;
    }

    public void setService(Map<Class, Object> service) {
        this.service = service;
    }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

工厂类

public class RetrofitBeanFactory {
    //key:请求地址 value:当前请求地址下class所对应的service(key:class value:service)
    private static Map<String, RetrofitBean> resolvableDependencies = new HashMap(16);
    private static final int readTimeOut = 15;
    private static final int writeTimeOut = 15;
    private static final int connTimeOut = 15;

    /** * 获得service服务实体 * * @param requiredType * @return * @throws BeansException */
    public static Object getBean(Class requiredType) throws BeansException {
        for (Map.Entry<String, RetrofitBean> entrySet : resolvableDependencies.entrySet()) {
            RetrofitBean retrofitBean = entrySet.getValue();
            for (Map.Entry<Class, Object> serviceSet : retrofitBean.getService().entrySet()) {
                if (requiredType == serviceSet.getKey()) {
                    return serviceSet.getValue();
                }
            }
        }
        return null;
    }

    /** * 创建service服务实体 * * @param baseUrl * @param serviceClass */
    public static Object putBean(String baseUrl, Class serviceClass, Class... interceptorClass) {
        if (StringUtils.isEmpty(baseUrl)) {
            return null;
        }
        RetrofitBean retrofitBean = resolvableDependencies.get(baseUrl);
        //如果为空设置一个
        if (retrofitBean == null) {
            retrofitBean = new RetrofitBean();
            OkHttpClient.Builder clientBuilder = new OkHttpClient().newBuilder()
                    .connectTimeout(readTimeOut, TimeUnit.SECONDS)
                    .writeTimeout(writeTimeOut, TimeUnit.SECONDS)
                    .readTimeout(connTimeOut, TimeUnit.SECONDS)
                    .addInterceptor(new LoggingInterceptor());
            if (interceptorClass != null && interceptorClass.length > 0) {
                for (Class clazz : interceptorClass) {
                    if (Interceptor.class.isAssignableFrom(clazz)) {
                        try {
                            clientBuilder.addInterceptor((Interceptor) clazz.newInstance());
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            Retrofit retrofit = new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .client(clientBuilder.build())
                    .addConverterFactory(FastJsonConverterFactory.create())
                    .build();
            retrofitBean.setRetrofit(retrofit);
            resolvableDependencies.put(baseUrl, retrofitBean);
        }
        Retrofit retrofit = retrofitBean.getRetrofit();
        Object bean = retrofit.create(serviceClass);
        retrofitBean.getService().put(serviceClass, bean);
        return bean;
    }

    public static Map<String, RetrofitBean> getResolvableDependencies() {
        return resolvableDependencies;
    }
}

  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

2.扩展spring生命周期

自定义配置文件读取工具

public class CustomPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    private Properties props;

    @Override
    protected void processProperties(
            ConfigurableListableBeanFactory beanFactory, Properties props)
            throws BeansException {
        super.processProperties(beanFactory, props);
        this.props = props;
    }

    public Object getProperty(String key) {
        return props.get(key);
    }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

自定义注解

/** * Created by zhangbowen on 2016/5/12. * 用于标识服务接口类 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface HttpApi {
    String value() default "";//通过key获得配置文件中的值
    Class[] interceptor() default {};
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
/** * Created by zhangbowen on 2016/5/12. * 用于自动注入服务 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface HttpService {
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

spring注入实体后的回调方法

public class RetrofitAutowiredProcessor extends InstantiationAwareBeanPostProcessorAdapter {
    private Logger logger = Logger.getLogger(RetrofitAutowiredProcessor.class);
    @Autowired
    private CustomPropertyPlaceholderConfigurer propertyConfigurer;

    @Override
    public boolean postProcessAfterInstantiation(final Object bean, final String beanName) throws BeansException {
        ReflectionUtils.doWithFields(bean.getClass(), new ReflectionUtils.FieldCallback() {
            @Override
            public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                HttpService httpApi = field.getAnnotation(HttpService.class);
                if (httpApi == null) {
                    return;
                }
                createRetrofitService(bean, field, field.getType());
            }
        });
        return super.postProcessAfterInstantiation(bean, beanName);
    }


    private void createRetrofitService(Object bean, Field field, Class clazz) throws IllegalAccessException {
        //读取注解中的值
        HttpApi httpApi = (HttpApi) clazz.getAnnotation(HttpApi.class);
        String key = httpApi.value();
        if (StringUtils.isBlank(key)) {
            return;
        }
        //根据注解的key获得配置文件中的url
        Object value = propertyConfigurer.getProperty(key);
        if (value == null) {
            return;
        }
        //根据地址创建retrofit
        Object object = RetrofitBeanFactory.putBean(value.toString(), clazz,httpApi.interceptor());
        if (object == null) {
            return;
        }
        field.setAccessible(true);
        field.set(bean, object);
    }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

3.在spring.config中注册组件

<!--注册加载retrofit服务的processor 只能在非controller中使用-->
    <bean id="retrofitProcessor" class="com.miyan.common.modules.retrofit.processor.RetrofitAutowiredProcessor"></bean>
  
  
  
  
  • 1
  • 2

4. 使用

Maven

Spring的就不再引入,建议使用Spring4,引入retrofit2框架

 <dependency>
      <groupId>com.squareup.retrofit2</groupId>
      <artifactId>retrofit</artifactId>
      <version>2.0.2</version>
 </dependency>
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5

properties

定义服务的地址

IM_BASE_URL=https://a1.easemob.com/huapingxin2015/miyan/
  
  
  
  
  • 1

创建retrofit服务接口

//IM_BASE_URL在配置文件中配置
//interceptor 为可选参数,与retrofit拦截器相同,实现拦截http
@HttpApi(value = "IM_BASE_URL", interceptor = {ImInterceptor.class})
public interface IMApi {
 /** * 修改群组信息 * * @param updateGroupInfoBean * @param groupId * @return */
    @PUT("chatgroups/{group_id}")
    Call<String> updateGroup(@Body UpdateGroupInfoBean updateGroupInfoBean, @Path("group_id") String groupId);
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

ImInterceptor

/** * Created by zhangbowen on 2016/5/17. * 环信公用请求头拦截器 */
public class ImInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request originalRequest = chain.request();
        String token = CacheFacade.getObject(Constants.IM.TOKEN);
        Request request = originalRequest
                .newBuilder()
                .addHeader(Constants.Http.AUTHORIZATION, "Bearer " + token)
                .build();
        return chain.proceed(request);
    }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

在Service层中使用

/** * Created by zhangbowen on 2016/1/21. * 环信及时通讯服务 */
@Service
public class IMService {
    @HttpService
    private IMApi imApi;
      /** * 修改群组信息 * * @param updateGroupInfoBean * @param groupId */
        public void updateGroupInfo(UpdateGroupInfoBean updateGroupInfoBean, String groupId) {
            try {
                imApi.updateGroup(updateGroupInfoBean, groupId).execute();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
}
  
  
  
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

5.小结

仅仅是将retrofit整合进spring,并没有扩展retortfit功能,通过BeanPostProcessor的子实现类InstantiationAwareBeanPostProcessor的生命周期postProcessAfterInstantiation实现,其中用到的拦截器,定义服务接口中的注解以及请求都是retorfit2.0中提供的。retrofit2.0是Android中比较流行的网络框架,是对okhttp的再次封装 
与spring整合后,web应用中调用三方接口的网络请求会简单清晰很多,比自己封装的网络框架好很多 
附retorfit github: 
http://square.github.io/retrofit/

你可能感兴趣的:(spring4,整合,Retrofit2)