2011-10-07 76 views
7

我有一个使用struts2-rest-plugin v.2.2.3的struts2应用程序。对REST插件没有收到响应的Struts2的POST请求

当涉及到将请求路由到动作及其方法时,所有工作都很好,而且我还使用ModelDriven指定要在使用JSON和XML等扩展时序列化的对象。

我遇到的问题是,当我发送POST或PUT请求到struts层时,我只是得到一个空的响应。

我正在发送POST请求,如下所示:http://localhost:8080/alert-settings!update.json。我在该方法中有一个断点,它被调用并且代码运行并完成。我有一种感觉,问题可能是我试图使用ModelDriven接口将回复发送给我,由于某种原因,其余插件不喜欢这样,但我不知道它为什么会这样。

在使用其余插件时,是否存在接收POST请求响应的已知问题?我到处寻找,真的找不到它。

任何帮助表示赞赏,我可以根据要求提供更多细节。

+0

我找不到解决的办法上一次的设置,但我对通过返回DefaultHttpHeaders而不是改变响应代码解决SUCCESS。我认为这可能是POST和PUT请求的方式。 – noShowP

+0

嗨,我正在使用struts2-rest-plugin,并且无法使update()方法接受JSON有效内容并将其正确映射到模型。你介意分享你是如何做到的吗?谢谢.. – shaunlim

回答

4

我遇到了同样的问题。你有没有试过在struts.xml中文件设置:

struts.rest.content.restrictToGET = false 

查看the rest plugin docs

1

其实我想通了,这是在其他线路插件造成的:

// don't return any content for PUT, DELETE, and POST where there are no errors 
if (!hasErrors && !"get".equalsIgnoreCase(ServletActionContext.getRequest().getMethod())) { 
    target = null; 
} 

这是org.apache.struts2.rest.RestActionInvocationselectTarget()方法。我觉得这很烦人,因为它并不真正遵循REST体系结构,就像在某些情况下可以为POST,DELETE和PUT请求返回响应对象一样。

我工作围绕这通过扩展RestActionProxyFactoryRestActionInvocation并指定使用这在我的支柱XML像这样:

<bean type="com.opensymphony.xwork2.ActionProxyFactory" name="restOverride" class="uk.co.ratedpeople.tp.rest.RPRestActionProxyFactory" /> 
<constant name="struts.actionProxyFactory" value="restOverride" /> 

这让我使用Struts插件贯穿而在POST请求返回的对象。

RestActionProxyFactory

public class RPRestActionProxyFactory extends RestActionProxyFactory { 

    @Override 
    public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext, boolean executeResult, boolean cleanupContext) { 
     if (namespace.startsWith(this.namespace)) { 
      ActionInvocation inv = new RPRestActionInvocation(extraContext, true); 
      container.inject(inv); 
      return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); 
     } else { 
      return super.createActionProxy(namespace, actionName, methodName, extraContext, executeResult, cleanupContext); 
     } 
    } 

} 

RestActionInvocation

public class RPRestActionInvocation extends RestActionInvocation { 

    public RPRestActionInvocation(Map extraContext, boolean pushAction) { 
     super(extraContext, pushAction); 
    } 

    @SuppressWarnings("unchecked") 
    @Override 
    protected void selectTarget() { 

     // Select target (content to return) 
     Throwable e = (Throwable)stack.findValue("exception"); 
     if (e != null) { 

      // Exception 
      target = e; 
      hasErrors = true; 

     } else if (action instanceof ValidationAware && ((ValidationAware)action).hasErrors()) { 

      // Error messages 
      ValidationAware validationAwareAction = ((ValidationAware)action); 

      Map errors = new HashMap(); 
      if (validationAwareAction.getActionErrors().size() > 0) { 
       errors.put("actionErrors", validationAwareAction.getActionErrors()); 
      } 
      if (validationAwareAction.getFieldErrors().size() > 0) { 
       errors.put("fieldErrors", validationAwareAction.getFieldErrors()); 
      } 
      target = errors; 
      hasErrors = true; 

     } else if (action instanceof ModelDriven) { 

      // Model 
      target = ((ModelDriven)action).getModel(); 

     } else { 
      target = action; 
     } 

     // don't return any content for PUT, DELETE, and POST where there are no errors 
//  if (!hasErrors && !"get".equalsIgnoreCase(ServletActionContext.getRequest().getMethod())) { 
//   target = null; 
//  } 
    } 

} 
+0

可能有更好的方法来解决这个问题,所以请分享,如果有的话。 – noShowP

0

我已经使用在过去的混合结果类型,返回JSON,XML和瓷砖例如Struts动作。我不确定是否推荐这样做,但即使使用约定,也需要使用struts.xml进行一些配置。也许你已经这样做了,不确定是否没有足够的信息来说明。

struts.xml的设置:

<constant name="struts.convention.default.parent.package" value="restful"/> 

<package name="restful" extends="rest-default, struts-default, json-default"> 
    <result-types> 
     <result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult" /> 
     <result-type name="json" class="com.googlecode.jsonplugin.JSONResult"/> 
    </result-types> 

    .... 
</package> 

我已经安装额外的结果类型将在后面的具体行动中。在动作类中,您可以通过操作或方法来设置结果类型。

Action类:

@Results({ 
    @Result(name = "JsonSuccess", type = "json"), 
    @Result(name = "success", type = "tiles", location = "/tickets.tiles") 
}) 

public class EventController extends RestActionSupport implements ModelDriven<EventBean>{ 
    ... 
} 

别的东西需要注意的JSON结果,我注意到,当我有一个序列化的对象返回的结果是,如果该对象包含与其他复杂的对象getter/setter返回嵌入对象,我会经常收到一个空结果或没有结果。我经常最终编写json包装器对象,用于我的json结果,其getter/setter只返回java类型(String,int,Boolean等),而不是嵌入式对象。我认为使用委托getter/setter解决了这个问题,但我必须回头看看一些旧代码。

+0

我已经完成了你在这里完成的任务,除了我已经使用了struts2-rest-plugin v.2.2.3来处理结果。因此,您不需要指定JsonSuccess类型,只需将.json添加到url的末尾,以便/job.json将调用JobAction的索引方法并以JSON格式返回其结果。这个问题具体到它的行为,当请求是一个POST时,它不会从任何操作返回任何内容(所以POST到/job.json不会返回任何数据,只是成功或失败)。 – noShowP