admin管理员组文章数量:1794759
Spring Mvc迁移到Spring Boot
Spring Mvc迁移到Spring Boot 题记
随着Spring Boot的蓬勃发展,在业界产生的影响已经十分深远,大多数分布式项目开始往微服务方向改造。由于多数公司依赖于强大的Spring Framework,所以Spring Boot的发展趋势就不言而喻了。当然伴随着多数追随者的主要原因还是自身功能的强大:
Spring 官方说明 Create stand-alone Spring applications -- 创建一个独立的Spring应用 Embed Tomcat, Jetty or Undertow directly (no need to deploy WAR files) -- 嵌入式的web服务器Tomcat、Jetty、Undertow(无需部署 war 文件) Provide opinionated 'starter' dependencies to simplify your build configuration -- 提供建议的 "启动" 依赖关系, 以简化生成配置 Automatically configure Spring and 3rd party libraries whenever possible -- 尽可能自动配置 spring 和第三方库 Provide production-ready features such as metrics, health checks and externalized configuration -- 具备为生产准备的特性,如指标、运行状况检查和外部化配置 Absolutely no code generation and no requirement for XML configuration -- 尽可能的无需代码生成并且无XML配置由于大部分项目属于web项目,前端展示使用jsp,在迁移的过程中使用的首先面对的就是Sring Mvc的迁移
Spring MVC架构图 Spring Web MVC各大组件HandlerMapping | 将请求映射到处理程序以及用于预处理和后处理的拦截器列表。映射基于一些条件, 这些条件的详细信因 HandlerMapping 实现的不同而不同。两个主要的 HandlerMapping 实现是 requestmappinghandl善于映射, 它支持 @RequestMapping 带注释的方法, 以及简单 urlhandl十分映射, 它维护 uri 路径模式对处理程序的显式注册。 |
HandlerAdapter | 帮助调度服务器调用映射到请求的处理程序, 而不考虑处理程序的实际调用方式。例如, 调用带注释的控制器需要解析批注。handleradapter 的主要目的是保护调度服务不受这些细节的影响。 |
HandlerExceptionResolver | 解决异常的策略可能会将它们映射到处理程序, 或 html 错误视图或其他。请参阅异常。 |
ViewResolver | 解析从处理程序返回到要呈现给响应的实际视图的基于逻辑 String-based 的视图名称。 |
LocaleResolver, LocaleContextResolver | 解析客户端正在使用的区域设置, 并可能解析其时区, 以便能够提供国际化视图。 |
ThemeResolver | 解决 web 应用程序可以使用的主题, 例如, 提供个性化布局。 |
MultipartResolver | 用于分析多部分请求的抽象 (例如,浏览器表单文件上传) 的帮助下, 一些多部分的分析库。即多媒体支持 |
FlashMapManager | 存储和检索 “输入” 和 “输出” flashmap, 这些信可用于将属性从一个请求传递到另一个请求, 通常是通过重定向。 |
在Spring Mvc项目中,随着web服务器,比如Tomcat的启动,会去加载webapp\\WEB-INF\\web.xml,在该文件中驱动Spring Context和Spring MVC Context的加载,完成容器的启动以及Spring的初始化。
下面从标准的官方web.xml 和 app-context.xml进行分析 <web-app> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/app-context.xml</param-value> </context-param> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value></param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping> </web-app> <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="www.springframework/schema/beans" xmlns:xsi="www.w3/2001/XMLSchema-instance" xmlns:p="www.springframework/schema/p" xmlns:context="www.springframework/schema/context" xsi:schemaLocation="www.springframework/schema/beans www.springframework/schema/beans/spring-beans-3.0.xsd www.springframework/schema/aop www.springframework/schema/aop/spring-aop-3.0.xsd www.springframework/schema/tx www.springframework/schema/tx/spring-tx-3.0.xsd www.springframework/schema/context www.springframework/schema/context/spring-context-3.0.xsd"> <context:annotation-config /> <!-- component-scan --> <context:component-scan base-package="com.sxs.web" /> <!-- 视图 beans --> <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/jsp/</value> </property> <property name="suffix"> <value>.jsp</value> </property> <property name="order" value="1" /> </bean> <!-- json消转换 --> <bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"> <property name="supportedMediaTypes"> <list> <value>text/html;charset=UTF-8</value> </list> </property> </bean> <!-- 文件上传 --> <bean id="multipartResolver" class="org.springframework.web.multipartmons.CommonsMultipartResolver"> <!-- set the max upload size100MB --> <property name="maxUploadSize"> <value>104857600</value> </property> <property name="maxInMemorySize"> <value>1024000</value> </property> </bean> </beans>-
org.springframework.web.context.ContextLoaderListener该类是Spring启动类
web容器启动后spring加载顺序ContextLoaderListener -> ContextLoader#initWebApplicationContext -> ContextLoader#configureAndRefreshWebApplicationContext -> wac.refresh() ->AbstractApplicationContext#refresh
-
org.springframework.web.servlet.DispatcherServlet该类是Spring MVC启动类
web容器启动后Spring MVC加载顺序HttpServletBean#initServletBean ->FrameworkServlet#initServletBean ->FrameworkServlet#initWebApplicationContext -> org.springframework.web.servlet.FrameworkServlet#createWebApplicationContext(org.springframework.web.context.WebApplicationContext) -> FrameworkServlet.ContextRefreshListener#onApplicationEvent ->DispatcherServlet -
DispatcherServlet#onRefresh -> DispatcherServlet#initStrategies ->DispatcherServlet#doService -> DispatcherServlet#doDispatch ->DispatcherServlet#getHandler -> DispatcherServlet#getHandlerAdapter -> HandlerAdapter#handle-> DispatcherServlet#processDispatchResult ->DispatcherServlet#render -> DispatcherServlet#resolveViewName -> ModelAndView#getView
迁移思路
在Spring Boot中是没有web.xml的,而且app-context.xml的各大组件配置完全可以依赖于WebMvcAutoConfiguration进行自动装配,此处需要说明的是必须要明确WebMvcAutoConfiguration自动装配的条件(自动装配详解下述分析),另外Spring Boot自身包含嵌入式的web服务器(如:Tomcat),所以当WebMvcAutoConfiguration自动装配完成后即可重启项目(在IDEA中可直接运行@SpringBootApplication标注的类,在环境中可以直接java -jar xxx.jar) WebMvcAutoConfiguration自动装配 @Configuration @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class }) @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class }) public class WebMvcAutoConfiguration { public static final String DEFAULT_PREFIX = ""; public static final String DEFAULT_SUFFIX = ""; private static final String[] SERVLET_LOCATIONS = { "/" }; @Bean @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { return new OrderedHiddenHttpMethodFilter(); } @Bean @ConditionalOnMissingBean(HttpPutFormContentFilter.class) @ConditionalOnProperty(prefix = "spring.mvc.formcontent.putfilter", name = "enabled", matchIfMissing = true) public OrderedHttpPutFormContentFilter httpPutFormContentFilter() { return new OrderedHttpPutFormContentFilter(); } // Defined as a nested config to ensure WebMvcConfigurer is not read when not // on the classpath @Configuration @Import(EnableWebMvcConfiguration.class) @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) @Order(0) public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ResourceLoaderAware { private static final Log logger = LogFactory.getLog(WebMvcConfigurer.class); private final ResourceProperties resourceProperties; private final WebMvcProperties mvcProperties; private final ListableBeanFactory beanFactory; private final HttpMessageConverters messageConverters; final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; private ResourceLoader resourceLoader; public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, @Lazy HttpMessageConverters messageConverters, ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) { this.resourceProperties = resourceProperties; this.mvcProperties = mvcProperties; this.beanFactory = beanFactory; this.messageConverters = messageConverters; this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider .getIfAvailable(); } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.addAll(this.messageConverters.getConverters()); } @Override public void configureAsyncSupport(AsyncSupportConfigurer configurer) { Duration timeout = this.mvcProperties.getAsync().getRequestTimeout(); if (timeout != null) { configurer.setDefaultTimeout(timeout.toMillis()); } } @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch( this.mvcProperties.getPathmatch().isUseSuffixPattern()); configurer.setUseRegisteredSuffixPatternMatch( this.mvcProperties.getPathmatch().isUseRegisteredSuffixPattern()); } @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { WebMvcProperties.Contentnegotiation contentnegotiation = this.mvcProperties .getContentnegotiation(); configurer.favorPathExtension(contentnegotiation.isFavorPathExtension()); configurer.favorParameter(contentnegotiation.isFavorParameter()); if (contentnegotiation.getParameterName() != null) { configurer.parameterName(contentnegotiation.getParameterName()); } Map<String, MediaType> mediaTypes = this.mvcProperties.getContentnegotiation() .getMediaTypes(); mediaTypes.forEach(configurer::mediaType); } @Bean @ConditionalOnMissingBean public InternalResourceViewResolver defaultViewResolver() { InternalResourceViewResolver resolver = new InternalResourceViewResolver(); resolver.setPrefix(this.mvcProperties.getView().getPrefix()); resolver.setSuffix(this.mvcProperties.getView().getSuffix()); return resolver; } @Bean @ConditionalOnBean(View.class) @ConditionalOnMissingBean public BeanNameViewResolver beanNameViewResolver() { BeanNameViewResolver resolver = new BeanNameViewResolver(); resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10); return resolver; } @Bean @ConditionalOnBean(ViewResolver.class) @ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class) public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) { ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver(); resolver.setContentNegotiationManager( beanFactory.getBean(ContentNegotiationManager.class)); // ContentNegotiatingViewResolver uses all the other view resolvers to locate // a view so it should have a high precedence resolver.setOrder(Ordered.HIGHEST_PRECEDENCE); return resolver; } @Bean @ConditionalOnMissingBean @ConditionalOnProperty(prefix = "spring.mvc", name = "locale") public LocaleResolver localeResolver() { if (this.mvcProperties .getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { return new FixedLocaleResolver(this.mvcProperties.getLocale()); } AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); return localeResolver; } @Override public MessageCodesResolver getMessageCodesResolver() { if (this.mvcProperties.getMessageCodesResolverFormat() != null) { DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver(); resolver.setMessageCodeFormatter( this.mvcProperties.getMessageCodesResolverFormat()); return resolver; } return null; } @Override public void addFormatters(FormatterRegistry registry) { for (Converter<?, ?> converter : getBeansOfType(Converter.class)) { registry.addConverter(converter); } for (GenericConverter converter : getBeansOfType(GenericConverter.class)) { registry.addConverter(converter); } for (Formatter<?> formatter : getBeansOfType(Formatter.class)) { registry.addFormatter(formatter); } } private <T> Collection<T> getBeansOfType(Class<T> type) { return this.beanFactory.getBeansOfType(type).values(); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { if (!this.resourceProperties.isAddMappings()) { logger.debug("Default resource handling disabled"); return; } Duration cachePeriod = this.resourceProperties.getCache().getPeriod(); CacheControl cacheControl = this.resourceProperties.getCache() .getCachecontrol().toHttpCacheControl(); if (!registry.hasMappingForPattern("/webjars/**")) { customizeResourceHandlerRegistration(registry .addResourceHandler("/webjars/**") .addResourceLocations("classpath:/META-INF/resources/webjars/") .setCachePeriod(getSeconds(cachePeriod)) .setCacheControl(cacheControl)); } String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration( registry.addResourceHandler(staticPathPattern) .addResourceLocations(getResourceLocations( this.resourceProperties.getStaticLocations())) .setCachePeriod(getSeconds(cachePeriod)) .setCacheControl(cacheControl)); } } private Integer getSeconds(Duration cachePeriod) { return (cachePeriod != null ? (int) cachePeriod.getSeconds() : null); } @Bean public WelcomePageHandlerMapping welcomePageHandlerMapping( ApplicationContext applicationContext) { return new WelcomePageHandlerMapping( new TemplateAvailabilityProviders(applicationContext), applicationContext, getWelcomePage(), this.mvcProperties.getStaticPathPattern()); } static String[] getResourceLocations(String[] staticLocations) { String[] locations = new String[staticLocations.length + SERVLET_LOCATIONS.length]; System.arraycopy(staticLocations, 0, locations, 0, staticLocations.length); System.arraycopy(SERVLET_LOCATIONS, 0, locations, staticLocations.length, SERVLET_LOCATIONS.length); return locations; } private Optional<Resource> getWelcomePage() { String[] locations = getResourceLocations( this.resourceProperties.getStaticLocations()); return Arrays.stream(locations).map(this::getIndexHtml) .filter(this::isReadable).findFirst(); } private Resource getIndexHtml(String location) { return this.resourceLoader.getResource(location + "index.html"); } private boolean isReadable(Resource resource) { try { return resource.exists() && (resource.getURL() != null); } catch (Exception ex) { return false; } } private void customizeResourceHandlerRegistration( ResourceHandlerRegistration registration) { if (this.resourceHandlerRegistrationCustomizer != null) { this.resourceHandlerRegistrationCustomizer.customize(registration); } } @Bean @ConditionalOnMissingBean({ RequestContextListener.class, RequestContextFilter.class }) public static RequestContextFilter requestContextFilter() { return new OrderedRequestContextFilter(); } @Configuration @ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true) public static class FaviconConfiguration implements ResourceLoaderAware { private final ResourceProperties resourceProperties; private ResourceLoader resourceLoader; public FaviconConfiguration(ResourceProperties resourceProperties) { this.resourceProperties = resourceProperties; } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } @Bean public SimpleUrlHandlerMapping faviconHandlerMapping() { SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1); mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", faviconRequestHandler())); return mapping; } @Bean public ResourceHttpRequestHandler faviconRequestHandler() { ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler(); requestHandler.setLocations(resolveFaviconLocations()); return requestHandler; } private List<Resource> resolveFaviconLocations() { String[] staticLocations = getResourceLocations( this.resourceProperties.getStaticLocations()); List<Resource> locations = new ArrayList<>(staticLocations.length + 1); Arrays.stream(staticLocations).map(this.resourceLoader::getResource) .forEach(locations::add); locations.add(new ClassPathResource("/")); return Collections.unmodifiableList(locations); } } } /** * Configuration equivalent to {@code @EnableWebMvc}. */ @Configuration public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration { private final WebMvcProperties mvcProperties; private final ListableBeanFactory beanFactory; private final WebMvcRegistrations mvcRegistrations; public EnableWebMvcConfiguration( ObjectProvider<WebMvcProperties> mvcPropertiesProvider, ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider, ListableBeanFactory beanFactory) { this.mvcProperties = mvcPropertiesProvider.getIfAvailable(); this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique(); this.beanFactory = beanFactory; } @Bean @Override public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(); adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect()); return adapter; } @Override protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() { if (this.mvcRegistrations != null && this.mvcRegistrations.getRequestMappingHandlerAdapter() != null) { return this.mvcRegistrations.getRequestMappingHandlerAdapter(); } return super.createRequestMappingHandlerAdapter(); } @Bean @Primary @Override public RequestMappingHandlerMapping requestMappingHandlerMapping() { // Must be @Primary for MvcUriComponentsBuilder to work return super.requestMappingHandlerMapping(); } @Bean @Override public FormattingConversionService mvcConversionService() { WebConversionService conversionService = new WebConversionService( this.mvcProperties.getDateFormat()); addFormatters(conversionService); return conversionService; } @Bean @Override public Validator mvcValidator() { if (!ClassUtils.isPresent("javax.validation.Validator", getClass().getClassLoader())) { return super.mvcValidator(); } return ValidatorAdapter.get(getApplicationContext(), getValidator()); } @Override protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() { if (this.mvcRegistrations != null && this.mvcRegistrations.getRequestMappingHandlerMapping() != null) { return this.mvcRegistrations.getRequestMappingHandlerMapping(); } return super.createRequestMappingHandlerMapping(); } @Override protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() { try { return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class); } catch (NoSuchBeanDefinitionException ex) { return super.getConfigurableWebBindingInitializer(); } } @Override protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() { if (this.mvcRegistrations != null && this.mvcRegistrations .getExceptionHandlerExceptionResolver() != null) { return this.mvcRegistrations.getExceptionHandlerExceptionResolver(); } return super.createExceptionHandlerExceptionResolver(); } @Override protected void configureHandlerExceptionResolvers( List<HandlerExceptionResolver> exceptionResolvers) { super.configureHandlerExceptionResolvers(exceptionResolvers); if (exceptionResolvers.isEmpty()) { addDefaultHandlerExceptionResolvers(exceptionResolvers); } if (this.mvcProperties.isLogResolvedException()) { for (HandlerExceptionResolver resolver : exceptionResolvers) { if (resolver instanceof AbstractHandlerExceptionResolver) { ((AbstractHandlerExceptionResolver) resolver) .setWarnLogCategory(resolver.getClass().getName()); } } } } @Bean @Override public ContentNegotiationManager mvcContentNegotiationManager() { ContentNegotiationManager manager = super.mvcContentNegotiationManager(); List<ContentNegotiationStrategy> strategies = manager.getStrategies(); ListIterator<ContentNegotiationStrategy> iterator = strategies.listIterator(); while (iterator.hasNext()) { ContentNegotiationStrategy strategy = iterator.next(); if (strategy instanceof PathExtensionContentNegotiationStrategy) { iterator.set(new OptionalPathExtensionContentNegotiationStrategy( strategy)); } } return manager; } } @Configuration @ConditionalOnEnabledResourceChain static class ResourceChainCustomizerConfiguration { @Bean public ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer() { return new ResourceChainResourceHandlerRegistrationCustomizer(); } } interface ResourceHandlerRegistrationCustomizer { void customize(ResourceHandlerRegistration registration); } private static class ResourceChainResourceHandlerRegistrationCustomizer implements ResourceHandlerRegistrationCustomizer { @Autowired private ResourceProperties resourceProperties = new ResourceProperties(); @Override public void customize(ResourceHandlerRegistration registration) { ResourceProperties.Chain properties = this.resourceProperties.getChain(); configureResourceChain(properties, registration.resourceChain(properties.isCache())); } private void configureResourceChain(ResourceProperties.Chain properties, ResourceChainRegistration chain) { Strategy strategy = properties.getStrategy(); if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) { chain.addResolver(getVersionResourceResolver(strategy)); } if (properties.isGzipped()) { chain.addResolver(new GzipResourceResolver()); } if (properties.isHtmlApplicationCache()) { chain.addTransformer(new AppCacheManifestTransformer()); } } private ResourceResolver getVersionResourceResolver( ResourceProperties.Strategy properties) { VersionResourceResolver resolver = new VersionResourceResolver(); if (properties.getFixed().isEnabled()) { String version = properties.getFixed().getVersion(); String[] paths = properties.getFixed().getPaths(); resolver.addFixedVersionStrategy(version, paths); } if (properties.getContent().isEnabled()) { String[] paths = properties.getContent().getPaths(); resolver.addContentVersionStrategy(paths); } return resolver; } } /** * Decorator to make {@link PathExtensionContentNegotiationStrategy} optional * depending on a request attribute. */ static class OptionalPathExtensionContentNegotiationStrategy implements ContentNegotiationStrategy { private static final String SKIP_ATTRIBUTE = PathExtensionContentNegotiationStrategy.class .getName() + ".SKIP"; private final ContentNegotiationStrategy delegate; OptionalPathExtensionContentNegotiationStrategy( ContentNegotiationStrategy delegate) { this.delegate = delegate; } @Override public List<MediaType> resolveMediaTypes(NativeWebRequest webRequest) throws HttpMediaTypeNotAcceptableException { Object skip = webRequest.getAttribute(SKIP_ATTRIBUTE, RequestAttributes.SCOPE_REQUEST); if (skip != null && Boolean.parseBoolean(skip.toString())) { return MEDIA_TYPE_ALL_LIST; } return this.delegate.resolveMediaTypes(webRequest); } } }- 在WebMvcAutoConfiguration中自动装配是有条件的,该处用到了条件装配和顺序装配:
- 即该装配必须在@ConditionalOnMissingBean条件满足WebMvcConfigurationSupport类或者子类不存在时,一般情况下是指在Spring Web MVC阶段没有@EnableWebMvc进行手动装配的条件下。
- 相对顺序装配@AutoConfigureAfter,指在DispatcherServletAutoConfiguration.class,和ValidationAutoConfiguration.class装配完成后执行。
- 绝对顺序装配@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10),在第十一位进行装配。
- 在WebMvcAutoConfiguration中主要是初始化各个上述组件,还有资源的加载setResourceLoader,消转换处理configureMessageConverters,内容调停configureContentNegotiation,此外在Servlet3.0之后提供了对异步的支持configureAsyncSupport等等。
- 对于DispatcherServletAutoConfiguration
-
条件装配@ConditionalOnClass和@ConditionalOnWebApplication(type = Type.SERVLET)装载顺序
@AutoConfigureOrder以及@AutoConfigureAfter表示在Servlet服务器装载完成后进行装配。
-
对于ServletWebServerFactoryAutoConfiguration
- 条件装配ConditionalOnClass和ConditionalOnWebApplication只有是Servlet时进行装配,@Import这个是该类的重点,即web服务器的选择
创建Spring Boot的Web项目,修改启动类
@SpringBootApplication(scanBasePackages = "com.sxs.web") public class SpringBootWebMvcBootstrap { public static void main(String[] args) { SpringApplication.run(SpringBootWebMvcBootstrap.class, args); } }修改aplication.properties配置文件
#服务器端口号 server.port = 8088 #修改视图映射前、后缀 spring.mvc.view.prefix = /WEB-INF/jsp/ spring.mvc.view.suffix = .jsp此外,所有的.jsp文件参考原有路径进行移植
完整代码及详情具体依赖及相关源码参照
github/dwyanewede/spring-boot/tree/master/springboot-webmvc/src/main/java/com/sxs/web相关详情参照公众号
我叫小朋友版权声明:本文标题:Spring Mvc迁移到Spring Boot 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686614068a86304.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论