【问题标题】:Supporting multiple content types in a Spring-MVC controller在 Spring-MVC 控制器中支持多种内容类型
【发布时间】:2011-05-23 03:56:27
【问题描述】:

Rails 控制器可以很容易地支持多种内容类型。

respond_to do |format|
  format.js { render :json => @obj }
  format.xml
  format.html
end

美丽。在一个控制器操作中,我可以很容易地响应多种内容类型,并且对于我希望呈现的内容具有很大的灵活性,无论是模板、我的对象的序列化形式等。

我可以在 Spring-MVC 中做类似的事情吗? Spring中支持多种内容类型的标准是什么?我见过涉及视图解析器的解决方案,但这看起来很难管理,特别是如果我想支持除了 xhtml 和 xml 之外的 JSON。

欢迎提出任何建议,但更简单、更优雅的解决方案将受到更多赞赏;)

编辑

如果我断言视图解析器难以管理是不正确的,请随时纠正我并提供示例。最好是可以返回 xml、xhtml 和 JSON 的。

【问题讨论】:

    标签: java ruby-on-rails model-view-controller spring-mvc content-type


    【解决方案1】:

    这里是工作示例控制器,它根据请求标头“Content-Type”呈现 JSON 和 HTML。

    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.util.MimeTypeUtils;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestHeader;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class PersonService {
        @RequestMapping(value = "/persons/{userId}", method = RequestMethod.GET)
        public ResponseEntity<?> getPersonByName(@RequestHeader("Content-Type") String contentMediaType,
                @PathVariable("userId") String userId,@RequestParam("anyParam") boolean isAscending) throws IOException {
    
            Person person = getPersonById(userId);
            if (isJSON(contentMediaType)) {
                return new ResponseEntity<Person>(person, HttpStatus.OK);
            }
    
            return new ResponseEntity("Your HTML Goes Here", HttpStatus.OK);
            //Note: Above you could use any HTML builder framework, like HandleBar/Moustache/JSP/Plain HTML Template etc.
        }
    
    
        private static final boolean isJSON(String contentMediaType) {
            if ("application/json".equalsIgnoreCase(contentMediaType)) {
                return true;
            }
    
            return false;
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      在 Spring 3 中,您想使用 org.springframework.web.servlet.view.ContentNegotiatingViewResolver

      它需要一个媒体类型列表和ViewResolvers。来自Spring docs

      <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
          <map>
            <entry key="atom" value="application/atom+xml"/>
            <entry key="html" value="text/html"/>
            <entry key="json" value="application/json"/>
          </map>
        </property>
        <property name="viewResolvers">
          <list>
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
              <property name="prefix" value="/WEB-INF/jsp/"/>
              <property name="suffix" value=".jsp"/>
            </bean>
          </list>
        </property>
        <property name="defaultViews">
          <list>
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
          </list>
        </property>
      </bean>
      <bean id="content" class="com.springsource.samples.rest.SampleContentAtomView"/>
      

      控制器:

      import org.springframework.stereotype.Controller;
      import org.springframework.ui.ModelMap;
      import org.springframework.web.bind.annotation.RequestMapping;
      
      @Controller
      public class BlogsController {
      
          @RequestMapping("/blogs")
          public String index(ModelMap model) {
              model.addAttribute("blog", new Blog("foobar"));
              return "blogs/index";
          }    
      }
      

      您还需要包含 Jackson JSON jar。

      【讨论】:

      • 是否像 Rails 一样简单和“漂亮”?不。但按照 Java 标准,可能与我们将得到的一样好。
      • P.S. - 我只测试了 HTML 和 JSON 内容类型。我现在正在研究原子。
      • @Todd:谢谢!不过这有点令人困惑。如果我返回字符串“blogs/index”,我的任何视图如何与我的模型交互?我期待它返回一个 ModelAndView 对象,我们会将字符串“blogs/index”传递给该对象,然后如果客户端请求 JSON,Spring 将忽略该字符串并通过 Jackson 序列化该对象。你能解释一下你的例子是如何工作的吗?
      • @Samo,博客模型在模型中设置,传入(通过引用)并作为“博客”提供给视图。视图“blogs/index”映射到“WEB-INF/jsp/blogs/index.jsp”。是的,当我将 .json 添加到我的 url 时,“/blogs.json”视图被忽略并打印 {"blog":{"name":"foobar"}}
      • @Samo,你也可以使用 ModelAndView。我刚试过。 @RequestMapping("/blogs") public ModelAndView index() { Blog blog = new Blog("foobar"); ModelAndView model = new ModelAndView("blogs/index", "blog", blog);返回模型; }
      猜你喜欢
      • 2018-07-17
      • 2018-08-05
      • 1970-01-01
      • 1970-01-01
      • 2016-11-17
      • 1970-01-01
      • 2014-04-06
      • 2021-04-12
      • 1970-01-01
      相关资源
      最近更新 更多