小编典典
您要解决的问题是
return writer.writeValueAsString(getData);
造成太大的String并导致了OutOfMemoryError。Jackson支持Streaming
API(Spring在其中使用),该APIMappingJackson2HttpMessageConverter在响应正文(和请求正文)中处理将POJO序列化为JSON。
有几种方法可以解决此问题。最简单的方法是将您的返回类型更改为,Map
@RequestMapping(method = RequestMethod.POST,params = {"dynamicScenario"})
@ResponseBody
public Map getDynamicScenarioData(@RequestParam Map map) throws JsonParseException, JsonMappingException, IOException
{
ObjectMapper mapper = new ObjectMapper();
@SuppressWarnings("unchecked")
Map queryParameters = mapper.readValue(map.get("parameters") , Map.class);
Map getData = service.runDynamicScenario(queryParameters, map.get("queryString"));
return getData;
}
Spring将getData通过将结果直接流式传输到响应中来进行序列化OutputStream。
这将无法单独工作。例如,您用来访问服务的网址
/dynamicScenario.htm
导致Spring的内容协商开始。它看到.htm并认为您正在期待text/html内容。关闭内容协商或使用不带扩展名的URL
/dynamicScenario
然后,Spring将查看Accept标头,以弄清客户的期望。因为那是
dataType: "json"
它将application/json与一起写入MappingJackson2HttpMessageConverter。
这里还有一些要解决的问题
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ApplicationConfig.class);
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic servletRegistration = servletContext.addServlet("dispatcher", new DispatcherServlet(context));
servletRegistration.setLoadOnStartup(1);
servletRegistration.addMapping("*.htmlx");
您目前正在ContextLoaderListener和DispatcherServlet加载相同ApplicationContext。这是不必要的,并且可能有害。在DispatcherServlet已经使用的ContextLoaderListener上下文父上下文。
如果ApplicationConfig仅包含MVC配置元素,则仅DispatcherServlet加载它。您不需要ContextLoaderListener。
如果它具有与MVC堆栈无关的其他类型的配置元素,请将其分为两个@Configuration类。将MVC一个传递给DispatcherServlet,另一个传递给ContextLoaderListener。
不要将JSON作为表单参数传递。将其直接传递到请求正文中,并用于@RequestBody将其反序列化为所需的类型。
@RequestMapping(method = RequestMethod.POST)
@ResponseBody
public Map getDynamicScenarioData(@RequestBody Map queryParameters) throws JsonParseException, JsonMappingException, IOException
{
Map getData = service.runDynamicScenario(queryParameters, /* find a better way to pass this map.get("queryString") */);
return getData;
}
您ObjectMapper在每个请求上都为自己节省了一个对象(这是一个沉重的对象),并让Spring负责所有反序列化(再次进行流传输)。您必须找到另一种传递的方法queryString(您仍然可以将其作为单个查询参数传递,并通过`@RequestParam获取)。
2020-06-01