我有一个使用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请求接收响应的已知问题?我到处都看,真的找不到任何关于它的东西。
任何帮助表示赞赏,我可以根据要求提供更多详细信息。
答案 0 :(得分:4)
我遇到了同样的问题。您是否尝试在struts.xml文件中设置:
struts.rest.content.restrictToGET = false
上的最后一项设置
答案 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请求返回响应对象的选项。
我通过扩展RestActionProxyFactory
和RestActionInvocation
并在我的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解决了这个问题,但我将不得不回过头来看一些旧的代码。