JavaRush /Курси /Модуль 5. Spring /Конфігурація Spring MVC

Конфігурація Spring MVC

Модуль 5. Spring
Рівень 10 , Лекція 12
Відкрита

Конфігурація MVC на Java та простір імен MVC на XML передбачають конфігурацію за замовчуванням, що підходить для більшості програм, і конфігураційний API для її налаштування.

Тобі не потрібно розбиратися в базових бінах, що створюються Java-конфігурацією MVC і простором імен MVC.

Активація конфігурації MVC

У Java-конфігурації можна використовувати анотацію @EnableWebMvc для активації конфігурації MVC, як показано в наведеному нижче прикладі:

Java

@Configuration
@EnableWebMvc
public class WebConfig {
}
Kotlin
@Configuration
@EnableWebMvc
class WebConfig

У конфігурації XML можна використовувати елемент <mvc:annotation-driven> для активації конфігурації MVC, як показано в наступному прикладі:


<?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>

У наступному прикладі реєструється ряд інфраструктурних бінів Spring MVC і підлаштовується під залежності, що доступні в classpath (наприклад, перетворювачі корисних даних для JSON, XML та ін.).

API конфігурації MVC

У Java-конфігурації можна реалізувати інтерфейс WebMvcConfigurer, як показано в наступному прикладі:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
// Реалізуємо методи конфігурації...
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
        // Реалізуємо методи конфігурації...
}

У XML можна перевіряти атрибути та піделементи <mvc:annotation-driven/>. Можна переглянути XML-схему Spring MVC або використовувати функцію автодоповнення коду в IDE, щоб дізнатися, які атрибути та піделементи доступні.

Перетворення типу

За замовчуванням встановлені форматувальники для різних типів чисел і дат поряд із засобами підтримки налаштування через @NumberFormat та @DateTimeFormat для полів.

Щоб зареєструвати кастомні форматувальники та перетворювачі в конфігурації Java, використовуй таке:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        // ...
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun addFormatters(registry: FormatterRegistry) {
        // ...
    }
}

Щоб зробити те саме в XML-конфігурації, використовуй таке:


<?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>

За замовчуванням Spring MVC враховує регіональні налаштування запиту під час парсингу та форматування значень дати. Це справедливо для форм, де дати подані у вигляді рядків із полями форми "input". Однак для полів форми "date" та "time" браузери використовують фіксований формат, визначений у специфікації HTML. Для таких випадків форматування дати та часу можна налаштувати так:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addFormatters(FormatterRegistry registry) {
        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
        registrar.setUseIsoFormat(true);
        registrar.registerFormatters(registry);
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun addFormatters(registry: FormatterRegistry) {
        val registrar = DateTimeFormatterRegistrar()
        registrar.setUseIsoFormat(true)
        registrar.registerFormatters(registry)
    }
}

Валідація

За замовчуванням, якщо в classpath є Bean Validation (наприклад, Hibernate Validator), LocalValidatorFactoryBean реєструється як глобальний валідатор для використання з анотацією @Valid та властівостю Validated на аргументи методів контролера.

У конфігурації Java можна налаштувати глобальний екземпляр Validator, як показано в наступному прикладі:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public Validator getValidator() {
        // ...
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun getValidator(): Validator {
        // ...
    }
}

У цьому прикладі показано, як отримати таку ж конфігурацію на XML:


<?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>

Зверни увагу, що також можна реєструвати реалізації Validator локально, як показано в наступному прикладі:

Java

@Controller
public class MyController {
    @InitBinder
    protected void initBinder(WebDataBinder binder) {
        binder.addValidators(new FooValidator());
    }
}
Kotlin

@Controller
class MyController {
    @InitBinder
    protected fun initBinder(binder: WebDataBinder) {
        binder.addValidators(FooValidator())
    }
}
Якщо необхідно, щоб LocalValidatorFactoryBean був кудись впроваджений, створи бін і позначийого анотацією @Primary, щоб уникнути конфлікту з тим, що було оголошено в конфігурації MVC.

Перехоплювачі

У конфігурації Java можна зареєструвати перехоплювачі для застосування до вхідних запитів, як показано в наступному прикладі:

Java

@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

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun addInterceptors(registry: InterceptorRegistry) {
        registry.addInterceptor(LocaleChangeInterceptor())
        registry.addInterceptor(ThemeChangeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**")
    }
}

У цьому прикладі показано, як отримати таку ж конфігурацію на XML:

<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>
Зіставлені перехоплювачі не ідеально підходять для використання як рівня безпеки через можливість виникнення невідповідності анотованого контролера узгодження шляхів, який також може прозоро узгоджувати косі риси та розширення шляхів, поряд з іншими варіантами узгодження шляхів. Багато які з цих варіантів вже застаріли, але ймовірність невідповідності залишається. Зазвичай ми рекомендуємо використовувати Spring Security, який містить спеціальний MvcRequestMatcher для узгодження шляхів Spring MVC, а також має брандмауер безпеки, який блокує багато небажаних символів у шляхах URL-адрес.

Типи вмісту

Можна конфігурувати спосіб, яким Spring MVC визначає типи середовища передачі даних, на які робиться запит (наприклад, заголовок Accept, розширення шляху URL-адреси, параметр запиту та інші).

За замовчуванням перевіряється лише заголовок Accept.

Якщо необхідно використовувати роздільну здатність типу вмісту на основі URL-адреси, розглянь можливість використання стратегії параметрів запиту замість розширень шляху.

У Java-конфігурації можна налаштувати дозвіл запитуваного типу вмісту, як показано в наступному прикладі:

Java

@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

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun configureContentNegotiation(configurer: ContentNegotiationConfigurer) {
        configurer.mediaType("json", MediaType.APPLICATION_JSON)
        configurer.mediaType("xml", MediaType.APPLICATION_XML)
    }
}

У цьому прикладі показано, як отримати таку ж конфігурацію на XML:


<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>

Перетворювачі повідомлень

Можна налаштувати HttpMessageConverter у Java-конфігурації, якщо перевизначити configureMessageConverters() (щоб замінити стандартні перетворювачі, створені Spring MVC) або перевизначити extendMessageConverters() (щоб налаштувати стандартні перетворювачі або додати додаткові перетворювачі до тих, що є за замовчуванням).

У наступному прикладі додані перетворювачі XML і Jackson JSON з налаштованим ObjectMapper замість стандартного:

Java

@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

@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()))

У попередньому прикладі Jackson2ObjectMapperBuilder використовується для створення загальної конфігурації для MappingJackson2HttpMessageConverter та MappingJackson2XmlHttpMessageConverter з увімкненим відступом, налаштованим форматом дати та реєстрацією модуля jackson-module-parameter-names, який додає підтримку доступу до імен параметрів (функція, додана в Java 8 ).

Цей засіб складання налаштовує властивості Jackson за замовчуванням таким чином:

Він також автоматично реєструє такі відомі модулі, якщо вони виявлені в classpath:

Увімкнення відступів з підтримкою Jackson XML вимагає наявності залежності woodstox-core-asl на додаток до jackson-dataformat-xml.

Є інші цікаві модулі Jackson:

  • jackson-datatype-money: Підтримка типів javax.money (неофіційний модуль).

  • jackson-datatype-hibernate: Підтримка специфічних для Hibernate типів та властивостей (включно з аспектами відкладеного завантаження).

У наступному прикладі показано, як отримати таку ж конфігурацію на XML:


<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"/>

Подання контролерів

Це скорочення для визначення ParameterizableViewController, який під час виклику негайно переходить до подання. Можна використовувати його в статичних випадках, коли немає логіки Java-контролера, яку потрібно виконати до того, як подання згенерує відповідь. У наступному прикладі Java-конфігурації спрямований запит на / до подання під назвою home:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("home");
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun addViewControllers(registry: ViewControllerRegistry) {
        registry.addViewController("/").setViewName("home")
    }
}

У наступному прикладі виходить те саме, що й у попередньому, але за допомогою XML, з використанням елементу <mvc:view-controller>:

<mvc:view-controller path="/" view-name="home"/>

Якщо метод з анотацією @RequestMapping відображено на URL-адресу для будь-якого HTTP-метода, то контролер подання не можна використовувати для обробки тієї ж URL-адреси. Це пов'язано з тим, що збіг URL-адреси з анотованим контролером вважається досить переконливою ознакою приналежності кінцевої точки, тому клієнт може отримати відповідь 405 (METHOD_NOT_ALLOWED), 415 (UNSUPPORTED_MEDIA_TYPE) або аналогічну відповідь для допомоги у налагодженні. З цієї причини рекомендується уникати поділу обробки URL-адреси на анотований контролер і контролер подання.

Розпізнавачі подання

Конфигурація MVC спрощує реєстрацію ррозпізнавачів подання. В наступному прикладі Java-конфігурації конфігурується дозвіл на узгодження контенту з використанням JSP і Jackson як View за замовчуванням для візуалізації у форматі JSON:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(new MappingJackson2JsonView());
        registry.jsp();
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun configureViewResolvers(registry: ViewResolverRegistry) {
        registry.enableContentNegotiation(MappingJackson2JsonView())
        registry.jsp()
    }
}

У наступному прикладі показано, як отримати таку ж конфігурацію на XML:


<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>

Зверни увагу, що FreeMarker, Tiles, Groovy Markup та шаблони скриптів також вимагають конфігурування технології подання. Простір імен MVC передбачає спеціальні елементи. Наступний приклад працює з FreeMarker:


<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>

У Java-конфігурації можна додати відповідний бін Configurer, як показано в наступному прикладі:

Java

@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

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun configureViewResolvers(registry: ViewResolverRegistry) {
        registry.enableContentNegotiation(MappingJackson2JsonView())
        registry.freeMarker().cache(false)
    }
    @Bean
    fun freeMarkerConfigurer() = FreeMarkerConfigurer().apply {
        setTemplateLoaderPath("/freemarker")
    }
}

Статичні ресурси

Ця опція забезпечує зручний спосіб обробки статичних ресурсів зі списку розташування на основі Resource.

У наступному прикладі, якщо запит починається з /resources, відносний шлях використовується для пошуку та обробки статичних ресурсів щодо /public в корені вебдодатку або в classpath у / static. Ресурси надаються із закінченням терміну дії в один рік, щоб забезпечити максимальне використання кеша браузера та скорочення HTTP-запитів, зроблених браузером. Інформація Last-Modified виводиться з Resource#lastModified, щоб надавати підтримку умовних HTTP-запитів із заголовками "Last-Modified".

У наступному лістингу показано, як це зробити за допомогою Java-конфігурації:

Java

@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

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/public", "classpath:/static/")
                .setCacheControl(CacheControl.maxAge(Duration.ofDays(365)))
    }
}

У наступному прикладі показано, як отримати таку ж конфігурацію на XML:


<mvc:resources mapping="/resources/**"
    location="/public, classpath:/static/"
    cache-period="31556926" />

Обробник ресурсів також підтримує ланцюжок реалізацій ResourceResolver та ResourceTransformer, які можна використовувати для створення набору інструментальних засобів для роботи з оптимізованими ресурсами.

Можна використовувати VersionResourceResolver для версійних URL-адрес ресурсів на основі хеша MD5 обчисленого з контенту, фіксованої версії програми або іншого. ContentVersionStrategy (хеш MD5) є продуманим вибором — за деякими значними винятками, такими як ресурси JavaScript, які використовуються із завантажувачем модулів.

У наступному прикладі показано, як використовувати VersionResourceResolver в Java-конфігурації:

Java

@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

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/public/")
                .resourceChain(true)
                .addResolver(VersionResourceResolver().addContentVersionStrategy("/**"))
    }
}

У наступному прикладі показано, як отримати таку ж конфігурацію на XML:


<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>

Потім можна використовувати ResourceUrlProvider для перезапису URL-адрес та застосування повного ланцюжка розпізнавачів та перетворювачів – наприклад, для вставлення версій. Конфігурація MVC передбачає бін ResourceUrlProvider, який можна впроваджувати в інші біни. Ти також можеш зробити перезапис прозорим за допомогою ResourceUrlEncodingFilter для Thymeleaf, JSP, FreeMarker та інших, використовуючи URL-теги, які покладаються на HttpServletResponse#encodeURL.

Зверни увагу, що при використанні EncodedResourceResolver (наприклад, для обробки закодованих ресурсів з методами стиснення gzip або brotli) та VersionResourceResolver, необхідно зареєструвати їх саме в такому порядку. Це забезпечує надійне обчислення версій, що базуються на вмісті, на основі некодованого файлу.

WebJars також підтримуються за допомогою WebJarsResourceResolver, який автоматично реєструється за наявності бібліотеки org.webjars:webjars-locator-core у classpath. Розпізнавач може переписувати URL-адреси, щоб включити до складу версію jar, а також зіставляти вхідні URL-адреси без версій — наприклад, з /jquery/jquery.min.js до /jquery/1.2 .0/jquery.min.js.

Java-конфігурація на основі ResourceHandlerRegistry передбачає додаткові можливості для тонкого контролю, наприклад, логіку роботи при останній зміні та оптимізований дозвіл ресурсів.

Сервлет за замовчуванням

Фреймворк Spring MVC дозволяє відображати DispatcherServlet на / (тим самим перевизначаючи відображення стандартного сервлета контейнера), водночас статичні запити до ресурсів будуть оброблятися стандартним сервлетом контейнера. Він конфігурує DefaultServletHttpRequestHandler з URL-відображенням /** та найнижчим пріоритетом щодо інших URL-відображень.

Цей обробник перенаправляє всі запити на сервлет за замовчуванням. Тому він повинен залишатися останнім у порядку проходження всіх інших HandlerMappings для URL. Це відбувається, якщо використовується <mvc:annotation-driven>. До того ж, якщо ти створюєш власний екземпляр HandlerMapping, не забудь встановити його властивість order у значення менше, ніж у DefaultServletHttpRequestHandler, яка є Integer.MAX_VALUE.

У цьому прикладі показано, як активувати цю функцію, використовуючи налаштування за замовчуванням:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun configureDefaultServletHandling(configurer: DefaultServletHandlerConfigurer) {
        configurer.enable()
    }
}

У наступному прикладі показано, як отримати таку ж конфігурацію на XML:

<mvc:default-servlet-handler/> 

Застереження під час перевизначення відображення / сервлету полягає в тому, що RequestDispatcher для сервлета за замовчуванням має бути знайдено на ім'я, а не за шляхом. DefaultServletHttpRequestHandler намагається автоматично визначити стандартний сервлет для контейнера під час запуску, використовуючи список відомих імен для більшості основних контейнерів сервлетів (включно з Tomcat, Jetty, GlassFish, JBoss, Resin, WebLogic і WebSphere). Якщо стандартний сервлет кастомно налаштований з іншим ім'ям, або якщо використовується інший контейнер сервлетів, де ім'я сервлета за замовчуванням невідоме, потрібно явно вказати ім'я сервлета за замовчуванням, як показано в наступному прикладі:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable("myCustomDefaultServlet");
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun configureDefaultServletHandling(configurer: DefaultServletHandlerConfigurer) {
        configurer.enable("myCustomDefaultServlet")
    }
}

У наступному прикладі показано, як отримати таку ж конфігурацію на XML:

<mvc:default-servlet-handler default-servlet- name="myCustomDefaultServlet"/>

Зіставлення шляхів

Ти можеш налаштувати параметри, пов'язані з зіставленням шляхів та обробкою URL-адрес. Докладніше про окремі опції див. у javadoc PathMatchConfigurer.

У наступному прикладі показано, як налаштувати узгодження шляхів у Java-конфігурації:

Java

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer
            .setPatternParser(new PathPatternParser())
            .addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController.class));
    }
    private PathPatternParser patternParser() {
        // ...
    }
}
Kotlin

@Configuration
@EnableWebMvc
class WebConfig : WebMvcConfigurer {
    override fun configurePathMatch(configurer: PathMatchConfigurer) {
        configurer
            .setPatternParser(patternParser)
            .addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
    }
    fun patternParser(): PathPatternParser {
        //...
    }
}

У наступному прикладі показано, як отримати таку ж конфігурацію на XML:


<mvc:annotation-driven>
    <mvc:path-matching
            trailing-slash="false"
            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"/>

Розширена Java-конфігурація

@EnableWebMvc імпортує DelegatingWebMvcConfiguration, яка:

  • Передає конфігурацію Spring за замовчуванням для програм Spring MVC

  • Виявляє та делегує реалізації WebMvcConfigurer для налаштування цієї конфігурації.

У розширеному режимі ти можеш видалити анотацію @EnableWebMvc і проводити розширення безпосередньо з DelegatingWebMvcConfiguration замість реалізації WebMvcConfigurer, як показано в наступному прикладі:

Java
@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {
    // ...
}
Kotlin
@Configuration
class WebConfig : DelegatingWebMvcConfiguration() {
    // ...
}

Можна зберігати існуючі методи в WebConfig, але тепер також є можливість перевизначати оголошення бінів з базового класу, і все ще можна мати будь-яку кількість інших реалізацій WebMvcConfigurer у classpath.

Розширена XML-конфігурація

Простір імен MVC не передбачає розширений режим. Якщо потрібно налаштувати властивість біна, яку не можна змінити іншим способом, то можна використовувати перехоплювач життєвого циклу BeanPostProcessor у ApplicationContext для Spring, як показано в наступному прикладі :

Java

@Component
public class MyPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        // ...
    }
}
Kotlin

@Component
class MyPostProcessor : BeanPostProcessor {
    override fun postProcessBeforeInitialization(bean: Any, name: String): Any {
        // ...
    }
}
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ