本文内容大多基于官方文档和网上前辈经验总结,经过个人实践加以整理积累,仅供参考。
在 Apache HttpClient 实现 Java 调用 Http 接口 中对 Http Response 的处理都是通过 org.apache.http.util.EntityUtils 的 toString 方法获取 Http 返回的文本信息,在之前提过官方文档中建议严格控制使用 EntityUtils 读取 HttpEntity 的信息
可以使用 org.apache.http.client.ResponseHandler 替代 EntityUtils 处理 Http Response
1 新建 CustomResponse 类作为所有 Http 接口的返回信息
public class CustomResponse {
public static final int OK =
100;
public static final int ERROR =
999;
public CustomResponse() {}
public CustomResponse(
int code, String msg) {
this.code = code;
this.msg = msg;
}
private int code;
private String msg;
public int getCode() {
return code;
}
public void setCode(
int code) {
this.code = code;
}
public String
getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
2 修改 LoginService 的返回信息,由一个普通的字符串变为 CustomResponse 类实例的 JSON 字符串
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import util.CustomResponse;
public class LoginService extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter(
"username");
String password = request.getParameter(
"password");
OutputStream outputStream = response.getOutputStream();
response.setHeader(
"content-type",
"application/json;charset=UTF-8");
CustomResponse result =
null;
if (username ==
null) {
result =
new CustomResponse(CustomResponse.ERROR,
"Post:请输入用户名!");
}
else if (password ==
null) {
result =
new CustomResponse(CustomResponse.ERROR,
"Post:请输入密码!");
}
else if (!username.equals(
"unique")) {
result =
new CustomResponse(CustomResponse.ERROR,
"Post:用户名错误!");
}
else if (!password.equals(
"ASDF")) {
result =
new CustomResponse(CustomResponse.ERROR,
"Post:密码错误!");
}
else {
result =
new CustomResponse(CustomResponse.ERROR,
"Post:验证通过~~");
}
outputStream.write(
new Gson().toJson(result).getBytes(
"UTF-8"));
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter(
"username");
String password = request.getParameter(
"password");
OutputStream outputStream = response.getOutputStream();
response.setHeader(
"content-type",
"application/json;charset=UTF-8");
CustomResponse result =
null;
if (username ==
null) {
result =
new CustomResponse(CustomResponse.ERROR,
"Get:请输入用户名!");
}
else if (password ==
null) {
result =
new CustomResponse(CustomResponse.ERROR,
"Get:请输入密码!");
}
else if (!username.equals(
"unique")) {
result =
new CustomResponse(CustomResponse.ERROR,
"Get:用户名错误!");
}
else if (!password.equals(
"ASDF")) {
result =
new CustomResponse(CustomResponse.ERROR,
"Get:密码错误!");
}
else {
result =
new CustomResponse(CustomResponse.ERROR,
"Get:验证通过~~");
}
outputStream.write(
new Gson().toJson(result).getBytes(
"UTF-8"));
}
}
3 修改 public static final String invokeHttpGet(String uri) 方法逻辑
修改前
public static final String
invokeHttpGet(String uri)
throws ClientProtocolException, IOException {
CloseableHttpClient client = HttpClients.createDefault();
CloseableHttpResponse response =
null;
HttpGet httpGet =
new HttpGet(uri);
try {
response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
return EntityUtils.toString(entity);
}
finally {
release(client, response);
}
}
修改后
public static final CustomResponse
invokeHttpGetS(String uri)
throws ClientProtocolException, IOException {
CloseableHttpClient client = HttpClients.createDefault();
HttpGet httpGet =
new HttpGet(uri);
ResponseHandler<CustomResponse> responseHandler =
new ResponseHandler<CustomResponse>() {
@Override
public CustomResponse
handleResponse(HttpResponse response)
throws ClientProtocolException, IOException {
StatusLine statusLine = response.getStatusLine();
if (statusLine.getStatusCode() >=
300) {
throw new HttpResponseException(
statusLine.getStatusCode(),
statusLine.getReasonPhrase());
}
HttpEntity entity = response.getEntity();
if (entity ==
null) {
throw new ClientProtocolException(
"Response contains no content!");
}
ContentType contentType = ContentType.getOrDefault(entity);
Charset charset = contentType.getCharset();
Reader reader =
new InputStreamReader(entity.getContent(), charset);
Gson gson =
new GsonBuilder().serializeNulls().create();
return gson.fromJson(reader, CustomResponse.class);
}
};
return client.execute(httpGet, responseHandler);
}
从以上代码中还可以看出,使用 ResponseHandler 的 handleResponse 方法无需管理连接,无论执行成功或出现异常,HttpClient 都会自动处理并保证释放连接。
4 单元测试
@Test
public void test() throws ClientProtocolException, IOException {
String uri1 =
"http://localhost:8080/Service/login"
String uri2 =
"http://localhost:8080/Service/login?username=unique"
String uri3 =
"http://localhost:8080/Service/login?password=ASDF"
String uri4 =
"http://localhost:8080/Service/login?username=unique1&password=ASDF"
String uri5 =
"http://localhost:8080/Service/login?username=unique&password=ASDF2"
String uri6 =
"http://localhost:8080/Service/login?username=unique&password=ASDF"
assertEquals(
"Get:请输入用户名!",
HttpClientTool
.invokeHttpGetS(uri1)
.getMsg())
assertEquals(
"Get:请输入密码!",
HttpClientTool
.invokeHttpGetS(uri2)
.getMsg())
assertEquals(
"Get:请输入用户名!",
HttpClientTool
.invokeHttpGetS(uri3)
.getMsg())
assertEquals(
"Get:用户名错误!",
HttpClientTool
.invokeHttpGetS(uri4)
.getMsg())
assertEquals(
"Get:密码错误!",
HttpClientTool
.invokeHttpGetS(uri5)
.getMsg())
assertEquals(
"Get:验证通过~~",
HttpClientTool
.invokeHttpGetS(uri6)
.getMsg())
}