Thymeleaf如何优雅地提交JSON请求:前端与后端交互实践指南
在Web开发中,Thymeleaf作为一款流行的服务器端模板引擎,常用于动态渲染HTML页面,虽然它以处理模板见长,但在前后端分离或需要提交复杂数据的场景下,如何让Thymeleaf页面发起JSON格式的请求并正确处理响应,是许多开发者关心的问题,本文将详细介绍Thymeleaf页面提交JSON请求的完整流程,包括前端实现、后端接收及跨域等关键环节。
Thymeleaf页面提交JSON请求的核心思路
Thymeleaf本质上是一个模板引擎,最终生成的是静态HTML页面,提交JSON请求”本质上是在HTML页面中通过JavaScript发起AJAX请求,并将数据以JSON格式发送给后端,Thymeleaf的作用是为页面提供动态数据(如初始表单数据、用户信息等),而实际的请求发送由前端JavaScript完成。
前端实现:Thymeleaf页面发起JSON请求
准备Thymeleaf模板与数据
在Thymeleaf模板中定义页面结构,并通过th:object、th:field等属性绑定数据,或直接通过th:attr、th:each等动态生成HTML元素,假设有一个用户表单页面:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">用户提交示例</title>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
<h1>用户信息提交</h1>
<form id="userForm">
<div>
<label>姓名:</label>
<input type="text" id="name" name="name" th:value="${user?.name}" />
</div>
<div>
<label>年龄:</label>
<input type="number" id="age" name="age" th:value="${user?.age}" />
</div>
<div>
<label>邮箱:</label>
<input type="email" id="email" name="email" th:value="${user?.email}" />
</div>
<button type="button" onclick="submitUser()">提交</button>
</form>
<!-- 动态加载的脚本(可选,用于处理Thymeleaf传递的数据) -->
<script th:inline="javascript">
// 获取Thymeleaf后端传递的变量(如初始用户数据)
const initialUser = /*[[${user}]]*/ {};
console.log("初始用户数据:", initialUser);
</script>
</body>
</html>
th:value="${user?.name}":从后端模型中获取user对象的name属性并填充到输入框(防止user为空时报错)。th:inline="javascript":Thymeleaf提供的JavaScript内联功能,可直接在JS中访问后端变量(如/*[[${user}]]*/)。
使用JavaScript发起JSON请求
在Thymeleaf页面中,通过axios(或fetch、jQuery.ajax)发起POST或PUT请求,并将表单数据转换为JSON格式,以下是使用axios的示例:
// 方式1:直接构造JSON对象
function submitUser() {
const userData = {
name: document.getElementById("name").value,
age: parseInt(document.getElementById("age").value),
email: document.getElementById("email").value
};
axios.post("/api/users", userData, {
headers: {
"Content-Type": "application/json" // 关键:指定请求体为JSON
}
})
.then(response => {
console.log("提交成功:", response.data);
alert("用户信息提交成功!");
})
.catch(error => {
console.error("提交失败:", error);
alert("提交失败,请检查数据格式!");
});
}
// 方式2:通过FormData转换(适合复杂表单,但需手动转JSON)
function submitUserWithFormData() {
const formData = new FormData(document.getElementById("userForm"));
const userData = Object.fromEntries(formData.entries()); // FormData转普通对象
userData.age = parseInt(userData.age); // 类型转换
axios.post("/api/users", JSON.stringify(userData), { // 手动序列化为JSON字符串
headers: {
"Content-Type": "application/json"
}
});
}
关键点说明:
Content-Type头:必须设置为application/json,否则后端无法正确解析JSON数据。- 数据序列化:
axios会自动将JavaScript对象序列化为JSON字符串(无需手动JSON.stringify),但fetch等工具可能需要手动处理。 - Thymeleaf数据传递:通过
th:inline="javascript"可将后端数据(如user对象)直接注入JS变量,用于初始化请求参数或默认值。
后端实现:接收Thymeleaf发送的JSON数据
后端框架(如Spring Boot)通过@RequestBody注解接收JSON格式的请求体数据,以下是Spring Boot的示例:
实体类定义
public class User {
private String name;
private Integer age;
private String email;
// 必须提供无参构造器(JSON反序列化需要)
public User() {}
// getter/setter
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
控制器接收JSON请求
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserController {
@PostMapping("/api/users")
public String createUser(@RequestBody User user) { // @RequestBody将请求体映射为User对象
System.out.println("接收到用户数据:" + user);
// 业务逻辑:保存用户到数据库等
return "{\"status\":\"success\", \"message\":\"用户创建成功\", \"id\":" + 123 + "}";
}
}
关键点说明:
@RequestBody注解:用于将HTTP请求体(JSON字符串)自动转换为Java对象(需配合Jackson或Gson等JSON库,Spring Boot默认已集成Jackson)。- 请求头匹配:前端设置的
Content-Type: application/json需与后端期望的格式一致,否则会抛出415 Unsupported Media Type错误。 - 响应格式:后端可直接返回JSON字符串(需设置
@ResponseBody),或通过ResponseEntity封装更复杂的响应(如状态码、头信息)。
跨域问题与解决方案
如果Thymeleaf页面与后端API接口不在同源(不同协议、域名或端口),浏览器会因同源策略(Same-Origin Policy)阻止AJAX请求,导致跨域错误(如Access-Control-Allow-Origin),解决方法:
后端配置CORS(推荐)
Spring Boot通过@CrossOrigin注解或全局配置允许跨域请求:
方式1:接口级别注解
import org.springframework.web.bind.annotation.CrossOrigin;
@RestController
public class UserController {
@PostMapping("/api/users")
@CrossOrigin(origins = "http://localhost:8080") // 允许来自http://localhost:8080的请求
public String createUser(@RequestBody User user) {
return "{\"status\":\"success\"}";
}
}
方式2:全局配置(推荐)
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**") // 对/api/**路径下的所有接口生效
.allowedOrigins("http://localhost:8080") // 允许的前端域名
.allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
.allowedHeaders("*") // 允许所有请求头
.allowCredentials(true); // 允许携带Cookie(可选)
}
}
前端代理(适用于开发环境)
若前端与后端未分离(如Thymeleaf应用与后端服务在同一项目),可通过Spring Boot的代理功能转发请求,避免跨域问题(无需额外配置)。
完整流程示例:Spring Boot + Thymeleaf提交JSON
项目结构
src/main/java/
├── com/example/demo/
│ ├── Demo


还没有评论,来说两句吧...