【问题标题】:Return JSON or View from Spring MVC Controller从 Spring MVC 控制器返回 JSON 或 View
【发布时间】:2011-02-07 00:54:16
【问题描述】:

我想根据逻辑从 Spring MVC 控制器返回一个视图。如果发生错误,我想返回 JSON,如果没有,则返回 HTML 视图。这就像 ASP.NET MVC ActionResult,您可以在其中返回任何类型的视图,它将呈现结果,并且不依赖于请求中发送的内容类型。我找不到任何这样的例子。

【问题讨论】:

标签: json spring spring-mvc


【解决方案1】:

我通过以下方式实现了这一点。

@RequestMapping(value="/users", method=RequestMethod.POST)
public Object index(@RequestBody SearchUsersViewModel model, HttpServletResponse response) {

    model.setList(userService.getUsers(model));

    if(true)
    {
        return new ModelAndView("controls/tables/users", "model", model);
    }
    else
    {
        return JsonView.Render(model, response);
    }    
}

JsonView.java

public class JsonView {

    public static ModelAndView Render(Object model, HttpServletResponse response)
    {
        MappingJacksonHttpMessageConverter jsonConverter = new MappingJacksonHttpMessageConverter();

        MediaType jsonMimeType = MediaType.APPLICATION_JSON;


        try {
            jsonConverter.write(model, jsonMimeType, new ServletServerHttpResponse(response));
        } catch (HttpMessageNotWritableException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
}

调用的JS函数

config.request = $
                .ajax({
                    url : url,
                    data : $.toJSON(def.data),
                    type : def.type,
                    dataType : def.dataType,
                    processData : true,
                    contentType : def.contentType,
                    success : function(data) {

                        try {
                            var json = data;
                            if (typeof data === "String" || typeof data == "string") {
                                json = (eval('(' + data + ')'));
                            }
                            if ('object' === typeof json) {
                                if (json.Validation && json.Validation.Errors.length > 0) {

                                    $.each(json.Validation.Errors, function() {
                                        // Error Code Check
                                    });

                                    // Error Callback
                                    if (typeof (def.errorCallback) == 'function') {
                                        def.errorCallback(json);
                                    }
                                } else {
                                    def.callback(data);
                                }
                            } else {
                                def.callback(data);
                            }
                        } catch (e) {
                            def.callback(data);
                            // Hide Loading
                        }
                    },
                    error : function(data) {


                    }
                });

【讨论】:

  • 在您的代码中,您有 if (true) - 那么 JSON 什么时候返回?
  • 我只是在那里测试。我会测试返回对象中的错误,然后返回 json,否则返回 HTML。
【解决方案2】:

以防万一您想在异常时返回 Json,您可以执行以下操作:

@ExceptionHandler(Exception.class)
    @ResponseBody
      public void handleIOException(Exception exception,HttpServletRequest request, HttpServletResponse response) {
        response.setContentType("application/json");
        String json = "{\"Name\": 50}";
        PrintWriter out=    response.getWriter();
        out.write(json);
      }

我不确定这是你想要做的,但以防万一...... :)

【讨论】:

  • 如果控制器中发生错误,这会捕获它并返回 JSON 吗?
  • 我记得是的,它会抓住。
【解决方案3】:

对控制器进行编程以根据条件返回不同的逻辑视图名称。例如:

@RequestMapping(value="/hello/{name}", method=RequestMethod.GET)
public ModelAndView hello(@PathVariable String name) {
    String viewName = (name.length() > 1) ? "hello" : "error";
    ModelAndView mav = new ModelAndView(viewName);
    mav.addObject("name", name);
    return mav;
}

配置视图解析器以将视图名称 "error" 解析为 JSON 视图。 Spring提供了多种方式来配置视图名到视图映射,包括:

例如,使用 BeanNameViewResolver:

<bean name="error" class="org.springframework.web.servlet.view.json.MappingJacksonJsonView"/>

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
  <property name="order" value="1"/>
</bean>

【讨论】:

    【解决方案4】:

    没有什么可以阻止您直接从控制器方法返回实际的 View 对象 - 它不必是视图名称。因此,您的控制器可以使用自己的逻辑构造一个 View 对象,然后将其返回,无论是否包含在 ModelAndView 对象中。

    这可能比试图说服ViewResolver 框架不要为您执行此操作更简单,尽管这也可以。

    【讨论】:

      【解决方案5】:

      也许你可以看看ResolveBundleViewResolver,它可以让你混合视图。 docs 提供了一些关于如何使用它的信息。

      来自文档(示例是混合瓷砖和 jstl,但也应适用于其他人)...

      上下文文件

      <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
        <property name="basename" value="views"/>
      </bean>
      

      views.properties

      ...
      welcomeView.(class)=org.springframework.web.servlet.view.tiles2.TilesView
      welcomeView.url=welcome (this is the name of a Tiles definition)
      
      vetsView.(class)=org.springframework.web.servlet.view.tiles2.TilesView
      vetsView.url=vetsView (again, this is the name of a Tiles definition)
      
      findOwnersForm.(class)=org.springframework.web.servlet.view.JstlView
      findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp
      ...
      

      【讨论】:

        【解决方案6】:

        为了扩展 Chin Huang 的答案,这对我有用。无需配置。

        response.setStatus(500);
        return new ModelAndView(new MappingJacksonJsonView(), model);
        

        这将自动将模型转换为 JSON 并写入响应。 这里模型的类型是Map&lt;String,Object&gt;,响应的类型是HttpServletResponse

        【讨论】:

        • 每次需要返回一个新的 JSON 视图时实例化一个新的 JSON 视图是个坏主意。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多