1

我对 Spring 比较陌生,所以有一点对我来说不是很明显。即,控制器是单例的事实。我同意这是一个很好的方法,但这并不能让我实现我曾经用其他框架实现的东西。

我构建了一个使用 AJAX 请求的 Web 应用程序。我有BaseController作为父级的控制器层次结构,所有其他控制器都对其进行了扩展。

应该向客户端返回响应的控制器操作使用注释进行@ResponseBody注释,并将序列化的 JSON 字符串返回给客户端。

createJSONResponse()执行此序列化的方法在 中实现,BaseController这里的主要思想是每个子控制器的操作都Map<String, Object> responseMap使用客户端数据所需的映射填充一个映射,然后在 中访问该映射BaseController并对其进行序列化。

我不想responseMap在每个动作中创建新实例,也不想每次都将它作为createJSONResponse().

responseMap我通过在其他框架中声明BaseControllerprotected属性来实现这一点。

我不能用 Spring 做到这一点,因为所有控制器都是单例的,而且我不会有responseMap每个请求的新实例。

我不确定将BaseController请求范围设为一个好主意。

我创建了一个助手类作为请求范围的 bean,并在这个助手中声明了 responseMap。然后我将这个 bean 注入@AutowiredBaseController. 我还移出了createJSONResponse()这个助手中的方法。然后从控制器中,我将此地图填充为helper.responseMap.add(<somedata>)并调用helper.createResponseMap().

在这种情况下responseMap变为空createResponseMap(),它不包含在控制器操作中填充的数据。不知何故,它responseMAp不是线程安全的,并且随着每个异步请求从一个线程移动到另一个线程。

有什么方法可以实现我需要的功能吗?


通过变通方法 解决:通过在每个请求之前实例化 responseMap 并添加到请求拦截器中的 HttpServletRequest 对象来解决问题。然后createJSONResponse() 方法和responseMap 填充方法参考getRequestMap() 方法从HttpServletRequest 中获取responseMap。

PS Still 很高兴知道更好的解决方案。

4

1 回答 1

0

为了做到这一点(线程安全),您将被迫在某些时候为每个请求拥有该映射的一个实例(如果您真的想在单例中注入它,您可以使用范围代理 - 但是您'最终会得到完全相同的结果,只是更复杂。

我的建议是使用模板方法并摆脱该受保护的属性;只需定义一个抽象方法,它将在每个子类中返回填充的地图。

如果您只是想摆脱Map<String, Object> responseMap = new HashMap<String, Object>()在所有具体控制器中的编写,您可以在基本控制器中执行此操作(对于每个请求),然后仅使用抽象方法来填充该映射(但实例每次都是新的) )。

以下是它在基本控制器中的外观:

public String handleRequest() {
    Map<String, Object> model = new HashMap<String, Object>();
    populateModel(model);
    model.put("success", true);  // as a response to your comment
    return serializeModel(model);
}

protected abstract void populateModel(Map<String, Object> model);

PS 作为旁注(尽管这可能是您问题的实际答案),如果您只是将它们作为类型安全对象返回,Spring 能够以多种格式序列化您的响应。只需在您的类路径中包含 jackson 映射器(以启用 JSON 格式),在您的模型类上添加一些 JAXB 注释并将您的模型作为MyBean实例返回。鉴于您提供正确的Accept:标头或produces在请求映射中定义正确的标头,Spring 会将其编组为 XML / JSON。

于 2012-05-17T09:39:03.213 回答