Use code includes and tabs in MVC Config documentation
This commit also refines the documentation related to `@EnableWebMvc` in order to make it more relevant for modern Boot applications. See gh-22171
This commit is contained in:
@@ -12,30 +12,7 @@ For advanced mode, you can remove `@EnableWebMvc` and extend directly from
|
||||
`DelegatingWebMvcConfiguration` instead of implementing `WebMvcConfigurer`,
|
||||
as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
public class WebConfig extends DelegatingWebMvcConfiguration {
|
||||
|
||||
// ...
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
class WebConfig : DelegatingWebMvcConfiguration() {
|
||||
|
||||
// ...
|
||||
}
|
||||
----
|
||||
======
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
You can keep existing methods in `WebConfig`, but you can now also override bean declarations
|
||||
from the base class, and you can still have any number of other `WebMvcConfigurer` implementations on
|
||||
|
||||
@@ -5,39 +5,7 @@ The MVC namespace does not have an advanced mode. If you need to customize a pro
|
||||
a bean that you cannot change otherwise, you can use the `BeanPostProcessor` lifecycle
|
||||
hook of the Spring `ApplicationContext`, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Component
|
||||
public class MyPostProcessor implements BeanPostProcessor {
|
||||
|
||||
public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Component
|
||||
class MyPostProcessor : BeanPostProcessor {
|
||||
|
||||
override fun postProcessBeforeInitialization(bean: Any, name: String): Any {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
include-code::./MyPostProcessor[tag=snippet,indent=0]
|
||||
|
||||
Note that you need to declare `MyPostProcessor` as a bean, either explicitly in XML or
|
||||
by letting it be detected through a `<component-scan/>` declaration.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -13,59 +13,9 @@ strategy over path extensions. See
|
||||
xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-suffix-pattern-match[Suffix Match] and xref:web/webmvc/mvc-controller/ann-requestmapping.adoc#mvc-ann-requestmapping-rfd[Suffix Match and RFD] for
|
||||
more details.
|
||||
|
||||
In Java configuration, you can customize requested content type resolution, as the
|
||||
following example shows:
|
||||
You can customize requested content type resolution, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
|
||||
configurer.mediaType("json", MediaType.APPLICATION_JSON);
|
||||
configurer.mediaType("xml", MediaType.APPLICATION_XML);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun configureContentNegotiation(configurer: ContentNegotiationConfigurer) {
|
||||
configurer.mediaType("json", MediaType.APPLICATION_JSON)
|
||||
configurer.mediaType("xml", MediaType.APPLICATION_XML)
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>
|
||||
|
||||
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
|
||||
<property name="mediaTypes">
|
||||
<value>
|
||||
json=application/json
|
||||
xml=application/xml
|
||||
</value>
|
||||
</property>
|
||||
</bean>
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,119 +6,16 @@
|
||||
By default, formatters for various number and date types are installed, along with support
|
||||
for customization via `@NumberFormat` and `@DateTimeFormat` on fields.
|
||||
|
||||
To register custom formatters and converters in Java config, use the following:
|
||||
To register custom formatters and converters, use the following:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addFormatters(FormatterRegistry registry) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun addFormatters(registry: FormatterRegistry) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
To do the same in XML config, use the following:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<mvc:annotation-driven conversion-service="conversionService"/>
|
||||
|
||||
<bean id="conversionService"
|
||||
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
|
||||
<property name="converters">
|
||||
<set>
|
||||
<bean class="org.example.MyConverter"/>
|
||||
</set>
|
||||
</property>
|
||||
<property name="formatters">
|
||||
<set>
|
||||
<bean class="org.example.MyFormatter"/>
|
||||
<bean class="org.example.MyAnnotationFormatterFactory"/>
|
||||
</set>
|
||||
</property>
|
||||
<property name="formatterRegistrars">
|
||||
<set>
|
||||
<bean class="org.example.MyFormatterRegistrar"/>
|
||||
</set>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
By default Spring MVC considers the request Locale when parsing and formatting date
|
||||
values. This works for forms where dates are represented as Strings with "input" form
|
||||
fields. For "date" and "time" form fields, however, browsers use a fixed format defined
|
||||
in the HTML spec. For such cases date and time formatting can be customized as follows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addFormatters(FormatterRegistry registry) {
|
||||
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
|
||||
registrar.setUseIsoFormat(true);
|
||||
registrar.registerFormatters(registry);
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun addFormatters(registry: FormatterRegistry) {
|
||||
val registrar = DateTimeFormatterRegistrar()
|
||||
registrar.setUseIsoFormat(true)
|
||||
registrar.registerFormatters(registry)
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
include-code::./DateTimeWebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
NOTE: See xref:core/validation/format.adoc#format-FormatterRegistrar-SPI[the `FormatterRegistrar` SPI]
|
||||
and the `FormattingConversionServiceFactoryBean` for more information on when to use
|
||||
|
||||
@@ -6,33 +6,7 @@
|
||||
In Java configuration, you can implement the `WebMvcConfigurer` interface, as the
|
||||
following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
// Implement configuration methods...
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
// Implement configuration methods...
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
In XML, you can check attributes and sub-elements of `<mvc:annotation-driven/>`. You can
|
||||
view the https://schema.spring.io/mvc/spring-mvc.xsd[Spring MVC XML schema] or use
|
||||
|
||||
@@ -15,44 +15,7 @@ lower than that of the `DefaultServletHttpRequestHandler`, which is `Integer.MAX
|
||||
|
||||
The following example shows how to enable the feature by using the default setup:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun configureDefaultServletHandling(configurer: DefaultServletHandlerConfigurer) {
|
||||
configurer.enable()
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:default-servlet-handler/>
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
The caveat to overriding the `/` Servlet mapping is that the `RequestDispatcher` for the
|
||||
default Servlet must be retrieved by name rather than by path. The
|
||||
@@ -63,45 +26,4 @@ If the default Servlet has been custom-configured with a different name, or if a
|
||||
different Servlet container is being used where the default Servlet name is unknown,
|
||||
then you must explicitly provide the default Servlet's name, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable("myCustomDefaultServlet");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun configureDefaultServletHandling(configurer: DefaultServletHandlerConfigurer) {
|
||||
configurer.enable("myCustomDefaultServlet")
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>
|
||||
----
|
||||
|
||||
|
||||
|
||||
include-code::./CustomDefaultServletConfiguration[tag=snippet,indent=0]
|
||||
|
||||
@@ -3,50 +3,11 @@
|
||||
|
||||
[.small]#xref:web/webflux/config.adoc#webflux-config-enable[See equivalent in the Reactive stack]#
|
||||
|
||||
In Java configuration, you can use the `@EnableWebMvc` annotation to enable MVC
|
||||
configuration, as the following example shows:
|
||||
You can use the `@EnableWebMvc` annotation to enable MVC configuration with programmatic configuration, or `<mvc:annotation-driven>` with XML configuration, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig {
|
||||
}
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig
|
||||
----
|
||||
======
|
||||
|
||||
In XML configuration, you can use the `<mvc:annotation-driven>` element to enable MVC
|
||||
configuration, as the following example shows:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<mvc:annotation-driven/>
|
||||
|
||||
</beans>
|
||||
----
|
||||
NOTE: When using Spring Boot, you may want to use `@Configuration` class of type `WebMvcConfigurer` but without `@EnableWebMvc` to keep Spring Boot MVC customizations. See more details in the xref:web/webmvc/mvc-config/customize.adoc[the MVC Config API section] and in {spring-boot-docs}/web.html#web.servlet.spring-mvc.auto-configuration[the dedicated Spring Boot documentation].
|
||||
|
||||
The preceding example registers a number of Spring MVC
|
||||
xref:web/webmvc/mvc-servlet/special-bean-types.adoc[infrastructure beans] and adapts to dependencies
|
||||
|
||||
@@ -1,56 +1,9 @@
|
||||
[[mvc-config-interceptors]]
|
||||
= Interceptors
|
||||
|
||||
In Java configuration, you can register interceptors to apply to incoming requests, as
|
||||
the following example shows:
|
||||
You can register interceptors to apply to incoming requests, as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(new LocaleChangeInterceptor());
|
||||
registry.addInterceptor(new ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun addInterceptors(registry: InterceptorRegistry) {
|
||||
registry.addInterceptor(LocaleChangeInterceptor())
|
||||
registry.addInterceptor(ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**")
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
----
|
||||
<mvc:interceptors>
|
||||
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
|
||||
<mvc:interceptor>
|
||||
<mvc:mapping path="/**"/>
|
||||
<mvc:exclude-mapping path="/admin/**"/>
|
||||
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
|
||||
</mvc:interceptor>
|
||||
</mvc:interceptors>
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
NOTE: Interceptors are not ideally suited as a security layer due to the potential
|
||||
for a mismatch with annotated controller path matching, which can also match trailing
|
||||
|
||||
@@ -15,48 +15,10 @@ Boot application, prefer to use the {spring-boot-docs}/web.html#web.servlet.spri
|
||||
mechanism. Or alternatively, use `extendMessageConverters` to modify message converters
|
||||
at the end.
|
||||
|
||||
The following example adds XML and Jackson JSON converters with a customized
|
||||
`ObjectMapper` instead of the default ones:
|
||||
The following example adds XML and Jackson JSON converters with a customized `ObjectMapper`
|
||||
instead of the default ones:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
|
||||
.indentOutput(true)
|
||||
.dateFormat(new SimpleDateFormat("yyyy-MM-dd"))
|
||||
.modulesToInstall(new ParameterNamesModule());
|
||||
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
|
||||
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfiguration : WebMvcConfigurer {
|
||||
|
||||
override fun configureMessageConverters(converters: MutableList<HttpMessageConverter<*>>) {
|
||||
val builder = Jackson2ObjectMapperBuilder()
|
||||
.indentOutput(true)
|
||||
.dateFormat(SimpleDateFormat("yyyy-MM-dd"))
|
||||
.modulesToInstall(ParameterNamesModule())
|
||||
converters.add(MappingJackson2HttpMessageConverter(builder.build()))
|
||||
converters.add(MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()))
|
||||
----
|
||||
======
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
In the preceding example,
|
||||
{spring-framework-api}/http/converter/json/Jackson2ObjectMapperBuilder.html[`Jackson2ObjectMapperBuilder`]
|
||||
@@ -76,7 +38,7 @@ It also automatically registers the following well-known modules if they are det
|
||||
* {jackson-github-org}/jackson-datatype-joda[jackson-datatype-joda]: Support for Joda-Time types.
|
||||
* {jackson-github-org}/jackson-datatype-jsr310[jackson-datatype-jsr310]: Support for Java 8 Date and Time API types.
|
||||
* {jackson-github-org}/jackson-datatype-jdk8[jackson-datatype-jdk8]: Support for other Java 8 types, such as `Optional`.
|
||||
* {jackson-github-org}/jackson-module-kotlin[`jackson-module-kotlin`]: Support for Kotlin classes and data classes.
|
||||
* {jackson-github-org}/jackson-module-kotlin[jackson-module-kotlin]: Support for Kotlin classes and data classes.
|
||||
|
||||
NOTE: Enabling indentation with Jackson XML support requires
|
||||
https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.codehaus.woodstox%22%20AND%20a%3A%22woodstox-core-asl%22[`woodstox-core-asl`]
|
||||
@@ -86,29 +48,3 @@ Other interesting Jackson modules are available:
|
||||
|
||||
* https://github.com/zalando/jackson-datatype-money[jackson-datatype-money]: Support for `javax.money` types (unofficial module).
|
||||
* {jackson-github-org}/jackson-datatype-hibernate[jackson-datatype-hibernate]: Support for Hibernate-specific types and properties (including lazy-loading aspects).
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:annotation-driven>
|
||||
<mvc:message-converters>
|
||||
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
|
||||
<property name="objectMapper" ref="objectMapper"/>
|
||||
</bean>
|
||||
<bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
|
||||
<property name="objectMapper" ref="xmlMapper"/>
|
||||
</bean>
|
||||
</mvc:message-converters>
|
||||
</mvc:annotation-driven>
|
||||
|
||||
<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
|
||||
p:indentOutput="true"
|
||||
p:simpleDateFormat="yyyy-MM-dd"
|
||||
p:modulesToInstall="com.fasterxml.jackson.module.paramnames.ParameterNamesModule"/>
|
||||
|
||||
<bean id="xmlMapper" parent="objectMapper" p:createXmlMapper="true"/>
|
||||
----
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -7,61 +7,6 @@ You can customize options related to path matching and treatment of the URL.
|
||||
For details on the individual options, see the
|
||||
{spring-framework-api}/web/servlet/config/annotation/PathMatchConfigurer.html[`PathMatchConfigurer`] javadoc.
|
||||
|
||||
The following example shows how to customize path matching in Java configuration:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configurePathMatch(PathMatchConfigurer configurer) {
|
||||
configurer.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
|
||||
}
|
||||
|
||||
private PathPatternParser patternParser() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun configurePathMatch(configurer: PathMatchConfigurer) {
|
||||
configurer.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
|
||||
}
|
||||
|
||||
fun patternParser(): PathPatternParser {
|
||||
//...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows how to customize path matching in XML configuration:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:annotation-driven>
|
||||
<mvc:path-matching
|
||||
path-helper="pathHelper"
|
||||
path-matcher="pathMatcher"/>
|
||||
</mvc:annotation-driven>
|
||||
|
||||
<bean id="pathHelper" class="org.example.app.MyPathHelper"/>
|
||||
<bean id="pathMatcher" class="org.example.app.MyPathMatcher"/>
|
||||
----
|
||||
|
||||
|
||||
The following example shows how to customize path matching:
|
||||
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
@@ -13,52 +13,9 @@ expiration to ensure maximum use of the browser cache and a reduction in HTTP re
|
||||
made by the browser. The `Last-Modified` information is deduced from `Resource#lastModified`
|
||||
so that HTTP conditional requests are supported with `"Last-Modified"` headers.
|
||||
|
||||
The following listing shows how to do so with Java configuration:
|
||||
The following listing shows how to do so:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("/public", "classpath:/static/")
|
||||
.setCacheControl(CacheControl.maxAge(Duration.ofDays(365)));
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("/public", "classpath:/static/")
|
||||
.setCacheControl(CacheControl.maxAge(Duration.ofDays(365)))
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:resources mapping="/resources/**"
|
||||
location="/public, classpath:/static/"
|
||||
cache-period="31556926" />
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
See also
|
||||
xref:web/webmvc/mvc-caching.adoc#mvc-caching-static-resources[HTTP caching support for static resources].
|
||||
@@ -73,60 +30,9 @@ computed from the content, a fixed application version, or other. A
|
||||
`ContentVersionStrategy` (MD5 hash) is a good choice -- with some notable exceptions, such as
|
||||
JavaScript resources used with a module loader.
|
||||
|
||||
The following example shows how to use `VersionResourceResolver` in Java configuration:
|
||||
The following example shows how to use `VersionResourceResolver`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("/public/")
|
||||
.resourceChain(true)
|
||||
.addResolver(new VersionResourceResolver().addContentVersionStrategy("/**"));
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
|
||||
registry.addResourceHandler("/resources/**")
|
||||
.addResourceLocations("/public/")
|
||||
.resourceChain(true)
|
||||
.addResolver(VersionResourceResolver().addContentVersionStrategy("/**"))
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim"]
|
||||
----
|
||||
<mvc:resources mapping="/resources/**" location="/public/">
|
||||
<mvc:resource-chain resource-cache="true">
|
||||
<mvc:resolvers>
|
||||
<mvc:version-resolver>
|
||||
<mvc:content-version-strategy patterns="/**"/>
|
||||
</mvc:version-resolver>
|
||||
</mvc:resolvers>
|
||||
</mvc:resource-chain>
|
||||
</mvc:resources>
|
||||
----
|
||||
include-code::./VersionedConfiguration[tag=snippet,indent=0]
|
||||
|
||||
You can then use `ResourceUrlProvider` to rewrite URLs and apply the full chain of resolvers and
|
||||
transformers -- for example, to insert versions. The MVC configuration provides a `ResourceUrlProvider`
|
||||
|
||||
@@ -8,93 +8,15 @@ on the classpath (for example, Hibernate Validator), the `LocalValidatorFactoryB
|
||||
registered as a global xref:core/validation/validator.adoc[Validator] for use with `@Valid` and
|
||||
`@Validated` on controller method arguments.
|
||||
|
||||
In Java configuration, you can customize the global `Validator` instance, as the
|
||||
You can customize the global `Validator` instance, as the
|
||||
following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public Validator getValidator() {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun getValidator(): Validator {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/mvc
|
||||
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
|
||||
|
||||
<mvc:annotation-driven validator="globalValidator"/>
|
||||
|
||||
</beans>
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
Note that you can also register `Validator` implementations locally, as the following
|
||||
example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Controller
|
||||
public class MyController {
|
||||
|
||||
@InitBinder
|
||||
protected void initBinder(WebDataBinder binder) {
|
||||
binder.addValidators(new FooValidator());
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Controller
|
||||
class MyController {
|
||||
|
||||
@InitBinder
|
||||
protected fun initBinder(binder: WebDataBinder) {
|
||||
binder.addValidators(FooValidator())
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
include-code::./MyController[tag=snippet,indent=0]
|
||||
|
||||
TIP: If you need to have a `LocalValidatorFactoryBean` injected somewhere, create a bean and
|
||||
mark it with `@Primary` in order to avoid conflict with the one declared in the MVC configuration.
|
||||
|
||||
@@ -5,47 +5,9 @@ This is a shortcut for defining a `ParameterizableViewController` that immediate
|
||||
forwards to a view when invoked. You can use it in static cases when there is no Java controller
|
||||
logic to run before the view generates the response.
|
||||
|
||||
The following example of Java configuration forwards a request for `/` to a view called `home`:
|
||||
The following example forwards a request for `/` to a view called `home`:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/").setViewName("home");
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun addViewControllers(registry: ViewControllerRegistry) {
|
||||
registry.addViewController("/").setViewName("home")
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
The following example achieves the same thing as the preceding example, but with XML, by
|
||||
using the `<mvc:view-controller>` element:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:view-controller path="/" view-name="home"/>
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
If an `@RequestMapping` method is mapped to a URL for any HTTP method then a view
|
||||
controller cannot be used to handle the same URL. This is because a match by URL to an
|
||||
|
||||
@@ -5,127 +5,12 @@
|
||||
|
||||
The MVC configuration simplifies the registration of view resolvers.
|
||||
|
||||
The following Java configuration example configures content negotiation view
|
||||
resolution by using JSP and Jackson as a default `View` for JSON rendering:
|
||||
The following example configures content negotiation view resolution by using JSP and Jackson as a
|
||||
default `View` for JSON rendering:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
registry.enableContentNegotiation(new MappingJackson2JsonView());
|
||||
registry.jsp();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun configureViewResolvers(registry: ViewResolverRegistry) {
|
||||
registry.enableContentNegotiation(MappingJackson2JsonView())
|
||||
registry.jsp()
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
The following example shows how to achieve the same configuration in XML:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:view-resolvers>
|
||||
<mvc:content-negotiation>
|
||||
<mvc:default-views>
|
||||
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
|
||||
</mvc:default-views>
|
||||
</mvc:content-negotiation>
|
||||
<mvc:jsp/>
|
||||
</mvc:view-resolvers>
|
||||
----
|
||||
include-code::./WebConfiguration[tag=snippet,indent=0]
|
||||
|
||||
Note, however, that FreeMarker, Groovy Markup, and script templates also require
|
||||
configuration of the underlying view technology.
|
||||
|
||||
The MVC namespace provides dedicated elements. The following example works with FreeMarker:
|
||||
|
||||
[source,xml,indent=0,subs="verbatim,quotes"]
|
||||
----
|
||||
<mvc:view-resolvers>
|
||||
<mvc:content-negotiation>
|
||||
<mvc:default-views>
|
||||
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
|
||||
</mvc:default-views>
|
||||
</mvc:content-negotiation>
|
||||
<mvc:freemarker cache="false"/>
|
||||
</mvc:view-resolvers>
|
||||
|
||||
<mvc:freemarker-configurer>
|
||||
<mvc:template-loader-path location="/freemarker"/>
|
||||
</mvc:freemarker-configurer>
|
||||
----
|
||||
|
||||
In Java configuration, you can add the respective `Configurer` bean,
|
||||
as the following example shows:
|
||||
|
||||
[tabs]
|
||||
======
|
||||
Java::
|
||||
+
|
||||
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void configureViewResolvers(ViewResolverRegistry registry) {
|
||||
registry.enableContentNegotiation(new MappingJackson2JsonView());
|
||||
registry.freeMarker().cache(false);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FreeMarkerConfigurer freeMarkerConfigurer() {
|
||||
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
|
||||
configurer.setTemplateLoaderPath("/freemarker");
|
||||
return configurer;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Kotlin::
|
||||
+
|
||||
[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"]
|
||||
----
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
class WebConfig : WebMvcConfigurer {
|
||||
|
||||
override fun configureViewResolvers(registry: ViewResolverRegistry) {
|
||||
registry.enableContentNegotiation(MappingJackson2JsonView())
|
||||
registry.freeMarker().cache(false)
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
|
||||
setTemplateLoaderPath("/freemarker")
|
||||
}
|
||||
}
|
||||
----
|
||||
======
|
||||
|
||||
|
||||
configuration of the underlying view technology. The following example works with FreeMarker:
|
||||
|
||||
include-code::./FreeMarkerConfiguration[tag=snippet,indent=0]
|
||||
|
||||
Reference in New Issue
Block a user