初入spring boot(四 )web项目
Posted kevin_shen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初入spring boot(四 )web项目相关的知识,希望对你有一定的参考价值。
1. 模板引擎
spring boot提供了大量的模板引擎,包括FreeMark、Groovy、Thymeleaf、Velocity等,但spring boot中推荐用Thymeleaf,因为Thymeleaf提供了完美的spring mvc的支持。
2. 与spring boot集成
在spring mvc中,若要集成一个模板引擎的话,需要定义ViewResolver,而ViewResolver需要定义一个View。Thymeleaf已经定义好了ViewResolver和View,分别是org.thymeleaf.spring4.view.ThymeleafViewResolver(默认使用ThymeleafView作为View)和org.thymeleaf.spring4.view.ThymeleafView。Thymeleaf提供了SpringTemplateEngine类,用来驱动在spring mvc下使用Thymeleaf模板引擎,另外还提供了一个TemplateResolver用来设置通用的模板引擎(包含前缀、后缀等),这使我们在spring mvc中集成Thymeleaf引擎变得十分简单。
上面说的是与spring mvc集成,但是ThymeleafView与Spring boot集成很方便,spring boot通过org.springframework.boot.autoconfigure.thymeleaf包对Thymeleaf进行了自动配置。
通过ThymeleafAutoConfiguration类对集成所需要的bean进行自动配置,包括templateResolver、templateEngine和thymeleafViewResolver的配置。
通过ThymeleafProperties来配置Thymeleaf,在application.properties中,以spring.thymeleaf开头来配置,通过查看ThymeleafProperties的主要源码,可以看出如何设置属性以及默认的配置:
1 @ConfigurationProperties(prefix = "spring.thymeleaf") 2 public class ThymeleafProperties { 3 4 private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8"); 5 6 private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html"); 7 8 public static final String DEFAULT_PREFIX = "classpath:/templates/"; 9 10 public static final String DEFAULT_SUFFIX = ".html"; 11 12 /** 13 * Check that the template exists before rendering it (Thymeleaf 3+). 14 */ 15 private boolean checkTemplate = true; 16 17 /** 18 * Check that the templates location exists. 19 */ 20 private boolean checkTemplateLocation = true; 21 22 /** 23 * Prefix that gets prepended to view names when building a URL. 24 */ 25 private String prefix = DEFAULT_PREFIX; 26 27 /** 28 * Suffix that gets appended to view names when building a URL. 29 */ 30 private String suffix = DEFAULT_SUFFIX; 31 32 /** 33 * Template mode to be applied to templates. See also StandardTemplateModeHandlers. 34 */ 35 private String mode = "HTML5"; 36 37 /** 38 * Template encoding. 39 */ 40 private Charset encoding = DEFAULT_ENCODING; 41 42 /** 43 * Content-Type value. 44 */ 45 private MimeType contentType = DEFAULT_CONTENT_TYPE; 46 47 /** 48 * Enable template caching. 49 */ 50 private boolean cache = true; 51 52 /** 53 * Order of the template resolver in the chain. By default, the template resolver is 54 * first in the chain. Order start at 1 and should only be set if you have defined 55 * additional "TemplateResolver" beans. 56 */ 57 private Integer templateResolverOrder; 58 59 /** 60 * Comma-separated list of view names that can be resolved. 61 */ 62 private String[] viewNames; 63 64 /** 65 * Comma-separated list of view names that should be excluded from resolution. 66 */ 67 private String[] excludedViewNames; 68 69 /** 70 * Enable MVC Thymeleaf view resolution. 71 */ 72 private boolean enabled = true; 73 74 public boolean isEnabled() { 75 return this.enabled; 76 } 77 78 public void setEnabled(boolean enabled) { 79 this.enabled = enabled; 80 } 81 82 public boolean isCheckTemplate() { 83 return this.checkTemplate; 84 } 85 86 public void setCheckTemplate(boolean checkTemplate) { 87 this.checkTemplate = checkTemplate; 88 } 89 90 public boolean isCheckTemplateLocation() { 91 return this.checkTemplateLocation; 92 } 93 94 public void setCheckTemplateLocation(boolean checkTemplateLocation) { 95 this.checkTemplateLocation = checkTemplateLocation; 96 } 97 98 public String getPrefix() { 99 return this.prefix; 100 } 101 102 public void setPrefix(String prefix) { 103 this.prefix = prefix; 104 } 105 106 public String getSuffix() { 107 return this.suffix; 108 } 109 110 public void setSuffix(String suffix) { 111 this.suffix = suffix; 112 } 113 114 public String getMode() { 115 return this.mode; 116 } 117 118 public void setMode(String mode) { 119 this.mode = mode; 120 } 121 122 public Charset getEncoding() { 123 return this.encoding; 124 } 125 126 public void setEncoding(Charset encoding) { 127 this.encoding = encoding; 128 } 129 130 public MimeType getContentType() { 131 return this.contentType; 132 } 133 134 public void setContentType(MimeType contentType) { 135 this.contentType = contentType; 136 } 137 138 public boolean isCache() { 139 return this.cache; 140 } 141 142 public void setCache(boolean cache) { 143 this.cache = cache; 144 } 145 146 public Integer getTemplateResolverOrder() { 147 return this.templateResolverOrder; 148 } 149 150 public void setTemplateResolverOrder(Integer templateResolverOrder) { 151 this.templateResolverOrder = templateResolverOrder; 152 } 153 154 public String[] getExcludedViewNames() { 155 return this.excludedViewNames; 156 } 157 158 public void setExcludedViewNames(String[] excludedViewNames) { 159 this.excludedViewNames = excludedViewNames; 160 } 161 162 public String[] getViewNames() { 163 return this.viewNames; 164 } 165 166 public void setViewNames(String[] viewNames) { 167 this.viewNames = viewNames; 168 } 169 170 }
3. web相关配置
3.1 spring boot提供的自动配置
通过查看WebMvcAutoConfiguration及WebMvcProperties的源码,可以发现spring boot提供了如下的自动配置
1 @Configuration 2 @ConditionalOnWebApplication 3 @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, 4 WebMvcConfigurerAdapter.class }) 5 @ConditionalOnMissingBean(WebMvcConfigurationSupport.class) 6 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10) 7 @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, 8 ValidationAutoConfiguration.class }) 9 public class WebMvcAutoConfiguration { 10 11 public static String DEFAULT_PREFIX = ""; 12 13 public static String DEFAULT_SUFFIX = ""; 14 15 @Bean 16 @ConditionalOnMissingBean(HiddenHttpMethodFilter.class) 17 public OrderedHiddenHttpMethodFilter hiddenHttpMethodFilter() { 18 return new OrderedHiddenHttpMethodFilter(); 19 } 20 21 @Bean 22 @ConditionalOnMissingBean(HttpPutFormContentFilter.class) 23 @ConditionalOnProperty(prefix = "spring.mvc.formcontent.putfilter", name = "enabled", matchIfMissing = true) 24 public OrderedHttpPutFormContentFilter httpPutFormContentFilter() { 25 return new OrderedHttpPutFormContentFilter(); 26 } 27 28 // Defined as a nested config to ensure WebMvcConfigurerAdapter is not read when not 29 // on the classpath 30 @Configuration 31 @Import(EnableWebMvcConfiguration.class) 32 @EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class }) 33 public static class WebMvcAutoConfigurationAdapter extends WebMvcConfigurerAdapter { 34 35 private static final Log logger = LogFactory 36 .getLog(WebMvcConfigurerAdapter.class); 37 38 private final ResourceProperties resourceProperties; 39 40 private final WebMvcProperties mvcProperties; 41 42 private final ListableBeanFactory beanFactory; 43 44 private final HttpMessageConverters messageConverters; 45 46 final ResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer; 47 48 public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, 49 WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, 50 HttpMessageConverters messageConverters, 51 ObjectProvider<ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider) { 52 this.resourceProperties = resourceProperties; 53 this.mvcProperties = mvcProperties; 54 this.beanFactory = beanFactory; 55 this.messageConverters = messageConverters; 56 this.resourceHandlerRegistrationCustomizer = resourceHandlerRegistrationCustomizerProvider 57 .getIfAvailable(); 58 } 59 60 @Override 61 public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 62 converters.addAll(this.messageConverters.getConverters()); 63 } 64 65 @Override 66 public void configureAsyncSupport(AsyncSupportConfigurer configurer) { 67 Long timeout = this.mvcProperties.getAsync().getRequestTimeout(); 68 if (timeout != null) { 69 configurer.setDefaultTimeout(timeout); 70 } 71 } 72 73 @Override 74 public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 75 Map<String, MediaType> mediaTypes = this.mvcProperties.getMediaTypes(); 76 for (Entry<String, MediaType> mediaType : mediaTypes.entrySet()) { 77 configurer.mediaType(mediaType.getKey(), mediaType.getValue()); 78 } 79 } 80 81 @Bean 82 @ConditionalOnMissingBean 83 public InternalResourceViewResolver defaultViewResolver() { 84 InternalResourceViewResolver resolver = new InternalResourceViewResolver(); 85 resolver.setPrefix(this.mvcProperties.getView().getPrefix()); 86 resolver.setSuffix(this.mvcProperties.getView().getSuffix()); 87 return resolver; 88 } 89 90 @Bean 91 @ConditionalOnBean(View.class) 92 @ConditionalOnMissingBean 93 public BeanNameViewResolver beanNameViewResolver() { 94 BeanNameViewResolver resolver = new BeanNameViewResolver(); 95 resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10); 96 return resolver; 97 } 98 99 @Bean 100 @ConditionalOnBean(ViewResolver.class) 101 @ConditionalOnMissingBean(name = "viewResolver", value = ContentNegotiatingViewResolver.class) 102 public ContentNegotiatingViewResolver viewResolver(BeanFactory beanFactory) { 103 ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver(); 104 resolver.setContentNegotiationManager( 105 beanFactory.getBean(ContentNegotiationManager.class)); 106 // ContentNegotiatingViewResolver uses all the other view resolvers to locate 107 // a view so it should have a high precedence 108 resolver.setOrder(Ordered.HIGHEST_PRECEDENCE); 109 return resolver; 110 } 111 112 @Bean 113 @ConditionalOnMissingBean 114 @ConditionalOnProperty(prefix = "spring.mvc", name = "locale") 115 public LocaleResolver localeResolver() { 116 if (this.mvcProperties 117 .getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) { 118 return new FixedLocaleResolver(this.mvcProperties.getLocale()); 119 } 120 AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver(); 121 localeResolver.setDefaultLocale(this.mvcProperties.getLocale()); 122 return localeResolver; 123 } 124 125 @Bean 126 @ConditionalOnProperty(prefix = "spring.mvc", name = "date-format") 127 public Formatter<Date> dateFormatter() { 128 return new DateFormatter(this.mvcProperties.getDateFormat()); 129 } 130 131 @Override 132 public MessageCodesResolver getMessageCodesResolver() { 133 if (this.mvcProperties.getMessageCodesResolverFormat() != null) { 134 DefaultMessageCodesResolver resolver = new DefaultMessageCodesResolver(); 135 resolver.setMessageCodeFormatter( 136 this.mvcProperties.getMessageCodesResolverFormat()); 137 return resolver; 138 } 139 return null; 140 } 141 142 @Override 143 public void addFormatters(FormatterRegistry registry) { 144 for (Converter<?, ?> converter : getBeansOfType(Converter.class)) { 145 registry.addConverter(converter); 146 } 147 for (GenericConverter converter : getBeansOfType(GenericConverter.class)) { 148 registry.addConverter(converter); 149 } 150 for (Formatter<?> formatter : getBeansOfType(Formatter.class)) { 151 registry.addFormatter(formatter); 152 } 153 } 154 155 private <T> Collection<T> getBeansOfType(Class<T> type) { 156 return this.beanFactory.getBeansOfType(type).values(); 157 } 158 159 @Override 160 public void addResourceHandlers(ResourceHandlerRegistry registry) { 161 if (!this.resourceProperties.isAddMappings()) { 162 logger.debug("Default resource handling disabled"); 163 return; 164 } 165 Integer cachePeriod = this.resourceProperties.getCachePeriod(); 166 if (!registry.hasMappingForPattern("/webjars/**")) { 167 customizeResourceHandlerRegistration( 168 registry.addResourceHandler("/webjars/**") 169 .addResourceLocations( 170 "classpath:/META-INF/resources/webjars/") 171 .setCachePeriod(cachePeriod)); 172 } 173 String staticPathPattern = this.mvcProperties.getStaticPathPattern(); 174 if (!registry.hasMappingForPattern(staticPathPattern)) { 175 customizeResourceHandlerRegistration( 176 registry.addResourceHandler(staticPathPattern) 177 .addResourceLocations( 178 this.resourceProperties.getStaticLocations()) 179 .setCachePeriod(cachePeriod)); 180 } 181 } 182 183 @Bean 184 public WelcomePageHandlerMapping welcomePageHandlerMapping( 185 ResourceProperties resourceProperties) { 186 return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage()); 187 } 188 189 private void customizeResourceHandlerRegistration( 190 ResourceHandlerRegistration registration) { 191 if (this.resourceHandlerRegistrationCustomizer != null) { 192 this.resourceHandlerRegistrationCustomizer.customize(registration); 193 } 194 195 } 196 197 @Bean 198 @ConditionalOnMissingBean({ RequestContextListener.class, 199 RequestContextFilter.class }) 200 public static RequestContextFilter requestContextFilter() { 201 return new OrderedRequestContextFilter(); 202 } 203 204 @Configuration 205 @ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true) 206 public static class FaviconConfiguration { 207 208 private final ResourceProperties resourceProperties; 209 210 public FaviconConfiguration(ResourceProperties resourceProperties) { 211 this.resourceProperties = resourceProperties; 212 } 213 214 @Bean 215 public SimpleUrlHandlerMapping faviconHandlerMapping() { 216 SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); 217 mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1); 218 mapping.setUrlMap(Collections.singletonMap("**/favicon.ico", 219 faviconRequestHandler())); 220 return mapping; 221 } 222 223 @Bean 224 public ResourceHttpRequestHandler faviconRequestHandler() { 225 ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler(); 226 requestHandler 227 .setLocations(this.resourceProperties.getFaviconLocations()); 228 return requestHandler; 229 } 230 231 } 232 233 } 234 235 /** 236 * Configuration equivalent to {@code @EnableWebMvc}. 237 */ 238 @Configuration 239 public static以上是关于初入spring boot(四 )web项目的主要内容,如果未能解决你的问题,请参考以下文章初入spring boot(五 )Spring Data JPA
初入spring boot(八 )Spring Data REST
Spring boot 默认首页配置 Spring boot web默认首页配置 Spring boot web项目默认首页配置