mid*_*ght 9 android rx-java retrofit
我正在实现基于会话的服务.所有请求都必须使用cookie会话参数进行订阅,然后使用单独的rest api检索该参数.因此,基本的工作流程是获取会话cookie并继续查询服务.有时cookie会过期,这会导致另一个会话cookie请求.
我正在尝试使客户端代码与会话无关,因此它不必担心维护会话,而是希望它隐藏在服务层内.
你能提出实施它的想法Retrofit/RxJava吗?我认为SessionService必须由所有其他服务封装,以便他们可以在需要时查询它,但我不知道如何使用RetrofitRestAdapter.create
kjo*_*nes 27
我之前做过类似的事情但是使用了OAuth授权.基本上,您有一个使用RequestInterceptor初始化的RestAdapter,它将会话cookie添加到每个请求.每当会话被授权时,RequestInterceptor都会获得一个新的会话cookie.
以下示例代码中使用了以下Retrofit REST接口定义:
interface ApiService {
@GET("/examples/v1/example")
Observable<Example> getExample();
}
Run Code Online (Sandbox Code Playgroud)
Request拦截器可以查看每个REST请求,并可以添加标头,查询参数或修改URL.此示例假定cookie已添加为HTTP标头.
class CookieHeaderProvider implements RequestInterceptor {
private String sessionCookie = "";
public CookieHeaderProvider() {
}
public void setSesstionCookie(String sessionCookie) {
this.sessionCookie = sessionCookie;
}
@Override
public void intercept(RequestFacade requestFacade) {
requestFacade.addHeader("Set-Cookie", sessionCookie);
}
}
Run Code Online (Sandbox Code Playgroud)
这是您提到的SessionService.它的职责是制作授权/刷新会话cookie的网络请求.
class SessionService {
// Modify contructor params to pass in anything needed
// to get the session cookie.
SessionService(...) {
}
public Observable<String> observeSessionCookie(...) {
// Modify to return an Observable that when subscribed to
// will make the network request to get the session cookie.
return Observable.just("Fake Session Cookie");
}
}
Run Code Online (Sandbox Code Playgroud)
RestService类包装Retrofit接口,以便可以将请求重试逻辑添加到每个Retrofit Observable.
class RestService {
private final apiService;
private final sessionSerivce;
private final cookieHeaderProvider;
RestService(ApiService apiService,
SessionService sessionSerivce,
CookieHeaderProvider cookieHeaderProvider) {
this.apiService = apiService;
this.sessionSerivce = sessionSerivce;
this.cookieHeaderProvider = cookieHeaderProvider;
}
Observable<Example> observeExamples() {
// Return a Retrofit Observable modified with
// session retry logic.
return
apiService
.observeExamples()
.retryWhen(new RetryWithSessionRefresh(sessionSerivce, cookieHeaderProvider));
}
}
Run Code Online (Sandbox Code Playgroud)
下面的重试逻辑将使用SessionService更新会话cookie,然后如果发送到服务器的会话cookie返回HTTP Unauthorized(401)错误,则重试失败的REST请求.
public class RetryWithSessionRefresh implements
Func1<Observable<? extends Throwable>, Observable<?>> {
private final SessionService sessionSerivce;
private final CookieHeaderProvider cookieHeaderProvider;
public RetryWithSessionRefresh(SessionService sessionSerivce,
CookieHeaderProvider cookieHeaderProvider) {
this.sessionSerivce = sessionSerivce;
this.cookieHeaderProvider = cookieHeaderProvider;
}
@Override
public Observable<?> call(Observable<? extends Throwable> attempts) {
return attempts
.flatMap(new Func1<Throwable, Observable<?>>() {
public int retryCount = 0;
@Override
public Observable<?> call(final Throwable throwable) {
// Modify retry conditions to suit your needs. The following
// will retry 1 time if the error returned was an
// HTTP Unauthoried (401) response.
retryCount++;
if (retryCount <= 1 && throwable instanceof RetrofitError) {
final RetrofitError retrofitError = (RetrofitError) throwable;
if (!retrofitError.isNetworkError()
&& retrofitError.getResponse().getStatus() == HttpStatus.SC_UNAUTHORIZED) {
return sessionSerivce
.observeSessionCookie()
.doOnNext(new Action1<String>() {
@Override
public void call(String sessionCookie) {
// Update session cookie so that next
// retrofit request will use it.
cookieHeaderProvider.setSesstionCookie(sessionCookie);
}
})
.doOnError(new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
// Clear session cookie on error.
cookieHeaderProvider.setSesstionCookie("");
}
});
}
}
// No more retries. Pass the original
// Retrofit error through.
return Observable.error(throwable);
}
});
}
}
Run Code Online (Sandbox Code Playgroud)
客户端初始化代码看起来类似于:
CookieHeaderProvider cookieHeaderProvider = new CookieHeaderProvider();
SessionService sessionSerivce = new SessionService();
ApiService apiService =
new RestAdapter.Builder()
.setEndpoint(...)
.setClient(...)
.setRequestInterceptor(cookieHeaderProvider)
.build()
.create(ApiService.class);
RestService restService =
new RestService(apiService, sessionSerivce, cookieHeaderProvider);
Run Code Online (Sandbox Code Playgroud)
然后从RestService获取一个REST observable并订阅它以启动网络请求.
Observable<Example> exampleObservable =
restService
.observeExamples();
Subsctiption subscription =
exampleObservable
.subscribe(new Observer<Example>() {
void onNext(Example example) {
// Do stuff with example
}
void onCompleted() {
// All done.
}
void onError(Throwalbe e) {
// All API errors will end up here.
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4821 次 |
| 最近记录: |