starter的定义:为了把第三方集成到springboot中,并且把第三方工具的实例融入到ioc中,并且可以去支持外部自定义的配置(一般在application.properties中配置)。
新建一个maven项目:
一般官方的starter是spring-boot-starter-{name} 这种命名,而第三方建议是{name}-spring-boot-starter。这个starter主要是用了来对对象转为字符串与json串的。
写好基本的代码:
package com.llicat.processor; /** * Copyright: Copyright (c) 2020 * * @ClassName: com.llicat.processor.formatProcessor * @Description: 标准转换接口 * @version: v1.0.0 * @author: lipan * @date: 2020/11/29 20:44 * <p> * Modification History: * Date Author Version Description * ------------------------------------------------------------ * 2020/11/29 lipan v1.0.0 修改原因 */ public interface FormatProcessor { /** * 对象转为代码 * @param obj * @param <T> * @return */ <T> String format(T obj); } package com.llicat.processor; import com.alibaba.fastjson.JSON; /** * Copyright: Copyright (c) 2020 * * @ClassName: com.llicat.processor.JsonFormatProcessor * @Description: 该类的功能描述 * @version: v1.0.0 * @author: lipan * @date: 2020/11/29 20:47 * <p> * Modification History: * Date Author Version Description * ------------------------------------------------------------ * 2020/11/29 lipan v1.0.0 修改原因 */ public class JsonFormatProcessor implements FormatProcessor { @Override public <T> String format(T obj) { return JSON.toJSONString(obj); } } package com.llicat.processor; import java.util.Objects; /** * Copyright: Copyright (c) 2020 * * @ClassName: com.llicat.processor.StringFormatProcessor * @Description: 该类的功能描述 * @version: v1.0.0 * @author: lipan * @date: 2020/11/29 20:46 * <p> * Modification History: * Date Author Version Description * ------------------------------------------------------------ * 2020/11/29 lipan v1.0.0 修改原因 */ public class StringFormatProcessor implements FormatProcessor { @Override public <T> String format(T obj) { return Objects.toString(obj); } } package com.llicat.template; import com.llicat.processor.FormatProcessor; /** * Copyright: Copyright (c) 2020 * * @ClassName: com.llicat.template.FormatTemplate * @Description: 通用模板 * @version: v1.0.0 * @author: lipan * @date: 2020/11/29 20:49 * <p> * Modification History: * Date Author Version Description * ------------------------------------------------------------ * 2020/11/29 lipan v1.0.0 修改原因 */ public class FormatTemplate { protected FormatProcessor processor; public <T> String formatToString(T obj){ return processor.format(obj); } }
然后可以测试一下,install之后测试一下基本功能:
@SpringBootTest(classes=Application.class) @RunWith(SpringRunner.class) public class FormatStarterTest { @Test public void test() throws Exception{ FormatProcessor processor=new JsonFormatProcessor(); FormatTemplate template=new FormatTemplate(processor); Person person = new Person(); person.setId(10); person.setName("小明"); System.out.println(template.formatToString(person)); } }
输出结果:
但是这样会有一个问题:对象FormatProcessor 与FormatTemplate都是自己new出来的,这样就违背了spring自动装配的约定。所以需要定义配置类将这些东西装载到ioc中。
定义一个类将processor加载到ioc中:
@Configuration public class ProcessorAutoConfig { //用来装配StringFormatProcessor到容器中 @Bean public FormatProcessor stringFormatProcessor(){ return new StringFormatProcessor(); } @Bean public JsonFormatProcessor jsonFormatProcessor(){ return new JsonFormatProcessor(); } }
将format加载到ioc中:
@Configuration @SuppressWarnings("all") @Import(ProcessorAutoConfig.class) public class TemplateAutoConfig { @Bean public FormatTemplate formatTemplate(FormatProcessor formatProcessor){ return new FormatTemplate(formatProcessor); } }
需要提一点的是通过@import将ProcessorAutoCofig中的也加载到了。修改一下测试代码:
@SpringBootTest(classes=Application.class) @RunWith(SpringRunner.class) public class FormatStarterTest { @Autowired FormatTemplate template; @Test public void test() throws Exception{ Person person = new Person(); person.setId(10); person.setName("小明"); System.out.println(template.formatToString(person)); } }
运行后:
因为找不到唯一匹配的实例。所以需要修改一下processor的加载代码:
@Configuration public class ProcessorAutoConfig { //用来装配StringFormatProcessor到容器中 @Bean @Primary public FormatProcessor stringFormatProcessor(){ return new StringFormatProcessor(); } @Bean public JsonFormatProcessor jsonFormatProcessor(){ return new JsonFormatProcessor(); } }
指定默认的就会返回stringFormatProcessor作为实例:
我们也可以使用条件注解来指定就是是哪一个processor会被加载:
@Configuration public class ProcessorAutoConfig { //用来装配StringFormatProcessor到容器中 @Bean @Primary @ConditionalOnMissingClass("com.alibaba.fastjson.JSON") public FormatProcessor stringFormatProcessor(){ return new StringFormatProcessor(); } @Bean @ConditionalOnClass(name = "com.alibaba.fastjson.JSON") public JsonFormatProcessor jsonFormatProcessor(){ return new JsonFormatProcessor(); } }
这段代码指明了,当前环境如果加载了com.alibaba.fastjson.JSON ,那么就会在加载jsonFormatProcessor,否则加载默认的processor。我们在pom.xml中引入jack的依赖:
此时是就是json对象的format在对对象进行解析了。
实际上在使用各种starter的时候我们还会自定义一些属性在application.properties如下:
,这些是由starter提供的,实际上也是可以自定义的:
@ConfigurationProperties(prefix = "com.llicat.format") @SuppressWarnings("all") public class FormatProperties { private String language; public String getLanguage() { return language; } public void setLanguage(String language) { this.language = language; } }
使用定义的属性:
public class FormatTemplate { protected FormatProperties properties; protected FormatProcessor processor; public FormatTemplate(FormatProperties properties,FormatProcessor processor) { this.properties=properties; this.processor = processor; } public <T> String formatToString(T obj){ if( "CN".equals(properties.getLanguage())){ return "format result:"+processor.format(obj); }else{ return "转换失败,请提供多语言资源包"; } } }
需要增加配置文件:
spring 使用spi来加载第三方,所以这个必须要。
使用自定义属性 :
运行结果:
tips:
resource下文件无法编译到target:
把这个干掉。
maven打包resource打不进去增加这个配置:
<resources> <!--用来解决install打包的时候resource下的配置文件打不进去--> <resource> <directory>src/main/java</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.properties</include> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> </resources>