Tomcat项目中通过Ajax JSON传递JS Map至Servlet的内容获取问题
解决Tomcat Servlet接收JavaScript Map的问题
嘿,我碰到过类似的坑,这就帮你捋清楚问题出在哪以及怎么解决!
问题根源
你之前用request.getParameterValues("datos")拿不到实际内容,是因为这个方法是用来获取**表单格式(application/x-www-form-urlencoded)**的请求参数,而你发送的是JSON格式的数据——要么是请求体里的纯JSON,要么是表单参数里的JSON字符串,但getParameterValues返回的是字符串数组,直接打印就会显示对象引用([Ljava.lang.String@xxx),根本没解析JSON内容。
正确解决方案步骤
1. 前端修正:正确转换Map并发送JSON
首先,JavaScript的Map直接用JSON.stringify会转成空对象{},所以得先把Map转成普通对象,再转JSON字符串。同时要设置正确的请求头,告诉后端这是JSON数据:
// 假设你的ticket Map结构是这样的 const ticket = new Map(); ticket.set('ticket1', { nombre: 'Entrada VIP', precio: 150, cantidad: 1 }); ticket.set('ticket2', { nombre: 'Entrada General', precio: 80, cantidad: 2 }); // 把Map转为普通对象(关键!不然JSON.stringify会得到空对象) const ticketObj = Object.fromEntries(ticket); const jsonData = JSON.stringify(ticketObj); // 发送Ajax请求 $.ajax({ url: '/TuServletPath', // 替换成你的Servlet路径 type: 'POST', contentType: 'application/json', // 必须设置这个请求头 data: jsonData, // 直接把JSON字符串作为请求体发送 success: function(res) { console.log("数据发送成功!", res); }, error: function(xhr, err) { console.error("发送失败:", err); } });
2. 后端Servlet:读取并解析JSON
后端需要读取请求体里的JSON字符串,然后用JSON解析库(比如Gson或Jackson)把它转成Java的Map或者自定义对象。这里以Gson为例:
第一步:添加Gson依赖(Maven项目)
如果是Maven,在pom.xml里加:
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.10.1</version> <!-- 用最新稳定版 --> </dependency>
第二步:Servlet代码修改
import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.BufferedReader; import java.io.IOException; import java.util.Map; @WebServlet("/TuServletPath") public class TicketServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 1. 读取请求体中的JSON字符串 BufferedReader reader = request.getReader(); StringBuilder jsonBuilder = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { jsonBuilder.append(line); } String jsonStr = jsonBuilder.toString(); // 2. 用Gson解析JSON为Java的Map<String, Ticket> Gson gson = new Gson(); // 这里用TypeToken来指定泛型类型,避免类型擦除问题 Map<String, Ticket> ticketMap = gson.fromJson( jsonStr, new TypeToken<Map<String, Ticket>>() {}.getType() ); // 3. 现在可以正常遍历Map获取内容了! for (Map.Entry<String, Ticket> entry : ticketMap.entrySet()) { String ticketId = entry.getKey(); Ticket ticket = entry.getValue(); System.out.println("Ticket ID: " + ticketId); System.out.println("Nombre: " + ticket.getNombre()); System.out.println("Precio: " + ticket.getPrecio()); System.out.println("Cantidad: " + ticket.getCantidad()); } // 给前端返回响应 response.setContentType("application/json"); response.getWriter().write("{\"status\":\"success\",\"message\":\"数据接收完成\"}"); } // 自定义Ticket类,用来映射JSON中的对象结构 static class Ticket { private String nombre; private double precio; private int cantidad; // Gson需要无参构造函数,必须写! public Ticket() {} // Getter和Setter方法 public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public double getPrecio() { return precio; } public void setPrecio(double precio) { this.precio = precio; } public int getCantidad() { return cantidad; } public void setCantidad(int cantidad) { this.cantidad = cantidad; } } }
备选方案:如果坚持用表单参数传递JSON
如果你不想改请求格式,还是把JSON作为表单参数datos发送,那前端可以这样写:
$.ajax({ url: '/TuServletPath', type: 'POST', data: { datos: jsonData }, // 把JSON字符串作为表单参数传递 success: function(res) { ... } });
后端就不用读请求体了,直接拿参数再解析:
String jsonStr = request.getParameter("datos"); // 后面的解析步骤和上面一样...
关键注意点
- 不要直接JSON.stringify JavaScript的Map,必须转成普通对象(
Object.fromEntries(ticket)) - 后端解析JSON时,必须用泛型类型(比如
TypeToken)来避免Java的类型擦除问题 - 确保添加了正确的JSON解析库依赖(Gson或Jackson都可以,选一个你熟悉的)
内容的提问来源于stack exchange,提问作者Abraham
相关产品推荐
相关产品推荐

