Saya memiliki kode berikut di salah satu pengontrol saya:
@Controller
@RequestMapping("/preference")
public class PreferenceController {
@RequestMapping(method = RequestMethod.GET, produces = "text/html")
public String preference() {
return "preference";
}
}
Saya hanya mencoba mengujinya menggunakan tes Spring MVC sebagai berikut:
@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());
}
}
Saya mendapatkan pengecualian berikut:
Jalur tampilan melingkar [preferensi]: akan mengirimkan kembali ke URL penangan saat ini [/ preferensi] lagi. Periksa penyiapan ViewResolver Anda! (Petunjuk: Ini mungkin hasil dari tampilan yang tidak ditentukan, karena pembuatan nama tampilan default.)
Yang saya anggap aneh adalah bahwa ini berfungsi dengan baik ketika saya memuat konfigurasi konteks "lengkap" yang menyertakan template dan resolver tampilan seperti yang ditunjukkan di bawah ini:
<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>
Saya sangat menyadari bahwa awalan yang ditambahkan oleh pemecah templat memastikan bahwa tidak ada "jalur tampilan melingkar" saat aplikasi menggunakan pemecah templat ini.
Tapi kemudian bagaimana saya bisa menguji aplikasi saya menggunakan tes Spring MVC?
ViewResolver
Anda gunakan saat gagal?@RestController
sebagai pengganti@Controller
Jawaban:
Ini tidak ada hubungannya dengan pengujian Spring MVC.
Saat Anda tidak mendeklarasikan a
ViewResolver
, Spring mendaftarkan defaultInternalResourceViewResolver
yang membuat instanceJstlView
untuk merenderView
.The
JstlView
kelas meluasInternalResourceView
yangBold adalah milikku. Dalam otherwords, pandangan, sebelum rendering, akan mencoba untuk mendapatkan
RequestDispatcher
yang keforward()
. Sebelum melakukan ini, periksa hal-hal berikutdi mana
path
nama tampilan, apa yang Anda kembalikan dari@Controller
. Dalam contoh ini, itupreference
. Variabeluri
menyimpan uri dari permintaan yang sedang ditangani, yaitu/context/preference
.Kode di atas menyadari bahwa jika Anda meneruskan ke
/context/preference
, servlet yang sama (karena yang sama menangani sebelumnya) akan menangani permintaan dan Anda akan masuk ke loop tanpa akhir.Ketika Anda mendeklarasikan a
ThymeleafViewResolver
dan aServletContextTemplateResolver
dengan spesifikprefix
dansuffix
, itu membangun secaraView
berbeda, memberinya jalur sepertiThymeleafView
Contoh menemukan file relatif keServletContext
jalur dengan menggunakan fileServletContextResourceResolver
yang akhirnya
Ini mendapatkan sumber daya yang relatif terhadap
ServletContext
jalur. Kemudian dapat menggunakanTemplateEngine
untuk menghasilkan HTML. Tidak mungkin loop tanpa akhir bisa terjadi di sini.sumber
ThymleafViewResolver
yangView
diselesaikan sebagai file relatif terhadapprefix
dansuffix
Anda berikan. Saat Anda tidak menggunakan penyelesaian itu, Spring menggunakan defaultInternalResourceViewResolver
yang mencari sumber daya dengan fileRequestDispatcher
. Sumber daya ini dapat berupaServlet
. Dalam hal ini itu karena jalur/preference
memetakan ke AndaDispatcherServlet
.ViewResolver
. BaikThymeleafViewResolver
seperti dalam pertanyaan Anda, Anda sendiri yang dikonfigurasiInternalResourceViewResolver
atau mengubah nama tampilan yang Anda kembalikan di pengontrol Anda.@RequestMapping
Metode penangan beranotasi denganString
tipe kembalian (dan tidak@ResponseBody
) memiliki nilai kembaliannya ditangani olehViewNameMethodReturnValueHandler
yang menafsirkan String sebagai nama tampilan, dan menggunakannya untuk melalui proses yang saya jelaskan dalam jawaban saya. Dengan@ResponseBody
, Spring MVC akan menggunakanRequestResponseBodyMethodProcessor
yang menulis String langsung ke respon HTTP, yaitu. tidak ada resolusi tampilan.Saya memecahkan masalah ini dengan menggunakan @ResponseBody seperti di bawah ini:
sumber
List<DomainObject>
.@Controller
→@RestController
Saya memiliki masalah yang sama dan saya perhatikan bahwa pengontrol saya juga diberi anotasi
@Controller
. Menggantinya dengan@RestController
memecahkan masalah. Berikut penjelasan dari Spring Web MVC :sumber
@ControllerAdvice
denganhandleXyException
metode di dalamnya, yang mengembalikan objek saya sendiri alih-alih ResponseEntity. Menambahkan@RestController
di atas@ControllerAdvice
anotasi berfungsi dan masalah hilang.Beginilah cara saya memecahkan masalah ini:
sumber
Saya menggunakan Spring Boot untuk mencoba dan memuat halaman web, bukan menguji, dan mengalami masalah ini. Solusi saya sedikit berbeda dari yang di atas mengingat keadaan yang sedikit berbeda. (meskipun jawaban itu membuat saya mengerti.)
Saya hanya perlu mengubah ketergantungan starter Spring Boot saya di Maven dari:
untuk:
Hanya mengubah 'web' menjadi 'thymeleaf' telah memperbaiki masalah saya.
sumber
Berikut ini perbaikan mudah jika Anda tidak benar-benar peduli tentang rendering tampilan.
Buat subclass InternalResourceViewResolver yang tidak memeriksa jalur tampilan melingkar:
Kemudian siapkan pengujian Anda dengannya:
sumber
Jika Anda menggunakan Spring Boot, tambahkan dependensi thymeleaf ke pom.xml Anda:
sumber
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
Menambahkan
/
setelah/preference
memecahkan masalah untuk saya:sumber
Dalam kasus saya, saya mencoba boot Kotlin + Spring dan saya mengalami masalah Circular View Path. Semua saran yang saya dapatkan secara online tidak dapat membantu, sampai saya mencoba yang di bawah ini:
Awalnya saya telah menjelaskan pengontrol saya menggunakan
@Controller
import org.springframework.stereotype.Controller
Saya kemudian diganti
@Controller
dengan@RestController
import org.springframework.web.bind.annotation.RestController
Dan itu berhasil.
sumber
jika Anda belum pernah menggunakan @RequestBody dan hanya menggunakan
@Controller
, cara paling sederhana untuk memperbaiki ini menggunakan@RestController
bukannya@Controller
sumber
Tambahkan anotasi
@ResponseBody
ke pengembalian metode Anda.sumber
Saya menggunakan Spring Boot dengan Thymeleaf. Inilah yang berhasil bagi saya. Ada jawaban yang mirip dengan JSP tetapi perhatikan bahwa saya menggunakan HTML, bukan JSP, dan ini ada di folder
src/main/resources/templates
seperti dalam proyek Spring Boot standar seperti yang dijelaskan di sini . Ini juga bisa menjadi kasus Anda.Semoga ini membantu.
sumber
Saat menjalankan Spring Boot + Freemarker jika halaman muncul:
Halaman Kesalahan Label Putih Aplikasi ini tidak memiliki pemetaan eksplisit untuk / error, jadi Anda melihatnya sebagai fallback.
Di spring-boot-starter-parent 2.2.1.RELEASE version freemarker tidak berfungsi:
spring.freemarker.suffix = .ftl
sumber
Untuk Thymeleaf:
Saya baru saja mulai menggunakan spring 4 dan thymeleaf, ketika saya menemukan kesalahan ini, itu diatasi dengan menambahkan:
sumber
Saat menggunakan
@Controller
anotasi, Anda membutuhkan@RequestMapping
dan@ResponseBody
anotasi. Coba lagi setelah menambahkan anotasi@ResponseBody
sumber
Saya menggunakan anotasi untuk mengonfigurasi aplikasi web musim semi, masalah diselesaikan dengan menambahkan
InternalResourceViewResolver
kacang ke konfigurasi. Semoga bermanfaat.sumber
Ini terjadi karena Spring menghapus "preferensi" dan menambahkan "preferensi" lagi dengan membuat jalur yang sama seperti Uri permintaan.
Terjadi seperti ini: request Uri: "/ preference"
hapus "preferensi": "/"
tambahkan jalur: "/" + "preferensi"
string akhir: "/ preferensi"
Ini memasuki loop yang Spring memberi tahu Anda dengan melemparkan pengecualian.
Sebaiknya berikan nama tampilan yang berbeda seperti "preferenceView" atau apa pun yang Anda suka.
sumber
coba tambahkan ketergantungan compile ("org.springframework.boot: spring-boot-starter-thymeleaf") ke file gradle Anda. Thymeleaf membantu memetakan tampilan.
sumber
Dalam kasus saya, saya mengalami masalah ini saat mencoba menyajikan halaman JSP menggunakan aplikasi Spring boot.
Inilah yang berhasil untuk saya:
application.properties
pom.xml
Untuk mengaktifkan dukungan untuk JSP, kita perlu menambahkan ketergantungan pada tomcat-embed-jasper.
sumber
Pendekatan sederhana lainnya:
sumber