2

我正在使用 struts2-rest-plugin 编写一个 REST 服务器。我正在使用 SoapUI 和 Postman 测试 REST 调用。我在这里关注示例代码:

https://cwiki.apache.org/confluence/display/WW/REST+Plugin

我的 REST 要求controller.index())并且controllers.create()工作正常。

但是虽然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)...
...

...它在“返回”时失败,出现以下错误:

...
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”;日志显示“没有为操作 com.example.contactsapp.controllers.ContactsController 和结果更新定义结果”

问:关于解决错误和让“update()”与 struts2-rest-plugin 一起工作的任何建议?

PS:我在“update()”、“show()”和“destroy()”这三个方面都遇到了类似的问题。每个都期望一个 id(我可以在 Eclipse 调试器中看到它被正确传递)。

还:

struts-rest-plugin 支持像http://localhost:8080/myapp/contacts.json(for JSON) 和http://localhost:8080/myapp/contacts.xml(for XML) 这样的 URL。我不确定“update()”是否需要contacts.json/id,或者只是contacts/id。都不工作:(

4

1 回答 1

0

好的 - 整个问题是我以“似乎合理”的方式采用了示例代码。但事实证明 struts2-rest-plugin 有许多我不知道的“潜规则”。具体来说:

  1. 默认情况下,struts2-rest-plugin 将预先指定的操作名称、、、和映射index()show()CRUD操作。create()update()destroy()

  2. 不需要在 struts.xml 中定义“包”或任何“动作”。除非我需要自定义,否则 Struts2-rest-plugin 想要自己管理这些细节。这是我最后得到的(最小的!)struts.xml:

  3. 我不想使用 .jsp(如示例)认为需要从每个操作中“返回一些东西”(如 JSON 响应)。

    相反,我只需要重定向到一个动作。例如:

    public HttpHeaders create() {
        log.debug("Creating new contact...", model);
        contactsRepository.addContact(model);
        return new DefaultHttpHeaders("index");
        ...
    
  4. 最重要的是,我不清楚 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...
    
于 2020-01-22T02:06:46.067 回答