Migrate to the Spring MVC Java Configuration

This commit is contained in:
Antoine Rey 2015-05-27 21:34:24 +02:00
parent fbd2946e8f
commit f157360eb9
5 changed files with 240 additions and 112 deletions

View file

@ -1,10 +1,148 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.MediaType;
import org.springframework.samples.petclinic.service.ClinicService;
import org.springframework.samples.petclinic.web.PetTypeFormatter;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
/**
* <p>
* The ContentNegotiatingViewResolver delegates to the
* InternalResourceViewResolver and BeanNameViewResolver, and uses the requested
* media type (determined by the path extension) to pick a matching view. When
* the media type is 'text/html', it will delegate to the
* InternalResourceViewResolver's JstlView, otherwise to the
* BeanNameViewResolver.
*
*/
@Configuration
@ImportResource("classpath:spring/mvc-core-config.xml")
public class MvcCoreConfig {
@EnableWebMvc
@Import(MvcViewConfig.class)
// POJOs labeled with the @Controller and @Service annotations are
// auto-detected.
@ComponentScan(basePackages = { "org.springframework.samples.petclinic.web" })
public class MvcCoreConfig extends WebMvcConfigurerAdapter {
@Autowired
private ClinicService clinicService;
@Override
public void configureContentNegotiation(
ContentNegotiationConfigurer configurer) {
configurer.ignoreAcceptHeader(true);
configurer.defaultContentType(MediaType.TEXT_HTML);
configurer.mediaType("html", MediaType.TEXT_HTML);
configurer.mediaType("xml", MediaType.APPLICATION_XML);
configurer.mediaType("atom", MediaType.APPLICATION_ATOM_XML);
}
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
// Serve static resources (*.html, ...) from src/main/webapp/
configurer.enable();
}
@Override
public void addFormatters(FormatterRegistry formatterRegistry) {
formatterRegistry.addFormatter(petTypeFormatter());
}
@Bean
public PetTypeFormatter petTypeFormatter() {
return new PetTypeFormatter(clinicService);
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// all resources inside folder src/main/webapp/resources are mapped so
// they can be refered to inside JSP files (see header.jsp for more
// details)
registry.addResourceHandler("/resources/**").addResourceLocations(
"/resources/");
// uses WebJars so Javascript and CSS libs can be declared as Maven dependencies (Bootstrap, jQuery...)
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("welcome");
}
@Bean(name = "messageSource")
@Description("Message source for this context, loaded from localized 'messages_xx' files.")
public ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource() {
// Files are stored inside src/main/resources
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages/messages");
return messageSource;
}
/**
* Resolves specific types of exceptions to corresponding logical view names
* for error views.
*
* <p>
* View name resolved using bean of type InternalResourceViewResolver
* (declared in {@link MvcViewConfig}).
*/
@Override
public void configureHandlerExceptionResolvers(
List<HandlerExceptionResolver> exceptionResolvers) {
SimpleMappingExceptionResolver exceptionResolver = new SimpleMappingExceptionResolver();
// results into 'WEB-INF/jsp/exception.jsp'
exceptionResolver.setDefaultErrorView("exception");
// needed otherwise exceptions won't be logged anywhere
exceptionResolver.setWarnLogCategory("warn");
exceptionResolvers.add(exceptionResolver);
}
}

View file

@ -0,0 +1,96 @@
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.samples.petclinic.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.samples.petclinic.model.Vets;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.BeanNameViewResolver;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.xml.MarshallingView;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class MvcViewConfig {
@Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver(ContentNegotiationManager manager) {
ContentNegotiatingViewResolver contentNegotiatingViewResolver = new ContentNegotiatingViewResolver();
List<ViewResolver> viewResolvers = new ArrayList<ViewResolver>();
viewResolvers.add(internalResourceViewResolver());
viewResolvers.add(beanNameViewResolver());
contentNegotiatingViewResolver.setViewResolvers(viewResolvers );
contentNegotiatingViewResolver.setContentNegotiationManager(manager);
return contentNegotiatingViewResolver;
}
@Bean
@Description("Default viewClass: JSTL view (JSP with html output)")
public ViewResolver internalResourceViewResolver() {
// Example: a logical view name of 'vets' is mapped to
// '/WEB-INF/jsp/vets.jsp'
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/jsp/");
bean.setSuffix(".jsp");
return bean;
}
@Bean
@Description("Used for 'xml' and 'atom' views")
public ViewResolver beanNameViewResolver() {
return new BeanNameViewResolver();
}
@Bean(name = "vets/vetList.xml")
@Description("Renders an XML view. Used by the BeanNameViewResolver")
public MarshallingView marshallingView() {
return new MarshallingView(marshaller());
}
@Bean
@Description("Object-XML mapping declared using annotations inside 'Vets'")
public Marshaller marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(Vets.class);
return marshaller;
}
}

View file

@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- DispatcherServlet application context for PetClinic's web tier.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<import resource="mvc-view-config.xml"/>
<!--
- POJOs labeled with the @Controller and @Service annotations are auto-detected.
-->
<context:component-scan
base-package="org.springframework.samples.petclinic.web"/>
<mvc:annotation-driven conversion-service="conversionService"/>
<!-- all resources inside folder src/main/webapp/resources are mapped so they can be refered to inside JSP files
(see header.jsp for more details) -->
<mvc:resources mapping="/resources/**" location="/resources/"/>
<!-- uses WebJars so Javascript and CSS libs can be declared as Maven dependencies (Bootstrap, jQuery...) -->
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>
<mvc:view-controller path="/" view-name="welcome" />
<!-- serve static resources (*.html, ...) from src/main/webapp/
Required when both servlet-mapping is '/' and static resources need to be served -->
<mvc:default-servlet-handler />
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<bean class="org.springframework.samples.petclinic.web.PetTypeFormatter"/>
</set>
</property>
</bean>
<!--
- Message source for this context, loaded from localized "messages_xx" files.
- Files are stored inside src/main/resources
-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages/messages"/>
<!--
- This bean resolves specific types of exceptions to corresponding logical
- view names for error views.
-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<!-- view name resolved using bean of type InternalResourceViewResolver (declared in mvc-view-config.xml) -->
<property name="defaultErrorView" value="exception"/>
<!-- results into 'WEB-INF/jsp/exception.jsp' -->
<property name="warnLogCategory" value="warn"/>
<!-- needed otherwise exceptions won't be logged anywhere -->
</bean>
</beans>

View file

@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- DispatcherServlet application context for PetClinic's web tier.
-->
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oxm="http://www.springframework.org/schema/oxm" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--
- The ContentNegotiatingViewResolver delegates to the InternalResourceViewResolver and BeanNameViewResolver,
- and uses the requested media type (determined by the path extension) to pick a matching view.
- When the media type is 'text/html', it will delegate to the InternalResourceViewResolver's JstlView,
- otherwise to the BeanNameViewResolver.
-->
<mvc:view-resolvers>
<mvc:content-negotiation use-not-acceptable="true">
<mvc:default-views>
<bean class="org.springframework.web.servlet.view.JstlView">
<property name="url" value="" />
</bean>
</mvc:default-views>
</mvc:content-negotiation>
<!-- Registering BeanNameViewResolver and InternalViewResolver -->
<mvc:bean-name />
<mvc:jsp prefix="/WEB-INF/jsp/" suffix=".jsp"/>
</mvc:view-resolvers>
<!-- Renders an XML view. Used by the BeanNameViewResolver -->
<bean id="vets/vetList.xml" class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller" ref="marshaller"/>
</bean>
<oxm:jaxb2-marshaller id="marshaller">
<!-- Object-XML mapping declared using annotations inside 'Vets' -->
<oxm:class-to-be-bound name="org.springframework.samples.petclinic.model.Vets"/>
</oxm:jaxb2-marshaller>
</beans>

View file

@ -11,6 +11,7 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.samples.petclinic.config.BusinessConfig;
import org.springframework.samples.petclinic.config.MvcCoreConfig;
import org.springframework.samples.petclinic.config.ToolsConfig;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
@ -31,7 +32,7 @@ import org.springframework.web.context.WebApplicationContext;
@WebAppConfiguration
@ContextHierarchy({
@ContextConfiguration(classes = { BusinessConfig.class, ToolsConfig.class }),
@ContextConfiguration(locations = "classpath:spring/mvc-core-config.xml")})
@ContextConfiguration(classes = MvcCoreConfig.class)})
@ActiveProfiles("spring-data-jpa")
public class VetControllerTests {