2011-02-07 75 views
15

Deseo devolver una vista desde un controlador Spring MVC según la lógica. Si ocurre un error, quiero devolver JSON, si no, una vista HTML. Esto es como ASP.NET MVC ActionResult, donde puede devolver cualquier tipo de vista y mostrará el resultado, y no dependerá del tipo de contenido que se envíe en la solicitud. No puedo encontrar ningún ejemplo de esto.Retorno JSON o vista desde el controlador MVC de Spring

+2

http://stackoverflow.com/questions/6173093/spring-return-json-from-controller-as-modelandview – Bozho

Respuesta

17

Lo logré con lo siguiente.

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

Función JS que hace la llamada

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


        } 
       }); 
+1

En su código tiene 'if (true)' - entonces, ¿cuándo se devuelve JSON? – Paul

+0

Estaba probando allí. Probaría un error en el objeto de retorno y luego devolveré json; de lo contrario, devolvería HTML. –

0

Quizás pueda mirar ResolveBundleViewResolver, que le permite mezclar vistas. El docs brinda información sobre cómo usar esto.

A partir de los documentos (ejemplo es mezclar los azulejos y jstl, pero debe aplicarse para otros también) ...

archivo de contexto

<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 
... 
4

Programe su controlador para devolver un nombre de vista lógica diferente dependiendo de una condición. Por ejemplo:

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

configurar la vista resolutores para resolver el nombre de vista "error" a la vista JSON. Primavera ofrece muchas maneras de configurar el nombre de la vista para ver el mapeo, incluyendo:

Por ejemplo, para utilizar 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> 
5

Por si acaso y que desea volver JSON de excepción se puede hacer lo siguiente:

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

no estoy seguro de que esto es lo que quería hacer, pero por si acaso ... :)

+0

Si ocurrió un error en un controlador, ¿Esto lo atraparía y devolvería JSON? –

+0

Por lo que recuerdo, sí atraparía. –

2

No hay nada que le impida devolver una real View Objeto directamente desde su método de controlador - no tiene que ser un nombre de vista. Por lo tanto, su controlador puede construir un objeto View utilizando su propia lógica, y devolverlo, con o sin estar envuelto en un objeto ModelAndView.

Esto es probablemente más simple que tratar de persuadir al marco ViewResolver para que lo haga por usted, aunque eso también funcionaría.

-1

Para extender la respuesta de Chin Huang, aquí es lo que funciona para mí. No se requiere configuración

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

Esto convertirá automáticamente el modelo en JSON y escribirá en respuesta. Aquí modelo es de tipo Map<String,Object> y la respuesta es de tipo HttpServletResponse

+0

Mala idea para instanciar una nueva vista JSON cada vez que necesita devolver una. –

+0

¿Cuál es la buena idea @JukkaDahlbom? –

Cuestiones relacionadas