首页 > 代码库 > struts2新增json返回类型,自动将action中的的成员变量转换成json字符串

struts2新增json返回类型,自动将action中的的成员变量转换成json字符串


做了一个小测试 struts2,spring,mybatis的框架,所需jar包如下:

       


新增result type:json


JsonResult.java


package com.test.xiaobc.login.server.util;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts2.ServletActionContext;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;

import com.test.xiaobc.base.action.AbstractAction;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.inject.Inject;

public class JsonResult implements Result{

	/** 继承ActionSupport中的属性 */
	protected static final Set<String> FIELDS = new HashSet<String>();
	
	private static final long serialVersionUID = 8840245761025613454L;
	
	private String defaultEncoding = "UTF-8";
	
	private Log log = LogFactory.getLog(getClass());

	private String includeProperties;
	
	private Set<String> includePropertiesSet;
	
	/**
	 * <action name="findAll" class="orderBillAction" method="findAll">
	 * 		<result name='success' type='json'>
	 *  		<param name="contentType">text/html</param>
	 * 		</result>
	 * </action>
	 */
	private String contentType;
	
	/** 序列化属性,默认为null替换为空字符串 */
	private JsonFeature feature = JsonFeature.getDefaultJsonFeature();

	/**
	 * 调用js函数名称
	 */
	private String callbackParameter;
	
    static {
		FIELDS.add("actionErrors");
		FIELDS.add("actionMessages");
		FIELDS.add("class");
		FIELDS.add("errorMessages");
		FIELDS.add("errors");
		FIELDS.add("locale");
		FIELDS.add("fieldErrors");
		FIELDS.add("texts");
		FIELDS.add("success");
		FIELDS.add("isException");
	}

	@Inject("struts.i18n.encoding")
	public void setDefaultEncoding(String val) {
		this.defaultEncoding = val;
	}
   /**
    * 
    * <p>设置编码格式utf-8</p> 
    * @date 2013-4-3 上午9:35:08
    * @return
    * @see
    */
	protected String getEncoding() {
		String encoding = this.defaultEncoding;

		if (encoding == null) {
			encoding = System.getProperty("file.encoding");
		}

		if (encoding == null) {
			encoding = "UTF-8";
		}

		return encoding;
	}

	public String getIncludeProperties() {
		return includeProperties;
	}
    /**
     * 
     * <p>拆分包含属性文件</p> 
     * @date 2013-4-3 上午9:35:39
     * @param includeProperties
     * @see
     */
	public void setIncludeProperties(String includeProperties) {
		if (includeProperties == null) {
			return;
		}
		this.includeProperties = includeProperties;
		String[] properties = this.includeProperties.split(",");
		includePropertiesSet = new HashSet<String>();
		for (String property : properties) {
			includePropertiesSet.add(property);
		}
		this.setIncludePropertiesList(includePropertiesSet);
	}

	public Set<String> getIncludePropertiesList() {
		return includePropertiesSet;
	}

	public void setIncludePropertiesList(Set<String> includePropertiesList) {
		this.includePropertiesSet = includePropertiesList;
	}

	public String getContentType() {
		return contentType;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}
	
	public String getFeature() {
        return feature.getFeature();
    }
    public void setFeature(String feature) {
    	if(StringUtils.isNotBlank(feature) && !this.feature.getFeature().equals(feature)) {
    		this.feature = new JsonFeature(feature);
    	}
    }
    /**
	 * 序列化对象成JSON
	 * 
	 * @param val
	 * @param sb
	 * @throws JsonGenerationException
	 * @throws JsonMappingException
	 * @throws IOException
	 */
	private void serialize(Object val, StringBuilder sb)
			throws JsonGenerationException, JsonMappingException, IOException {
		if (val == null) {
			sb.append(feature.doFeature()).append(",");
		} else if (val instanceof Number || val instanceof Boolean) {
			sb.append(val.toString()).append(",");
		} else if (val instanceof Date) {
			sb.append((Long) ((Date) val).getTime()).append(",");
		} else if (val instanceof Calendar) {
			sb.append((Long) ((Calendar) val).getTime().getTime()).append(",");
		} else {
			sb.append(feature.doFeature(
					JsonHelps.toString(val)
			)).append(",");
		}
	}
	
    /**
     * 
     * <p>向叶面输入json</p> 
     * @date 2013-4-3 上午9:37:10
     * @param invocation
     * @throws Exception 
     * @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)
     */
	public void execute(ActionInvocation invocation) throws Exception {
		if (log.isDebugEnabled()) {
			log.debug("begin JSONResult");
		}
		HttpServletRequest request= ServletActionContext.getRequest();
		HttpServletResponse response = ServletActionContext.getResponse();

		if (getContentType() != null) {
			response.setContentType(this.getContentType());
		} else {
			response.setContentType("application/json");
		}
		response.setCharacterEncoding(defaultEncoding);
		StringBuilder sb = new StringBuilder();
		sb.append("{");
		Object obj = invocation.getAction();
		BeanInfo ip = Introspector.getBeanInfo(obj.getClass());
		PropertyDescriptor[] pros = ip.getPropertyDescriptors();
		// 对success、isException属性特别处理
		if (obj instanceof AbstractAction) {//此处是自己创建的父类action(AbstractAction)
			PropertyDescriptor spd = new PropertyDescriptor("success",
					obj.getClass());
			Method smd = spd.getReadMethod();
			Object success = smd.invoke(obj);
			//返回的success属性名的前后都加上双引号
			sb.append("\"success\"").append(":");
			serialize(success, sb);

			PropertyDescriptor epd = new PropertyDescriptor("exception",
					obj.getClass());
			Method emd = epd.getReadMethod();
			Object isException = emd.invoke(obj);
			//返回的isException属性名的前后都加上双引号
			sb.append("\"isException\"").append(":");
			serialize(isException, sb);
		}
		for (PropertyDescriptor pro : pros) {
			if (includePropertiesSet != null && !includePropertiesSet.contains(pro.getDisplayName())) {
				continue;
			}
			Method method = pro.getReadMethod();
			if (method != null) {
				Object val = method.invoke(obj, new Object[0]);
				String proName = pro.getDisplayName();
				if (FIELDS.contains(proName)) {
					continue;
				}
				//返回的请求类的所有属性名的前后都加上双引号
				sb.append("\"");
				sb.append(pro.getDisplayName());
				sb.append("\"");
				sb.append(":");
				serialize(val, sb);
			}
		}
		String result = "";
		if (sb.length() > 1) {
			result = sb.substring(0, sb.length() - 1);
		}
		result = result.concat("}");
	    result = addCallbackIfApplicable(request, result);
		OutputStream out = response.getOutputStream();
		out.write(result.getBytes(defaultEncoding));
		out.flush();
		out.close();
	}
	
	/**
	 * 增加js方法调用
	 * @date 2012-12-5 下午3:35:43
	 * @param request
	 * @param json
	 * @return
	 * @see
	 */
	private String addCallbackIfApplicable(HttpServletRequest request, String json) {
        if ((callbackParameter != null) && (callbackParameter.length() > 0)) {
            String callbackName = request.getParameter(callbackParameter);
            if ((callbackName != null) && (callbackName.length() > 0)) {
                json = callbackName + "(" + json + ")";
            }
        }
        return json;
    }
	
	public void setCallbackParameter(String callbackParameter) {
	    this.callbackParameter = callbackParameter;
	}
	
	public String getCallbackParameter() {
        return callbackParameter;
    }
	
}

class JsonFeature {
	
	public static final String ALLOW_NULL_REPLACED_EMPTY = "ALLOW_NULL_REPLACED_EMPTY";
	
	public static final String ALLOW_NULL = "ALLOW_NULL";
	
	public static final String REGEX_NULL = "['\"]*null['\"]*";
	
	public static final String EMPTY_STRING = "\"\"";
	
	public static final String NULL_STRING = "null";
	
	static final JsonFeature defaultJsonFeature = new JsonFeature(ALLOW_NULL);
	
	private String feature;
	
	public JsonFeature(String feature) {
		this.feature = feature;
	}

	public static JsonFeature getDefaultJsonFeature() {
		return defaultJsonFeature;
	}
	
	public String getFeature() {
		return feature;
	}

	/**
	 * 根据特性返回对应的字符串
	 * 
	 * @return 字符串
	 */
	public String doFeature() {
		if (feature.equalsIgnoreCase(ALLOW_NULL_REPLACED_EMPTY)) {
			return EMPTY_STRING;
        } else {
            return NULL_STRING;
        }
	}
	
	/**
	 * 根据特性替换字符串并返回替换后的字符串
	 * 
	 * @param str 被替换的目标
	 * @return 替换后的字符串
	 */
	public String doFeature(String str) {
		if (feature.equalsIgnoreCase(ALLOW_NULL_REPLACED_EMPTY)) {
		    return str.replaceAll(REGEX_NULL, EMPTY_STRING);
		} else {
		    return str;
		}
	}

}


在struts.xml中添加result type:


	<!-- 定义一个resultType -->
		<result-types>
			<result-type name="json" class="com.test.xiaobc.login.server.util.JsonResult"></result-type>
		</result-types>



上面JsonResult.java用到一个工具类 JsonHelps.java:


package com.test.xiaobc.login.server.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;

/**
 * json工具类
 * <p style="display:none">modifyRecord</p>
 * @since
 */
public abstract class JsonHelps {
	
	/**
	 * Object序列化为json字符串
	 * @param obj
	 * @return
	 */
	public static final String toString(Object obj) {
		return JSON.toJSONString(obj, SerializerFeature.WriteMapNullValue, SerializerFeature.DisableCircularReferenceDetect);
	}
	
}

最后配置 action的返回类型:


	<action name="menu" class = "loginAction" method = "menu">
			<result name="success" type="json"/>
			<result name="error"/>
		</action>

action中有相应的成员变量,并且有get,set方法:



然后请求后前台返回字符串:



struts2新增json返回类型,自动将action中的的成员变量转换成json字符串