【问题标题】:Can I make HTTP POST request from Thymeleaf table in Spring Boot application我可以在 Spring Boot 应用程序中从 Thymeleaf 表发出 HTTP POST 请求吗
【发布时间】:2016-11-27 12:25:18
【问题描述】:

我在一个简单的 Spring Boot 应用程序中有一个 Thymeleaf 模板。该模板包含一个表中的列表,如下所示:

<p>There are <span th:text="${#lists.size(persons)}"></span> people:</p>
<table th:if="${not #lists.isEmpty(persons)}" border="1">
    <tr>
        <th>ID</th>
        <th>Name</th>
        <th>Address</th>
        <th>Telephone</th>
        <th>Email</th>
        <th>Actions</th>
    </tr>
    <tr th:each="person : ${persons}">
        <td th:text="${person.personId}"></td>
        <td th:text="${person.name}"></td>
        <td th:text="${person.address}"></td>
        <td th:text="${person.telephone}"></td>
        <td th:text="${person.email}"></td>
        <td>
            <a href="#" data-th-href="@{/edit(personId=${person.personId})}">Edit</a> |
            <a href="#" data-th-href="@{/delete(personId=${person.personId})}">Delete</a>
        </td>
    </tr>
</table>

我想根据表格中的最后一个单元格启用编辑和删除功能。但目前这两个请求都是针对 HTTP GET 的。这对于从服务器获取一个人的详细信息进行编辑的编辑来说很好,但由于服务器上的数据更改,删除应该触发一个 POST 请求。

有谁知道 Thymeleaf 是否允许每行表的 POST 请求?还是我必须每行编写一个简单的 HTML 表单?

GET 表单当前是:

<td>
    <a href="#" data-th-href="@{/edit(personId=${person.personId})}">Edit</a>
    <!--a href="#" data-th-href="@{/delete(personId=${person.personId})}">Delete</a></td-->
    <form method="get" th:action="@{/edit(personId=${person.personId})}">
        <button type="submit" name="submit" value="value">Edit</button>
    </form>
</td>

我有一个链接和一个测试表格。

要调用的控制器方法是:

// Gets a Person.
@RequestMapping(value="/edit", method=RequestMethod.GET)
public String getEditPerson(@RequestParam("personId") String personId, Model model) {
    logger.info(PersonController.class.getName() + ".getEditPerson() method called."); 

    Person person = personDAO.get(Integer.parseInt(personId));
    model.addAttribute("person", person);

    // Set view.      
    return "/edit";
}    

按钮版GET调用时的错误是:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Jul 24 00:26:16 BST 2016
There was an unexpected error (type=Bad Request, status=400).
Required String parameter 'personId' is not present`

我正在使用 GET 来触发编辑,因为这里除了 personId 之外没有数据发送到服务器。没有采取任何数据库操作,所以它应该是一个 GET。

【问题讨论】:

    标签: html http-post thymeleaf http-get


    【解决方案1】:

    有谁知道 Thymeleaf 是否允许每行表的 POST 请求?还是我必须每行编写一个简单的 HTML 表单?

    HTML 不支持带有链接的 POST 请求,您必须使用表单(正如 Rayweb_on 解释的那样)。但是 Thymeleaf 允许您定义自定义标签,这很有帮助:

    <a th:href="@{/edit(personId=${person.personId})}" custom:linkMethod="post">Edit</a>
    

    ... 这将生成以下 HTML(假设 jQuery 可用):

    <a href="#" onclick="$('<form action=&quot;/edit/personId=123456&quot; method=&quot;post&quot;></form>').appendTo('body').submit(); return false;">Edit</a>
    

    自定义标签定义(没有错误检查以保持简单):

    /**
     * Custom attribute processor that allows to specify which method (get or post) is used on a standard link.
     */
    public class LinkMethodAttrProcessor extends AbstractAttributeTagProcessor {
    
        private static final String ATTR_NAME = "linkMethod";
        private static final int PRECEDENCE = 10000;
    
        public LinkMethodAttrProcessor(final String dialectPrefix) {
            super(
                    TemplateMode.HTML, // This processor will apply only to HTML mode
                    dialectPrefix,     // Prefix to be applied to name for matching
                    null,              // No tag name: match any tag name
                    false,             // No prefix to be applied to tag name
                    ATTR_NAME,         // Name of the attribute that will be matched
                    true,              // Apply dialect prefix to attribute name
                    PRECEDENCE,        // Precedence (inside dialect's own precedence)
                    true);             // Remove the matched attribute afterwards
        }
    
        @Override
        protected void doProcess(final ITemplateContext context, final IProcessableElementTag tag,
                                 final AttributeName attributeName, final String attributeValue,
                                 final IElementTagStructureHandler structureHandler) {
    
            // get the method name (tag parameter)
            final IEngineConfiguration configuration = context.getConfiguration();
            final IStandardExpressionParser parser = StandardExpressions.getExpressionParser(configuration);
            final IStandardExpression expression = parser.parseExpression(context, attributeValue);
            final String method = (String) expression.execute(context);
    
            // add custom javascript to change link method
            final String link = tag.getAttribute("href").getValue();
            final String action = "$('<form action=&quot;" + link + "&quot; method=&quot;" + method + "&quot;></form>').appendTo('body').submit(); return false;";
            structureHandler.setAttribute("onclick", action);
            structureHandler.setAttribute("href", "#");
        }
    }
    

    请参阅the Thymelead documentation,了解如何注册此自定义属性。

    【讨论】:

      【解决方案2】:

      您正在使用链接,我认为这是不可能的,您需要使用可以指定要使用的方法 POST 的表单。

      在下面的示例中,我使用 &lt;button&gt; 而不是 &lt;a&gt; 元素,但它会起作用,您唯一需要做的就是使用 CSS 设置按钮样式,使其看起来像您的链接

      <form method="POST" th:action="@{/edit(personId=${person.personId})}">
          <button type="submit" name="submit" value="value" class="link-button">This is a link that sends a POST request</button>
      </form> 
      

      现在你的代码应该是这样的

      <tr th:each="person : ${persons}">                
          <td th:text="${person.personId}"></td>
          <td th:text="${person.name}"></td>
          <td th:text="${person.address}"></td>
          <td th:text="${person.telephone}"></td>
          <td th:text="${person.email}"></td>
          <td>
              <form method="POST" th:action="@{/edit(personId=${person.personId})}">
                  <button type="submit" name="submit" value="value" class="link-button">EDIT</button>
              </form> | 
              <form method="POST" th:action="@{/delete(personId=${person.personId})}">
                  <button type="submit" name="submit" value="value" class="link-button">DELETE</button>
              </form>
          </td>
      </tr>
      

      编辑

      正如您刚刚分享的 Java 代码一样,在控制器中您期望的 personId 不是 PathVariable,而是 RequestParam, 在这种情况下,您的表单应该具有该值...

      编辑您的表单并添加人员 ID,如下所示。

      <form method="POST" th:action="@{/edit}">
          <input type="hidden" name="personid" id="personId" th:value="${person.personId}" />
          <button type="submit" name="submit" value="value" class="link-button">This is a link that sends a POST request</button>
      </form> 
      

      还请注意,我将表单的操作更改为只是 /edit,因为它是您的控制器的样子

      【讨论】:

      • 很奇怪,删除表单的 POST 有效,但编辑的 GET 无效。
      • 详情已发布到问题中。
      • 错误告诉您您的帖子中缺少请求参数
      猜你喜欢
      • 2020-06-05
      • 1970-01-01
      • 2017-07-18
      • 2014-08-30
      • 1970-01-01
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      • 2011-02-28
      相关资源
      最近更新 更多