在特定条件下,也许需要来定制HTTP报文通过线路传递,越过了可能使用的HTTP参数来处理非标准不兼容行为的方式。比如,对于Web爬虫,它可能需要强制HttpClient接受格式错误的响应头部信息,来抢救报文的内容。
通常插入一个自定义的报文解析器的过程或定制连接实现需要几个步骤:
提供一个自定义LineParser/LineFormatter接口实现。如果需要,实现报文解析/格式化逻辑。
class MyLineParser extends BasicLineParser { @Override public Header parseHeader( final CharArrayBuffer buffer) throws ParseException { try { return super.parseHeader(buffer); } catch (ParseException ex) { // 压制ParseException异常 return new BasicHeader("invalid", buffer.toString()); } } }提过一个自定义的OperatedClientConnection实现。替换需要自定义的默认请求/响应解析器,请求/响应格式化器。如果需要,实现不同的报文写入/读取代码。
class MyClientConnection extends DefaultClientConnection { @Override protected HttpMessageParser createResponseParser( final SessionInputBuffer buffer, final HttpResponseFactory responseFactory, final HttpParams params) { return new DefaultResponseParser(buffer, new MyLineParser(),responseFactory,params); } }为了创建新类的连接,提供一个自定义的ClientConnectionOperator接口实现。如果需要,实现不同的套接字初始化代码。
class MyClientConnectionOperator extends DefaultClientConnectionOperator { public MyClientConnectionOperator( final SchemeRegistry sr) { super(sr); } @Override public OperatedClientConnection createConnection() { return new MyClientConnection(); } }为了创建新类的连接操作,提供自定义的ClientConnectionManager接口实现。
class MyClientConnManager extends SingleClientConnManager { public MyClientConnManager( final HttpParams params, final SchemeRegistry sr) { super(params, sr); } @Override protected ClientConnectionOperator createConnectionOperator( final SchemeRegistry sr) { return new MyClientConnectionOperator(sr); } }如果它可以从给定的执行上下文中来获得,UserTokenHandler接口的默认实现是使用主类的一个实例来代表HTTP连接的状态对象。UserTokenHandler将会使用基于如NTLM或开启的客户端认证SSL会话认证模式的用户的主连接。如果二者都不可用,那么就不会返回令牌。
如果默认的不能满足它们的需要,用户可以提供一个自定义的实现: DefaultHttpClient httpclient = new DefaultHttpClient(); httpclient.setUserTokenHandler(new UserTokenHandler() { public Object getUserToken(HttpContext context) { return context.getAttribute("my-token"); } });'http.user-token':对象实例代表真实的用户标识,通常期望Principle接口的实例。
我们可以在请求被执行后,通过检查本地HTTP上下文的内容,发现是否用于执行请求的连接是有状态的。 DefaultHttpClient httpclient = new DefaultHttpClient(); HttpContext localContext = new BasicHttpContext(); HttpGet httpget = new HttpGet("http://localhost:8080/"); HttpResponse response = httpclient.execute(httpget, localContext); HttpEntity entity = response.getEntity(); if (entity != null) { entity.consumeContent(); } Object userToken = localContext.getAttribute(ClientContext.USER_TOKEN); System.out.println(userToken);