我可以在Spring Boot应用程序中从Thymeleaf表发出HTTP POST请求

时间:2016-07-23 20:23:03

标签: html http-post thymeleaf http-get

我在一个简单的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。

2 个答案:

答案 0 :(得分:7)

您正在使用链接而我认为不可能,您需要使用一个表单来指定要使用的POST方法。

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

<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,就像控制器的操作一样

答案 1 :(得分:2)

有人知道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