触发 Spring 没有页面的 MVC 控制器方法 redirect/refresh

Triggering Spring MVC controller method without page redirect/refresh

我想从 Thymeleaf 视图触发 Spring MVC 控制器方法而不从该方法返回任何内容并且不刷新页面。

我有以下 HTML 页面:

<!-- 'block item' button code-->
<div class="row">
  <form method="get" th:action="@{'/items/block/' + ${item.itemId}}">
      <button type="submit" class="btn btn-warning">block item</button>
  </form>
</div>

相关控制器如下所示:

@GetMapping("/items/block/{itemId}")
@ResponseStatus(value = HttpStatus.OK)
public void blockItem(@PathVariable String itemId) {
    itemService.blockItem(itemId);
}

itemService.blockItem(itemId) 调用只是更改数据库中相关 item 对象的相应布尔属性。

目前,每次当我按下 阻止项目 按钮触发此方法时,我都会被重定向到 URL,例如 http://localhost:8080/item/block/7C4A3744375523

我不想做任何重定向,只是执行相关的服务方法逻辑。我还需要从视图中删除相关项 div,但我可以使用 JavaScript.
非常简单地完成此操作 我该怎么做?谢谢。

您的按钮定义为 type submit.

因此,当您单击它时,将提交表单。

要防止这种默认行为,您需要做几件事:主要思想是为表单 submit 事件定义一个处理程序,并使用 Javascript 执行实际的服务器调用。

您可以在 different ways 中执行此操作,但我认为最好使用事件处理程序来定义所需的行为并将 HTML 代码与 Javascript 尽可能分开可能。

此外,您似乎正在遍历项目列表。

考虑到这两点,请考虑以下代码片段:

<script>
  // We use the DOMContentLoaded event (https://developer.mozilla.org/en-US/docs/Web/API/Document/DOMContentLoaded_event)
  // but please, register the form event as you consider appropriate
  document.addEventListener('DOMContentLoaded', () => {
    // Register form submit event handler for every form in your page
    const forms = document.querySelectorAll('form');
    if (forms) {
      forms.forEach(f => {
        let action = f.action;
        f.addEventListener('submit', (event) => {
          // prevent default behavior, i.e., form submission
          event.preventDefault();
          // perform server side request. you can use several options
          // see https://developers.google.com/web/updates/2015/03/introduction-to-fetch, for instance
          // For example, let's use fetch (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
          fetch(action)
            .then((response) => {
              if (!response.ok) {
                throw new Error('Network response was not ok');
              }
              console.log('Request successfully completed');
            })
            .catch((error) => {
              console.error('There has been a problem while contacting server:',      error);
            });
          });
      });
    }
  });
</script>

事实上,您可以去掉表格。请考虑一种稍微不同的方法。首先,在遍历您的项目时,生成以下 HTML 块(如果您愿意,可以使用 data 或任何自定义属性来存储当前处理的项目 ID):

<!-- 'block item' button code-->
<div class="row">
  <button type="button" class="btn btn-warning item-button" th:id="${item.itemId}">block item</button>
</div>

现在,以与上述类似的方式,为每个项目按钮注册处理程序:

<script th:inline="javascript">
  document.addEventListener('DOMContentLoaded', () => {
    // Register handlers for every button
    const buttons = document.querySelectorAll('.item-button');
    if (buttons) {
      buttons.forEach(b => {
        b.addEventListener('click', (event) => {
          let itemId = b.getAttribute('id');
          let link = /*[[@{/items/block/}]]*/ 'link';
          // Perform server side request
          fetch(link + itemId)
            .then((response) => {
              if (!response.ok) {
                throw new Error('Network response was not ok');
              }
              console.log('Request successfully completed');
            })
            .catch((error) => {
              console.error('There has been a problem while contacting server:', error);
            });
        });
      }
    }
  });
</script>

导致重定向的不是 Thymeleaf 或 Spring MVC,而是 form 标签中的 submit 按钮。您需要覆盖此按钮的行为以通过 Ajax 发送表单数据并自行处理响应(基本上 - 忽略它) - 例如使用 jQuery 它可能看起来像:

<!-- 'block item' button code-->
<div class="row">
    <form id="someFormId" method="get" th:action="@{'/items/block/' + ${item.itemId}}">
        <button type="submit" class="btn btn-warning">block item</button>
    </form>
</div>

//...

$('#someFormId').submit(function(e) {
    e.preventDefault();
    $.ajax({
        type: 'GET',
        url: '@{'/items/block/' + ${item.itemId}}',
        data: $(this).serialize(),
        // here you can define some actions for beforeSend, success, etc...
        // for example to just ignore:
        success: function(){}
    });
})

有很多想法可以解决这个问题。请阅读例如

  • Prevent redirect after form is submitted
  • How to submit an HTML form without redirection