Tengo el siguiente código en uno de mis controladores:
@Controller
@RequestMapping("/preference")
public class PreferenceController {
@RequestMapping(method = RequestMethod.GET, produces = "text/html")
public String preference() {
return "preference";
}
}
Simplemente estoy tratando de probarlo usando la prueba Spring MVC de la siguiente manera:
@ContextConfiguration
@WebAppConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class PreferenceControllerTest {
@Autowired
private WebApplicationContext ctx;
private MockMvc mockMvc;
@Before
public void setup() {
mockMvc = webAppContextSetup(ctx).build();
}
@Test
public void circularViewPathIssue() throws Exception {
mockMvc.perform(get("/preference"))
.andDo(print());
}
}
Recibo la siguiente excepción:
Ruta de vista circular [preferencia]: se enviaría de nuevo a la URL del controlador actual [/ preferencia] nuevamente. ¡Compruebe la configuración de ViewResolver! (Sugerencia: esto puede ser el resultado de una vista no especificada, debido a la generación de nombre de vista predeterminada).
Lo que encuentro extraño es que funciona bien cuando cargo la configuración de contexto "completa" que incluye la plantilla y los resolutores de vista como se muestra a continuación:
<bean class="org.thymeleaf.templateresolver.ServletContextTemplateResolver" id="webTemplateResolver">
<property name="prefix" value="WEB-INF/web-templates/" />
<property name="suffix" value=".html" />
<property name="templateMode" value="HTML5" />
<property name="characterEncoding" value="UTF-8" />
<property name="order" value="2" />
<property name="cacheable" value="false" />
</bean>
Soy consciente de que el prefijo agregado por el solucionador de plantillas garantiza que no haya una "ruta de vista circular" cuando la aplicación utiliza este solucionador de plantillas.
Pero entonces, ¿cómo se supone que debo probar mi aplicación usando la prueba Spring MVC?
ViewResolver
que usas cuando está fallando?@RestController
lugar de@Controller
Respuestas:
Esto no tiene nada que ver con las pruebas Spring MVC.
Cuando no declara a
ViewResolver
, Spring registra un valor predeterminadoInternalResourceViewResolver
que crea instancias deJstlView
para representar elView
.La
JstlView
clase se extiendeInternalResourceView
que esAtrevido es mío. En otras palabras, la vista, antes de renderizar, intentará obtener un
RequestDispatcher
destinoforward()
. Antes de hacer esto, verifica lo siguientedonde
path
está el nombre de la vista, lo que devolvió del@Controller
. En este ejemplo, eso espreference
. La variableuri
contiene el uri de la solicitud que se está manejando, que es/context/preference
.El código anterior se da cuenta de que si tuviera que reenviar
/context/preference
, el mismo servlet (ya que el mismo manejó el anterior) manejaría la solicitud y entraría en un bucle sin fin.Cuando declaras a
ThymeleafViewResolver
y aServletContextTemplateResolver
con unprefix
y específicosuffix
, se construye de maneraView
diferente, dándole una ruta comoThymeleafView
instancias localizan el archivo en relación con laServletContext
ruta mediante unServletContextResourceResolver
que eventualmente
Esto obtiene un recurso que es relativo a la
ServletContext
ruta. Luego puede usar elTemplateEngine
para generar el HTML. No hay forma de que ocurra un ciclo sin fin aquí.fuente
ThymleafViewResolver
elView
se resuelve como un archivo relativo alprefix
ysuffix
usted proporciona. Cuando no usa esa resolución, Spring usa un valor predeterminadoInternalResourceViewResolver
que busca recursos con una extensiónRequestDispatcher
. Este recurso puede ser unServlet
. En este caso es porque la ruta se/preference
asigna a suDispatcherServlet
.ViewResolver
. Ya seaThymeleafViewResolver
como en su pregunta, la suya propia configuradaInternalResourceViewResolver
o cambie el nombre de la vista que está devolviendo en su controlador.@RequestMapping
método de controlador anotado con unString
tipo de retorno (y no@ResponseBody
) tiene su valor de retorno manejado por unViewNameMethodReturnValueHandler
que interpreta la Cadena como un nombre de vista y lo usa para pasar por el proceso que explico en mi respuesta. Con@ResponseBody
, Spring MVC usará en su lugar,RequestResponseBodyMethodProcessor
que en su lugar escribe la cadena directamente en la respuesta HTTP, es decir. sin resolución de vista.Resolví este problema usando @ResponseBody como se muestra a continuación:
fuente
List<DomainObject>
.@Controller
→@RestController
Tuve el mismo problema y noté que mi controlador también estaba anotado con
@Controller
. Reemplazarlo con@RestController
resolvió el problema. Aquí está la explicación de Spring Web MVC :fuente
@ControllerAdvice
con unhandleXyException
, que devolvía mi propio objeto en lugar de un ResponseEntity. Agregar@RestController
encima de la@ControllerAdvice
anotación funcionó y el problema desapareció.Así es como resolví este problema:
fuente
Estoy usando Spring Boot para intentar cargar una página web, no para probar, y tuve este problema. Mi solución fue un poco diferente a las anteriores considerando las circunstancias ligeramente diferentes. (aunque esas respuestas me ayudaron a entender).
Simplemente tuve que cambiar mi dependencia de arranque Spring Boot en Maven de:
a:
Simplemente cambiando la 'web' a 'thymeleaf' solucionó el problema.
fuente
Aquí hay una solución fácil si realmente no le importa renderizar la vista.
Cree una subclase de InternalResourceViewResolver que no compruebe las rutas de vista circular:
Luego configure su prueba con él:
fuente
Si está utilizando Spring Boot, agregue la dependencia de thymeleaf en su pom.xml:
fuente
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Agregar
/
después de/preference
resolver el problema para mí:fuente
En mi caso, estaba probando Kotlin + Spring boot y me metí en el problema de Circular View Path. Todas las sugerencias que recibí en línea no pudieron ayudar, hasta que intenté lo siguiente:
Originalmente había anotado mi controlador usando
@Controller
import org.springframework.stereotype.Controller
Luego reemplacé
@Controller
con@RestController
import org.springframework.web.bind.annotation.RestController
Y funcionó.
fuente
si no ha usado un @RequestBody y lo está usando solo
@Controller
, la forma más sencilla de solucionar esto es usar en@RestController
lugar de@Controller
fuente
Agregue la anotación
@ResponseBody
a su método return.fuente
Estoy usando Spring Boot con Thymeleaf. Esto es lo que funcionó para mí. Hay respuestas similares con JSP, pero tenga en cuenta que estoy usando HTML, no JSP, y están en la carpeta
src/main/resources/templates
como en un proyecto Spring Boot estándar como se explica aquí . Este también podría ser tu caso.Espero que esto ayude.
fuente
Al ejecutar Spring Boot + Freemarker si aparece la página:
Página de error de etiqueta blanca Esta aplicación no tiene un mapeo explícito para / error, por lo que está viendo esto como una alternativa.
En spring-boot-starter-parent 2.2.1.RELEASE versión freemarker no funciona:
spring.freemarker.suffix = .ftl
fuente
Para Thymeleaf:
Acabo de comenzar a usar Spring 4 y Thymeleaf, cuando encontré este error, se resolvió agregando:
fuente
Al usar la
@Controller
anotación, necesita@RequestMapping
y@ResponseBody
anotaciones. Vuelva a intentarlo después de agregar una anotación@ResponseBody
fuente
Utilizo la anotación para configurar la aplicación web Spring, el problema se resuelve agregando un
InternalResourceViewResolver
bean a la configuración. Espero que sea de ayuda.fuente
Esto sucede porque Spring está eliminando la "preferencia" y agregando la "preferencia" nuevamente haciendo la misma ruta que la solicitud Uri.
Sucediendo así: solicitud Uri: "/ preferencia"
eliminar "preferencia": "/"
añadir ruta: "/" + "preferencia"
cadena final: "/ preferencia"
Esto se está metiendo en un bucle que Spring le notifica lanzando una excepción.
Es mejor para su interés dar un nombre de vista diferente, como "ver preferencia" o cualquier cosa que desee.
fuente
intente agregar la dependencia compile ("org.springframework.boot: spring-boot-starter-thymeleaf") a su archivo gradle. Thhymeleaf ayuda a mapear vistas.
fuente
En mi caso, tuve este problema al intentar servir páginas JSP usando la aplicación Spring Boot.
Esto es lo que funcionó para mí:
application.properties
pom.xml
Para habilitar el soporte para JSP, necesitaríamos agregar una dependencia en tomcat-embed-jasper.
fuente
Otro enfoque simple:
fuente