本来Struts2有自己的json类型的返回结果,并提供了插件,但是它有一个问题,那就是它会将所有序列化的字段都返回,如果想要制定返回Action的某一个属性,则需要在配置result时,配置参数(这里只是举个例子):
<param name="root">responseMap</param>
配置了这个参数,返回结果就会从Action中的responseMap为根进行返回。
但是如果自定义结果类型,就可以自己控制了,而且不需要struts2-json-result插件,以下是配置信息:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.objectFactory" value="spring" /> <constant name="struts.i18n.encoding" value="utf-8" /> <constant name="struts.enable.SlashesInActionNames" value="true" /> <package name="default" extends="struts-default" namespace="/login"> <result-types> <result-type name="jsonResult" class="com.lxl.student.mng.base.JSONResult" /> </result-types> <action name="*/*" class="{1}" method="{2}"> <result type="jsonResult" name="success"> <param name="resultName">responseData</param> </result> </action> </package> </struts>
com.lxl.erp.base.JSONResult为我们自己需要实现的返回类型的实现类:
package com.lxl.student.mng.base; import java.io.PrintWriter; import java.lang.reflect.UndeclaredThrowableException; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import org.apache.struts2.dispatcher.StrutsResultSupport; import com.lxl.student.mng.common.HttpConstant; import com.lxl.student.mng.common.ResourceLanguage; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.ExceptionHolder; import com.opensymphony.xwork2.util.ValueStack; import net.sf.json.JSONObject; public final class JSONResult extends StrutsResultSupport { private static final long serialVersionUID = 1L; private String resultName; public void setResultName(String resultName) { this.resultName = resultName; } @Override protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception { BaseAction bas = (BaseAction) invocation.getAction(); bas.clearErrorsAndMessages(); HttpServletResponse response = (HttpServletResponse) invocation.getInvocationContext().get(HTTP_RESPONSE); response.setContentType(HttpConstant.RESPONSE_CONTENT_TYPE); @SuppressWarnings("unchecked") Map<String, Object> responseMap = (Map<String, Object>) invocation.getStack().findValue(resultName); if (responseMap == null) { responseMap = new HashMap<String, Object>(3); } else if (responseMap.get(HttpConstant.RETCODE) == null) { ValueStack s = invocation.getStack(); for (int i = s.size(); i > 0; i--) { Object obj = s.pop(); if (obj instanceof ExceptionHolder) { responseMap.put(HttpConstant.RETCODE, HttpConstant.ERROR_CODE); responseMap.put(HttpConstant.RETMSG, HttpConstant.UNKNOWNERROR); Object o = ((ExceptionHolder) obj).getException(); if (o instanceof ServiceException) { String accept_language = ServletActionContext.getRequest() .getHeader(HttpConstant.REQUEST_HEADER_LANG); String language = accept_language.split(",")[0]; Locale locale = Locale.getDefault(); if (language.toLowerCase().indexOf(ResourceLanguage.CHINESE) > -1) { locale = Locale.CHINA; } else if (language.toLowerCase().indexOf(ResourceLanguage.ENGLISH) > -1) { locale = Locale.US; } ResourceBundle bundle = ResourceBundle.getBundle(ResourceLanguage.SOURCELOCATION, locale); ServiceException exception = (ServiceException) o; responseMap.put(HttpConstant.RETMSG, exception.getErrorMsg(bundle)); } else if (o instanceof Exception) { Exception exception = (Exception) o; responseMap.put(HttpConstant.RETMSG, exception.getCause().getMessage()); } else if (o instanceof UndeclaredThrowableException) { o = ((UndeclaredThrowableException) o).getUndeclaredThrowable(); } break; } } } PrintWriter pw = response.getWriter(); pw.write(JSONObject.fromObject(responseMap).toString()); System.out.println(JSONObject.fromObject(responseMap)); return; } }
这样,只要在Action中添加一个属性responseMap存储要返回的数据,通过
(Map<String, Object>) invocation.getStack().findValue(resultName)
在值栈中获取返回的数据(resultName是在struts.xml中配置的,struts会将值压入到值栈中,通过这个配置的名字就可以找到)。
这样Action请求处理函数中,将要返回的请求数据结果放到responseMap中,然后返回SUCCESS就可以了,前台就可以通过ajax请求访问了。
注:
HttpConstant.RESPONSE_CONTENT_TYPE="text/plain; charset=UTF-8"