ssh ajax怎么返回text,SSH系列:(15)自定义Result返回类型(StrutsResultSupport)

总的来说,写一个自定义的Result Type有三个步骤:

(1)写一个实现了Result接口的类

(2)对该类进行注册

(3)使用该类

下面分成两个部分:第1个部分,只要是侧重于项目上的使用方式,第2部分是整理自Sturcts In Action书上的自定义返回Json类型的Result Tye。

1、对错误的特殊处理(项目中)

在有些特殊情况下,如果没有异常信息,但是有错误,并且有错误信息等内容,此时也需要进行友好的错误处理的话,那么可以借助StrutsResultSupport返回结果类型来实现特定处理。此种方式先需要继承StrutsResultSupport,然后可以在子类中获取本次请求的相关信息,再根据相关信息进行结果处理:

1.1、自定义实现了Result接口的类package com.rk.core.action;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import org.apache.struts2.dispatcher.StrutsResultSupport;

import com.opensymphony.xwork2.ActionInvocation;

public class SysResult extends StrutsResultSupport {

@Override

protected void doExecute(String finalLocation, ActionInvocation invocation)

throws Exception {

HttpServletRequest request = ServletActionContext.getRequest();

HttpServletResponse response = ServletActionContext.getResponse();

BaseAction action = (BaseAction)invocation.getAction();

// do something

System.out.println("进入了SysResult...");

}

}

1.2、注册和使用添加的Result Type类

/WEB-INF/jsp/error.jsp

/WEB-INF/jsp/error.jsp

其中注册的是

其中使用的声明是/WEB-INF/jsp/error.jsp

1.3、API知识

1.3.1、Result接口

Result接口只定义了一个execute方法。/**

* All results (except for Action.NONE) of an {@link Action} are mapped to a View implementation.

* Action所有result中,除了Action.NONE,都会对应一个View。

*/

public interface Result extends Serializable {

/**

* Represents a generic interface for all action execution results.

* Whether that be displaying a webpage, generating an email, sending a JMS message, etc.

* Result接口唯一定义的方法的就是execute。

*/

public void execute(ActionInvocation invocation) throws Exception;

}

1.3.2、StrutsResultSupport类

StrutsResultSupport类实现了Result接口,有三点需要注意:

(1)在配置下的时,它有一个默认参数location,是通过DEFAULT_PARAM来定义的。这里有个知识点就是:使用DEFAULT_PARAM变量来指定,在下面的使用JsonResult的例子中,也使用了DEFAULT_PARAM。

(2)在配置下的时,支持ONGL表达式,它是通过conditionalParse方法来处理的

(3)重点关注对Result接口下的execute方法的实现,它会调用抽象方法doExecute方法。这样做的好处就是各个子类可以提供自己对doExecute方法的实现。public abstract class StrutsResultSupport implements Result, StrutsStatics {

private static final Logger LOG = LoggerFactory.getLogger(StrutsResultSupport.class);

/** The default parameter */

/** 如果不指定参数,那么默认的参数就是location。 */

public static final String DEFAULT_PARAM = "location";

/** use UTF-8 as this is the recommended encoding by W3C to avoid incompatibilities. */

public static final String DEFAULT_URL_ENCODING = "UTF-8";

private boolean parse;

private boolean encode;

private String location;

private String lastFinalLocation;

public void setLocation(String location) {

this.location = location;

}

public String getLocation() {

return location;

}

/**

* Implementation of the execute method from the Result interface. This will call

* the abstract method {@link #doExecute(String, ActionInvocation)} after optionally evaluating the

* location as an OGNL evaluation.

*

*/

public void execute(ActionInvocation invocation) throws Exception {

lastFinalLocation = conditionalParse(location, invocation);/** 处理ONGL表达式 */

doExecute(lastFinalLocation, invocation);/** 通过下面的方法可以得到doExecute是一个抽象方法 */

}

/**

* Parses the parameter for OGNL expressions against the valuestack

* 处理ONGL表达式

*/

protected String conditionalParse(String param, ActionInvocation invocation) {

if (parse && param != null && invocation != null) {

return TextParseUtil.translateVariables(

param,

invocation.getStack(),

new EncodingParsedValueEvaluator());

} else {

return param;

}

}

/**

* Executes the result given a final location (jsp page, action, etc) and the action invocation

* (the state in which the action was executed). Subclasses must implement this class to handle

* custom logic for result handling.

*

*/

protected abstract void doExecute(String finalLocation, ActionInvocation invocation) throws Exception;

}

1.3.3、ServletRedirectResult

在strutf-default.xml中定义了redirect类型的结果

我们重点关注它的execute方法和doExecute方法public class ServletRedirectResult extends StrutsResultSupport implements ReflectionExceptionHandler {

//int javax.servlet.http.HttpServletResponse.SC_FOUND = 302 [0x12e]

protected int statusCode = SC_FOUND;

/**

* Redirects to the location specified by calling

* {@link HttpServletResponse#sendRedirect(String)}.

* 在execute方法上,它还是调用父类(StrutsResultSupport类)的execute方法

*/

public void execute(ActionInvocation invocation) throws Exception {

if (anchor != null) {

anchor = conditionalParse(anchor, invocation);

}

super.execute(invocation);

}

/**

* Redirects to the location specified by calling

* {@link HttpServletResponse#sendRedirect(String)}.

* 在本方法的最后,我们可以看到:会调用sendRedirect(response, finalLocation)方法

*/

protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {

ActionContext ctx = invocation.getInvocationContext();

HttpServletRequest request = (HttpServletRequest) ctx.get(ServletActionContext.HTTP_REQUEST);

HttpServletResponse response = (HttpServletResponse) ctx.get(ServletActionContext.HTTP_RESPONSE);

if (isPathUrl(finalLocation)) {

if (!finalLocation.startsWith("/")) {

ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());

String namespace = null;

if (mapping != null) {

namespace = mapping.getNamespace();

}

if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {

finalLocation = namespace + "/" + finalLocation;

} else {

finalLocation = "/" + finalLocation;

}

}

// if the URL's are relative to the servlet context, append the servlet context path

if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {

finalLocation = request.getContextPath() + finalLocation;

}

}

ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());

if (resultConfig != null) {

Map resultConfigParams = resultConfig.getParams();

List prohibitedResultParams = getProhibitedResultParams();

for (Map.Entry e : resultConfigParams.entrySet()) {

if (!prohibitedResultParams.contains(e.getKey())) {

Collection values = conditionalParseCollection(e.getValue(), invocation, suppressEmptyParameters);

if (!suppressEmptyParameters || !values.isEmpty()) {

requestParameters.put(e.getKey(), values);

}

}

}

}

StringBuilder tmpLocation = new StringBuilder(finalLocation);

urlHelper.buildParametersString(requestParameters, tmpLocation, "&");

// add the anchor

if (anchor != null) {

tmpLocation.append('#').append(anchor);

}

finalLocation = response.encodeRedirectURL(tmpLocation.toString());

sendRedirect(response, finalLocation);

}

/**

* Sends the redirection. Can be overridden to customize how the redirect is

* handled (i.e. to use a different status code)

*

* @param response The response

* @param finalLocation The location URI

* @throws IOException

*/

protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {

if (SC_FOUND == statusCode) {

response.sendRedirect(finalLocation);

} else {

response.setStatus(statusCode);

response.setHeader("Location", finalLocation);

response.getWriter().write(finalLocation);

response.getWriter().close();

}

}

}

1.3.4、ServletActionRedirectResult

在strutf-default.xml中定义了redirectAction类型的结果

ServletActionRedirectResult需要注意的有3点:

(1)它继承自ServletRedirectResult类

(2)在下写时,它的默认参数改写为actionName。

(3)关注对execute方法的实现,它还是调用了父类(ServletRedirectResult类)的execute方法,它的原理应该是将相应的actionName和namespace参数转换成目标url。public class ServletActionRedirectResult extends ServletRedirectResult implements ReflectionExceptionHandler {

/* The default parameter */

public static final String DEFAULT_PARAM = "actionName";

protected String actionName;

protected String namespace;

protected String method;

/**

* @see com.opensymphony.xwork2.Result#execute(com.opensymphony.xwork2.ActionInvocation)

*/

public void execute(ActionInvocation invocation) throws Exception {

actionName = conditionalParse(actionName, invocation);

if (namespace == null) {

namespace = invocation.getProxy().getNamespace();

} else {

namespace = conditionalParse(namespace, invocation);

}

if (method == null) {

method = "";

} else {

method = conditionalParse(method, invocation);

}

String tmpLocation = actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null));

setLocation(tmpLocation);

super.execute(invocation);

}

}

1.3.5、ServletDispatcherResult

在strutf-default.xml中定义了dispatcher类型的结果

在这里主要是关注对execute方法的实现:最后是调用dispatcher.forward或dispatcher.include方法public class ServletDispatcherResult extends StrutsResultSupport {

/**

* Dispatches to the given location. Does its forward via a RequestDispatcher. If the

* dispatch fails, a 404 error will be sent back in the http response.

*

*/

public void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {

PageContext pageContext = ServletActionContext.getPageContext();

if (pageContext != null) {

pageContext.include(finalLocation);

} else {

HttpServletRequest request = ServletActionContext.getRequest();

HttpServletResponse response = ServletActionContext.getResponse();

RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);

//add parameters passed on the location to #parameters

// see WW-2120

if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {

String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);

Map parameters = getParameters(invocation);

Map queryParams = urlHelper.parseQueryString(queryString, true);

if (queryParams != null && !queryParams.isEmpty())

parameters.putAll(queryParams);

}

// if the view doesn't exist, let's do a 404

if (dispatcher == null) {

response.sendError(404, "result '" + finalLocation + "' not found");

return;

}

//if we are inside an action tag, we always need to do an include

Boolean insideActionTag = (Boolean) ObjectUtils.defaultIfNull(request.getAttribute(StrutsStatics.STRUTS_ACTION_TAG_INVOCATION), Boolean.FALSE);

// If we're included, then include the view

// Otherwise do forward

// This allow the page to, for example, set content type

if (!insideActionTag && !response.isCommitted() && (request.getAttribute("javax.servlet.include.servlet_path") == null)) {

request.setAttribute("struts.view_uri", finalLocation);

request.setAttribute("struts.request_uri", request.getRequestURI());

dispatcher.forward(request, response);

} else {

dispatcher.include(request, response);

}

}

}

}

2、写一个处理返回Json数据的Result(Struts In Action整理)

Struts 2 framework是MVC架构,而result就是其中的V(View)。

Struts 2 framework提供了不同类型的result,其中常用的result type包括dispatcher、redirect和redirectAction,默认使用的的是result type: dispatcher。

By default, the framework uses a result type that works with JSPs to render these response pages. This result, the dispatcher result, makes all the ValueStack data available to the executing JSP page. With access to that data, the JSP can render a dynamic HTML page.

Thanks to the intelligent defaults, we’ve been happily using JSPs, all the while oblivious to the existence of a variety of result types. All you need to know is that a result is the element into which you stuff the location of your JSP page. And that’s about all you need to know as long as your project stays the JSP course.

Struts 2 framework的result有非常大的灵活性,我们既可以使用Struts框架提供了result type类型,我们也可以自定义一种新的result type。

#话题由result转至action#

Struts 2 的action是用来接收来自客户端的请求、处理业务逻辑,并将the resulting state of domain data保留在ValueStack上。接下来,action返回一个control string,用来告诉struts框架要使用哪一个result。When the framework determines that a given request should be handled by a given action, the action receives the request data, runs its business logic, and leaves the resulting state of domain data exposed on the ValueStack. The last thing the action does is return a control string that tells the framework which of the available results should render the view. Typically, the chosen result uses the data on the ValueStack to render some sort of dynamic response to the client.

If you want, however, to see how you can adapt results to nonstandard patterns of usage, such as the nonclassic patterns of Ajax applications, then stick around.

classic web application与Ajax web application的区别

A classic web application architecture uses the HTTP request and response cycle to submit requests to the server, and receive dynamically created HTML page responses back from that server. This architecture can most notably be distinguished from Ajax web applications that generally receive HTML fragments, XML, or JSON responses from the server, rather than full HTML pages.

how to use custom results to build Ajax applications with Struts 2

JavaScript Object Notation (JSON) provides a succinct text-based serialization of data objects. JSON can be a powerfully succinct and lightweight means of communication between a web application server and an Ajax client. By using JSON, we can serialize our Java-side data objects and send that serialization in a response to the client. On the client side, we can easily deserialize this JSON into runtime JavaScript objects and make  targeted  updates  to  our  client-side  view  without  requiring  a  page  refresh. Sounds pretty clean in theory, and it’s even cleaner in practice.

CODING THE JSONRESULT

First things first. If we plan to have Ajax clients demanding JSON responses, we need to build a result that can do that. This leads us to our custom JSONResult. Making a custom result is, in some ways, just as easy as writing an action. The only requirement imposed  on  a  result  implementation  is  that  it  implement  the  com.opensymphony.xwork2.Result interface, as shown:public interface Result extends Serializable {

public void execute(ActionInvocation invocation) throws Exception;

}

As with most framework components, a simple interfacedefines a highly decoupled and nonrestrictive contract for the component implementation. In this case, we need only  provide  an  execute()  method  for  an  entry  point.  This  method  receives  the ActionInvocation, which gives it access to all the relevant information for the current request. As we’ve learned, this ActionInvocation provides access to such things as the action  itself,  the  ActionContext, and the ValueStack.  This  is  how  results get their hands on the data.

Let’s dive in and have a look at our JSONResult.

2.1、自定义JsonResult类,实现Result接口

注意:这里使用到了Gson的jar包package com.rk.core.action;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.google.gson.Gson;

import com.google.gson.GsonBuilder;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.Result;

import com.opensymphony.xwork2.util.ValueStack;

public class JsonResult implements Result {

public static final String DEFAULT_PARAM = "jsonModelName";

private String jsonModelName = "jsonModel";

public String getJsonModelName() {

return jsonModelName;

}

public void setJsonModelName(String jsonModelName) {

this.jsonModelName = jsonModelName;

}

public void execute(ActionInvocation invocation) throws Exception {

//1、得到JSON字符串

//1.1、获取目标对象

ValueStack valueStack = invocation.getStack();

Object jsonModel = valueStack.findValue(jsonModelName);

//1.2、将目标对象转换为JSON

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd").create();

String jsonStr = gson.toJson(jsonModel);

//2、将JSON进行输出

HttpServletResponse response = ServletActionContext.getResponse();

response.setContentType("application/json;charset=utf-8");

PrintWriter out = response.getWriter();

out.println(jsonStr);

}

}

2.2、注册新增的Result Type

注意的有两点:

(1)声明base-default包,继承struts-default包,且abstract="true"

(2)定义json类型的Result

2.3、使用新增的Result Type

值得注意的有2方面:

(1)继承了base-default包

(2)指明type="json"

/WEB-INF/jsp/tax/user/{1}.jsp

user_listUI

/tax

userList

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值