Ich habe den folgenden Code in einem meiner Controller:
@Controller
@RequestMapping("/preference")
public class PreferenceController {
@RequestMapping(method = RequestMethod.GET, produces = "text/html")
public String preference() {
return "preference";
}
}
Ich versuche einfach, es mit dem Spring MVC-Test wie folgt zu testen :
@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());
}
}
Ich erhalte die folgende Ausnahme:
Kreisansichtspfad [Präferenz]: würde erneut an die aktuelle Handler-URL [/ Präferenz] zurücksenden. Überprüfen Sie Ihr ViewResolver-Setup! (Hinweis: Dies kann das Ergebnis einer nicht angegebenen Ansicht sein, da der Name der Standardansicht generiert wurde.)
Was ich seltsam finde, ist, dass es gut funktioniert, wenn ich die "vollständige" Kontextkonfiguration lade , die die Vorlage und die Ansichtsauflöser enthält, wie unten gezeigt:
<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>
Mir ist klar, dass das vom Vorlagen-Resolver hinzugefügte Präfix sicherstellt, dass es keinen "kreisförmigen Ansichtspfad" gibt, wenn die App diesen Vorlagen-Resolver verwendet.
Aber wie soll ich dann meine App mit dem Spring MVC-Test testen?
ViewResolver
Sie verwenden, posten , wenn es fehlschlägt?@RestController
anstelle von@Controller
Antworten:
Dies hat nichts mit Spring MVC-Tests zu tun.
Wenn Sie a nicht deklarieren
ViewResolver
, registriert Spring einen Standardwert,InternalResourceViewResolver
der InstanzenJstlView
für das Rendern von erstelltView
.Die
JstlView
Klasse erweitertInternalResourceView
sichMutig ist meins. Mit anderen Worten, die Ansicht wird vor dem Rendern versuchen, eine
RequestDispatcher
zu bekommen, zu derforward()
. Zuvor wird Folgendes überprüftWo
path
ist der Ansichtsname, was Sie von der zurückgegeben haben@Controller
. In diesem Beispiel alsopreference
. Die Variableuri
enthält die URL der zu bearbeitenden Anforderung/context/preference
.Der obige Code erkennt, dass bei einer Weiterleitung
/context/preference
dasselbe Servlet (da dasselbe das vorherige behandelt hat) die Anforderung verarbeiten würde und Sie in eine Endlosschleife geraten würden.Wenn Sie a
ThymeleafViewResolver
und aServletContextTemplateResolver
mit einem bestimmtenprefix
und deklarierensuffix
, baut es dasView
anders auf und gibt ihm einen Pfad wieThymeleafView
Instanzen suchen die Datei relativ zumServletContext
Pfad mithilfe von aServletContextResourceResolver
was schließlich
Dadurch wird eine Ressource abgerufen, die relativ zum
ServletContext
Pfad ist. Es kann dann das verwendenTemplateEngine
, um den HTML-Code zu generieren. Hier kann keine Endlosschleife passieren.quelle
ThymleafViewResolver
dasView
als eine Datei in Bezug auf die aufgelöstprefix
undsuffix
Sie zur Verfügung stellen. Wenn Sie diese Auflösung nicht verwenden, verwendet Spring einen Standardwert,InternalResourceViewResolver
der Ressourcen mit a findetRequestDispatcher
. Diese Ressource kann eine seinServlet
. In diesem Fall liegt es daran, dass der Pfad/preference
Ihrem Pfad zugeordnet istDispatcherServlet
.ViewResolver
. EntwederThymeleafViewResolver
wie in Ihrer Frage, Ihren eigenen konfiguriertenInternalResourceViewResolver
oder den Ansichtsnamen ändern, den Sie in Ihrem Controller zurückgeben.@RequestMapping
Anmerkungen versehenen Handlermethode mit einemString
Rückgabetyp (und Nein@ResponseBody
) wird der Rückgabewert von a behandelt,ViewNameMethodReturnValueHandler
der den String als Ansichtsnamen interpretiert und ihn verwendet, um den in meiner Antwort erläuterten Prozess zu durchlaufen. Mit@ResponseBody
verwendetRequestResponseBodyMethodProcessor
stattdessen Spring MVC, das stattdessen den String direkt in die HTTP-Antwort schreibt, d. H. Keine Ansichtsauflösung.Ich habe dieses Problem mit @ResponseBody wie folgt gelöst:
quelle
List<DomainObject>
.@Controller
→@RestController
Ich hatte das gleiche Problem und bemerkte, dass mein Controller auch mit Anmerkungen versehen war
@Controller
. Das Ersetzen durch hat@RestController
das Problem behoben. Hier ist die Erklärung von Spring Web MVC :quelle
@ControllerAdvice
mit einemhandleXyException
Verfahren darin, die anstelle eines ResponseEntity mein eigenes Objekt zurückgegeben. Das Hinzufügen@RestController
zu der@ControllerAdvice
Anmerkung hat funktioniert und das Problem ist behoben.So habe ich dieses Problem gelöst:
quelle
Ich verwende Spring Boot, um eine Webseite zu laden, nicht zu testen, und hatte dieses Problem. Meine Lösung war etwas anders als die oben genannten, wenn man die etwas anderen Umstände berücksichtigt. (obwohl diese Antworten mir geholfen haben zu verstehen.)
Ich musste einfach meine Spring Boot-Starter-Abhängigkeit in Maven ändern von:
zu:
Nur das 'Web' in 'Thymeleaf' zu ändern, hat das Problem für mich behoben.
quelle
Hier ist eine einfache Lösung, wenn Sie das Rendern der Ansicht nicht wirklich interessieren.
Erstellen Sie eine Unterklasse von InternalResourceViewResolver, die nicht nach kreisförmigen Ansichtspfaden sucht:
Dann richten Sie Ihren Test damit ein:
quelle
Wenn Sie Spring Boot verwenden, fügen Sie Ihrer pom.xml die Abhängigkeit von Thymeleaf hinzu:
quelle
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Hinzufügen
/
nach/preference
gelöst das Problem für mich:quelle
In meinem Fall habe ich Kotlin + Spring Boot ausprobiert und bin zum Thema Circular View Path gekommen. Alle Vorschläge, die ich online bekam, konnten nicht helfen, bis ich Folgendes versuchte:
Ursprünglich hatte ich meinen Controller mit kommentiert
@Controller
import org.springframework.stereotype.Controller
Ich habe dann ersetzt
@Controller
mit@RestController
import org.springframework.web.bind.annotation.RestController
Und es hat funktioniert.
quelle
Wenn Sie keinen @RequestBody verwendet haben und nur verwenden
@Controller
, ist die einfachste Möglichkeit, dies zu beheben, die Verwendung von@RestController
anstelle von@Controller
quelle
Fügen Sie die Anmerkung
@ResponseBody
Ihrer Methodenrückgabe hinzu.quelle
Ich benutze Spring Boot mit Thymeleaf. Das hat bei mir funktioniert. Es gibt ähnliche Antworten mit JSP, aber beachten Sie, dass ich HTML verwende, nicht JSP, und diese befinden sich im Ordner
src/main/resources/templates
wie in einem Standard-Spring Boot-Projekt, wie hier erläutert . Dies könnte auch Ihr Fall sein.Hoffe das hilft.
quelle
Wenn Sie Spring Boot + Freemarker ausführen, wird folgende Seite angezeigt:
Whitelabel-Fehlerseite Diese Anwendung hat keine explizite Zuordnung für / error, daher sehen Sie dies als Fallback.
In der Version Spring-Boot-Starter-Parent 2.2.1.RELEASE funktioniert Freemarker nicht:
spring.freemarker.suffix = .ftl
quelle
Für Thymeleaf:
Ich habe gerade angefangen, Spring 4 und Thymeleaf zu verwenden. Als ich auf diesen Fehler stieß, wurde er durch Hinzufügen von:
quelle
Wenn Sie
@Controller
Anmerkungen verwenden, benötigen Sie@RequestMapping
und@ResponseBody
Anmerkungen. Versuchen Sie es erneut, nachdem Sie eine Anmerkung hinzugefügt haben@ResponseBody
quelle
Ich verwende die Anmerkung, um die Spring Web App
InternalResourceViewResolver
zu konfigurieren. Das Problem wurde durch Hinzufügen einer Bean zur Konfiguration gelöst . Hoffe es wäre hilfreich.quelle
Dies geschieht, weil Spring "Präferenz" entfernt und die "Präferenz" erneut anfügt, wobei derselbe Pfad wie bei der Anforderung Uri verwendet wird.
So passiert: Anfrage Uri: "/ Präferenz"
"Präferenz" entfernen: "/"
Pfad anhängen: "/" + "Voreinstellung"
Endzeichenfolge: "/ Präferenz"
Dies gerät in eine Schleife, die der Frühling durch Auslösen einer Ausnahme benachrichtigt.
Es ist am besten in Ihrem Interesse, einen anderen Ansichtsnamen wie "PreferenceView" oder etwas anderes anzugeben, das Sie mögen.
quelle
Versuchen Sie, Ihrer Gradle-Datei eine Kompilierungsabhängigkeit ("org.springframework.boot: spring-boot-Starter-thymeleaf") hinzuzufügen. Thymeleaf hilft beim Zuordnen von Ansichten.
quelle
In meinem Fall hatte ich dieses Problem beim Versuch, JSP-Seiten mit der Spring-Boot-Anwendung bereitzustellen.
Folgendes hat bei mir funktioniert:
application.properties
pom.xml
Um die Unterstützung für JSPs zu aktivieren, müssten wir eine Abhängigkeit von Tomcat-Embed-Jasper hinzufügen.
quelle
Ein weiterer einfacher Ansatz:
quelle