import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.SocketTimeoutException; import java.net.URL; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.springframework.beans.factory.InitializingBean; public class HttpClient implements InitializingBean { private static final String DEBUG_HTTP_RESULT = "Result of calling http service: "; private static final String ERROR_DEFAULT_HTTP = "Failed to call HTTP Service at "; private static final String ERROR_CONNECTION = "Failed to connect to "; private static final String ERROR_TIMEOUT = "Timeout occured connecting to "; private static final String ERROR_UNKNOWN_RESPONSE_CODE_RECIEVED = "Unknown Response Code %s recieved: "; private static final String ERROR_INTERNAL_ERROR = "Internal Server Error: "; private static final String ERROR_BAD_REQUEST = "Bad Request: "; private static final String URL_FORMAT = "%s://%s:%s"; private static final String REQUEST_METHOD_POST = "POST"; private static final Logger LOGGER = Logger.getLogger(HttpClient.class); private String m_hostname = ""; private String m_protocol = ""; private String m_port = ""; //default is set to 10 seconds private int m_timeoutMs = 10000; private URL endpoint = null; /** * Must be called after connection params are set * @throws MalformedURLException */ public void afterPropertiesSet() throws MalformedURLException { endpoint = new URL(getHttpEndpoint()); } public byte[] send(byte[] input, int numRetries) throws DataTransportException { byte[] payload = null; for (int i=1; i<=numRetries; i++) { try { //create a new connection for each request HttpURLConnection connection = (HttpURLConnection) endpoint.openConnection(); connection.setReadTimeout(m_timeoutMs); connection.setConnectTimeout(m_timeoutMs); connection.setRequestMethod(REQUEST_METHOD_POST); connection.setDoInput(true); connection.setDoOutput(true); //write our request to the post body using an outputstream DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); wr.write(input); wr.flush(); wr.close(); //check for success or failure handleResponseCodes(connection); //how big is our response int length = connection.getContentLength(); LOGGER.debug("bytes received: " + length); //read response payload = readPayload(connection, length); break; } catch (ConnectException ce) { hrowDataTransportException(..........) } catch (SocketTimeoutException ste) { throwDataTransportException(.....); } catch (Throwable t) { throwDataTransportException(i, numRetries, EventLogIds.HTTP_DEFAULT_ERROR, ERROR_DEFAULT_HTTP + endpoint, t); } } return payload; } /** * Logs error message and throws exception * @param errorCode * @param errorMessage * @param e * @throws CommonHotelException */ private void throwDataTransportException(int currentAttempt, int totalAttempt, int errorCode, String errorMessage, Throwable e) throws DataTransportException { if (currentAttempt==totalAttempt) { throw new DataTransportException(errorMessage, errorCode, e); } else { String message = String.format("Http Client attempt %d of %d failed: %s", currentAttempt, totalAttempt, errorMessage); EventLogEntry.logEvent(LOGGER, Level.WARN, errorCode, message, e); } } /** * Checks http error code and message * @param errorCode * @param errorMessage * @param e * @throws IOException * @throws CommonHotelException */ private void throwDataTransportException(int errorCode, String errorMessage, Throwable e, InputStream errorStream) throws DataTransportException, IOException { //try to read from stderr StringBuilder builder = new StringBuilder(errorMessage); builder.append(". Details: "); if(errorStream != null) { BufferedReader in = null; try { in = new BufferedReader(new InputStreamReader(errorStream)); String line = in.readLine(); while(line != null) { builder.append(line); line = in.readLine(); } } catch (IOException e1) { LOGGER.warn(Utilities.getExceptionStackTrace(e1)); } finally { if(in != null) { in.close(); } } } throw new DataTransportException(builder.toString(), errorCode, e); } private void handleResponseCodes(HttpURLConnection connection) throws DataTransportException, IOException { int responseCode = connection.getResponseCode(); String responseMessage = connection.getResponseMessage(); InputStream errorStream = connection.getErrorStream(); switch (responseCode) { case HttpURLConnection.HTTP_OK: EventLogEntry.logEvent(LOGGER, Level.DEBUG, EventLogIds.HTTP_TRANSFER_SUCCESS, DEBUG_HTTP_RESULT + responseMessage); break; case HttpURLConnection.HTTP_BAD_REQUEST: throwDataTransportException(EventLogIds.HTTP_BAD_REQUEST, ERROR_BAD_REQUEST + responseMessage, null, errorStream); case HttpURLConnection.HTTP_INTERNAL_ERROR: throwDataTransportException(EventLogIds.HTTP_INTERNAL_SERVER_ERROR, ERROR_INTERNAL_ERROR + responseMessage, null, errorStream); default: String message = String.format(ERROR_UNKNOWN_RESPONSE_CODE_RECIEVED, responseCode); throwDataTransportException(EventLogIds.HTTP_DEFAULT_ERROR, message + responseMessage, null, errorStream); } } /** * reads all bytes in the response * * @param connection * @param length * must specify length of expected payload * @throws IOException */ private byte[] readPayload(HttpURLConnection connection, int length) throws IOException { byte[] payload = new byte[length]; //read all bytes //TODO: need a way to break loop in error cases InputStream is = null; try{ is = connection.getInputStream(); int bytesRemaining = length; while( bytesRemaining > 0) { int off = length - bytesRemaining; int avail = is.available(); int bytesRead = is.read(payload, off, avail); bytesRemaining -= bytesRead; } } finally{ if(is != null) { is.close(); } } return payload; } private String getHttpEndpoint() { return String.format(URL_FORMAT, m_protocol, m_hostname, m_port); } /** * Set hostname we are sending to * @param hostname */ public void setHostname(String hostname) { m_hostname = hostname; } /** * Set protocol. eg. "http" * @param protocol */ public void setProtocol(String protocol) { m_protocol = protocol; } /** * Set port * @param port */ public void setPort(String port) { m_port = port; } public void setTimeoutMs(int timeoutMs) { m_timeoutMs = timeoutMs; } }
使用HttpConnection发送Post请求
这是在项目中运用HttpURLConnection发送post请求(我们项目中是用来发送soap),完整的处理,包括如何处理异常。需要注意一个小地方,我们把创建URL放在afterPropertiesSet方法中,是因为这个类只是为下游某一个特定的Service服务的,如果要作用共用的,不能这样做。
猜你喜欢
转载自cyril0513.iteye.com/blog/1764728
今日推荐
周排行