7

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

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

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

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

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

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

4

3 回答 3

4

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

struts.rest.content.restrictToGET = false

请参阅其余插件文档中的最后一个设置

于 2012-02-22T21:46:18.143 回答
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 架构,就像在某些情况下能够为 POST、DELETE 和 PUT 请求返回响应对象的选项一样。

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

<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);
        }
    }

}

休息动作调用

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

}
于 2011-11-10T17:46:14.180 回答
0

我过去曾使用过具有混合结果类型的 struts 操作,例如返回 json、xml 和图块。我不确定这是否是推荐的方法,但即使使用了约定,它也需要使用 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 解决了这个问题,但我必须回去看看一些旧代码。

于 2011-11-17T14:37:22.750 回答