public static final class Builder {
// 具体使用平台,Platform.get()方法来获取,这里只分析Android
private final Platform platform;
// 指定用来构建Call实例的Call.Factory类
private @Nullable okhttp3.Call.Factory callFactory;
// 请求的baseUrl,注释建议我们使用相对路径的方式来配置
// Base URL: http://example.com/api/
// Endpoint: foo/bar/
// Result: http://example.com/api/foo/bar/
private HttpUrl baseUrl;
// 用于对象序列化(serialization)和反序列化(deserialization),常用GsonConverterFactory
private final List converterFactories = new ArrayList<>();
// 请求返回类型(除了Call之外),若Retrofit结合RxJava一起使用,那么就可以添加RxJava2CallAdapterFactory
// 来返回Observable类型,无缝对接RxJava
private final List callAdapterFactories = new ArrayList<>();
// 异步回调执行者
private @Nullable Executor callbackExecutor;
// 是否提前校验注解方法
private boolean validateEagerly;
......
public Retrofit build() {
// 必须指定baseUrl,否则异常
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//默认OkHttpClient来创建请求Call
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// Android平台默认回调在主线程
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 默认添加一个CallAdapter和Converter
// Make a defensive copy of the adapters and add the default Call adapter.
List callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
List converterFactories = new ArrayList<>(1 + this.converterFactories.size());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
}
3、Retrofit.create()
public final class Retrofit {
......
public T create(final Class service) {
// 校验class必须是接口,并且不能继承其他接口
Utils.validateServiceInterface(service);
// 是否提前校验方法,提前创建ServiceMethod,如果自定义的接口方法存在不合规范则抛出异常
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 返回一个代理对象,当调用api方法的时候,代理对象执行
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
// 下面这两行是核心代码,生成ServiceMethod和请求OkHttpCall
ServiceMethod
@Override public void enqueue(final Callback callback) {
checkNotNull(callback, "callback == null");
// 这里的delegate就是OkHttpCall,最终还是走到OkHttpCall的enqueue方法
delegate.enqueue(new Callback() {
@Override public void onResponse(Call call, final Response response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, response);
}
}
});
}
@Override public void onFailure(Call call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallAdapterFactory.ExecutorCallbackCall.this, t);
}
});
}
});
}
9、BuiltInConverters
如果没有添加ConverterFactory,则会使用默认的BuiltInConverters进行requestBody序列化和responseBody反序列化。当然,在BuiltInConverters还存在一个重要的类ToStringConverter,不管有没有额外添加ConverterFactory,其在ServiceMethod进行注解解析时都会使用到,具体参见ServiceMethod类中的ParameterHandler> parseParameterAnnotation( int p, Type type, Annotation[] annotations, Annotation annotation)方法。
final class BuiltInConverters extends Converter.Factory {
// 响应数据反序列化转换器
@Override
public Converter responseBodyConverter(Type type, Annotation[] annotations,
Retrofit retrofit) {
// 根据要求响应数据类型的不同,返回不同的converter
if (type == ResponseBody.class) {
return Utils.isAnnotationPresent(annotations, Streaming.class)
? retrofit2.BuiltInConverters.StreamingResponseBodyConverter.INSTANCE
: retrofit2.BuiltInConverters.BufferingResponseBodyConverter.INSTANCE;
}
if (type == Void.class) {
return retrofit2.BuiltInConverters.VoidResponseBodyConverter.INSTANCE;
}
return null;
}
// 请求体数据序列化转化器
@Override
public Converter, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
if (RequestBody.class.isAssignableFrom(Utils.getRawType(type))) {
return retrofit2.BuiltInConverters.RequestBodyConverter.INSTANCE;
}
return null;
}
static final class VoidResponseBodyConverter implements Converter {
static final retrofit2.BuiltInConverters.VoidResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.VoidResponseBodyConverter();
@Override public Void convert(ResponseBody value) {
// 不需要返回,直接close,返回null
value.close();
return null;
}
}
// RequestBody请求体转换器
static final class RequestBodyConverter implements Converter {
static final retrofit2.BuiltInConverters.RequestBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.RequestBodyConverter();
@Override public RequestBody convert(RequestBody value) {
return value;
}
}
// 流转换器
static final class StreamingResponseBodyConverter
implements Converter {
static final retrofit2.BuiltInConverters.StreamingResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.StreamingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) {
return value;
}
}
// 容器转换器
static final class BufferingResponseBodyConverter
implements Converter {
static final retrofit2.BuiltInConverters.BufferingResponseBodyConverter
INSTANCE = new retrofit2.BuiltInConverters.BufferingResponseBodyConverter();
@Override public ResponseBody convert(ResponseBody value) throws IOException {
try {
// Buffer the entire body to avoid future I/O.
return Utils.buffer(value);
} finally {
value.close();
}
}
}
// 转换成String
static final class ToStringConverter implements Converter {
static final retrofit2.BuiltInConverters.ToStringConverter
INSTANCE = new retrofit2.BuiltInConverters.ToStringConverter();
@Override public String convert(Object value) {
return value.toString();
}
}
}
以教员和课程为例介绍一对多关联关系,在这里认为一个教员可以叫多门课程,而一门课程只有1个教员教,这种关系在实际中不太常见,通过教员和课程是多对多的关系。
示例数据:
地址表:
CREATE TABLE ADDRESSES
(
ADDR_ID INT(11) NOT NULL AUTO_INCREMENT,
STREET VAR
In this lesson we used the key "UITextAttributeTextColor" to change the color of the UINavigationBar appearance to white. This prompts a warning "first deprecated in iOS 7.0."
Ins
质数也叫素数,是只能被1和它本身整除的正整数,最小的质数是2,目前发现的最大的质数是p=2^57885161-1【注1】。
判断一个数是质数的最简单的方法如下:
def isPrime1(n):
for i in range(2, n):
if n % i == 0:
return False
return True
但是在上面的方法中有一些冗余的计算,所以
hbase(hadoop)是用java编写的,有些语言(例如python)能够对它提供良好的支持,但也有很多语言使用起来并不是那么方便,比如c#只能通过thrift访问。Rest就能很好的解决这个问题。Hbase的org.apache.hadoop.hbase.rest包提供了rest接口,它内嵌了jetty作为servlet容器。
启动命令:./bin/hbase rest s
下面这段sql本来目的是想更新条件下的数据,可是这段sql却更新了整个表的数据。sql如下:
UPDATE tops_visa.visa_order
SET op_audit_abort_pass_date = now()
FROM
tops_visa.visa_order as t1
INNER JOIN tops_visa.visa_visitor as t2
ON t1.