You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不刷新页面、不重定向的情况下从Thymeleaf视图触发Spring MVC控制器方法

实现Thymeleaf触发Spring MVC方法无页面刷新的方案

问题的核心在于你当前用的是传统同步表单提交,浏览器会在提交后自动跳转到请求的URL,这就是页面刷新/跳转的原因。要实现只执行业务逻辑、不刷新页面的效果,我们需要用异步AJAX请求来替代表单提交,之后再通过JavaScript手动处理DOM元素的移除。

下面是具体的实现步骤:


1. 修改HTML按钮结构

首先,我们不需要传统的<form>标签(因为会触发同步提交),直接给按钮添加标识来存储itemId,同时给对应的item行添加标记,方便后续移除:

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

这里用data-item-id属性存储物品ID,给按钮添加统一的类名block-item-btn,给父容器添加item-row类,方便后续定位要移除的元素。


2. 编写异步请求的JavaScript代码

使用现代的fetch API发送异步GET请求,监听按钮点击事件,请求成功后移除对应的item行:

// 页面加载完成后绑定事件
document.addEventListener('DOMContentLoaded', function() {
  // 给所有"block item"按钮绑定点击事件
  document.querySelectorAll('.block-item-btn').forEach(button => {
    button.addEventListener('click', async function() {
      const itemId = this.dataset.itemId;
      
      try {
        // 发送异步GET请求到控制器
        const response = await fetch(`/items/block/${itemId}`, {
          method: 'GET',
          headers: {
            'Accept': 'application/json' // 可选,标识接受JSON响应
          }
        });

        if (response.ok) {
          // 请求成功:移除对应的item行
          const targetRow = document.querySelector(`.item-row[data-item-id="${itemId}"]`);
          if (targetRow) {
            targetRow.remove();
          }
        } else {
          // 请求失败:提示用户
          alert('Failed to block the item. Please try again.');
        }
      } catch (error) {
        // 捕获网络错误
        console.error('Error blocking item:', error);
        alert('An unexpected error occurred.');
      }
    });
  });
});

3. 控制器代码(可选优化)

你当前的控制器代码已经可以正常工作,因为@ResponseStatus(HttpStatus.OK)配合void返回值会告诉Spring MVC返回200状态码,不需要额外处理。如果想更明确地返回响应,可以改成返回ResponseEntity<Void>:

@GetMapping("/items/block/{itemId}")
public ResponseEntity<Void> blockItem(@PathVariable String itemId) {
    itemService.blockItem(itemId);
    return ResponseEntity.ok().build();
}

两种写法都能满足需求,选你觉得更清晰的即可。


4. 注意:CSRF防护处理

如果你的Spring Boot应用启用了CSRF防护(默认是启用的),需要在请求中携带CSRF令牌,否则会被拦截。可以在HTML的<head>中添加以下meta标签:

<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>

然后修改JavaScript中的fetch请求,在headers里添加CSRF令牌:

// 获取CSRF令牌和头部名称
const csrfToken = document.querySelector('meta[name="_csrf"]').content;
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content;

// 修改fetch的headers部分
headers: {
  'Accept': 'application/json',
  [csrfHeader]: csrfToken
}

这样修改后,点击"block item"按钮时,浏览器会在后台发送异步请求,控制器执行业务逻辑,页面不会刷新,请求成功后对应的item行会被自动移除,完全符合你的需求。

内容的提问来源于stack exchange,提问作者DimaSan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 15:52:43