最近公司实现一个银行网关系统,主要目的是接收银行的结果通知,并转发到后台的支付处理集群,在同时对银行的结果通知进行存储。如果银行网关系统通知处理集群失败。则在未来一段时间内对这些数据实施重发补偿。简而言之,这样做的好处是减少掉单率,在集群遇到重大问题宕机时,也能在很大程度上挽回损失,因为存储了银行通知,有补偿机制。我负责系统的主要编码工作。废话从简,把这个系统的核心代码贴上再说。
1 接收转发类
[
java]
package com.vness.httpforward.handler;
import
java.io.ByteArrayOutputStream;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.OutputStream;
import
java.util.Iterator;
import
java.util.Map;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import com.vness.common.logger.writeLog;
import com.vness.httpforward.connector.VnHttpConnector;
/*
* author:v.tone
* time:2012.05
*/
public class VnHttpForwardHanlder {
private HttpServletRequest request; // 原有请求串
private HttpServletResponse response;
private String targetAddr; // 转发目标地址
private Map<String, Object> returnData;
private int _maxDataSize = 1024;
private int timelimit = 10;
public HttpServletRequest getRequest() {
return request;
}
public void setRequest(HttpServletRequest request) {
this.request = request;
}
public HttpServletResponse getResponse() {
return response;
}
public void setResponse(HttpServletResponse response) {
this.response = response;
}
public String getTargetAddr() {
return targetAddr;
}
public void setTargetAddr(String targetAddr) {
this.targetAddr = targetAddr;
}
public Map<?, ?> getReturnData() {
return returnData;
}
@SuppressWarnings("unchecked")
public void setReturnData(Map<?, ?> returnData) {
this.returnData = ((Map<String, Object>) returnData);
}
public int getTimelimit() {
return timelimit;
}
public void setTimelimit(int timelimit) {
this.timelimit = timelimit;
}
public VnHttpForwardHanlder(HttpServletResponse rsp,
HttpServletRequest req, String addr) {
this.request = req;
this.targetAddr = addr;
this.response = rsp;
}
public VnHttpForwardHanlder() {
}
// 转发前检查
protected boolean preCheck() {
if (this.targetAddr == null || this.targetAddr.equals("")) {
writeLog.write("dispatch_", "dispatcher address is null.");
returnData.put("ERR_CD", "0001");
return false;
}
// 请求串为空
if (this.request == null || this.request.equals("")) {
writeLog.write("dispatch_", "Entry request string:" + this.request);
returnData.put("ERR_CD", "0002");
return false;
}
return true;
}
protected byte[] receiveData() throws Exception {
byte[] data = new byte[0];
if (request.getMethod() == "GET") {
String queryStr = request.getQueryString();
if (null != queryStr) {
data = queryStr.getBytes();
}
} else {
int msgLen = request.getContentLength();
if (msgLen <= 0) {
msgLen = request.getInputStream().available();
}
// dataSize check
if (-1 != _maxDataSize) {
if (msgLen > _maxDataSize) {
returnData.put("ERR_CD", "0003");
throw new Exception("post data is too large, size="
+ msgLen);
}
}
data = new byte[msgLen];
data = InputStreamToByte(request.getInputStream());
}
// ByteBuffer buff = ByteBuffer.wrap(data);
return data;
}
private byte[] InputStreamToByte(InputStream iStrm) throws IOException {
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
int ch;
while ((ch = iStrm.read()) != -1) {
bytestream.write(ch);
}
byte imgdata[] = bytestream.toByteArray();
bytestream.close();
return imgdata;
}
@SuppressWarnings("unchecked")
public void request() {
if (!preCheck()) {
writeLog.write("dispatch_", "dispatch check error.");
return;
}
InputStream in = null;
OutputStream out = null;
try {
in = request.getInputStream();
out = response.getOutputStream();
byte[] data = receiveData();
writeLog.write("dispatch_", "dispatch datas [ " + data.toString()
+ " ]");
returnData = (Map<String, Object>) VnHttpConnector.request(
targetAddr, data, request.getMethod(), timelimit);
setResponseHeader();
String err = (String) returnData.get("ERR_CD");
if (!"0000".equalsIgnoreCase(err)) {
response.sendError(500);
return;
}
// 返回处理结果
www.atcpu.com out.write((byte[]) returnData.get(VnHttpConnector.RET_MESSAGE));
out.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (null != in) {
try {
in.close();
} catch (Exception e) {
}
}
if (null != out) {
try {
out.close();
} catch (Exception e) {
}
}
}
return;
}
private void setResponseHeader() {
if (null != returnData) {
returnData.put("ERR_CD", "0004");
return;
}
// 设置header
Map<?, ?> resHeaders = (Map<?, ?>) returnData
.get(VnHttpConnector.RET_HEAD);
if (null != resHeaders) {
// RESPONSE HEADER
Iterator<?> i = resHeaders.keySet().iterator();
String key = null;
String value = null;
while (i.hasNext()) {
key = (String) i.next();
value = (String) resHeaders.get(key);
response.setHeader(key, value);
}
}
// 设置状态
response.setStatus((Integer) returnData.get(VnHttpConnector.RET_STATUS));
}
}
2 转发实施类
[html]
package com.vness.httpforward.connector;
import
java.io.IOException;
import
java.util.HashMap;
import
java.util.Iterator;
import
java.util.Map;
import net.sf.json.JSONObject;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import com.vness.common.logger.writeLog;
/*
* author:v.tone
* time:2012.05
*/
public class VnHttpConnector {
public static final String METHOD_TYPE_GET = "GET";
public static final String METHOD_TYPE_POST = "POST";
public static final String RET_HEAD = "HEAD";
public static final String RET_STATUS = "STATUS";
public static final String RET_MESSAGE = "MESSAGE";
public static Map<String, Object> request(String url, byte[] data, String methodType,
int timeout, JSONObject header) throws HttpException, IOException {
timeout = timeout * 1000;
Map<String, Object> response = new HashMap<String, Object>();
HttpClient client = new HttpClient();
client.getParams().setSoTimeout(timeout);
client.getHttpConnectionManager().getParams().setConnectionTimeout(
timeout);
writeLog.write("dispatch_","request mothed type:"+methodType);
HttpMethod method = null;
try {
if (METHOD_TYPE_GET.equals(methodType)) {
// GET
GetMethod get = new GetMethod(url);
if (null != data ;; data.length > 0) {
get.setQueryString(new String(data));
}
method = get;
} else {
// DEFAULT POST
PostMethod post = new PostMethod(url);
if (null != data ;; data.length > 0) {
ByteArrayRequestEntity entity = new ByteArrayRequestEntity(
data);
post.setRequestEntity(entity);
}
method = post;
}
writeLog.write("dispatch_","request data."+ new String(data));
method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(0, false));
if (null != header) {
// HTTP HEADER
Iterator<?> i = header.keySet().iterator();
String key = null;
String value = null;
while (i.hasNext()) {
key = (String) i.next();
value = (String) header.get(key);
method.setRequestHeader(key, value);
}
}
writeLog.write("dispatch_","will execute send.");
int status = client.executeMethod(method);
writeLog.write("dispatch_","dispatcher return code:"+status);
response.put(RET_STATUS, status);
response.put(RET_MESSAGE, method.getResponseBody());
response.put(RET_HEAD, header2Map(method.getResponseHeaders()));
} finally {
if (null != method) {
method.releaseConnection();
}
client = null;
}
return response;
}
public static Map<?, ?> request(String url, byte[] data, String methodType,
int timeout, String jsonFmtHeaders) throws HttpException,
IOException {
return request(url, data, methodType, timeout, JSONObject
.fromObject(jsonFmtHeaders));
}
public static Map<?, ?> request(String url, byte[] data, String methodType,
int timeout) throws HttpException, IOException {
writeLog.write("dispatch_","Connector request().");
return request(url, data, methodType, timeout, (JSONObject) null);
}
private static Map<String, String> header2Map(Header[] headers) {
Map<String, String> tmp = null;
if (null != headers) {
tmp = new HashMap<String, String>();
for (Header header : headers) {
tmp.put(header.getName(), header.getValue());
}
}
return tmp;
}
}
作者 Willon_tom