struts2-rest-插件失败:"org.apache.struts2.dispatcher.Dispatcher - Could not find action or result"
struts2-rest-plugin failing: "org.apache.struts2.dispatcher.Dispatcher - Could not find action or result"
我正在编写一个 REST 服务器,使用 struts2-rest-plugin。我正在使用 SoapUI 和 Postman 测试 REST 调用。我在这里遵循示例代码:
https://cwiki.apache.org/confluence/display/WW/REST+Plugin
我对 controller.index()
) 和 controllers.create()
的 REST 调用工作正常。
但是虽然controller.update()
成功调用控制器并更新了记录:
19:46:05.361 [http-nio-8080-exec-3] DEBUG com.opensymphony.xwork2.validator.ValidationInterceptor - Validating /contacts with method update.
19:46:05.393 [http-nio-8080-exec-3] DEBUG com.opensymphony.xwork2.DefaultActionInvocation - Executing action method = update
19:46:05.398 [http-nio-8080-exec-3] DEBUG com.opensymphony.xwork2.ognl.SecurityMemberAccess - Checking access for [target: com.example.contactsapp.controllers.ContactsController@7e69160c, member: public java.lang.String com.example.contactsapp.controllers.ContactsController.update(), property: null]
19:46:07.862 [http-nio-8080-exec-3] DEBUG com.example.contactsapp.controllers.ContactsController - Updating existing contact(97)...
...
...它在 "return" 上失败,出现此错误:
...
19:46:11.380 [http-nio-8080-exec-3] WARN org.apache.struts2.dispatcher.Dispatcher - Could not find action or result: /StrutsContactsApp/contacts/97
com.opensymphony.xwork2.config.ConfigurationException: No result defined for action com.example.contactsapp.controllers.ContactsController and result update
at org.apache.struts2.rest.RestActionInvocation.findResult(RestActionInvocation.java:283) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at org.apache.struts2.rest.RestActionInvocation.executeResult(RestActionInvocation.java:225) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at org.apache.struts2.rest.RestActionInvocation.processResult(RestActionInvocation.java:189) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at org.apache.struts2.rest.RestActionInvocation.invoke(RestActionInvocation.java:137) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at com.opensymphony.xwork2.DefaultActionProxy.execute(DefaultActionProxy.java:157) ~[struts2-core-2.5.22.jar:2.5.22]
...
这是控制器:
public class ContactsController implements ModelDriven<Object> {
private static final Logger log = LogManager.getLogger(ContactsController.class);
private String id;
private Contact model = new Contact();
private Collection<Contact> list;
private ContactsRepository contactsRepository = new ContactsRepositoryImpl();
@Override
public Object getModel() {
return (list != null ? list : model);
}
public void setId(String id) {
if (id != null) {
int contactId = Integer.parseInt(id);
this.model = contactsRepository.getContact(contactId);
}
this.id = id;
}
public HttpHeaders index () {
log.debug("Reading all contacts...");
list = contactsRepository.getContacts();
return new DefaultHttpHeaders("index").disableCaching();
}
...
// PUT /orders/1
public String update() {
log.debug("Updating existing contact(" + id + ")...", model);
contactsRepository.updateContact(model);
return "update";
}
...
... 和 struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.mapper.class" value="rest" />
<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="rest-default"/>
<constant name="struts.convention.package.locators" value="controllers"/>
<package name="contacts" extends="rest-default">
<global-allowed-methods>index,show,create,update,destroy,deleteConfirm</global-allowed-methods>
</package>
</struts>
在我添加 <package name="contacts">
之前没有任何效果。我尝试了几种添加 <action>
和 <result>
的不同变体,但无济于事。
示例网址:
GET Endpoint= http://localhost:8080, Resource= /StrutsContactsApp/contacts.json
: 好的
POST Endpoint= http://localhost:8080, Resource= /StrutsContactsApp/contacts.json + JSON body
:好的
PUT Endpoint= http://localhost:8080, Resource= http://localhost:8080, + JSON body
:
API调用成功,浏览器获取"HTTP 404";日志显示 "No result defined for action com.example.contactsapp.controllers.ContactsController and result update"
问:对于解决错误和让 "update()" 使用 struts2-rest-plugin 有什么建议吗?
PS:
我在 "update()"、"show()" 和 "destroy()" 这三个方面都遇到了类似的问题。每个人都期望一个 id(我可以在 Eclipse 调试器中看到它被正确传递)。
还有:
struts-rest-plugin 支持像 http://localhost:8080/myapp/contacts.json
(对于 JSON)和 http://localhost:8080/myapp/contacts.xml
(对于 XML)这样的 URL。我不确定 "update()" 是否需要 contacts.json/id
,或者只是 contacts/id
。都不起作用:(
好的 - 整个问题是我以 "seemed reasonable" 的方式采用了示例代码。
但事实证明 struts2-rest-plugin 有很多我不知道的 "unspoken conventions"。具体来说:
默认情况下,struts2-rest-plugin 映射预先指定的操作名称 index()
、show()
、create()
、update()
和 destroy()
到 CRUD 操作。
我确实 不需要 需要在 struts.xml 中定义 "package" 或任何 "actions"。除非我需要自定义,否则 Struts2-rest-plugin 想要自己管理这些细节。这是(最小的!)struts.xml 我结束了:
我 不想 使用 .jsp(如示例)。我 认为 需要从每个动作中 "return something"(如 JSON 响应)。
相反,我只需要重定向到一个动作。例如:
public HttpHeaders create() {
log.debug("Creating new contact...", model);
contactsRepository.addContact(model);
return new DefaultHttpHeaders("index");
...
最重要的是,我不清楚 struts2-rest-plugin URI 约定来调用每个不同的 CRUD 操作:
Struts-rest-plugin URL mappings (https://struts.apache.org/plugins/rest/):
**Default**
**Method** **Description** **Example**
------ ----------- -------
index() GET request with no id parameter. GET http://localhost:8080/StrutsContactsApp/contacts.json
show() GET request with an id parameter. GET http://localhost:8080/StrutsContactsApp/contacts/1.json
create() POST request with no id parameter and JSON/XML body. POST http://localhost:8080/StrutsContactsApp/contacts.json
update() PUT request with an id parameter and JSON/XML body. PUT http://localhost:8080/StrutsContactsApp/contacts/65.json
destroy() DELETE request with an id parameter. DELETE http://localhost:8080/StrutsContactsApp/contacts/33.json
edit() GET request with an id parameter and the edit view specified.
editNew() GET request with no id parameter and the new view specified.
Struts-rest-plugin runtime automatically manages:
- Parsing object ID from REST URI
- Serializing/deserializing input parameters and return objects
- By default, controller will implement interface com.opensymphony.xwork2.ModelDriven
- By default, shouldn't need to (i.e. *shouldn't*) declare any packages or actions in struts.xml
<= "Follow conventions", and struts2-rest-plugin will manage all the details...
我正在编写一个 REST 服务器,使用 struts2-rest-plugin。我正在使用 SoapUI 和 Postman 测试 REST 调用。我在这里遵循示例代码:
https://cwiki.apache.org/confluence/display/WW/REST+Plugin
我对 controller.index()
) 和 controllers.create()
的 REST 调用工作正常。
但是虽然controller.update()
成功调用控制器并更新了记录:
19:46:05.361 [http-nio-8080-exec-3] DEBUG com.opensymphony.xwork2.validator.ValidationInterceptor - Validating /contacts with method update.
19:46:05.393 [http-nio-8080-exec-3] DEBUG com.opensymphony.xwork2.DefaultActionInvocation - Executing action method = update
19:46:05.398 [http-nio-8080-exec-3] DEBUG com.opensymphony.xwork2.ognl.SecurityMemberAccess - Checking access for [target: com.example.contactsapp.controllers.ContactsController@7e69160c, member: public java.lang.String com.example.contactsapp.controllers.ContactsController.update(), property: null]
19:46:07.862 [http-nio-8080-exec-3] DEBUG com.example.contactsapp.controllers.ContactsController - Updating existing contact(97)...
...
...它在 "return" 上失败,出现此错误:
...
19:46:11.380 [http-nio-8080-exec-3] WARN org.apache.struts2.dispatcher.Dispatcher - Could not find action or result: /StrutsContactsApp/contacts/97
com.opensymphony.xwork2.config.ConfigurationException: No result defined for action com.example.contactsapp.controllers.ContactsController and result update
at org.apache.struts2.rest.RestActionInvocation.findResult(RestActionInvocation.java:283) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at org.apache.struts2.rest.RestActionInvocation.executeResult(RestActionInvocation.java:225) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at org.apache.struts2.rest.RestActionInvocation.processResult(RestActionInvocation.java:189) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at org.apache.struts2.rest.RestActionInvocation.invoke(RestActionInvocation.java:137) ~[struts2-rest-plugin-2.5.22.jar:2.5.22]
at com.opensymphony.xwork2.DefaultActionProxy.execute(DefaultActionProxy.java:157) ~[struts2-core-2.5.22.jar:2.5.22]
...
这是控制器:
public class ContactsController implements ModelDriven<Object> {
private static final Logger log = LogManager.getLogger(ContactsController.class);
private String id;
private Contact model = new Contact();
private Collection<Contact> list;
private ContactsRepository contactsRepository = new ContactsRepositoryImpl();
@Override
public Object getModel() {
return (list != null ? list : model);
}
public void setId(String id) {
if (id != null) {
int contactId = Integer.parseInt(id);
this.model = contactsRepository.getContact(contactId);
}
this.id = id;
}
public HttpHeaders index () {
log.debug("Reading all contacts...");
list = contactsRepository.getContacts();
return new DefaultHttpHeaders("index").disableCaching();
}
...
// PUT /orders/1
public String update() {
log.debug("Updating existing contact(" + id + ")...", model);
contactsRepository.updateContact(model);
return "update";
}
...
... 和 struts.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<constant name="struts.mapper.class" value="rest" />
<constant name="struts.convention.action.suffix" value="Controller"/>
<constant name="struts.convention.action.mapAllMatches" value="true"/>
<constant name="struts.convention.default.parent.package" value="rest-default"/>
<constant name="struts.convention.package.locators" value="controllers"/>
<package name="contacts" extends="rest-default">
<global-allowed-methods>index,show,create,update,destroy,deleteConfirm</global-allowed-methods>
</package>
</struts>
在我添加 <package name="contacts">
之前没有任何效果。我尝试了几种添加 <action>
和 <result>
的不同变体,但无济于事。
示例网址:
GET Endpoint= http://localhost:8080, Resource= /StrutsContactsApp/contacts.json
: 好的POST Endpoint= http://localhost:8080, Resource= /StrutsContactsApp/contacts.json + JSON body
:好的PUT Endpoint= http://localhost:8080, Resource= http://localhost:8080, + JSON body
:API调用成功,浏览器获取"HTTP 404";日志显示 "No result defined for action com.example.contactsapp.controllers.ContactsController and result update"
问:对于解决错误和让 "update()" 使用 struts2-rest-plugin 有什么建议吗?
PS: 我在 "update()"、"show()" 和 "destroy()" 这三个方面都遇到了类似的问题。每个人都期望一个 id(我可以在 Eclipse 调试器中看到它被正确传递)。
还有:
struts-rest-plugin 支持像 http://localhost:8080/myapp/contacts.json
(对于 JSON)和 http://localhost:8080/myapp/contacts.xml
(对于 XML)这样的 URL。我不确定 "update()" 是否需要 contacts.json/id
,或者只是 contacts/id
。都不起作用:(
好的 - 整个问题是我以 "seemed reasonable" 的方式采用了示例代码。 但事实证明 struts2-rest-plugin 有很多我不知道的 "unspoken conventions"。具体来说:
默认情况下,struts2-rest-plugin 映射预先指定的操作名称
index()
、show()
、create()
、update()
和destroy()
到 CRUD 操作。我确实 不需要 需要在 struts.xml 中定义 "package" 或任何 "actions"。除非我需要自定义,否则 Struts2-rest-plugin 想要自己管理这些细节。这是(最小的!)struts.xml 我结束了:
我 不想 使用 .jsp(如示例)。我 认为 需要从每个动作中 "return something"(如 JSON 响应)。
相反,我只需要重定向到一个动作。例如:
public HttpHeaders create() { log.debug("Creating new contact...", model); contactsRepository.addContact(model); return new DefaultHttpHeaders("index"); ...
最重要的是,我不清楚 struts2-rest-plugin URI 约定来调用每个不同的 CRUD 操作:
Struts-rest-plugin URL mappings (https://struts.apache.org/plugins/rest/): **Default** **Method** **Description** **Example** ------ ----------- ------- index() GET request with no id parameter. GET http://localhost:8080/StrutsContactsApp/contacts.json show() GET request with an id parameter. GET http://localhost:8080/StrutsContactsApp/contacts/1.json create() POST request with no id parameter and JSON/XML body. POST http://localhost:8080/StrutsContactsApp/contacts.json update() PUT request with an id parameter and JSON/XML body. PUT http://localhost:8080/StrutsContactsApp/contacts/65.json destroy() DELETE request with an id parameter. DELETE http://localhost:8080/StrutsContactsApp/contacts/33.json edit() GET request with an id parameter and the edit view specified. editNew() GET request with no id parameter and the new view specified. Struts-rest-plugin runtime automatically manages: - Parsing object ID from REST URI - Serializing/deserializing input parameters and return objects - By default, controller will implement interface com.opensymphony.xwork2.ModelDriven - By default, shouldn't need to (i.e. *shouldn't*) declare any packages or actions in struts.xml <= "Follow conventions", and struts2-rest-plugin will manage all the details...