0
点赞
收藏
分享

微信扫一扫

十、使用责任链模式,重构http请求


一、背景:

我们写 http请求的post json方法,也写了post form方法,当调用的时候,我们要根据不同的类型使用,不同的post方法。

这里引入责任链模式,我们则在做请求的时候,不需要判断参数的类型,统一使用一种请求方式。

二、实现

1、我们使用责任链模式,post json 不能处理,交给下一个post form处理

2、责任链中的Manger的实现,使用了单例模式

3、在编写自己的HttpRqeust的类时,使用了建造者模式。

2.1 编写自定义的类,HttpRquest 与HttpRespone

okhttp 这个包里,有请求类Request 与返回类Response。

我们为了方便扩展自己的功能,我们重新定义一下自己的类。

HttpRequest

package com.example.autoapi.model;

import lombok.Getter;
import lombok.ToString;

import java.util.Map;

@ToString
@Getter
public class HttpRequest {
private String url;
private Map<String,String> headers;
private Object data;
private Map<String,Object> params;
private MethodType methodType;
private ContentType contentType;

// 这里自己写一个建造者模式,不直接用@Builder,是为了方便自己扩展

// 一个静态的Builder
public static Builder builder(){
return new Builder();
}

// 构造器
public HttpRequest(Builder builder){
this.url = builder.url;
this.headers = builder.headers;
this.data = builder.data;
this.params = builder.params;
this.methodType = builder.methodType;
this.contentType = builder.contentType;
}

// 这是一个内部类
public static class Builder{
private String url;
private Map<String,String> headers;
private Object data;
private Map<String,Object> params;
private MethodType methodType;
private ContentType contentType;

public Builder url(String url) {
this.url = url;
return this;
}

public Builder headers(Map<String, String> headers) {
this.headers = headers;
return this;
}

public Builder data(Object data) {
this.data = data;
return this;
}

public Builder params(Map<String, Object> params) {
this.params = params;
return this;
}

public Builder methodType(MethodType methodType) {
this.methodType = methodType;
return this;
}

public Builder post() {
this.methodType = MethodType.POST;
return this;
}
public Builder postForm() {
this.methodType = MethodType.POST;
this.contentType = ContentType.FORM;
return this;
}
public Builder postJson() {
this.methodType = MethodType.POST;
this.contentType = ContentType.JSON;
return this;
}

public Builder get() {
this.methodType = MethodType.GET;
return this;
}

public Builder contentType(ContentType contentType) {
this.contentType = contentType;
return this;
}
public Builder json() {
this.contentType = ContentType.JSON;
return this;
}
public Builder form() {
this.contentType = ContentType.FORM;
return this;
}

public HttpRequest build(){
return new HttpRequest(this);
}
}

}

这里自己写一个建造者模式,不直接用@Builder,是为了方便自己扩展

HttpResponse

package com.example.autoapi.model;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class HttpResponse {
private String body;

}

2.2 AbstractHttpHandle

责任链模式的学习:

​​责任链设计模式_傲娇的喵酱的博客-​​

这里就是具体实现责任链模式了

package com.example.autoapi.http.chain;

import com.example.autoapi.model.HttpRequest;
import com.example.autoapi.model.HttpResponse;
import okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import java.io.IOException;

// 抽象类
public abstract class AbstractHttpHandle {
private AbstractHttpHandle httpHandle;

public void setHttpHandle(AbstractHttpHandle httpHandle) {
this.httpHandle = httpHandle;
}

// 抽象方法
// 判断,当时是否能处理,ture,自己处理,false交给下一个处理
protected abstract boolean preHttp(HttpRequest request);

// 具体的
protected abstract Request createRequest(HttpRequest request);


// 抽象方法
// 具体的处理逻辑
protected HttpResponse onHttp(HttpRequest httpRequest){
// 将我们自定义的httpRequest,转成请求要用的request
Request request = createRequest(httpRequest);

// 发送这个请求,并得到返回值
return handleRequest(request);
};


// 发送请求的,得到返回值HttpResponse的固定写法
private HttpResponse handleRequest(Request request){
OkHttpClient client = new OkHttpClient();

Call call = client.newCall(request);
try {
Response response = call.execute();
String body = response.body().string();
return new HttpResponse(body);
} catch (IOException e) {
throw new IllegalStateException(e);
}

}


// 模版,规定好了整个流程的逻辑
public HttpResponse doHttp(HttpRequest request){
if(preHttp(request)){
// 如果能处理,则直接处理
return onHttp(request);
}
// 如果不能处理
// 交给下一个处理
if(httpHandle != null){
return httpHandle.doHttp(request);

}
throw new IllegalStateException("unknow http request");

}

}

实现类 PostFormHttpHandle

package com.example.autoapi.http.chain;

import com.example.autoapi.model.ContentType;
import com.example.autoapi.model.HttpRequest;
import com.example.autoapi.model.MethodType;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Request;
import okhttp3.RequestBody;

import java.util.HashMap;
import java.util.Map;

public class PostFormHttpHandle extends AbstractHttpHandle{
@Override
protected boolean preHttp(HttpRequest request) {
// 判断是否能处理
return request.getContentType()== ContentType.FORM && request.getMethodType()== MethodType.POST;
}

@Override
protected Request createRequest(HttpRequest httpRequest) {
FormBody.Builder builder= new FormBody.Builder();
for (Map.Entry<String,Object> entry:httpRequest.getParams().entrySet()){
builder.add(entry.getKey(), String.valueOf(entry.getValue()));
}
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(httpRequest.getUrl())
.headers(Headers.of(httpRequest.getHeaders()==null?new HashMap<>():httpRequest.getHeaders()))
.post(requestBody)
.build();
return request;
}

}

实现类 PostJsonHttpHandle

package com.example.autoapi.http.chain;

import com.example.autoapi.model.ContentType;
import com.example.autoapi.model.HttpRequest;
import com.example.autoapi.model.MethodType;
import com.google.gson.Gson;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.RequestBody;

import java.util.HashMap;

public class PostJsonHttpHandle extends AbstractHttpHandle{
@Override
protected boolean preHttp(HttpRequest request) {
// 判断是否能处理
return request.getContentType()== ContentType.JSON && request.getMethodType()== MethodType.POST;
}


// 这里的具体处理方式,不是去发送请求,而是构建request
// 将 HttpRequest --》 Request
// 构建post json 的request
@Override
protected Request createRequest(HttpRequest httpRequest) {
MediaType mediaType = MediaType.parse("application/json");
// Gson是json工具类,将x转成json
Gson gson = new Gson();
RequestBody requestBody = RequestBody.create(gson.toJson(httpRequest.getData()), mediaType);
Request request = new Request.Builder()
.url(httpRequest.getUrl())
.headers(Headers.of(httpRequest.getHeaders()==null?new HashMap<>():httpRequest.getHeaders()))
.post(requestBody)
.build();
return request;
}

}

HttpHandleManager

package com.example.autoapi.http.chain;

import com.example.autoapi.model.HttpRequest;
import com.example.autoapi.model.HttpResponse;

public class HttpHandleManager {
private AbstractHttpHandle httpHandle;

// 构造器,私有,不能被new
private HttpHandleManager(){
httpHandle = initHandle();
}

private AbstractHttpHandle initHandle() {
PostJsonHttpHandle postJsonHttpHandle = new PostJsonHttpHandle();
PostFormHttpHandle postFormHttpHandle = new PostFormHttpHandle();

// 将json与form串起来
postJsonHttpHandle.setHttpHandle(postFormHttpHandle);
return postJsonHttpHandle;
}

// ClassHolder属于静态内部类,在加载类Demo03的时候,只会加载内部类ClassHolder,
// 但是不会把内部类的属性加载出来
private static class ClassHolder{
// 这里执行类加载,是jvm来执行类加载,它一定是单例的,不存在线程安全问题
// 这里不是调用,是类加载,是成员变量
private static final HttpHandleManager holder =new HttpHandleManager();

}

public static HttpHandleManager of(){//第一次调用getInstance()的时候赋值
return ClassHolder.holder;
}

// 去做请求
// 用第一个节点/用这条链,去处理请求
public HttpResponse doRequest(HttpRequest httpRequest){
return httpHandle.doHttp(httpRequest);
}


}

调用

package com.example.autoapi.http;

import com.example.autoapi.http.chain.HttpHandleManager;
import com.example.autoapi.http.service.HttpService;
import com.example.autoapi.model.HttpRequest;
import com.example.autoapi.model.HttpResponse;

public class HttpFacade {
public static String doPostJson(String url,Object data){
return new HttpService().doPostJson(url, data);
}

public static HttpResponse doRequest(HttpRequest httpRequest){
return HttpHandleManager.of().doRequest(httpRequest);
}
}

HttpRequest httpRequest = HttpRequest.builder()
.postJson()
.url(url)
.data(data)
.build();
HttpFacade.doRequest(httpRequest);

上一章:

下一章:

​​十一、junit5 自定义参数化注解_傲娇的喵酱的博客​​

举报

相关推荐

0 条评论