首页

分享Jfinal源码中实现JsonManager基于工厂模式管理设计实现分析(图)

标签:JSON管理,jfinal源码,自定义json,工厂模式     发布时间:2018-02-03   

一、前言

关于开源jfinal-3.0包中对于自定义com.jfinal.json.Json,并分别实现com.jfinal.json.JFinalJson、com.jfinal.json.FastJson、com.jfinal.json.Jackson、com.jfinal.json.MixedJson及通过各自工厂类JFinalJsonFactory、FastJsonFactory、JacksonFactory及MixedJsonFactory,最后通过JsonManager进行统一管理,如下图所示

分享Jfinal源码中实现JsonManager基于工厂模式管理设计实现分析(图)

二、源码说明

1.Json类

package com.jfinal.json;@b@@b@import com.jfinal.kit.StrKit;@b@@b@/**@b@ * json string 与 object 互转抽象@b@ */@b@public abstract class Json {@b@	@b@	private static IJsonFactory defaultJsonFactory = new JFinalJsonFactory();@b@ @b@	private static String defaultDatePattern = null;@b@ @b@	protected String datePattern = null;@b@	@b@	static void setDefaultJsonFactory(IJsonFactory defaultJsonFactory) {@b@		if (defaultJsonFactory == null) {@b@			throw new IllegalArgumentException("defaultJsonFactory can not be null.");@b@		}@b@		Json.defaultJsonFactory = defaultJsonFactory;@b@	}@b@	@b@	static void setDefaultDatePattern(String defaultDatePattern) {@b@		if (StrKit.isBlank(defaultDatePattern)) {@b@			throw new IllegalArgumentException("defaultDatePattern can not be blank.");@b@		}@b@		Json.defaultDatePattern = defaultDatePattern;@b@	}@b@	@b@	public Json setDatePattern(String datePattern) {@b@		if (StrKit.isBlank(datePattern)) {@b@			throw new IllegalArgumentException("datePattern can not be blank.");@b@		}@b@		this.datePattern = datePattern;@b@		return this;@b@	}@b@	@b@	public String getDatePattern() {@b@		return datePattern;@b@	}@b@	@b@	public String getDefaultDatePattern() {@b@		return defaultDatePattern;@b@	}@b@	@b@	public static Json getJson() {@b@		return defaultJsonFactory.getJson();@b@	}@b@	@b@	public abstract String toJson(Object object);@b@	@b@	public abstract <T> T parse(String jsonString, Class<T> type);@b@}

2.FastJson.java、Jackson.java、JFinalJson.java、MixedJsonFactory.java

package com.jfinal.json;@b@@b@import com.alibaba.fastjson.JSON;@b@import com.alibaba.fastjson.serializer.SerializerFeature;@b@@b@/**@b@ * Json 转换 fastjson 实现.@b@ */@b@public class FastJson extends Json {@b@	@b@	public static FastJson getJson() {@b@		return new FastJson();@b@	}@b@	@b@	public String toJson(Object object) {@b@		// 优先使用对象级的属性 datePattern, 然后才是全局性的 defaultDatePattern@b@		String dp = datePattern != null ? datePattern : getDefaultDatePattern();@b@		if (dp == null) {@b@			return JSON.toJSONString(object);@b@		} else {@b@			return JSON.toJSONStringWithDateFormat(object, dp, SerializerFeature.WriteDateUseDateFormat);	// return JSON.toJSONString(object, SerializerFeature.WriteDateUseDateFormat);@b@		}@b@	}@b@	@b@	public <T> T parse(String jsonString, Class<T> type) {@b@		return JSON.parseObject(jsonString, type);@b@	}@b@}
import java.text.SimpleDateFormat;@b@import com.fasterxml.jackson.annotation.JsonInclude.Include;@b@import com.fasterxml.jackson.databind.ObjectMapper;@b@@b@/**@b@ * Json 转换 jackson 实现.@b@ * @b@ * json 到 java 类型转换规则: http://wiki.fasterxml.com/JacksonInFiveMinutes@b@ * JSON TYPE				JAVA TYPE@b@ * object					LinkedHashMap<String,Object>@b@ * array					ArrayList<Object>@b@ * string					String@b@ * number (no fraction)		Integer, Long or BigInteger (smallest applicable)@b@ * number (fraction)		Double (configurable to use BigDecimal)@b@ * true|false				Boolean@b@ * null						null@b@ */@b@public class Jackson extends Json {@b@	@b@	// Jackson 生成 json 的默认行为是生成 null value,可设置此值全局改变默认行为@b@	private static boolean defaultGenerateNullValue = true;@b@	@b@	// generateNullValue 通过设置此值,可临时改变默认生成 null value 的行为@b@	protected Boolean generateNullValue = null;@b@	@b@	protected ObjectMapper objectMapper = new ObjectMapper();@b@	@b@	public static void setDefaultGenerateNullValue(boolean defaultGenerateNullValue) {@b@		Jackson.defaultGenerateNullValue = defaultGenerateNullValue;@b@	}@b@	@b@	public Jackson setGenerateNullValue(boolean generateNullValue) {@b@		this.generateNullValue = generateNullValue;@b@		return this;@b@	}@b@	@b@	/**@b@	 * 通过获取 ObjectMapper 进行更个性化设置,满足少数特殊情况@b@	 */@b@	public ObjectMapper getObjectMapper() {@b@		return objectMapper;@b@	}@b@	@b@	public static Jackson getJson() {@b@		return new Jackson();@b@	}@b@	@b@	public String toJson(Object object) {@b@		try {@b@			// 优先使用对象级的属性 datePattern, 然后才是全局性的 defaultDatePattern@b@			String dp = datePattern != null ? datePattern : getDefaultDatePattern();@b@			if (dp != null) {@b@				objectMapper.setDateFormat(new SimpleDateFormat(dp));@b@			}@b@			@b@			// 优先使用对象属性 generateNullValue,决定转换 json时是否生成 null value@b@			Boolean pnv = generateNullValue != null ? generateNullValue : defaultGenerateNullValue;@b@			if (pnv == false) {@b@				objectMapper.setSerializationInclusion(Include.NON_NULL);@b@			}@b@			@b@			return objectMapper.writeValueAsString(object);@b@		} catch (Exception e) {@b@			throw e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e);@b@		}@b@	}@b@	@b@	public <T> T parse(String jsonString, Class<T> type) {@b@		try {@b@			return objectMapper.readValue(jsonString, type);@b@		} catch (Exception e) {@b@			throw e instanceof RuntimeException ? (RuntimeException)e : new RuntimeException(e);@b@		}@b@	}@b@}
package com.jfinal.json;@b@@b@import java.lang.reflect.Array;@b@import java.lang.reflect.Method;@b@import java.text.SimpleDateFormat;@b@import java.util.ArrayList;@b@import java.util.Collection;@b@import java.util.Collections;@b@import java.util.Enumeration;@b@import java.util.HashMap;@b@import java.util.Iterator;@b@import java.util.List;@b@import java.util.Map;@b@import com.jfinal.kit.StrKit;@b@import com.jfinal.plugin.activerecord.Model;@b@import com.jfinal.plugin.activerecord.Record;@b@@b@/**@b@ * Json 转换 JFinal 实现.@b@ * @b@ * json 到 java 类型转换规则:@b@ * string			java.lang.String@b@ * number			java.lang.Number@b@ * true|false		java.lang.Boolean@b@ * null				null@b@ * array			java.util.List@b@ * object			java.util.Map@b@ */@b@@SuppressWarnings({"rawtypes", "unchecked"})@b@public class JFinalJson extends Json {@b@	@b@	private static int defaultConvertDepth = 15;@b@	@b@	protected int convertDepth = defaultConvertDepth;@b@	protected String timestampPattern = "yyyy-MM-dd HH:mm:ss";@b@	protected String datePattern = "yyyy-MM-dd";@b@	@b@	/**@b@	 * 设置全局性默认转换深度@b@	 */@b@	public static void setDefaultConvertDepth(int defaultConvertDepth) {@b@		if (defaultConvertDepth < 2) {@b@			throw new IllegalArgumentException("defaultConvertDepth depth can not less than 2.");@b@		}@b@		JFinalJson.defaultConvertDepth = defaultConvertDepth;@b@	}@b@	@b@	public JFinalJson setConvertDepth(int convertDepth) {@b@		if (convertDepth < 2) {@b@			throw new IllegalArgumentException("convert depth can not less than 2.");@b@		}@b@		this.convertDepth = convertDepth;@b@		return this;@b@	}@b@	@b@	public JFinalJson setTimestampPattern(String timestampPattern) {@b@		if (StrKit.isBlank(timestampPattern)) {@b@			throw new IllegalArgumentException("timestampPattern can not be blank.");@b@		}@b@		this.timestampPattern = timestampPattern;@b@		return this;@b@	}@b@	@b@	public Json setDatePattern(String datePattern) {@b@		if (StrKit.isBlank(datePattern)) {@b@			throw new IllegalArgumentException("datePattern can not be blank.");@b@		}@b@		this.datePattern = datePattern;@b@		return this;@b@	}@b@	@b@	public static JFinalJson getJson() {@b@		return new JFinalJson();@b@	}@b@	@b@	protected String mapToJson(Map map, int depth) {@b@		if(map == null) {@b@			return "null";@b@		}@b@        StringBuilder sb = new StringBuilder();@b@        boolean first = true;@b@		Iterator iter = map.entrySet().iterator();@b@		@b@        sb.append('{');@b@		while(iter.hasNext()){@b@            if(first)@b@                first = false;@b@            else@b@                sb.append(',');@b@            @b@			Map.Entry entry = (Map.Entry)iter.next();@b@			toKeyValue(String.valueOf(entry.getKey()),entry.getValue(), sb, depth);@b@		}@b@        sb.append('}');@b@		return sb.toString();@b@	}@b@	@b@	protected String toKeyValue(String key, Object value, StringBuilder sb, int depth){@b@		sb.append('\"');@b@        if(key == null)@b@            sb.append("null");@b@        else@b@            escape(key, sb);@b@		sb.append('\"').append(':');@b@		@b@		sb.append(toJson(value, depth));@b@		@b@		return sb.toString();@b@	}@b@	@b@	protected String iteratorToJson(Iterator iter, int depth) {@b@        boolean first = true;@b@        StringBuilder sb = new StringBuilder();@b@        @b@        sb.append('[');@b@		while(iter.hasNext()){@b@            if(first)@b@                first = false;@b@            else@b@                sb.append(',');@b@            @b@			Object value = iter.next();@b@			if(value == null){@b@				sb.append("null");@b@				continue;@b@			}@b@			sb.append(toJson(value, depth));@b@		}@b@        sb.append(']');@b@		return sb.toString();@b@	}@b@	@b@	/**@b@	 * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).@b@	 */@b@	protected String escape(String s) {@b@		if(s == null)@b@			return null;@b@        StringBuilder sb = new StringBuilder();@b@        escape(s, sb);@b@        return sb.toString();@b@    }@b@	@b@	protected void escape(String s, StringBuilder sb) {@b@		for(int i=0; i<s.length(); i++){@b@			char ch = s.charAt(i);@b@			switch(ch){@b@			case '"':@b@				sb.append("\\\"");@b@				break;@b@			case '\\':@b@				sb.append("\\\\");@b@				break;@b@			case '\b':@b@				sb.append("\\b");@b@				break;@b@			case '\f':@b@				sb.append("\\f");@b@				break;@b@			case '\n':@b@				sb.append("\\n");@b@				break;@b@			case '\r':@b@				sb.append("\\r");@b@				break;@b@			case '\t':@b@				sb.append("\\t");@b@				break;@b@			//case '/':@b@			//	sb.append("\\/");@b@			//	break;@b@			default:@b@				if((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') || (ch >= '\u2000' && ch <= '\u20FF')) {@b@					String str = Integer.toHexString(ch);@b@					sb.append("\\u");@b@					for(int k=0; k<4-str.length(); k++) {@b@						sb.append('0');@b@					}@b@					sb.append(str.toUpperCase());@b@				}@b@				else{@b@					sb.append(ch);@b@				}@b@			}@b@		}@b@	}@b@	@b@	public String toJson(Object object) {@b@		return toJson(object, convertDepth);@b@	}@b@	@b@	protected String toJson(Object value, int depth) {@b@		if(value == null || (depth--) < 0)@b@			return "null";@b@		@b@		if(value instanceof String)@b@			return "\"" + escape((String)value) + "\"";@b@		@b@		if(value instanceof Double){@b@			if(((Double)value).isInfinite() || ((Double)value).isNaN())@b@				return "null";@b@			else@b@				return value.toString();@b@		}@b@		@b@		if(value instanceof Float){@b@			if(((Float)value).isInfinite() || ((Float)value).isNaN())@b@				return "null";@b@			else@b@				return value.toString();@b@		}@b@		@b@		if(value instanceof Number)@b@			return value.toString();@b@		@b@		if(value instanceof Boolean)@b@			return value.toString();@b@		@b@		if (value instanceof java.util.Date) {@b@			if (value instanceof java.sql.Timestamp) {@b@				return "\"" + new SimpleDateFormat(timestampPattern).format(value) + "\"";@b@			}@b@			if (value instanceof java.sql.Time) {@b@				return "\"" + value.toString() + "\"";@b@			}@b@			// 优先使用对象级的属性 datePattern, 然后才是全局性的 defaultDatePattern@b@			String dp = datePattern != null ? datePattern : getDefaultDatePattern();@b@			if (dp != null) {@b@				return "\"" + new SimpleDateFormat(dp).format(value) + "\"";@b@			} else {@b@				return "" + ((java.util.Date)value).getTime();@b@			}@b@		}@b@		@b@		if(value instanceof Collection) {@b@			return iteratorToJson(((Collection)value).iterator(), depth);@b@		}@b@		@b@		if(value instanceof Map) {@b@			return mapToJson((Map)value, depth);@b@		}@b@		@b@		String result = otherToJson(value, depth);@b@		if (result != null)@b@			return result;@b@		@b@		// 类型无法处理时当作字符串处理,否则ajax调用返回时js无法解析@b@		// return value.toString();@b@		return "\"" + escape(value.toString()) + "\"";@b@	}@b@	@b@	protected String otherToJson(Object value, int depth) {@b@		if (value instanceof Character) {@b@			return "\"" + escape(value.toString()) + "\"";@b@		}@b@		@b@		if (value instanceof Model) {@b@			Map map = com.jfinal.plugin.activerecord.CPI.getAttrs((Model)value);@b@			return mapToJson(map, depth);@b@		}@b@		if (value instanceof Record) {@b@			Map map = ((Record)value).getColumns();@b@			return mapToJson(map, depth);@b@		}@b@		if (value.getClass().isArray()) {@b@			int len = Array.getLength(value);@b@			List<Object> list = new ArrayList<Object>(len);@b@			for (int i=0; i<len; i++) {@b@				list.add(Array.get(value, i));@b@			}@b@			return iteratorToJson(list.iterator(), depth);@b@		}@b@		if (value instanceof Iterator) {@b@			return iteratorToJson((Iterator)value, depth);@b@		}@b@		if (value instanceof Enumeration) {@b@			ArrayList<?> list = Collections.list((Enumeration<?>)value);@b@			return iteratorToJson(list.iterator(), depth);@b@		}@b@		if (value instanceof Enum) {@b@			return "\"" + ((Enum)value).toString() + "\"";@b@		}@b@		@b@		return beanToJson(value, depth);@b@	}@b@	@b@	protected String beanToJson(Object model, int depth) {@b@		Map map = new HashMap();@b@		Method[] methods = model.getClass().getMethods();@b@		for (Method m : methods) {@b@			String methodName = m.getName();@b@			int indexOfGet = methodName.indexOf("get");@b@			if (indexOfGet == 0 && methodName.length() > 3) {	// Only getter@b@				String attrName = methodName.substring(3);@b@				if (!attrName.equals("Class")) {				// Ignore Object.getClass()@b@					Class<?>[] types = m.getParameterTypes();@b@					if (types.length == 0) {@b@						try {@b@							Object value = m.invoke(model);@b@							map.put(StrKit.firstCharToLowerCase(attrName), value);@b@						} catch (Exception e) {@b@							throw new RuntimeException(e.getMessage(), e);@b@						}@b@					}@b@				}@b@			}@b@			else {@b@               int indexOfIs = methodName.indexOf("is");@b@               if (indexOfIs == 0 && methodName.length() > 2) {@b@                  String attrName = methodName.substring(2);@b@                  Class<?>[] types = m.getParameterTypes();@b@                  if (types.length == 0) {@b@                      try {@b@                          Object value = m.invoke(model);@b@                          map.put(StrKit.firstCharToLowerCase(attrName), value);@b@                      } catch (Exception e) {@b@                          throw new RuntimeException(e.getMessage(), e);@b@                      }@b@                  }@b@               }@b@            }@b@		}@b@		return mapToJson(map, depth);@b@	}@b@	@b@	public <T> T parse(String jsonString, Class<T> type) {@b@		throw new RuntimeException("jfinal " + com.jfinal.core.Const.JFINAL_VERSION + @b@		"默认 json 实现暂不支持 json 到 object 的转换,建议使用 active recrord 的 Generator 生成 base model," +@b@		"再通过 me.setJsonFactory(new JacksonFactory()) 来支持");@b@	}@b@}
 class MixedJson extends Json {@b@@b@		private static JFinalJson jFinalJson = JFinalJson.getJson();@b@		private static FastJson fastJson = FastJson.getJson();@b@@b@		public String toJson(Object object) {@b@			return jFinalJson.toJson(object);@b@		}@b@@b@		public <T> T parse(String jsonString, Class<T> type) {@b@			return fastJson.parse(jsonString, type);@b@		}@b@	}

2.工厂接口及实现工厂类

package com.jfinal.json;@b@@b@public interface IJsonFactory {@b@	Json getJson();@b@}
package com.jfinal.json;@b@ @b@public class FastJsonFactory implements IJsonFactory {@b@	@b@	private static final FastJsonFactory me = new FastJsonFactory();@b@	@b@	public static FastJsonFactory me() {@b@		return me;@b@	}@b@	@b@	public Json getJson() {@b@		return new FastJson();@b@	}@b@}
package com.jfinal.json;@b@@b@public class JacksonFactory implements IJsonFactory {@b@	@b@	private static final JacksonFactory me = new JacksonFactory();@b@	@b@	public static JacksonFactory me() {@b@		return me;@b@	}@b@	@b@	public Json getJson() {@b@		return new Jackson();@b@	}@b@}
package com.jfinal.json;@b@@b@public class JacksonFactory implements IJsonFactory {@b@	@b@	private static final JacksonFactory me = new JacksonFactory();@b@	@b@	public static JacksonFactory me() {@b@		return me;@b@	}@b@	@b@	public Json getJson() {@b@		return new Jackson();@b@	}@b@}
package com.jfinal.json;@b@@b@import com.jfinal.json.FastJson;@b@import com.jfinal.json.IJsonFactory;@b@import com.jfinal.json.JFinalJson;@b@import com.jfinal.json.Json;@b@ @b@public class MixedJsonFactory implements IJsonFactory {@b@	@b@	private static final MixedJsonFactory me = new MixedJsonFactory();@b@	@b@	public static MixedJsonFactory me() {@b@		return me;@b@	}@b@@b@	private static MixedJson mixedJson =  new MixedJson();@b@@b@	public Json getJson() {@b@		return mixedJson;@b@	}@b@}

3.JsonManager类

package com.jfinal.json;@b@ @b@public class JsonManager {@b@	@b@	private static final JsonManager me = new JsonManager();@b@	@b@	private JsonManager() {}@b@	@b@	public static JsonManager me() {@b@		return me;@b@	}@b@	@b@	public void setDefaultJsonFactory(IJsonFactory defaultJsonFactory) {@b@		Json.setDefaultJsonFactory(defaultJsonFactory);@b@	}@b@	@b@	public void setDefaultDatePattern(String defaultDatePattern) {@b@		Json.setDefaultDatePattern(defaultDatePattern);@b@	}@b@}