使用REST插件向Struts2发送POST请求未收到响应

时间:2011-10-07 09:44:46

标签: struts2 struts2-rest-plugin

我有一个使用struts2-rest-plugin v.2.2.3的struts2应用程序。

当涉及到请求到操作及其方法的路由时,一切都很好用,我还使用ModelDriven来指定在使用JSON和XML等扩展时要序列化的对象。

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

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

在使用其余插件时,是否存在从POST请求接收响应的已知问题?我到处都看,真的找不到任何关于它的东西。

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

3 个答案:

答案 0 :(得分:4)

我遇到了同样的问题。您是否尝试在struts.xml文件中设置:

struts.rest.content.restrictToGET = false

查看the rest plugin docs

上的最后一项设置

答案 1 :(得分: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.RestActionInvocation方法中的selectTarget()。我觉得这很烦人,因为它并没有真正遵循REST架构,id就像能够在某些情况下为POST,DELETE和PUT请求返回响应对象的选项。

我通过扩展RestActionProxyFactoryRestActionInvocation并在我的struts xml中指定使用它来解决这个问题,如下所示:

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

这允许我在POST请求中返回对象时始终使用struts插件。

<强> 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;
//      }
    }

}

答案 2 :(得分:0)

我过去曾使用混合结果类型的struts动作,例如返回json,xml和tiles。我不确定它是否是推荐的方法,但它需要使用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>

我已经设置了额外的结果类型,以便稍后用于特定的操作。然后,您可以在操作类中按操作或方法设置结果类型。

行动类:

@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解决了这个问题,但我将不得不回过头来看一些旧的代码。