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; }}
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)); }}
工厂生产的实体类
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 { 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); }}
自定义注解
/** * Created by zhangbowen on 2016/5/12. * 用于标识服务接口类 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface HttpApi { String value() default ""; Class[] interceptor() default {};}
/** * Created by zhangbowen on 2016/5/12. * 用于自动注入服务 */@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface HttpService {}
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; } Object value = propertyConfigurer.getProperty(key); if (value == null) { return; } 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中注册组件
<bean id="retrofitProcessor" class="com.miyan.common.modules.retrofit.processor.RetrofitAutowiredProcessor"></bean>
4. 使用
Maven
Spring的就不再引入,建议使用Spring4,引入retrofit2框架
<dependency> <groupId>com.squareup.retrofit2</groupId> <artifactId>retrofit</artifactId> <version>2.0.2</version> </dependency>
properties
定义服务的地址
IM_BASE_URL=https://a1.easemob.com/huapingxin2015/miyan/
创建retrofit服务接口
@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);}
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); }}
在Service层中使用
/** * Created by zhangbowen on 2016/1/21. * 环信及时通讯服务 */@Servicepublic 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/
0 0