return none java struts2,struts2乱码与json插件[转]

在前一篇中 ,讲到了解决在struts2中出现的一点点乱码问题,就想看看json中的数据处理方式.由struts2的处理流程来看,主要处理result的代码如下在defaultActionInvocation中:

Java代码 icon_copy.gif

privatevoidexecuteResult()throwsException {

result = createResult();

String timerKey ="executeResult: "+getResultCode();

try{

UtilTimerStack.push(timerKey);

if(result !=null) {

result.execute(this);

}elseif(resultCode !=null&& !Action.NONE.equals(resultCode)) {

thrownewConfigurationException("No result defined for action "+ getAction().getClass().getName()

+" and result "+ getResultCode(), proxy.getConfig());

}else{

if(LOG.isDebugEnabled()) {

LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());

}

}

}finally{

UtilTimerStack.pop(timerKey);

}

}

private void executeResult() throws Exception {

result = createResult();

String timerKey = "executeResult: "+getResultCode();

try {

UtilTimerStack.push(timerKey);

if (result != null) {

result.execute(this);

} else if (resultCode != null && !Action.NONE.equals(resultCode)) {

throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()

+ " and result " + getResultCode(), proxy.getConfig());

} else {

if (LOG.isDebugEnabled()) {

LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());

}

}

} finally {

UtilTimerStack.pop(timerKey);

}

}

如上所示,result就是返回的result,而resultCode就是我们通用的String返回类型了.而json插件中,采用默认值Action.Success来得到json类型,而在result中处理,即调用上面的result.invoke(this).json中的主要处理代码如下(省略中间一些代码):

Java代码 icon_copy.gif

publicvoidexecute(ActionInvocation invocation)throwsException {

ActionContext actionContext = invocation.getInvocationContext();

HttpServletRequest request = (HttpServletRequest) actionContext

.get(StrutsStatics.HTTP_REQUEST);

HttpServletResponse response = (HttpServletResponse) actionContext

.get(StrutsStatics.HTTP_RESPONSE);

try{

String json;

Object rootObject;

if(this.enableSMD) {

//generate SMD

rootObject =this.writeSMD(invocation);

}else{

// generate JSON

if(this.root !=null) {

ValueStack stack = invocation.getStack();

rootObject = stack.findValue(this.root);

}else{

rootObject = invocation.getAction();

}

}

json = JSONUtil

.serialize(rootObject,this.excludeProperties, ignoreHierarchy, enumAsBean);

booleanwriteGzip = enableGZIP && JSONUtil.isGzipInRequest(request);

JSONUtil.writeJSONToResponse(response,this.defaultEncoding,

isWrapWithComments(), json,false, writeGzip);

}catch(IOException exception) {

log.error(exception);

throwexception;

}

}

public void execute(ActionInvocation invocation) throws Exception {

ActionContext actionContext = invocation.getInvocationContext();

HttpServletRequest request = (HttpServletRequest) actionContext

.get(StrutsStatics.HTTP_REQUEST);

HttpServletResponse response = (HttpServletResponse) actionContext

.get(StrutsStatics.HTTP_RESPONSE);

try {

String json;

Object rootObject;

if (this.enableSMD) {

//generate SMD

rootObject = this.writeSMD(invocation);

} else {

// generate JSON

if (this.root != null) {

ValueStack stack = invocation.getStack();

rootObject = stack.findValue(this.root);

} else {

rootObject = invocation.getAction();

}

}

json = JSONUtil

.serialize(rootObject, this.excludeProperties, ignoreHierarchy, enumAsBean);

boolean writeGzip = enableGZIP && JSONUtil.isGzipInRequest(request);

JSONUtil.writeJSONToResponse(response, this.defaultEncoding,

isWrapWithComments(), json, false, writeGzip);

} catch (IOException exception) {

log.error(exception);

throw exception;

}

}

可以看出,json插件的功能(在处理json上),就是将invocation中的action对象转化成json对象,再输出到页面上.

在上面的应用上来看,用json插件必须注册json的resultType,而且,返回类型一定是json,也就是说,你必须给每一个json调用定义一个json的返回类型,而实际上这个类型就是转向jsonResult上,和一般的调用不一样,它不返回任何视图.即json这个返回类型感觉上完全是多余的,除了标明是json返回之外没有其他作用.而且对于解析来说,它是解析一个action对象,所就是说,如果你的action是富对象,里面有很多的属性,而实际你需要的不多时,那这个解析就完全失去了作用了.

话说这么多,改进方法,从根本上来说,就是改进这种解析机制.是不解析当前的action对象,而是像spring一样,解析只需要解析的对象一样.如返回a,就只需要解析a.查看上面的executeResult()方法,其中对result和resultCode进行了处理.其中有这么一句

Java代码 icon_copy.gif

if(result !=null) {

result.execute(this);

}elseif(resultCode !=null&& !Action.NONE.equals(resultCode)) {

thrownewConfigurationException("No result defined for action "+ getAction().getClass().getName()

+" and result "+ getResultCode(), proxy.getConfig());

}else{

if(LOG.isDebugEnabled()) {

LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());

}

}

if (result != null) {

result.execute(this);

} else if (resultCode != null && !Action.NONE.equals(resultCode)) {

throw new ConfigurationException("No result defined for action " + getAction().getClass().getName()

+ " and result " + getResultCode(), proxy.getConfig());

} else {

if (LOG.isDebugEnabled()) {

LOG.debug("No result returned for action "+getAction().getClass().getName()+" at "+proxy.getConfig().getLocation());

}

}

第一句,也就是一般我们进行处理的地方,调用result进行最后的处理.而第二句,则是对resultCode进行判断,而第三句什么都不做.所以,对于其他的处理,可以从resultCode下手.方法有两种,一是返回无类型,即void类型,二是返回Action.NONE.当是这两种类型的时候,struts2就不会对result进行主动处理了.详细可参见struts2对Action.NONE的说明,如下:

Java代码 icon_copy.gif

/**

* The action execution was successful but do not

* show a view. This is useful for actions that are

* handling the view in another fashion like redirect.

*/

publicstaticfinalString NONE ="none";

/**

* The action execution was successful but do not

* show a view. This is useful for actions that are

* handling the view in another fashion like redirect.

*/

public static final String NONE = "none";

即我们只需要在action方法中,处理ajax调用,而返回void或者"none"就行了.参考方法调用就如下:

Java代码 icon_copy.gif

publicvoidshowCategoryListAjax2()throwsException {

this.category =this.service.getCategory(this.id);

/** 如果该类别为空 **/

if(this.category ==null) {

AjaxResponse.sendAjaxText(null, ServletActionContext.getResponse());

return;

}

this.categoryList =this.service.getCategoryListBySuperCategory(this.category);

AjaxResponse.sendAjaxText(this.categoryList, ServletActionContext.getResponse());

}

public void showCategoryListAjax2() throws Exception {

this.category = this.service.getCategory(this.id);

/** 如果该类别为空 **/

if(this.category == null) {

AjaxResponse.sendAjaxText(null, ServletActionContext.getResponse());

return;

}

this.categoryList = this.service.getCategoryListBySuperCategory(this.category);

AjaxResponse.sendAjaxText(this.categoryList, ServletActionContext.getResponse());

}

上面的返回类别是一种取巧的方法,更好的方法是返回Action.NONE.这样在struts.xml配置就像这样:

Java代码 icon_copy.gif

是不是更好,惟一要做的就是在action方法处理json转换.不过这不是主要问题,在参考json的转换模式上,我对json转换进行了改进.在Fly_m的注解上如下:

Java代码 icon_copy.gif

public@InterfaceFly_m{

String name()default"";

String format()default"";

booleanexclude()defaultfalse;

}

public @Interface Fly_m{

String name() default "";

String format() default "";

boolean exclude() default false;

}

支持如json一样的名称和format以及exclude(如果为真则不进行转换).另外,支持排除指定类(如果转换对象类型和排除类一致而不进行转换)和指定名称的对象(如果对象名称和排除对象名称一致,则被忽略,只限于对象和map.这对于hibernate这种相互调用的持久层对象最好了).如对象a.b.c的形式.默认的json转换是完全转换,在json插件上,如果在b上设定json(exclude),则无论如何b都不会被转换,这种方法太过固定,不支持临时配置.而在改进中,只需要加一个"a.b"形式的excludeProperties参数就可以了.如果想转换时,把参数去掉就行了.相应的转换方法如下:

Java代码 icon_copy.gif

publicstaticString convertToJson(Object obj, String... excludeProperties) {

returnconvertToJson(obj,null,null, excludeProperties);

}

public static String convertToJson(Object obj, String... excludeProperties) {

return convertToJson(obj, null, null, excludeProperties);

}

Java代码 icon_copy.gif

publicstaticString convertToJson(Object obj, Format format, Class[] excludeClasses, String... excludeProperties) {

JsonHandle jsonHandle =newJsonHandle();

jsonHandle.excludeProperties = excludeProperties;

jsonHandle.excludeClasses = excludeClasses;

if(format !=null)

jsonHandle.defaultFormat = format;

returnjsonHandle.convertToJson(null,0, obj);

}

public static String convertToJson(Object obj, Format format, Class[] excludeClasses, String... excludeProperties) {

JsonHandle jsonHandle = new JsonHandle();

jsonHandle.excludeProperties = excludeProperties;

jsonHandle.excludeClasses = excludeClasses;

if(format != null)

jsonHandle.defaultFormat = format;

return jsonHandle.convertToJson(null, 0, obj);

}

而在jsonHandle中是这样处理的.

Java代码 icon_copy.gif

publicString convertToJson(String s,intdepth, Object obj) {

if(obj ==null|| obj.getClass().getName().indexOf("$$EnhancerByCGLIB$$") != -1|| contains(excludeClasses, obj.getClass())) {

sb.append("null");

}elseif(isSimpleType(obj.getClass())) {

if(objinstanceofCharacter) {

sb.append("'").append(obj).append("'");

}else{

sb.append(obj);

}

}else

if(String.class.isAssignableFrom(obj.getClass()) || StringBuffer.class.isAssignableFrom(obj.getClass())

|| StringBuilder.class.isAssignableFrom(obj.getClass())) {

sb.append('"');

CharacterIterator it =newStringCharacterIterator(obj.toString());

for(charc = it.first(); c != CharacterIterator.DONE; c = it.next()) {

if(c =='"') {

sb.append("\\\"");

}elseif(c =='\\') {

sb.append("\\\\");

}elseif(c =='/') {

sb.append("\\/");

}elseif(c =='\b') {

sb.append("\\b");

}elseif(c =='\f') {

sb.append("\\f");

}elseif(c =='\n') {

sb.append("\\n");

}elseif(c =='\r') {

sb.append("\\r");

}elseif(c =='\t') {

sb.append("\\t");

}elseif(Character.isISOControl(c)) {

sb.append(unicode(c));

}else{

sb.append(c);

}

}

sb.append('"');

}elseif(objinstanceofCollection) {

booleanhibernateFlag;

try{

((Collection) obj).size();

hibernateFlag =true;

}catch(Exception ex) {

hibernateFlag =false;

}

if(hibernateFlag) {

sb.append("[");

for(Iterator iterator = ((Collection) obj).iterator(); iterator.hasNext();) {

convertToJson(s, depth, iterator.next());

if(iterator.hasNext()) {

sb.append(",\n");

}

}

sb.append("]");

}else{

sb.append("null");

}

}elseif(obj.getClass().isArray()) {

sb.append("[");

intmax = java.lang.reflect.Array.getLength(obj);

for(inti =0; i 

if(i >0) {

sb.append(",");

}

convertToJson(s, depth, java.lang.reflect.Array.get(obj, i));

}

sb.append("]");

}elseif(java.util.Map.class.isAssignableFrom(obj.getClass())) {

if(sb.length() >0&& sb.lastIndexOf(",") != -1) {

sb.insert(sb.lastIndexOf(",") +1,"\n");

}

sb.append("{");

for(Map.Entry e : ((Map, ?>) obj).entrySet()) {

if(!(e.getKey()instanceofString))

continue;

if(contains(excludeProperties, e.getKey().toString())) {

continue;

}

if(sb.length() >0&& sb.charAt(sb.length() -1) ==','&& sb.charAt(sb.length() -2) =='}') {

sb.insert(sb.length(),"\n");

}

sb.append("\"").append(e.getKey()).append("\"").append(":");

if(depth <= DEFAULT_DEPTH) {

convertToJson(add(s, e.getKey().toString()), depth +1, e.getValue());

}else{

sb.append("undefined");

}

sb.append(",");

}

if(sb.length() >3) {

sb.deleteCharAt(sb.length() -1);

}

sb.append("}");

}else{

Map map =null;

try{

map = getPropertiesByReflect(this, obj);

}catch(Exception ex) {

ex.printStackTrace();

}

convertToJson(s, depth, map);

}

returnsb.toString();

}

}

public String convertToJson(String s, int depth, Object obj) {

if(obj == null || obj.getClass().getName().indexOf("$$EnhancerByCGLIB$$") != -1 || contains(excludeClasses, obj.getClass())) {

sb.append("null");

} else if(isSimpleType(obj.getClass())) {

if(obj instanceof Character) {

sb.append("'").append(obj).append("'");

} else {

sb.append(obj);

}

} else

if(String.class.isAssignableFrom(obj.getClass()) || StringBuffer.class.isAssignableFrom(obj.getClass())

|| StringBuilder.class.isAssignableFrom(obj.getClass())) {

sb.append('"');

CharacterIterator it = new StringCharacterIterator(obj.toString());

for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {

if(c == '"') {

sb.append("\\\"");

} else if(c == '\\') {

sb.append("\\\\");

} else if(c == '/') {

sb.append("\\/");

} else if(c == '\b') {

sb.append("\\b");

} else if(c == '\f') {

sb.append("\\f");

} else if(c == '\n') {

sb.append("\\n");

} else if(c == '\r') {

sb.append("\\r");

} else if(c == '\t') {

sb.append("\\t");

} else if(Character.isISOControl(c)) {

sb.append(unicode(c));

} else {

sb.append(c);

}

}

sb.append('"');

} else if(obj instanceof Collection) {

boolean hibernateFlag;

try {

((Collection) obj).size();

hibernateFlag = true;

} catch(Exception ex) {

hibernateFlag = false;

}

if(hibernateFlag) {

sb.append("[");

for(Iterator iterator = ((Collection) obj).iterator(); iterator.hasNext();) {

convertToJson(s, depth, iterator.next());

if(iterator.hasNext()) {

sb.append(",\n");

}

}

sb.append("]");

} else {

sb.append("null");

}

} else if(obj.getClass().isArray()) {

sb.append("[");

int max = java.lang.reflect.Array.getLength(obj);

for(int i = 0; i < max; i++) {

if(i > 0) {

sb.append(",");

}

convertToJson(s, depth, java.lang.reflect.Array.get(obj, i));

}

sb.append("]");

} else if(java.util.Map.class.isAssignableFrom(obj.getClass())) {

if(sb.length() > 0 && sb.lastIndexOf(",") != -1) {

sb.insert(sb.lastIndexOf(",") + 1, "\n");

}

sb.append("{");

for(Map.Entry e : ((Map, ?>) obj).entrySet()) {

if(!(e.getKey() instanceof String))

continue;

if(contains(excludeProperties, e.getKey().toString())) {

continue;

}

if(sb.length() > 0 && sb.charAt(sb.length() - 1) == ',' && sb.charAt(sb.length() - 2) == '}') {

sb.insert(sb.length(), "\n");

}

sb.append("\"").append(e.getKey()).append("\"").append(":");

if(depth <= DEFAULT_DEPTH) {

convertToJson(add(s, e.getKey().toString()), depth + 1, e.getValue());

} else {

sb.append("undefined");

}

sb.append(",");

}

if(sb.length() > 3) {

sb.deleteCharAt(sb.length() - 1);

}

sb.append("}");

} else {

Map map = null;

try {

map = getPropertiesByReflect(this, obj);

} catch(Exception ex) {

ex.printStackTrace();

}

convertToJson(s, depth, map);

}

return sb.toString();

}

}

相关的转换方法都参照了其他的处理方式,具体解析方法请参照附件中的JsonUtils类.

这篇文章只是说明了一种对于json的一种新的处理方式,并不是对于json插件的不满,当然我还是喜欢自己的处理方式.加上前面对乱码的处理,算是对struts2的一种补充吧.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值