package org.springside.examples.showcase.web;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 获取远程静态内容并进行展示的Servlet.
*
* 演示使用多线程安全的Apache HttpClient获取远程静态内容.
*
* 演示访问地址如下(contentUrl已经过URL编码):
* remote-content?contentUrl=http%3A%2F%2Flocalhost%3A8080%2Fshowcase%2Fimg%2Flogo.jpg
*
* @author calvin
*/
public class RemoteContentServlet extends HttpServlet {
private static final long serialVersionUID = -8483811141908827663L;
private static Logger logger = LoggerFactory.getLogger(RemoteContentServlet.class);
private HttpClient httpClient = null;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取参数
String contentUrl = request.getParameter("contentUrl");
if (StringUtils.isBlank(contentUrl)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "contentUrl parameter is required.");
}
//远程访问获取内容
HttpEntity entity = fetchContent(contentUrl);
if (entity == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, contentUrl + "is not found.");
return;
}
//设置Header
response.setContentType(entity.getContentType().getValue());
if (entity.getContentLength() > 0) {
response.setContentLength((int) entity.getContentLength());
}
//输出内容
InputStream input = entity.getContent();
OutputStream output = response.getOutputStream();
try {
//基于byte数组读取InputStream并直接写入OutputStream, 数组默认大小为4k.
IOUtils.copy(input, output);
output.flush();
} finally {
//保证Input/Output Stream的关闭.
IOUtils.closeQuietly(input);
IOUtils.closeQuietly(output);
}
}
/**
* 使用HttpClient取得内容.
*/
private HttpEntity fetchContent(String targetUrl) {
HttpGet httpGet = new HttpGet(targetUrl);
HttpContext context = new BasicHttpContext();
try {
HttpResponse remoteResponse = httpClient.execute(httpGet, context);
return remoteResponse.getEntity();
} catch (Exception e) {
logger.error("fetch remote content" + targetUrl + " error", e);
httpGet.abort();
return null;
}
}
/**
* 创建多线程安全的HttpClient实例.
*/
@Override
public void init() throws ServletException {
// Create and initialize HTTP parameters
HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params, 50);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
// Create and initialize scheme registry
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Create an HttpClient with the ThreadSafeClientConnManager.
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
httpClient = new DefaultHttpClient(cm, params);
}
/**
* 销毁HttpClient实例.
*/
@Override
public void destroy() {
if (httpClient != null) {
httpClient.getConnectionManager().shutdown();
}
}
}