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;
}
}
public class FastJsonConverterFactory extends Converter.Factory{
public static FastJsonConverterFactory create() {
return new FastJsonConverterFactory();
}
/**
* 需要重写父类中responseBodyConverter,该方法用来转换服务器返回数据
*/
@Override
public Converter 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<>();
}
}
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;
}
}
}
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 service = new HashMap<>();
public Retrofit getRetrofit() {
return retrofit;
}
public void setRetrofit(Retrofit retrofit) {
this.retrofit = retrofit;
}
public Map getService() {
return service;
}
public void setService(Map service) {
this.service = service;
}
}
public class RetrofitBeanFactory {
//key:请求地址 value:当前请求地址下class所对应的service(key:class value:service)
private static Map 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 entrySet : resolvableDependencies.entrySet()) {
RetrofitBean retrofitBean = entrySet.getValue();
for (Map.Entry 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 getResolvableDependencies() {
return resolvableDependencies;
}
}
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 "";//通过key获得配置文件中的值
Class[] interceptor() default {};
}
/**
* Created by zhangbowen on 2016/5/12.
* 用于自动注入服务
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface HttpService {
}
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);
}
}
<bean id="retrofitProcessor" class="com.miyan.common.modules.retrofit.processor.RetrofitAutowiredProcessor">bean>
Spring的就不再引入,建议使用Spring4,引入retrofit2框架
<dependency>
<groupId>com.squareup.retrofit2groupId>
<artifactId>retrofitartifactId>
<version>2.0.2version>
dependency>
定义服务的地址
IM_BASE_URL=https://a1.easemob.com/huapingxin2015/miyan/
//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 updateGroup(@Body UpdateGroupInfoBean updateGroupInfoBean, @Path("group_id") String groupId);
}
/**
* 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);
}
}
/**
* 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();
}
}
}
仅仅是将retrofit整合进spring,并没有扩展retortfit功能,通过BeanPostProcessor的子实现类InstantiationAwareBeanPostProcessor的生命周期postProcessAfterInstantiation实现,其中用到的拦截器,定义服务接口中的注解以及请求都是retorfit2.0中提供的。retrofit2.0是Android中比较流行的网络框架,是对okhttp的再次封装
与spring整合后,web应用中调用三方接口的网络请求会简单清晰很多,比自己封装的网络框架好很多
附retorfit github:
http://square.github.io/retrofit/