从Spring MVC Controller返回JSON或View

时间:2022-10-18 14:16:00

I am wanting to return a view from a Spring MVC Controller depending on logic. If an error occurs I want to return JSON, if not, an HTML view. This is like ASP.NET MVC ActionResult, where you can return any kind of view and it will render the result, and it won't depend on the content-type being sent in the request. I can't find any examples of this.

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

6 个解决方案

#1


17  

I achieved this with the following.

我用以下方法实现了这一点。

@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

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 Function that makes the call

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) {


                    }
                });

#2


5  

Just in case and you want to return Json on exception you can do the following:

以防万一你想要在异常时返回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);
      }

I'm not sure that this is what you wanted to do, but just in case.... :)

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

#3


4  

Program your controller to return a different logical view name depending on a condition. For example:

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

@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;
}

Configure the view resolvers to resolve the view name "error" to the JSON view. Spring provides many ways to configure the view name to view mapping, including:

配置视图解析程序以将视图名称“error”解析为JSON视图。 Spring提供了许多方法来配置视图名称以查看映射,包括:

  • XmlViewResolver which reads bean definition XML files,
  • XmlViewResolver读取bean定义XML文件,
  • ResourceBundleViewResolver which reads properties files, and
  • ResourceBundleViewResolver读取属性文件,和
  • BeanNameViewResolver which looks in the application context of the executing DispatcherServlet for a bean having the same name as the view name.
  • BeanNameViewResolver,它在正在执行的DispatcherServlet的应用程序上下文中查找与视图名称同名的bean。

For example, to use BeanNameViewResolver:

例如,要使用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


2  

There's nothing to prevent you from returning an actual View object directly from your controller method - it doesn't have to be a view name. So your controller can construct a View object using its own logic, and return that, with or without being wrapped in a ModelAndView object.

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

This is probably simpler than trying to persuade the ViewResolver framework from doing this for you, although that would work as well.

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

#5


0  

Perhaps you can look at ResolveBundleViewResolver, which allows you to mix views. The docs give some info on how to use this.

也许您可以查看ResolveBundleViewResolver,它允许您混合视图。文档提供了有关如何使用它的一些信息。

From the docs (example is to mix tiles and jstl, but should apply for others as well)...

从文档(例如混合瓷砖和jstl,但也应该适用于其他人)...

context file

上下文文件

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

views.properties

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


-1  

To extend Chin Huang's answer, here is what works for me. No configuration required.

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

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

This will automatically convert the model into JSON and write to response. Here model is of type Map<String,Object> and response is of type HttpServletResponse

这将自动将模型转换为JSON并写入响应。这里的模型是Map 类型,响应类型为HttpServletResponse ,object>

#1


17  

I achieved this with the following.

我用以下方法实现了这一点。

@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

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 Function that makes the call

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) {


                    }
                });

#2


5  

Just in case and you want to return Json on exception you can do the following:

以防万一你想要在异常时返回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);
      }

I'm not sure that this is what you wanted to do, but just in case.... :)

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

#3


4  

Program your controller to return a different logical view name depending on a condition. For example:

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

@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;
}

Configure the view resolvers to resolve the view name "error" to the JSON view. Spring provides many ways to configure the view name to view mapping, including:

配置视图解析程序以将视图名称“error”解析为JSON视图。 Spring提供了许多方法来配置视图名称以查看映射,包括:

  • XmlViewResolver which reads bean definition XML files,
  • XmlViewResolver读取bean定义XML文件,
  • ResourceBundleViewResolver which reads properties files, and
  • ResourceBundleViewResolver读取属性文件,和
  • BeanNameViewResolver which looks in the application context of the executing DispatcherServlet for a bean having the same name as the view name.
  • BeanNameViewResolver,它在正在执行的DispatcherServlet的应用程序上下文中查找与视图名称同名的bean。

For example, to use BeanNameViewResolver:

例如,要使用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


2  

There's nothing to prevent you from returning an actual View object directly from your controller method - it doesn't have to be a view name. So your controller can construct a View object using its own logic, and return that, with or without being wrapped in a ModelAndView object.

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

This is probably simpler than trying to persuade the ViewResolver framework from doing this for you, although that would work as well.

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

#5


0  

Perhaps you can look at ResolveBundleViewResolver, which allows you to mix views. The docs give some info on how to use this.

也许您可以查看ResolveBundleViewResolver,它允许您混合视图。文档提供了有关如何使用它的一些信息。

From the docs (example is to mix tiles and jstl, but should apply for others as well)...

从文档(例如混合瓷砖和jstl,但也应该适用于其他人)...

context file

上下文文件

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

views.properties

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


-1  

To extend Chin Huang's answer, here is what works for me. No configuration required.

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

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

This will automatically convert the model into JSON and write to response. Here model is of type Map<String,Object> and response is of type HttpServletResponse

这将自动将模型转换为JSON并写入响应。这里的模型是Map 类型,响应类型为HttpServletResponse ,object>