【问题标题】:Scala, @ResponseBody, and MapScala、@ResponseBody 和 Map
【发布时间】:2016-01-08 07:08:31
【问题描述】:

我正在 spring3 项目中试验 Scala,当我返回带有 @ResponseBody 的地图时,我没有得到我期望的结果。我在 java 中包含了一个工作示例以及我在 scala 中的尝试

// This is Java
@RequestMapping(value="/pbx.admin", method=RequestMethod.GET)
public @ResponseBody Map<String, Object> getInfo2(HttpServletRequest request, Model model){
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("pbx", "admin");
    map.put("method", "s");
    return map;
}

java 返回 json 并定义了 pbx & 方法,这是我所期望的。

// This is Scala
@RequestMapping(value= Array("/pbx.admin"), 
  method=Array(RequestMethod.GET))
@ResponseBody
def getInfo2() = {
  Map("pbx" -> "admin", "method" -> "s")
}

scala 会返回一些不同的东西:

{
    empty: false,
    traversableAgain: true
}

我需要做什么才能获得我的地图键/值?

为了获得额外的荣誉,有没有更好的“scala 方式”来做到这一点?谢谢!

【问题讨论】:

    标签: spring scala spring-mvc


    【解决方案1】:

    Spring MVC 框架在构建时并未考虑到 Scala,并且它无法识别 Scala 的 Map。您必须将 scala.collection.Map 转换为 java.util.Map。您可以使用隐式转换:

    import collection.JavaConversions._
    
    def getInfo2(): java.util.Map[String, String] = {
      Map("pbx" -> "admin", "method" -> "s")
    }
    

    或手动转换:

    import collection.JavaConverters._
    
    def getInfo2() = {
      Map("pbx" -> "admin", "method" -> "s").asJava
    }
    

    注意导入,它们很重要。

    我怀疑 Spring 可以被黑客入侵以接受 Scala 集合,但显然不是开箱即用的。

    【讨论】:

    • 所以,当 Spring MVC 没有将 scala.collection.Map 识别为 Map 时,它决定应用它用来序列化 JavaBeans 的策略,即查找所有符合 JavaBean 约定的方法,并将它们用作 JSON 对象的元素。有两种方法可以满足这些条件:isEmptyisTraversableAgain
    • @KenBloom:确切地说,+1 表示好评。当您尝试返回 Scala 的 List 时,也会发生类似的情况。
    • @KenBloom Neat,我期望发生的事情是在编译时将我的地图转换为 java.util.HashMap,但那是我是一个 scala 新手 :)
    【解决方案2】:

    Spring MVC 使用 Jackson。您需要将 Jackson scala 模块注册为映射器。这为 Jackson 添加了对 scala 的支持,使其能够识别集合。

    例子:

    import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.scala.ScalaModule import com.fasterxml.jackson.module.scala.DefaultScalaModule class ScalaObjectMapper extends ObjectMapper { { registerModule(DefaultScalaModule) } }

    然后你需要将它添加到你的消息转换器

    <mvc:annotation-driven> <mvc:message-converters> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.petzfactor.packwall.web.module.ScalaObjectMapper"></bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>

    该模块在 github 上https://github.com/FasterXML/jackson-module-scala

    【讨论】:

      【解决方案3】:

      Scala 模块需要序列化 ​​scala 对象,例如 Collections、Option 和 case 类。这是一种仅通过修改 Spring 上下文来注册 Jackson Scala 模块的方法。

      <mvc:annotation-driven>
          <mvc:message-converters>
              <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                  <property name="objectMapper" ref="objectMapperWithScala"/>
              </bean>
          </mvc:message-converters>
      </mvc:annotation-driven>
      <bean name="scalaModule" class="com.fasterxml.jackson.module.scala.DefaultScalaModule"/>
      <bean name="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>
      <bean name="objectMapperWithScala" factory-bean="objectMapper" factory-method="registerModule">
          <constructor-arg ref="scalaModule"/>
      </bean>
      

      【讨论】:

        猜你喜欢
        • 2017-02-02
        • 2016-11-28
        • 1970-01-01
        • 2012-01-26
        • 1970-01-01
        • 2015-09-23
        • 2012-02-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多