webwork 2.2.7 中新增加了 JSONResult 视图类型,它有两个参数:
在 Action 中,只要在上下文中返回一个 JSONObject 类型的数据即可:
不过,默认输出的字符集代码页是系统当前的代码页,如果想输出指定的 charset ,如 UTF-8, 我们需要修改一下 JSONResult ,追回一个参数 charset ,红色部分的代码为变更点:
<
action
name
="getActiveCustomers"
class
="..."
>
< result name ="success" type ="json" >
< param name ="jsonObjectProperty" > activeCustomer </ param >
< param name ="contentType" > application/json </ param >
</ result >
...
</ action > >
< result name ="success" type ="json" >
< param name ="jsonObjectProperty" > activeCustomer </ param >
< param name ="contentType" > application/json </ param >
</ result >
...
</ action > >
在 Action 中,只要在上下文中返回一个 JSONObject 类型的数据即可:
private
JSONObject jsonObject;
@Override
protected String doInit() throws Exception {
if (!StringUtil.isEmptyOrNull(model.getProductCode(), true)){
ProductSearchDao dao = new ProductSearchDao();
dao.getLastProduct(this.model.getProductCode(), model);
jsonObject = new JSONObject();
jsonObject.put("en", model.getProductEn());
jsonObject.put("cn", model.getProductCn());
}
return SUCCESS;
}
public JSONObject getJsonObject() {
return jsonObject;
}
@Override
protected String doInit() throws Exception {
if (!StringUtil.isEmptyOrNull(model.getProductCode(), true)){
ProductSearchDao dao = new ProductSearchDao();
dao.getLastProduct(this.model.getProductCode(), model);
jsonObject = new JSONObject();
jsonObject.put("en", model.getProductEn());
jsonObject.put("cn", model.getProductCn());
}
return SUCCESS;
}
public JSONObject getJsonObject() {
return jsonObject;
}
不过,默认输出的字符集代码页是系统当前的代码页,如果想输出指定的 charset ,如 UTF-8, 我们需要修改一下 JSONResult ,追回一个参数 charset ,红色部分的代码为变更点:
/*
* Copyright (c) 2002-2007 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.webwork.dispatcher.json;
import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.webwork.WebWorkException;
import com.opensymphony.xwork.ActionContext;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.Result;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* <!-- START SNIPPET: description -->
*
* Attempt to retrieve an instance of {@link JSONObject} from WebWork's ValueStack through property returned from
* {@link #getJSONObjectProperty()} and write the String representation of the retrived {@link JSONObject} to
* {@link HttpServletResponse}'s outputstream. Normally having accessor methods for the property in WebWork's action
* would do the trick.
*
* <!-- END SNIPPET: description -->
*
*
* <!-- START SNIPPET: params -->
*
* <ul>
* <li>contentType - Defines the content-type header to be used. Default to 'application/json'</li>
* <li>jsonObjectProperty - Defines the property used to look up WebWork's ValueStack to find an instance of
* {@link JSONObject}. Default to 'jsonObject'.
* </ul>
*
* <!-- END SNIPPET: params -->
*
*
* <pre>
* <!-- START SNIPPET: examples -->
*
* <action name="getActiveCustomers" class="...">
* <result name="success" type="json">
* <param name="jsonObjectProperty">activeCustomer</param>
* <param name="contentType">application/json</param>
* </result>
* ...
* </action>>
*
* Or just
*
* <action name="getActiveCustomers" class="...">
* <result name="success" type="json" />
* ...
* </action>
*
* if we used the default property ('jsonObject') and default content-type ('application/json')
*
* <!-- END SNIPPET: examples -->
* </pre>
*
* @author tmjee
* @version $Date$ $Id$
*/
public class JSONResult implements Result {
private static final Log LOG = LogFactory.getLog(JSONResult.class);
private String jsonObjectProperty = "jsonObject";
private String contentType = "application/json";
private String charset = "utf-8";
/**
* Returns the property which will be used to lookup {@link JSONObject} in WebWork's ValueStack. Default to
* 'jsonObject'.
*
* @return String
*/
public String getJSONObjectProperty() {
return jsonObjectProperty;
}
/**
* Set the property which will be used to lookup {@link JSONObject} in WebWork's ValueStack. Default to
* 'jsonObject'.
*
* @param jsonObject
*/
public void setJSONObjectProperty(String jsonObject) {
this.jsonObjectProperty = jsonObject;
}
/**
* Returns the content-type header to be used. Default to 'application/json'.
*
* @return String
*/
public String getContentType() {
return contentType;
}
/**
* Set the content-type header to be used. Default to 'application/json'.
*
* @param contentType
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* Writes the string representation of {@link JSONObject} defined through {@link #getJSONObjectProperty()}
* to {@link javax.servlet.http.HttpServletResponse}'s outputstream.
*
* @param invocation
* @throws Exception
*/
public void execute(ActionInvocation invocation) throws Exception {
if (LOG.isDebugEnabled()) {
LOG.debug("executing JSONResult");
}
JSONObject jsonObject = getJSONObject(invocation);
if (jsonObject != null) {
String json = jsonObject.toString();
HttpServletResponse response = getServletResponse(invocation);
response.setContentType(getContentType());
byte[] bs = json.getBytes(charset);
response.setContentLength(bs.length);
OutputStream os = response.getOutputStream();
os.write(bs);
os.flush();
if (LOG.isDebugEnabled()) {
LOG.debug("written ["+json+"] to HttpServletResponse outputstream");
}
}
}
/**
* Attempt to look up a {@link com.opensymphony.webwork.dispatcher.json.JSONObject} instance through the property
* ({@link #getJSONObjectProperty()}) by looking up the property in WebWork's ValueStack. It shall be found if there's
* accessor method for the property in WebWork's action itself.
* <p/>
* Returns null if one cannot be found.
* <p/>
* We could override this method to return the desired JSONObject when writing testcases.
*
* @param invocation
* @return {@link JSONObject} or null if one cannot be found
*/
protected JSONObject getJSONObject(ActionInvocation invocation) throws JSONException {
ActionContext actionContext = invocation.getInvocationContext();
Object obj = actionContext.getValueStack().findValue(jsonObjectProperty);
if (obj == null) {
LOG.error("property ["+ jsonObjectProperty +"] returns null, expecting JSONObject", new WebWorkException());
return null;
}
if (! JSONObject.class.isInstance(obj)) {
LOG.error("property ["+ jsonObjectProperty +"] is ["+obj+"] especting an instance of JSONObject", new WebWorkException());
return null;
}
return (JSONObject) obj;
}
/**
* Returns a {@link javax.servlet.http.HttpServletResponse} by looking it up through WebWork's ActionContext Map.
* </p>
* We could override this method to return the desired Mock HttpServletResponse when writing testcases.
*
* @param invocation
* @return {@link javax.servlet.http.HttpServletResponse}
*/
protected HttpServletResponse getServletResponse(ActionInvocation invocation) {
return (HttpServletResponse) invocation.getInvocationContext().getContextMap().get(ServletActionContext.HTTP_RESPONSE);
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
}
* Copyright (c) 2002-2007 by OpenSymphony
* All rights reserved.
*/
package com.opensymphony.webwork.dispatcher.json;
import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.webwork.WebWorkException;
import com.opensymphony.xwork.ActionContext;
import com.opensymphony.xwork.ActionInvocation;
import com.opensymphony.xwork.Result;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* <!-- START SNIPPET: description -->
*
* Attempt to retrieve an instance of {@link JSONObject} from WebWork's ValueStack through property returned from
* {@link #getJSONObjectProperty()} and write the String representation of the retrived {@link JSONObject} to
* {@link HttpServletResponse}'s outputstream. Normally having accessor methods for the property in WebWork's action
* would do the trick.
*
* <!-- END SNIPPET: description -->
*
*
* <!-- START SNIPPET: params -->
*
* <ul>
* <li>contentType - Defines the content-type header to be used. Default to 'application/json'</li>
* <li>jsonObjectProperty - Defines the property used to look up WebWork's ValueStack to find an instance of
* {@link JSONObject}. Default to 'jsonObject'.
* </ul>
*
* <!-- END SNIPPET: params -->
*
*
* <pre>
* <!-- START SNIPPET: examples -->
*
* <action name="getActiveCustomers" class="...">
* <result name="success" type="json">
* <param name="jsonObjectProperty">activeCustomer</param>
* <param name="contentType">application/json</param>
* </result>
* ...
* </action>>
*
* Or just
*
* <action name="getActiveCustomers" class="...">
* <result name="success" type="json" />
* ...
* </action>
*
* if we used the default property ('jsonObject') and default content-type ('application/json')
*
* <!-- END SNIPPET: examples -->
* </pre>
*
* @author tmjee
* @version $Date$ $Id$
*/
public class JSONResult implements Result {
private static final Log LOG = LogFactory.getLog(JSONResult.class);
private String jsonObjectProperty = "jsonObject";
private String contentType = "application/json";
private String charset = "utf-8";
/**
* Returns the property which will be used to lookup {@link JSONObject} in WebWork's ValueStack. Default to
* 'jsonObject'.
*
* @return String
*/
public String getJSONObjectProperty() {
return jsonObjectProperty;
}
/**
* Set the property which will be used to lookup {@link JSONObject} in WebWork's ValueStack. Default to
* 'jsonObject'.
*
* @param jsonObject
*/
public void setJSONObjectProperty(String jsonObject) {
this.jsonObjectProperty = jsonObject;
}
/**
* Returns the content-type header to be used. Default to 'application/json'.
*
* @return String
*/
public String getContentType() {
return contentType;
}
/**
* Set the content-type header to be used. Default to 'application/json'.
*
* @param contentType
*/
public void setContentType(String contentType) {
this.contentType = contentType;
}
/**
* Writes the string representation of {@link JSONObject} defined through {@link #getJSONObjectProperty()}
* to {@link javax.servlet.http.HttpServletResponse}'s outputstream.
*
* @param invocation
* @throws Exception
*/
public void execute(ActionInvocation invocation) throws Exception {
if (LOG.isDebugEnabled()) {
LOG.debug("executing JSONResult");
}
JSONObject jsonObject = getJSONObject(invocation);
if (jsonObject != null) {
String json = jsonObject.toString();
HttpServletResponse response = getServletResponse(invocation);
response.setContentType(getContentType());
byte[] bs = json.getBytes(charset);
response.setContentLength(bs.length);
OutputStream os = response.getOutputStream();
os.write(bs);
os.flush();
if (LOG.isDebugEnabled()) {
LOG.debug("written ["+json+"] to HttpServletResponse outputstream");
}
}
}
/**
* Attempt to look up a {@link com.opensymphony.webwork.dispatcher.json.JSONObject} instance through the property
* ({@link #getJSONObjectProperty()}) by looking up the property in WebWork's ValueStack. It shall be found if there's
* accessor method for the property in WebWork's action itself.
* <p/>
* Returns null if one cannot be found.
* <p/>
* We could override this method to return the desired JSONObject when writing testcases.
*
* @param invocation
* @return {@link JSONObject} or null if one cannot be found
*/
protected JSONObject getJSONObject(ActionInvocation invocation) throws JSONException {
ActionContext actionContext = invocation.getInvocationContext();
Object obj = actionContext.getValueStack().findValue(jsonObjectProperty);
if (obj == null) {
LOG.error("property ["+ jsonObjectProperty +"] returns null, expecting JSONObject", new WebWorkException());
return null;
}
if (! JSONObject.class.isInstance(obj)) {
LOG.error("property ["+ jsonObjectProperty +"] is ["+obj+"] especting an instance of JSONObject", new WebWorkException());
return null;
}
return (JSONObject) obj;
}
/**
* Returns a {@link javax.servlet.http.HttpServletResponse} by looking it up through WebWork's ActionContext Map.
* </p>
* We could override this method to return the desired Mock HttpServletResponse when writing testcases.
*
* @param invocation
* @return {@link javax.servlet.http.HttpServletResponse}
*/
protected HttpServletResponse getServletResponse(ActionInvocation invocation) {
return (HttpServletResponse) invocation.getInvocationContext().getContextMap().get(ServletActionContext.HTTP_RESPONSE);
}
public String getCharset() {
return charset;
}
public void setCharset(String charset) {
this.charset = charset;
}
}