本人最近通过自己动手处理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. RabbitMQ入门教程

    1.下载安装RabbitMQ windows下 先 下载Erlang 64位 其它去这里下载 http://www.erlang.org/downloads 然后 下载RabbitMQ  官网 htt ...

  2. 老李分享:MySql的insert语句的性能优化方案

    老李分享:MySql的insert语句的性能优化方案   性能优化一直是测试人员比较感兴趣的内容,poptest在培训学员的时候也加大了性能测试调优的方面的内容,而性能优化需要经验的积累,经验的积累依 ...

  3. 测试开发Python培训:抓取新浪微博抓取数据-技术篇

    测试开发Python培训:抓取新浪微博抓取数据-技术篇   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的se ...

  4. AngularJS1.X学习笔记5-加强版的表单

    大家愚人节快乐!表单是沟通服务器端和客户端的桥梁,为数据从客户端传到服务端打开了一扇大门.AngularJS增加了一些新特性,使我们能够更加方便的操作表单.OK!开始学习!学习使我快乐. 一.双向数据 ...

  5. Hibernate(三)之配置文件详解

    一.核心配置文件(hibernate.cfg.xml) <?xml version="1.0" encoding="UTF-8"?> <!DO ...

  6. Javascript删除数组中指定值的元素

    Array.prototype.remove = function(index){ if(isNaN(index) || index > this.length){return false;} ...

  7. MySQL中文全文搜索

    我们在mysql数据中可以使用match against语句解决中文全文搜索的问题 先看一个例句: SELECT * FROM v9_search WHERE `siteid`= '1' AND `t ...

  8. Linux命令的复习总结学习

    1.-------------------------linux系统介绍------------------------------------------------------- Linux是一套 ...

  9. navicat与phpmyadmin做mysql的自定义函数和事件

    自定义函数和事件是mysql一个很方便的功能,navicat在5.1以上版本就支持了自定义函数和事件,phpmyadmim不清楚. 用这个是由于一些简单的事情,没有必要去做一个服务器计划使用 接下来我 ...

  10. RabbitMQ-从基础到实战(6)— 与Spring集成

    0.目录 RabbitMQ-从基础到实战(1)- Hello RabbitMQ RabbitMQ-从基础到实战(2)- 防止消息丢失 RabbitMQ-从基础到实战(3)- 消息的交换(上) Rabb ...