Spring Boot 实践折腾记:自定义配置,扩展Spring MVC配置并使用fastjson

Posted mickjoust

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot 实践折腾记:自定义配置,扩展Spring MVC配置并使用fastjson相关的知识,希望对你有一定的参考价值。

专注和简单一直是我的秘诀之一。
简单可能比复杂更难做到:你必须努力理清思路,从而使其变得简单。
但最终这是值得的,因为一旦你做到了,便可以创造奇迹。
——乔布斯

题记

前两天有点忙,没有连续更新,今天接着聊。金句里老乔的话说得多好,但能真正做到的人又有多少?至少就我个人而言,我还远远没有做到这样,只是一个在朝着这个方向努力的人,力求简明易懂,用大白话让人快速的明白理解,简单的例子上手,让使用的人更多的去实战使用扩展,折腾记即是对自己学习使用很好的一次总结,对看的人也是一个参考的方法,希望大家能够找到对自己有用的思路或方法。今天主要说的是,继续上一章的配置,我们自己如何自定义类型安全的配置,并使用一个常用的工具fastjson集成来切入,虽然有自定义的jackson和gson,折腾记就是要折腾一下嘛,不然怎么能打开新思路。

类型安全的配置

在上一篇文章中,我们有使用过直接在application.properties中设置变量,这种方式是Spring中常用的方式,但对Spring Boot来说,既不是安全的,也会因为频繁使用@Value来注入配置而过于繁琐,项目中使用起来尤其麻烦,真实项目中的变量就不像我演示的Demo里的只有一两行了,很多时候都会是几十行上百行,所以,Spring Boot中提供了基于类型安全的配置方式,通过@ConfigurationProperties将properties属性和一个Bean及其属性关联,从而实现类型安全的配置。

实战1:自定义的配置通过类似Service的方式注入是使用

项目使用:boot_properties

1、创建Bean。

// TestInfoSettings.class

@Component
@ConfigurationProperties( //1
        prefix = "usetest",
        locations = "classpath:config/app.properties"
)
public class TestInfoSettings {
    private String name;
    private String age;
	//省略get、set
}

说明:
1:@ConfigurationProperties加载properties文件内的配置,prefix属性指定配置的前缀,例如:usetest.*=string 。locations可以指定自定义的文件位置,不指定默认使用application.properties。

2、在src/main/resources下新增config/app.properties。

usetest.name=mickjoust
usetest.age=18

3、在Controller里添加一个接口调用.

//TestController.class

...原有省略

@RequestMapping("/showSetting")
    public Object showSetting(){
        StringBuffer sb = new StringBuffer();
        sb.append("setting name is : ").append(testInfoSettings.getName());
        sb.append("setting age is : ").append(testInfoSettings.getAge());
        sb.append("all is : ").append(testInfoSettings);
        return JsonResp.success(sb);
    }

4、启动,设置的数据注入进去了。
这里写图片描述

Spring Boot里的Spring MVC配置

用惯了Spring MVC,突然用Spring Boot反而会觉得很不习惯,因为很多配置消失了。简单不是说配置都没有了,而是Spring Boot通过某种方式帮助你快速的完成了一些前期的工作,上一章里说过,Spring Boot的一大特性就是自动配置并采用了条件注解@Conditional的方式自动扫描并开启你配置的功能,二是对于MVC里的viewResolver、interceptors、静态资源、formatter和converter、HttpMessageConverts、Servlet、Filter、Listener等,Spring Boot使用了一个叫WebMvcAutoConfigurationWebMvcProperties的文件来进行自动配置,如图路径下:
这里写图片描述

接下来我们看看一般都有哪些自动配置

自动配置的静态资源

在原有的Spring MVC的配置,静态资源通常是这样配置的。

<mvc:default-servlet-handler />
	
<mvc:resources location="/static/" mapping="/static/**" cache-period="864000" />

在Spring Boot里是在方法addResourceHandlers中来定义静态资源的配置的。其实,就是一个if-else(有兴趣的同学自行看看源码),概括起来包含两类:

1、类路径文件
把类路径下的/static、/public、/resources和/META-INF/resources文件夹下的静态文件直接映射为/**来提供访问。

2、webjar
把webjar的/META-INF/resources/webjars下的静态文件映射为/webjar/**。
什么是webjar?就是有人帮我们将常用的前端脚本框架之类封装在jar包里,然后通过jar包的方式来调用脚本,详细的可以看网站:http://www.webjar.org

最后,如果我们要修改静态路径的映射并增加缓存时间,只需要在配置文件修改static-path-pattern和cache-period:

spring.mvc.static-path-pattern=/static/**
spring.resources.cache-period=864000

至于静态文件的存放路径,因为一般常用的静态文件都是放在这几个目录下的,基本上可以满足要求了,如果要自定义,修改spring.resources.static-locations=即可。

自动配置Formatter和Converter

搜索Formatter,就能够找到addFormatters这个方法里的定义,我们只需要定义Converter、GenericConverter和Formatter接口实现的实现类Bean,就会注册Bean到Spring MVC中了。比较简单,不再举例子了。

自动配置HttpMessageConverters

同理,搜索MessageConverters,会找到configureMessageConverters,这个方法就是直接添加HttpMessageConverters的Bean,而这个Bean是在HttpMessageConvertAutoConfiguration类中定义的,源码如下:
这里写图片描述

比较简单,就是加入定义好的converter,其中,默认加载的有以下八类:
这里写图片描述

有同学要问StringHttpMessageConverter为什么有两个,其实只是字符集使用了一个UTF-8和一个ISO-8859-1。还有默认goson的convert为啥没有看到呢,本章后面会说到原因。
##自动配置的ViewResolver
同样道理,搜索ViewResolver,会搜索到三个: InternalResourceViewResolver、BeanNameViewResolver、ContentNegotiatingViewResolver。

【1】ContentNegotiatingViewResolver
Spring MVC里提供的特殊的ViewResolver,它自己是不处理View的,它的作用是代理给不同的ViewResolver来处理不同的View。源码如下:
这里写图片描述

【2】InternalResourceViewResolver
这个是内置最常用的解析器,通过设置前缀,后缀和controller中方法来返回视图名的字符串,以此来得到实际页面。源码如下:
这里写图片描述

它是通过配置文件获取前后缀的,设置参数如下:

spring.mvc.view.prefix=
spring.mvc.view.suffix=

【3】BeanNameViewResolver
定义很简单,作用就是它会去查找Controller方法返回值的字符串中是否有定义过的Bean名称,如果有,则用定义的View来渲染。

例如:我们定义一个Bean叫testView,返回类型是MappingJackson2JsonView,只要在@Controller返回的方法中返回,就可以获得指定的视图渲染。

return "testView";

对于视图,这里多说一句,不同的人有不同的喜好和习惯,有的项目喜欢直接前后分离,有的项目需要返回一些视图模板渲染基本的框架,怎么用顺手怎么用,没有好坏优劣之分,只有使用的场景不同,用得好,视图一样能发挥作用。


上面只是简单说明了一些常用的自动配置,至于更多更详细的配置,大家抽空可以看看自动配置的相关源码,对思路扩展也是有好处的。因为如果只想快速应用,通常的常用配置已经够用了,对于需要自定义的应用场景里,可自行参看配置修改。

扩展Spring MVC配置

上面大概介绍了Spring Boot里对MVC的自动配置,其实,大家可以对照着原有MVC的配置查看Spring Boot都有哪些配置项,你会发现其实都是原来已经有的,现在只是换了一种方式:通过配置或重写方法来达到修改或增加Spring MVC的配置。下面用一个例子来说明接管Spring Boot的Spring MVC的配置的方式并通过修改的方式来配置一个fastjson的converter。

如何定制Boot里的MVC配置?

在又需要默认的配置,又需要自己定制的配置的时候,我们需要自定义配置,Spring Boot官方提供了一个适配器类WebMvcConfigurerAdapter来扩展功能。可以通过重写接口来支持MVC配置。

@Configuration
public class CustomMVCConfiguration extends WebMvcConfigurerAdapter{//1

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.clear(); //实验发现,不起作用,可能是boot的bug,或者官方不让修改?
    }

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> messageConverter : converters) {
            System.out.println(messageConverter); //2
        }
    }
}

说明:
1:继承父类,是一个适配器模式类,可以重新定义MVC的功能和配置,但不会影响已有配置,属于增加功能扩展,不知道这是好还是不好。
2:找到扩展方法,可以添加自定义方法。

实战2:在已有的自动功能中增加新的功能fastjson

fastjson,国产,有很多人喜欢用,因为速度快,操作简单。以前老版本时其实也是坑很多啦,不过还是挺好用的,支持起,现在官方版本1.2.12,并没有支持Spring Boot的starter,但是它有HttpMessageConvert的支持,其实要支持也很方便。下面演示一下如何集成。

方法1:直接注册HttpMessageConverts的Bean

1、首先新建一个配置文件。

//FastJsonHttpMessageConvertersConfiguration .class

@Configuration
@ConditionalOnClass({JSON.class}) //1
public class FastJsonHttpMessageConvertersConfiguration {

    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters(){
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();//2

        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.PrettyFormat,
                SerializerFeature.WriteClassName
        );
        fastConverter.setFastJsonConfig(fastJsonConfig);

        HttpMessageConverter<?> converter = fastConverter;

        return new HttpMessageConverters(converter);
    }

说明:
1、判断JSON这个类文件是否存在,存在才会创建配置。
2、我看官方文档说的1.2.10以后,会有两个方法支持HttpMessageconvert,一个是FastJsonHttpMessageConverter,支持4.2以下的版本,一个是FastJsonHttpMessageConverter4支持4.2以上的版本,具体有什么区别暂时没有深入研究。

2、查看是否注册成功。

这里写图片描述
成功了。

3、启动。 执行http://locahost:8080/showSetting

这里写图片描述

这个方法其实只是注册了Bean,由于没有指定执行的配置,使用了新方法,这种方式其实并不好,没办法灵活控制。所以我们看能不能像gson那样指定使用,看图:

这里写图片描述

如图,httpmessageconvert在自动配置时就会自动初始化gson和jackson,默认使用用jackson,找到了配置名为:spring.http.converters.preferred-json-mapper。于是有了方法2.

方法2:自动配置Bean并指定配置项

1、创建新配置

// FastJsonHttpMessageConvertersConfiguration.class
//...注释方法1的代码

	@Configuration
    @ConditionalOnClass({FastJsonHttpMessageConverter.class}) //1
    @ConditionalOnProperty(//2
            name = {"spring.http.converters.preferred-json-mapper"},
            havingValue = "fastjson", 
            matchIfMissing = true
    )
    protected static class FastJson2HttpMessageConverterConfiguration{
        protected FastJson2HttpMessageConverterConfiguration() {
        }

        @Bean
        @ConditionalOnMissingBean({FastJsonHttpMessageConverter.class})//3
        public FastJsonHttpMessageConverter fastJsonHttpMessageConverter() {
            FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();

            FastJsonConfig fastJsonConfig = new FastJsonConfig();//4
            fastJsonConfig.setSerializerFeatures(
                    SerializerFeature.PrettyFormat,
                    SerializerFeature.WriteClassName,
                    SerializerFeature.WriteMapNullValue
            );
            ValueFilter valueFilter = new ValueFilter() {//5
                //o 是class
                //s 是key值
                //o1 是value值
                public Object process(Object o, String s, Object o1) {
                    if (null == o1){
                        o1 = "";
                    }
                    return o1;
                }
            };
            fastJsonConfig.setSerializeFilters(valueFilter);

            converter.setFastJsonConfig(fastJsonConfig);

            return converter;
        }
    }

说明:
1:判断是否存在类。
2:使用spring.http.converters.preferred-json-mapper属性来启动功能。
3:当没有注册这个类时,自动注册Bean。
4:使用最新的官方推荐配置对象的方式来注入fastjson的序列化特征。
5:添加对json值的过滤,因为像移动APP,服务端在传json值时最好不要传null,而是使用“”,这是一个演示。

2、指定使用fastjson。

spring.http.converters.preferred-json-mapper=fastjson

3、启动运行,成功。现在就能很方便的切换fastjson或gson了。

这里写图片描述

小结

本章主要是说明了如何在自定义配置的基础上定制MVC和集成新的自动配置功能,很多同学觉得配置很简单基本已经够用了,自定义配置干啥?默认配置也许刚开始能满足一些需求,但更多的时候还需要针对特定的场景来自定义配置,比如拦截器和过滤器,虽然这一节没有讲,实际中用得是很多的,但通常基本原理是想通的,多实战实战,有写的不对的地方,大家多讨论交流。


本章示例地址:boot-properties


page 168 of 366 in chapter 2016

以上是关于Spring Boot 实践折腾记:自定义配置,扩展Spring MVC配置并使用fastjson的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 实践折腾记:Spring Boot中的容器配置和SSL支持

Spring Boot 实践折腾记:配置即使用,常用配置

(汇总)Spring Boot 实践折腾记 & Spring Boot 2.x 实践记

Spring Boot 实践折腾记:三板斧,Spring Boot下使用Mybatis

Spring Boot 实践折腾记(20):Thymleaf + webjar + ECharts 构建本地图表

Spring Boot 自定义kafka 消费者配置 ContainerFactory最佳实践