public final class SimpleService {
public static final String API_URL = "https://api.github.com";
public static class Contributor {
public final String login;
public final int contributions;
public Contributor(String login, int contributions) {
this.login = login;
this.contributions = contributions;
}
}
// 1
public interface GitHub {
@GET("/repos/{owner}/{repo}/contributors")
Call> contributors(
@Path("owner") String owner,
@Path("repo") String repo);
}
public static void main(String... args) throws IOException {
// Create a very simple REST adapter which points the GitHub API.
//2
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// Create an instance of our GitHub API interface.
//3
GitHub github = retrofit.create(GitHub.class);
// Create a call instance for looking up Retrofit contributors.
//4
Call> call = github.contributors("square", "retrofit");
// Fetch and print a list of the contributors to the library.
//5
List contributors = call.execute().body();
//6
for (Contributor contributor : contributors) {
System.out.println(contributor.login + " (" + contributor.contributions + ")");
}
}
}
public static final class Builder {
private final Platform platform;
private @Nullable okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private final List converterFactories = new ArrayList<>();
private final List adapterFactories = new ArrayList<>();
private @Nullable Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
....
/**
* Create the {@link Retrofit} instance using the configured values.
*
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
//1
callFactory = new OkHttpClient();
}
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
// 2
List adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.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.
//3
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
}
通过build() 创建 OkHttpClient对象。
设置一个CallAdapterFactory.
添加各种Converter 转换工厂。
这里的AdapterFactory 默认使用DefaultCallAdapterFactory
final class DefaultCallAdapterFactory extends CallAdapter.Factory {
static final CallAdapter.Factory INSTANCE = new DefaultCallAdapterFactory();
@Override
public CallAdapter, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter
这个DefaultCallAdapterFactory 下面会用到。
3、retrofit.create() 返回4 中的 Call对象
通过retrofit.create ,动态创建一个接口代理对象。
public T create(final Class service) {
//判断是否是接口.
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
//Proxy.newProxyInstance 返回一个service 的代理对象。
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 serviceMethod =
(ServiceMethod) loadServiceMethod(method);
//创建OkHttpCall
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
ServiceMethod, ?> loadServiceMethod(Method method) {
ServiceMethod, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//构建ServiceMethod
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
ServiceMethod 的构建还是用到build模式。
public ServiceMethod build() {
//1
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
//2
responseConverter = createResponseConverter();
// 3
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
if (httpMethod == null) {
throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
}
if (!hasBody) {
if (isMultipart) {
throw methodError(
"Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
}
if (isFormEncoded) {
throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
+ "request body (e.g., @POST).");
}
}
//4
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
if (relativeUrl == null && !gotUrl) {
throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
}
if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
throw methodError("Non-body HTTP method cannot contain @Body.");
}
if (isFormEncoded && !gotField) {
throw methodError("Form-encoded method must contain at least one @Field.");
}
if (isMultipart && !gotPart) {
throw methodError("Multipart method must contain at least one @Part.");
}
return new ServiceMethod<>(this);
}
创建 CallAdapter
创建转换器,将返回的结果进行转换。
处理请求的Annotation 注解。
处理参数的注解。
看一下createCallAdapter()
private CallAdapter createCallAdapter() {
//获取Type
Type returnType = method.getGenericReturnType();
if (Utils.hasUnresolvableType(returnType)) {
throw methodError(
"Method return type must not include a type variable or wildcard: %s", returnType);
}
if (returnType == void.class) {
throw methodError("Service methods cannot return void.");
}
//获取 目标方法的Annotation
Annotation[] annotations = method.getAnnotations();
try {
//noinspection unchecked
//获取 CallAdapter
return (CallAdapter) retrofit.callAdapter(returnType, annotations);
} catch (RuntimeException e) { // Wide exception range because factories are user code.
throw methodError(e, "Unable to create call adapter for %s", returnType);
}
}
动态代理代理模式的解释:为其他对象提供一种代理以控制对这个对象的访问,增强一个类中的某个方法,对程序进行扩展。比如,现在存在一个UserService类:public class UserService { public void test() { System.out.println("test..."); }}此时,我们new一个UserService对象,然后执行test()方法,结果是
分页显示一直是web开发中一大烦琐的难题,传统的网页设计只在一个JSP或者ASP页面中书写所有关于数据库操作的代码,那样做分页可能简单一点,但当把网站分层开发后,分页就比较困难了,下面是我做Spring+Hibernate+Struts2项目时设计的分页代码,与大家分享交流。
1、DAO层接口的设计,在MemberDao接口中定义了如下两个方法:
public in
/*
*使用对象类型
*/
--建立和使用简单对象类型
--对象类型包括对象类型规范和对象类型体两部分。
--建立和使用不包含任何方法的对象类型
CREATE OR REPLACE TYPE person_typ1 as OBJECT(
name varchar2(10),gender varchar2(4),birthdate date
);
drop type p
what 什么
your 你
name 名字
my 我的
am 是
one 一
two 二
three 三
four 四
five 五
class 班级,课
six 六
seven 七
eight 八
nince 九
ten 十
zero 零
how 怎样
old 老的
eleven 十一
twelve 十二
thirteen
spring security 3中推荐使用BCrypt算法加密密码了,以前使用的是md5,
Md5PasswordEncoder 和 ShaPasswordEncoder,现在不推荐了,推荐用bcrpt
Bcrpt中的salt可以是随机的,比如:
int i = 0;
while (i < 10) {
String password = "1234
1.前言。
如题。
2.代码
(1)单表查重复数据,根据a分组
SELECT m.a,m.b, INNER JOIN (select a,b,COUNT(*) AS rank FROM test.`A` A GROUP BY a HAVING rank>1 )k ON m.a=k.a
(2)多表查询 ,
使用改为le