Compare InternalResourceViewResolver (JSP) with ThymeleafViewResolver. How does Spring Boot auto-configure Thymeleaf, and why is Thymeleaf preferred for modern server-side rendering?
answer
- InternalResourceViewResolver -> JSP via servlet forward, /WEB-INF
- ThymeleafViewResolver -> classpath:/templates/*.html
- Boot: ThymeleafAutoConfiguration + starter
- spring.thymeleaf.cache=false in dev
- JSP doesn't work in executable JAR
basics
~20 sInternalResourceViewResolver resolves names to JSPs via a servlet forward (prefix/suffix, files under /WEB-INF). ThymeleafViewResolver resolves them to .html templates in classpath:/templates rendered by the Thymeleaf engine. Boot auto-configures Thymeleaf when the starter is on the classpath.
solid answer
~40 sInternalResourceViewResolver maps a logical name to a JSP under a prefix/suffix (e.g. /WEB-INF/views/home.jsp) and renders it through a servlet RequestDispatcher forward — so it requires a servlet container that compiles JSPs and templates must live under /WEB-INF. ThymeleafViewResolver delegates to Thymeleaf's SpringTemplateEngine, resolving names to natural-HTML templates on the classpath (default classpath:/templates/, .html suffix). Spring Boot's ThymeleafAutoConfiguration wires the template resolver, engine, and view resolver automatically once spring-boot-starter-thymeleaf is present; properties like spring.thymeleaf.prefix/suffix/cache tune it. Thymeleaf is preferred because templates are valid, browser-openable HTML (natural templating), it works cleanly with executable JARs (JSP doesn't), integrates with Spring EL, forms, and security dialects, and doesn't need /WEB-INF or a JSP-capable container.
code
java · 17 lines// Legacy JSP resolver (manual config)
@Bean
public InternalResourceViewResolver jspResolver() {
InternalResourceViewResolver r = new InternalResourceViewResolver();
r.setPrefix("/WEB-INF/views/");
r.setSuffix(".jsp");
r.setViewClass(JstlView.class);
r.setOrder(Ordered.LOWEST_PRECEDENCE); // it never returns null -> keep last
return r;
}
// Thymeleaf: usually you write NO Java at all.
// Just add spring-boot-starter-thymeleaf and application.properties:
// spring.thymeleaf.prefix=classpath:/templates/
// spring.thymeleaf.suffix=.html
// spring.thymeleaf.cache=false # dev only
// ThymeleafAutoConfiguration builds resolver + engine + view resolver.go deeper
Knows Thymeleaf renders .html templates and JSP is the older option.
Must describe prefix/suffix mapping, classpath:/templates default, and that Boot auto-configures Thymeleaf.
Explains the servlet-forward mechanism of JSP, executable-JAR limitation, and resolver ordering when mixing.
Weighs natural templating, i18n/security dialects, caching in dev vs prod, and packaging implications for delivery.
## Two server-side view technologies ### InternalResourceViewResolver (JSP / JSTL) - Implements `ViewResolver`; you configure a **`prefix`** and **`suffix`**. Logical name `"home"` → `prefix + "home" + suffix` = `/WEB-INF/views/home.jsp`. - It produces an `InternalResourceView` (or `JstlView`) which renders by doing a **servlet `RequestDispatcher` forward** to that JSP resource. The container compiles the JSP to a servlet and executes it. - Templates conventionally live under **`/WEB-INF/`** so they can't be requested directly by URL. - It is a **catch-all** resolver: it always returns a View (it can't check whether the JSP exists), so it must be ordered **last** in a resolver chain (lowest priority) or it will shadow others. - Limitations: requires a servlet container that supports JSP; **does not work inside an executable JAR** (JSPs need to be unpacked to a real path / WAR); JSP is legacy for greenfield apps. ### ThymeleafViewResolver - Delegates rendering to Thymeleaf's **`SpringTemplateEngine`**, backed by an **`ITemplateResolver`** (e.g. `SpringResourceTemplateResolver`). - Default template location: **`classpath:/templates/`**, suffix **`.html`**. Name `"home"` → `classpath:/templates/home.html`. - **Natural templating**: a Thymeleaf template is valid HTML that opens in a browser as-is (attributes like `th:text`, `th:each` are ignored by browsers but processed by the engine). Designers can work on the raw file. - Ships Spring-aware dialects: form binding (`th:field`, `th:object`), URL rewriting (`@{...}`), Spring EL (`${...}`), and an optional **thymeleaf-extras-springsecurity** dialect (`sec:authorize`). ## Spring Boot auto-configuration Add `spring-boot-starter-thymeleaf`. Then **`ThymeleafAutoConfiguration`** creates, if you don't define your own: - a `SpringResourceTemplateResolver` (prefix `classpath:/templates/`, suffix `.html`), - a `SpringTemplateEngine`, - a `ThymeleafViewResolver`. Tune via `application.properties`: - `spring.thymeleaf.prefix` / `spring.thymeleaf.suffix` - `spring.thymeleaf.cache` (true in prod, **set false in dev** so template edits show without restart) - `spring.thymeleaf.mode`, `spring.thymeleaf.encoding`, `spring.thymeleaf.check-template-location`. ## Why Thymeleaf is preferred today 1. **Executable-JAR friendly** — no JSP/WAR requirement; works with `java -jar`. 2. **Natural templates** — valid HTML, prototype-able, easier for designers. 3. **No `/WEB-INF` ceremony** — classpath templates. 4. **Rich Spring integration** — form binding, message resolution (i18n via `#{...}`), security dialect. 5. **JSP is effectively deprecated** for new Spring Boot apps. ## Gotchas - Leaving `spring.thymeleaf.cache=true` in dev forces a restart to see template changes. - Mixing both resolvers: give JSP's `InternalResourceViewResolver` the lowest priority (`order` = highest int) since it never returns null. - Missing template → `TemplateInputException`, not a silent 404. - Thymeleaf `.html` templates must be well-formed by default (`HTML` mode is lenient in Thymeleaf 3, but still expects sane markup). ## When to use - New Spring Boot server-rendered apps → **Thymeleaf**. - Legacy apps already on JSP/JSTL, deployed as WAR → InternalResourceViewResolver may remain.
- Why can't you use JSP with a standard Spring Boot executable JAR?JSPs must be compiled by the servlet container from a real filesystem path and aren't loadable from inside a nested JAR. Boot's fat-JAR layout can't serve them, so JSP apps must be packaged as WAR and run in an external container. Thymeleaf reads templates from the classpath and has no such constraint.
- You edit a Thymeleaf template in dev but the browser shows the old content. What's the fix?Thymeleaf template caching is on by default. Set spring.thymeleaf.cache=false (spring-boot-devtools sets this automatically) so the engine re-reads templates on each request.
saying these in an interview costs you the question
- Saying Thymeleaf templates live under /WEB-INF like JSPs
- Claiming you must manually declare the ThymeleafViewResolver bean in Spring Boot
- Thinking JSP works fine in a Boot executable JAR
- Not knowing InternalResourceViewResolver must be ordered last because it never returns null