本人最近通过自己动手处理http请求,对http协议、Jetty以及HttpClient有了更深刻的理解,特在此与大家分享。

此图是http协议的请求格式。根据请求方法,有get和post之分。get和post的区别在于参数传递的方式:post的参数就是请求包体那一行;get的参数跟在URL后面,也就没有请求包体。

get方式的请求格式

GET /search?hl=zh-CN&source=hp&q=domety&aq=f&oq= HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint,
application/msword, application/x-silverlight, application/x-shockwave-flash, */*
Referer: <a href="http://www.google.cn/">http://www.google.cn/</a>
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)
Host: <a href="http://www.google.cn">www.google.cn</a>
Connection: Keep-Alive
Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g;
NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-
FxlRugatx63JLv7CWMD6UB_O_r

post方式的请求格式

POST /search HTTP/1.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint,
application/msword, application/x-silverlight, application/x-shockwave-flash, */*
Referer: <a href="http://www.google.cn/">http://www.google.cn/</a>
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; TheWorld)
Host: <a href="http://www.google.cn">www.google.cn</a>
Connection: Keep-Alive
Cookie: PREF=ID=80a06da87be9ae3c:U=f7167333e2c3b714:NW=1:TM=1261551909:LM=1261551917:S=ybYcq2wpfefs4V9g;
NID=31=ojj8d-IygaEtSxLgaJmqSjVhCspkviJrB6omjamNrSm8lZhKy_yMfO2M4QMRKcH1g0iQv9u-2hfBW7bUFwVh7pGaRUb0RnHcJU37y-
FxlRugatx63JLv7CWMD6UB_O_r hl=zh-CN&source=hp&q=domety

所以,对请求进行解析的时候需要区分。

1、用Jetty捕获请求

直接上代码

 package test;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; public class JettyServer {
public static void main(String[] args) {
try {
// 进行服务器配置
Server server = new Server(8888);
server.setHandler(new MyHandler());
// 启动服务器
server.start();
server.join();
} catch (Exception e) {
e.printStackTrace();
}
}
} class MyHandler extends AbstractHandler { @Override
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
//写自己的处理
} }

Jetty类似于tomcat,但是Jetty比较轻量级,特别适合内嵌到自己写的程序中,比如Hadoop的内置Server就是Jetty。

Jetty将请求进行了封装,比如Jetty自己的Request类,以及我们熟悉的HttpServletRequest类;并且把对象传递给handler。我们拿到HttpServletRequest的对象,就可以对请求进行解析、修改和拼装

Enumeration params = request.getParameterNames();
while(params.hasMoreElements()){
String paraName = (String)params.nextElement();
String paraValue = request.getParameter(paraName);
paramList.add(new BasicNameValuePair(paraName, paraValue));
} Enumeration headerNames = request.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
//HttpClient会自动加上这个请求头
if(headerName.equals("Content-Length")) {
continue;
}
String headerValue = request.getHeader(headerName);
Header header = new BasicHeader(headerName, headerValue);
headers.add(header);
}

2、用HttpClient转发请求

把捕获的请求进行重新组装之后,就可以通过HttpClient转发出去。

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包。多说无益,简单语法请自行百度。

下面是一个完整的加入了HttpClient进行请求转发的类

 package service;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List; import javax.servlet.http.HttpServletRequest; import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair; public class RequestSender implements Runnable {
private HttpClient httpclient = null;
private RequestAdaptor requestAdaptor = null;//封装之后的请求
private String ip = null;
private String port = null; public RequestSender(RequestAdaptor requestAdaptor, String ip, String port) {
httpclient = new DefaultHttpClient();
this.requestAdaptor = requestAdaptor;
this.ip = ip;
this.port = port;
} @Override
public void run() {
send();
} public void send() {
if(requestAdaptor == null) {
return;
}
String method = requestAdaptor.getMethod();
String uri = requestAdaptor.getUri();
String host = ip + ":" + port;
String url = "http://" + host + uri;
if(method.equals("GET")) {
get(url);
}else if(method.equals("POST")) {
post(url);
}
} public void get(String url) {
url = url + "?" + requestAdaptor.getQueryString();
HttpGet httpGet = new HttpGet(url);
addHeaders(httpGet);
try{ HttpResponse resp = httpclient.execute(httpGet);
System.out.println(resp.getStatusLine().getStatusCode());
}catch(ClientProtocolException cp) {
cp.printStackTrace();
}catch(IOException io) {
io.printStackTrace();
}
//return showResponse(httpGet);
} public void post(String url) {
System.out.println(url);
HttpPost httpPost = new HttpPost(url);
addHeaders(httpPost);
UrlEncodedFormEntity uefEntity = null;
try {
uefEntity = new UrlEncodedFormEntity(requestAdaptor.getParamList(), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
httpPost.setEntity(uefEntity);
try{
HttpResponse resp = httpclient.execute(httpPost);
System.out.println(resp.getStatusLine().getStatusCode());
}catch(ClientProtocolException cp) {
cp.printStackTrace();
}catch(IOException io) {
io.printStackTrace();
}
//return showResponse(httpPost);
} public void addHeaders(HttpUriRequest httpUriRequest) {
List<Header> headers = requestAdaptor.getHeaders();
for(int i = 0 ; i< headers.size();i++){
httpUriRequest.addHeader(headers.get(i));
}
} public String showResponse(HttpUriRequest httpUriRequest) {
HttpResponse response = null;
try {
response = httpclient.execute(httpUriRequest);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
HttpEntity entity = response.getEntity();
if (entity != null) {
InputStream instreams = null;
try {
instreams = entity.getContent();
} catch (UnsupportedOperationException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String str = convertStreamToString(instreams);
//System.out.println(str);
// Do not need the rest
httpUriRequest.abort();
return str;
}
return null;
} public static String convertStreamToString(InputStream is) {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
try {
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return sb.toString();
}
}

转发的核心是httpclient.execute(httpGet)和httpclient.execute(httpPost)

转发post请求的时候,需要把参数一个一个的组装进去;而转发get请求的时候就不用,应为参数已经跟在URL后面。但是,无论get还是post,都需要把请求头原封不动的组装进去。

基于以上两点,我们可以做的事情就有很多了。

Jetty + HttpClient 处理http请求的更多相关文章

  1. HttpClientUtil [使用apache httpclient模拟http请求]

    基于httpclient-4.5.2 模拟http请求 以get/post方式发送json请求,并获取服务器返回的json -------------------------------------- ...

  2. 【JAVA】通过HttpClient发送HTTP请求的方法

    HttpClient介绍 HttpClient 不是一个浏览器.它是一个客户端的 HTTP 通信实现库.HttpClient的目标是发 送和接收HTTP 报文.HttpClient不会去缓存内容,执行 ...

  3. Android系列之网络(三)----使用HttpClient发送HTTP请求(分别通过GET和POST方法发送数据)

    ​[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/ ...

  4. Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  5. 一步步教你为网站开发Android客户端---HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新ListView

    本文面向Android初级开发者,有一定的Java和Android知识即可. 文章覆盖知识点:HttpWatch抓包,HttpClient模拟POST请求,Jsoup解析HTML代码,动态更新List ...

  6. 使用httpclient发送post请求与get请求

    最近因为项目的要求,需要使用httpclient来发送请求.但是查阅了许多博客,大家发送请求的方法各不相同.原因是因为httpclient的jar包的不同版本,其内部方法也不相同.因此抛开具体用到的j ...

  7. Java Apcahe的HTTPClient工具Http请求当请求超时重发

    java Apcahe的HTTPClient工具Http请求当请求超时时底层会默认进行重发,默认重发次数为3次,在某些情况下为了防止重复的请求,需要将自动重发覆盖. 设置HTTP参数,设置不进行自动重 ...

  8. (一)----使用HttpClient发送HTTP请求(通过get方法获取数据)

    (一)----使用HttpClient发送HTTP请求(通过get方法获取数据) 一.HTTP协议初探: HTTP(Hypertext Transfer Protocol)中文 “超文本传输协议”,是 ...

  9. SpringMVC,MyBatis项目中兼容Oracle和MySql的解决方案及其项目环境搭建配置、web项目中的单元测试写法、HttpClient调用post请求等案例

     要搭建的项目的项目结构如下(使用的框架为:Spring.SpingMVC.MyBatis): 2.pom.xml中的配置如下(注意,本工程分为几个小的子工程,另外两个工程最终是jar包): 其中 ...

随机推荐

  1. JavaWeb之cookie

    什么叫做会话 ? 用户从打开一个浏览器开始,浏览器网站,到关闭浏览器的整个过程叫做一次会话! 每个用户与服务器进行交互的过程中,各自会有一些数据,程序要想办法保存每个用户的数据. 例如:用户点击超链接 ...

  2. AngularJS1.X学习笔记3-内置模板指令

    前面学习了数据绑定指令,现在开始学习内置模板指令.看起来有点多,目测比较好理解.OK!开始! 一.ng-repeat 1.基本用法 <!DOCTYPE html> <html lan ...

  3. ElasticSearch查询 第五篇:布尔查询

    布尔查询是最常用的组合查询,不仅将多个查询条件组合在一起,并且将查询的结果和结果的评分组合在一起.当查询条件是多个表达式的组合时,布尔查询非常有用,实际上,布尔查询把多个子查询组合(combine)成 ...

  4. 性能优化之AJAX

    明天就放假啦~哈哈.四月份好像还没有输出呢,吓得我赶紧写点东西... Ajax是高性能JavaScript的基础. Ajax,从最基本的层面来说,是一种与服务器通信而无需重载页面的方法.数据可以从服务 ...

  5. 设计模式的征途—2.简单工厂(Simple Factory)模式

    工厂模式是最常用的一种创建型模式,通常所说的工厂模式一般是指工厂方法模式.本篇是是工厂方法模式的“小弟”,我们可以将其理解为工厂方法模式的预备知识,它不属于GoF 23种设计模式,但在软件开发中却也应 ...

  6. Apache2.4.23+PHP5.6.30+MySQL5.7.18安装教程

    最近在工作中常常接触到PHP,自己也写过一些简单的PHP页面.我们知道PHP是在服务器端运行的脚本语言,因此我们需要配置服务器环境.之前为了省事直接使用的是wamp集成环境,但是突然某一天领导要求我们 ...

  7. Git协作

    前面的话 本文将详细介绍Git多人协作的具体内容 远程仓库 当你从远程仓库克隆时,实际上Git自动把本地的master分支和远程的master分支对应起来了,并且,远程仓库的默认名称是origin. ...

  8. Java中的排序方法

    冒泡排序法 快速排序

  9. margin外边距合并问题以及解决方式

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. 通过web对.exe程序进行更新和修改

    实现功能:通过网站更新用户的软件,需要联网,也可以通过本地网站更新局域网用户软件. 根本实现:1.一个网站(我用的是自己的www.aq36.xyz ,本地就可以,可以用localhost)然后运行up ...