Spring Boot 学习笔记(二)—— WEB相关配置

一、前言

上次我们快速搭建了一个Spring Boot项目,我们只需添加业务逻辑就能直接运行访问了,说明Spring Boot已经自动为我们做完了配置工作,这次我们就来看看具体是哪些工作,如果我们想接管配置又该怎么做。

二、WEB相关配置

查看WebMvcAutoConfigurationWebMvcProperties的源码,可以发现Spring MVC全局配置以spring.mvc开头,而Spring Boot提供了如下配置

1.自动配置的ViewResolver

1)ContentNegotiatingViewResolver

优先级最高,自己不处理View,而是将View代理给其他ViewResolver处理

        @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;
        }

2)BeanNameViewResolver

根据Controller中方法的返回值来查找ViewResolver处理View

        @Bean
        @ConditionalOnBean(View.class)
        @ConditionalOnMissingBean
        public BeanNameViewResolver beanNameViewResolver() {
            BeanNameViewResolver resolver = new BeanNameViewResolver();
            resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
            return resolver;
        }

3)InternalResourceViewResolver

这个很常见了,设置视图路径前后缀

        @Bean
        @ConditionalOnMissingBean
        public InternalResourceViewResolver defaultViewResolver() {
            InternalResourceViewResolver resolver = new InternalResourceViewResolver();
            resolver.setPrefix(this.mvcProperties.getView().getPrefix());
            resolver.setSuffix(this.mvcProperties.getView().getSuffix());
            return resolver;
        }

上篇文章我们添加了Thymeleaf,就自动为我们配置了前后缀。

2.自动配置的静态资源

addResourceHandlers方法中可以看到有以下静态资源的配置

@Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
                return;
            }
            Integer cachePeriod = this.resourceProperties.getCachePeriod();
            if (!registry.hasMappingForPattern("/webjars/**")) {
            //映射webjar路径为 /webjars/**,可直接访问,有关webjar的内容可访问 www.webjars.org
                customizeResourceHandlerRegistration(
                        registry.addResourceHandler("/webjars/**")
                                .addResourceLocations(
                                        "classpath:/META-INF/resources/webjars/")
                        .setCachePeriod(cachePeriod));
            }
            String staticPathPattern = this.mvcProperties.getStaticPathPattern();
            if (!registry.hasMappingForPattern(staticPathPattern)) {
            //"classpath:/META-INF/resources/", "classpath:/resources/","classpath:/static/", "classpath:/public/",统统映射为 "/**",可以直接访问
                customizeResourceHandlerRegistration(
                        registry.addResourceHandler(staticPathPattern)
                                .addResourceLocations(
                                        this.resourceProperties.getStaticLocations())
                        .setCachePeriod(cachePeriod));
            }
        }

3.自动配置Formatter和Converter

查看Formatter配置源码

@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);
            }
        }

可以看到只要我们定义了ConverterGenericConverterFormatter实现类的Bean,就会自动注册到Spring MVC中。

4.自动配置的HttpMessageConverter

        @Override
        public void configureMessageConverters(List> converters) {
            converters.addAll(this.messageConverters.getConverters());
        }

除了默认的StringHttpMessageConverterByteArrayHttpMessageConverter等,Spring MVC默认使用MappingJackson2HttpMessageConverterMappingJackson2XmlHttpMessageConverter,如果要新增自定义的HttpMessageConverter,只需定义一个HttpMessageConverters的bean即可

5.静态首页支持

private WelcomePageHandlerMapping(Resource welcomePage,
                String staticPathPattern) {
            if (welcomePage != null && "/**".equals(staticPathPattern)) {
                logger.info("Adding welcome page: " + welcomePage);
                ParameterizableViewController controller = new ParameterizableViewController();
                controller.setViewName("forward:index.html");
                setRootHandler(controller);
                setOrder(0);
            }
        }

在以下目录放置index.html会自动设为首页

  • classpath:/META-INF/resources/
  • classpath:/resources/
  • classpath:/static/
  • classpath:/public/

三、接管Spring Boot的WEB配置

如果要完全接管Web配置,只需新建一个配置类(注解@Configuration @EnableWebMvc),然后就能实现自己完全控制的Spring MVC。如果要保留自动配置并新增额外配置的话也很简单,定义一个配置类(注解@Configuration不需要 @EnableWebMvc)继承WebMvcConfigurerAdapter,就能在保留自动配置的基础上添加自己想要的配置了,以下是个小例子

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //此方法不会覆盖自动配置,而是额外添加
        registry.addViewController("/login").setViewName("/login");
    }

    @Override
    public void configureMessageConverters(List> converters) {
        //配置fastjson替换jackson
        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter ();
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
        stringConverter.setDefaultCharset(Charset.forName("UTF-8"));
        FastJsonConfig config = new FastJsonConfig();
        config.setSerializerFeatures(SerializerFeature.PrettyFormat,
                                    SerializerFeature.DisableCircularReferenceDetect);
        converter.setFastJsonConfig(config);
        //添加字符串解析器,防止返回字符串时多出双引号
        converters.add(stringConverter);
        converters.add(converter);
    }

}

四、注册Servlet、Filter、Listener

ServletFilterListener声明为Bean,或者注册ServletRegistrationBeanFilterRegistrationBeanServletListenerRegistrationBean 的Bean

    //直接注册Bean
    @Bean
    public XxServlet xxServlet(){
        return new XxServlet();
    }
    @Bean
    public XxServlet xxServlet(){
        return new XxServlet();
    }
    @Bean
    public XxFilter xxFilter(){
        return new XxFilter();
    }
    //通过RegistrationBean注册
    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        return new ServletRegistrationBean(new XxServlet(),"/xx/*");    
    }
    @Bean
    public FilterRegistrationBean filterRegistrationBean(){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(new YyFilter()); 
        registrationBean.setOrder(2);
        return registrationBean;
    }
    @Bean
    public ServletListenerRegistrationBean zzListenerServletRegistrationBean(){
        return new ServletListenerRegistrationBean(new ZzListener());   
    }   

五、总结

本文介绍了Spring Boot关于Spring MVC的自动配置项,这样我们在开发时也能根据业务需要手动修改配置,以实现我们想要的功能。
参考文献:
《javaee开发的颠覆者 Spring Boot实战》

你可能感兴趣的:(Spring,Boot)