com.logicbus.backend.message.JsonMessage Maven / Gradle / Ivy
package com.logicbus.backend.message;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import com.anysoft.util.compress.Compressor;
import com.anysoft.util.compress.compressor.GZIP;
import com.logicbus.backend.message.tools.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alogic.idnote.IdNote;
import com.anysoft.util.IOTools;
import com.anysoft.util.JsonTools;
import com.anysoft.util.PropertiesConstants;
import com.anysoft.util.Settings;
import com.logicbus.backend.Context;
/**
* 基于JSON的消息协议
* @author duanyy
*
* @since 1.2.1
*
* @version 1.4.0 [20141117 duanyy]
* - Message被改造为接口
*
* @version 1.6.1.1 [20141118 duanyy]
* - 修正没有读入的情况下,root为空的bug
* - MessageDoc暴露InputStream和OutputStream
*
* @version 1.6.1.2 [20141118 duanyy]
* - 支持MessageDoc的Raw数据功能
*
* @version 1.6.2.1 [20141223 duanyy]
* - 增加对Comet的支持
*
* @version 1.6.3.14 [20150409 duanyy]
* - 修正formContentType所取的参数名问题,笔误
*
* @version 1.6.5.6 [20160523 duanyy]
* - 淘汰MessageDoc,采用Context替代
* - 增加getContentType和getContentLength
*
* @version 1.6.7.9 [20170201 duanyy]
* - 采用SLF4j日志框架输出日志
*
* @version 1.6.7.15 [20170221 duanyy]
* - 输出时设置Content-Length以便支持keepalive
*
* @version 1.6.11.22 [duanyy 20180314]
* - 支持按指定jsonpath路径来输出文档
*
* @version 1.6.11.62 [duanyy 20180928]
* - 删除冗余的代码
*
* @version 1.6.12.8 [20181121 duanyy]
* - 关闭缺省的jsonp支持
*
* @version 1.6.12.13 [20181213 duanyy]
* - 增加code字段的拦截,通过idnote框架展现错误reason
*
* @version 1.6.12.19 [20190118 duanyy]
* - 对文档返回的主机信息做掩码处理
*
* @version 1.6.13.21 [20201021 duanyy]
* - 支持gzip压缩
*
* @version 1.6.14.2 [20210316 duanyy]
* - 移植逻辑到Tools框架
* - 增加输入payload的摘要功能
*/
public class JsonMessage implements Message {
protected static final Logger logger = LoggerFactory.getLogger(JsonMessage.class);
protected static String formContentType = "application/x-www-form-urlencoded";
protected static GzipTool gzipTool = null;
protected static JsonFactory jsonFactory = null;
protected static HostMask hostMask = null;
protected static IdNoteTool idnoteTool = null;
protected static ContentDigest contentDigest = null;
static {
gzipTool = Settings.getToolkit(GzipTool.class);
jsonFactory = Settings.getToolkit(JsonFactory.class);
hostMask = Settings.getToolkit(HostMask.class);
idnoteTool = Settings.getToolkit(IdNoteTool.class);
contentDigest = Settings.getToolkit(ContentDigest.class);
formContentType = PropertiesConstants.getString(Settings.get(),
"http.formContentType", "application/x-www-form-urlencoded");
}
/**
* Json结构的根节点
*/
protected Map root = null;
private long contentLength = 0;
private String contentType = "application/json;charset=utf-8";
private String outputPath = null;
/**
* 获取JSON结构的根节点
*
* @return JSON结构的根节点
*/
public Map getRoot(){
return root;
}
@Override
public String toString(){
return jsonFactory.toJsonString(root);
}
@Override
public String getContentType() {
return contentType;
}
@Override
public long getContentLength() {
return contentLength;
}
/**
* 设置输出目录
* @param path jsonPath
*/
public void setOutputPath(String path){
this.outputPath = path;
}
@SuppressWarnings("unchecked")
@Override
public void init(Context ctx) {
boolean gzipEnable = gzipTool.isRequestGzipEnable(ctx);
String data = null;
{
byte [] inputData = ctx.getRequestRaw();
if (inputData != null){
try {
if (gzipEnable){
inputData = gzipTool.decompress(ctx,inputData);
}
data = new String(inputData,ctx.getEncoding());
}catch (Exception ex){
}
}
}
if (data == null){
//当客户端通过form来post的时候,Message不去读取输入流。
String _contentType = ctx.getRequestContentType();
if (_contentType == null || !_contentType.startsWith(formContentType)){
InputStream in = null;
try {
in = ctx.getInputStream();
if (gzipEnable){
in = gzipTool.getInputStream(ctx,in);
}
data = Context.readFromInputStream(in, ctx.getEncoding());
}catch (Exception ex){
logger.error("Error when reading data from inputstream",ex);
}finally{
IOTools.close(in);
}
}
}
if (contentDigest != null) {
contentDigest.digest(ctx, data);
}
if (StringUtils.isNotEmpty(data)){
contentLength += data.getBytes().length;
Object rootObj = jsonFactory.fromJsonString(data);
if (rootObj instanceof Map){
root = (Map)rootObj;
}
}
if (root == null){
root = new HashMap();
}
contentType = "application/json;charset=" + ctx.getEncoding();
}
@Override
public void finish(Context ctx,boolean closeStream) {
Map _root = getRoot();
JsonTools.setString(_root, "code", ctx.getReturnCode());
IdNote idnote = idnoteTool.getIdNote(ctx.getReturnCode());
if (idnote != null){
JsonTools.setString(_root, "reason", idnote.getNote());
JsonTools.setString(_root, "advise", ctx.getReason());
}else{
JsonTools.setString(_root, "reason", ctx.getReason());
}
JsonTools.setString(_root, "duration", String.valueOf(ctx.getDuration()));
JsonTools.setString(_root, "host", hostMask.getHost(ctx.getHost()));
JsonTools.setString(_root, "serial", ctx.getGlobalSerial());
OutputStream out = null;
try {
Object outputObject = _root;
try {
outputObject = jsonFactory.readJsonPath(outputObject,outputPath);
}catch (Exception ex){
logger.error("Can not location jsonpath " + outputPath);
}
outputObject = outputObject == null ? _root : outputObject;
String data = jsonFactory.toJsonString(outputObject);
data = jsonFactory.wrapJsonp(ctx,data);
out = ctx.getOutputStream();
ctx.setResponseContentType(contentType);
byte [] bytes = data.getBytes(ctx.getEncoding());
if (gzipTool.isResponseGzipEnable(ctx)){
bytes = gzipTool.compress(ctx,bytes);
}
contentLength += bytes.length;
ctx.setResponseContentLength(bytes.length);
Context.writeToOutpuStream(out, bytes);
out.flush();
}catch (Exception ex){
logger.error("Error when writing data to outputstream",ex);
}finally{
if (closeStream) {
IOTools.close(out);
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy