首页 > 代码库 > 初入spring boot(四 )web项目

初入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 = http://www.mamicode.com/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 = "http://www.mamicode.com/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 class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
240 
241         private final WebMvcProperties mvcProperties;
242 
243         private final ListableBeanFactory beanFactory;
244 
245         private final WebMvcRegistrations mvcRegistrations;
246 
247         public EnableWebMvcConfiguration(
248                 ObjectProvider<WebMvcProperties> mvcPropertiesProvider,
249                 ObjectProvider<WebMvcRegistrations> mvcRegistrationsProvider,
250                 ListableBeanFactory beanFactory) {
251             this.mvcProperties = mvcPropertiesProvider.getIfAvailable();
252             this.mvcRegistrations = mvcRegistrationsProvider.getIfUnique();
253             this.beanFactory = beanFactory;
254         }
255 
256         @Bean
257         @Override
258         public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
259             RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter();
260             adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null ? true
261                     : this.mvcProperties.isIgnoreDefaultModelOnRedirect());
262             return adapter;
263         }
264 
265         @Override
266         protected RequestMappingHandlerAdapter createRequestMappingHandlerAdapter() {
267             if (this.mvcRegistrations != null
268                     && this.mvcRegistrations.getRequestMappingHandlerAdapter() != null) {
269                 return this.mvcRegistrations.getRequestMappingHandlerAdapter();
270             }
271             return super.createRequestMappingHandlerAdapter();
272         }
273 
274         @Bean
275         @Primary
276         @Override
277         public RequestMappingHandlerMapping requestMappingHandlerMapping() {
278             // Must be @Primary for MvcUriComponentsBuilder to work
279             return super.requestMappingHandlerMapping();
280         }
281 
282         @Bean
283         @Override
284         public Validator mvcValidator() {
285             if (!ClassUtils.isPresent("javax.validation.Validator",
286                     getClass().getClassLoader())) {
287                 return super.mvcValidator();
288             }
289             return WebMvcValidator.get(getApplicationContext(),
290                     getValidator());
291         }
292 
293         @Override
294         protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
295             if (this.mvcRegistrations != null
296                     && this.mvcRegistrations.getRequestMappingHandlerMapping() != null) {
297                 return this.mvcRegistrations.getRequestMappingHandlerMapping();
298             }
299             return super.createRequestMappingHandlerMapping();
300         }
301 
302         @Override
303         protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
304             try {
305                 return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);
306             }
307             catch (NoSuchBeanDefinitionException ex) {
308                 return super.getConfigurableWebBindingInitializer();
309             }
310         }
311 
312         @Override
313         protected ExceptionHandlerExceptionResolver createExceptionHandlerExceptionResolver() {
314             if (this.mvcRegistrations != null && this.mvcRegistrations
315                     .getExceptionHandlerExceptionResolver() != null) {
316                 return this.mvcRegistrations.getExceptionHandlerExceptionResolver();
317             }
318             return super.createExceptionHandlerExceptionResolver();
319         }
320 
321         @Override
322         protected void configureHandlerExceptionResolvers(
323                 List<HandlerExceptionResolver> exceptionResolvers) {
324             super.configureHandlerExceptionResolvers(exceptionResolvers);
325             if (exceptionResolvers.isEmpty()) {
326                 addDefaultHandlerExceptionResolvers(exceptionResolvers);
327             }
328             if (this.mvcProperties.isLogResolvedException()) {
329                 for (HandlerExceptionResolver resolver : exceptionResolvers) {
330                     if (resolver instanceof AbstractHandlerExceptionResolver) {
331                         ((AbstractHandlerExceptionResolver) resolver)
332                                 .setWarnLogCategory(resolver.getClass().getName());
333                     }
334                 }
335             }
336         }
337 
338     }
339 
340     @Configuration
341     @ConditionalOnEnabledResourceChain
342     static class ResourceChainCustomizerConfiguration {
343 
344         @Bean
345         public ResourceChainResourceHandlerRegistrationCustomizer resourceHandlerRegistrationCustomizer() {
346             return new ResourceChainResourceHandlerRegistrationCustomizer();
347         }
348 
349     }
350 
351     interface ResourceHandlerRegistrationCustomizer {
352 
353         void customize(ResourceHandlerRegistration registration);
354 
355     }
356 
357     private static class ResourceChainResourceHandlerRegistrationCustomizer
358             implements ResourceHandlerRegistrationCustomizer {
359 
360         @Autowired
361         private ResourceProperties resourceProperties = new ResourceProperties();
362 
363         @Override
364         public void customize(ResourceHandlerRegistration registration) {
365             ResourceProperties.Chain properties = this.resourceProperties.getChain();
366             configureResourceChain(properties,
367                     registration.resourceChain(properties.isCache()));
368         }
369 
370         private void configureResourceChain(ResourceProperties.Chain properties,
371                 ResourceChainRegistration chain) {
372             Strategy strategy = properties.getStrategy();
373             if (strategy.getFixed().isEnabled() || strategy.getContent().isEnabled()) {
374                 chain.addResolver(getVersionResourceResolver(strategy));
375             }
376             if (properties.isGzipped()) {
377                 chain.addResolver(new GzipResourceResolver());
378             }
379             if (properties.isHtmlApplicationCache()) {
380                 chain.addTransformer(new AppCacheManifestTransformer());
381             }
382         }
383 
384         private ResourceResolver getVersionResourceResolver(
385                 ResourceProperties.Strategy properties) {
386             VersionResourceResolver resolver = new VersionResourceResolver();
387             if (properties.getFixed().isEnabled()) {
388                 String version = properties.getFixed().getVersion();
389                 String[] paths = properties.getFixed().getPaths();
390                 resolver.addFixedVersionStrategy(version, paths);
391             }
392             if (properties.getContent().isEnabled()) {
393                 String[] paths = properties.getContent().getPaths();
394                 resolver.addContentVersionStrategy(paths);
395             }
396             return resolver;
397         }
398 
399     }
400 
401     static final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {
402 
403         private static final Log logger = LogFactory
404                 .getLog(WelcomePageHandlerMapping.class);
405 
406         private WelcomePageHandlerMapping(Resource welcomePage) {
407             if (welcomePage != null) {
408                 logger.info("Adding welcome page: " + welcomePage);
409                 ParameterizableViewController controller = new ParameterizableViewController();
410                 controller.setViewName("forward:index.html");
411                 setRootHandler(controller);
412                 setOrder(0);
413             }
414         }
415 
416         @Override
417         public Object getHandlerInternal(HttpServletRequest request) throws Exception {
418             for (MediaType mediaType : getAcceptedMediaTypes(request)) {
419                 if (mediaType.includes(MediaType.TEXT_HTML)) {
420                     return super.getHandlerInternal(request);
421                 }
422             }
423             return null;
424         }
425 
426         private List<MediaType> getAcceptedMediaTypes(HttpServletRequest request) {
427             String acceptHeader = request.getHeader(HttpHeaders.ACCEPT);
428             return MediaType.parseMediaTypes(
429                     StringUtils.hasText(acceptHeader) ? acceptHeader : "*/*");
430         }
431 
432     }
433 
434 }

 

  1 @ConfigurationProperties(prefix = "spring.mvc")
  2 public class WebMvcProperties {
  3 
  4     /**
  5      * Formatting strategy for message codes (PREFIX_ERROR_CODE, POSTFIX_ERROR_CODE).
  6      */
  7     private DefaultMessageCodesResolver.Format messageCodesResolverFormat;
  8 
  9     /**
 10      * Locale to use. By default, this locale is overridden by the "Accept-Language"
 11      * header.
 12      */
 13     private Locale locale;
 14 
 15     /**
 16      * Define how the locale should be resolved.
 17      */
 18     private LocaleResolver localeResolver = LocaleResolver.ACCEPT_HEADER;
 19 
 20     /**
 21      * Date format to use (e.g. dd/MM/yyyy).
 22      */
 23     private String dateFormat;
 24 
 25     /**
 26      * Dispatch TRACE requests to the FrameworkServlet doService method.
 27      */
 28     private boolean dispatchTraceRequest = false;
 29 
 30     /**
 31      * Dispatch OPTIONS requests to the FrameworkServlet doService method.
 32      */
 33     private boolean dispatchOptionsRequest = true;
 34 
 35     /**
 36      * If the content of the "default" model should be ignored during redirect scenarios.
 37      */
 38     private boolean ignoreDefaultModelOnRedirect = true;
 39 
 40     /**
 41      * If a "NoHandlerFoundException" should be thrown if no Handler was found to process
 42      * a request.
 43      */
 44     private boolean throwExceptionIfNoHandlerFound = false;
 45 
 46     /**
 47      * Enable warn logging of exceptions resolved by a "HandlerExceptionResolver".
 48      */
 49     private boolean logResolvedException = false;
 50 
 51     /**
 52      * Maps file extensions to media types for content negotiation, e.g. yml->text/yaml.
 53      */
 54     private Map<String, MediaType> mediaTypes = new LinkedHashMap<String, MediaType>();
 55 
 56     /**
 57      * Path pattern used for static resources.
 58      */
 59     private String staticPathPattern = "/**";
 60 
 61     private final Async async = new Async();
 62 
 63     private final Servlet servlet = new Servlet();
 64 
 65     private final View view = new View();
 66 
 67     public DefaultMessageCodesResolver.Format getMessageCodesResolverFormat() {
 68         return this.messageCodesResolverFormat;
 69     }
 70 
 71     public void setMessageCodesResolverFormat(
 72             DefaultMessageCodesResolver.Format messageCodesResolverFormat) {
 73         this.messageCodesResolverFormat = messageCodesResolverFormat;
 74     }
 75 
 76     public Locale getLocale() {
 77         return this.locale;
 78     }
 79 
 80     public void setLocale(Locale locale) {
 81         this.locale = locale;
 82     }
 83 
 84     public LocaleResolver getLocaleResolver() {
 85         return this.localeResolver;
 86     }
 87 
 88     public void setLocaleResolver(LocaleResolver localeResolver) {
 89         this.localeResolver = localeResolver;
 90     }
 91 
 92     public String getDateFormat() {
 93         return this.dateFormat;
 94     }
 95 
 96     public void setDateFormat(String dateFormat) {
 97         this.dateFormat = dateFormat;
 98     }
 99 
100     public boolean isIgnoreDefaultModelOnRedirect() {
101         return this.ignoreDefaultModelOnRedirect;
102     }
103 
104     public void setIgnoreDefaultModelOnRedirect(boolean ignoreDefaultModelOnRedirect) {
105         this.ignoreDefaultModelOnRedirect = ignoreDefaultModelOnRedirect;
106     }
107 
108     public boolean isThrowExceptionIfNoHandlerFound() {
109         return this.throwExceptionIfNoHandlerFound;
110     }
111 
112     public void setThrowExceptionIfNoHandlerFound(
113             boolean throwExceptionIfNoHandlerFound) {
114         this.throwExceptionIfNoHandlerFound = throwExceptionIfNoHandlerFound;
115     }
116 
117     public boolean isLogResolvedException() {
118         return this.logResolvedException;
119     }
120 
121     public void setLogResolvedException(boolean logResolvedException) {
122         this.logResolvedException = logResolvedException;
123     }
124 
125     public Map<String, MediaType> getMediaTypes() {
126         return this.mediaTypes;
127     }
128 
129     public void setMediaTypes(Map<String, MediaType> mediaTypes) {
130         this.mediaTypes = mediaTypes;
131     }
132 
133     public boolean isDispatchOptionsRequest() {
134         return this.dispatchOptionsRequest;
135     }
136 
137     public void setDispatchOptionsRequest(boolean dispatchOptionsRequest) {
138         this.dispatchOptionsRequest = dispatchOptionsRequest;
139     }
140 
141     public boolean isDispatchTraceRequest() {
142         return this.dispatchTraceRequest;
143     }
144 
145     public void setDispatchTraceRequest(boolean dispatchTraceRequest) {
146         this.dispatchTraceRequest = dispatchTraceRequest;
147     }
148 
149     public String getStaticPathPattern() {
150         return this.staticPathPattern;
151     }
152 
153     public void setStaticPathPattern(String staticPathPattern) {
154         this.staticPathPattern = staticPathPattern;
155     }
156 
157     public Async getAsync() {
158         return this.async;
159     }
160 
161     public Servlet getServlet() {
162         return this.servlet;
163     }
164 
165     public View getView() {
166         return this.view;
167     }
168 
169     public static class Async {
170 
171         /**
172          * Amount of time (in milliseconds) before asynchronous request handling times
173          * out. If this value is not set, the default timeout of the underlying
174          * implementation is used, e.g. 10 seconds on Tomcat with Servlet 3.
175          */
176         private Long requestTimeout;
177 
178         public Long getRequestTimeout() {
179             return this.requestTimeout;
180         }
181 
182         public void setRequestTimeout(Long requestTimeout) {
183             this.requestTimeout = requestTimeout;
184         }
185 
186     }
187 
188     public static class Servlet {
189 
190         /**
191          * Load on startup priority of the dispatcher servlet.
192          */
193         private int loadOnStartup = -1;
194 
195         public int getLoadOnStartup() {
196             return this.loadOnStartup;
197         }
198 
199         public void setLoadOnStartup(int loadOnStartup) {
200             this.loadOnStartup = loadOnStartup;
201         }
202 
203     }
204 
205     public static class View {
206 
207         /**
208          * Spring MVC view prefix.
209          */
210         private String prefix;
211 
212         /**
213          * Spring MVC view suffix.
214          */
215         private String suffix;
216 
217         public String getPrefix() {
218             return this.prefix;
219         }
220 
221         public void setPrefix(String prefix) {
222             this.prefix = prefix;
223         }
224 
225         public String getSuffix() {
226             return this.suffix;
227         }
228 
229         public void setSuffix(String suffix) {
230             this.suffix = suffix;
231         }
232 
233     }
234 
235     public enum LocaleResolver {
236 
237         /**
238          * Always use the configured locale.
239          */
240         FIXED,
241 
242         /**
243          * Use the "Accept-Language" header or the configured locale if the header is not
244          * set.
245          */
246         ACCEPT_HEADER
247 
248     }
249 
250 }

 3.2 接管spring boot的web配置

  在既需要保留spring boot提供的便利,又需要增加自己的额外的配置的时候,可以定义一个配置类并继承WebMvcConfigurerAdapter,无须使用@EnableWebMvc注解,然后按照spring mvc的配置方法来添加spring boot其他配置。值得指出的是重写addViewControllers方法,并不会覆盖WebMvcConfigurerAdapter中的addViewControllers(在此方法中,spring boot 将“/”映射至index.html),这也就意味着我们自己的配置和spring boot的自动配置同时有效,这也是推荐添加自己的mvc配置的方式。

 

 3.3 注册servlet、filter、Listener

  当使用嵌入式的servlet容器(tomcat、jetty等)时,通过将servlet、filter和listener声明为spring bean而达到注册的效果;或者注册ServletRegistrationBean、FilterRegistrationBean、ServletListenerRegistrationBean的bean。

 

3.4 Tomcat配置

  关于tomcat的所有属性都在org.springframework.boot.autoconfigure.web.ServerProperties配置类中做了定义,我们只需要在application.Properties配置属性做配置即可。通用的Servlet容器配置都以“server”作为前缀,而tomcat特有的配置都以“server.tomcat”作为前缀。配置tomcat还可以用代码的方式配置,以后再说。

初入spring boot(四 )web项目