一、start是什么
在springboot出现之前,我们的微博项目大多是ssm框架,即spring+springMVC+mybatis。这就会有一个巨大的问题,每一次新建项目我们都需要对其进行繁琐的环境配置,例如,我们新建一个spring项目,我们需要做到这些;
1.加载相关jar包
2.配置 web.xml,加载 Spring,SpringMVC
3.配置数据库连接,spring 事务
4.配置加载配置文件的读取,开启注解
5.配置日志文件
6.部署 tomcat 调试
每次我们似乎都做着类似或者相同的事,但是还是常常会出错,直到springboot出现之后,我们彻底摆脱了配置的束缚。springboot的官方解释文档是这样的:
1.内置Tomcat服务等服务器,不需要依赖其他war文件
2.Starter依赖简化了各种构建配置
3.尽可能自动配置Spring和第三方库
4.绝对没有代码生成,不需要XML配置
这里面它帮我们实现了底层配置,那么springboot是如何实现底层配置的呢,这就是start的强大之处。start在我们引入一个主要的jar包时就自动对它所依赖的其他文件做了配置,这些配置在我们使用时是默认的,也就是可以直接使用,当我们在配置文件中设置了部分配置后,我们手动设置的配置就会覆盖原有配置。
二、start依赖自动配置用到的spring注解
stater的自动配置基于spring,也就是说它的底层还是基于spring注解实现的,那么这里我贴出他的几个常用的注解:
@EnableConfigurationProperties(BpNetProperties.class) //使使用 @ConfigurationProperties 注解的类生效。
@Configuration //注解的类可以看作是能生产让Spring IoC容器管理的Bean实例的工厂。
@Bean //该注解告诉Spring,一个带有@Bean的注解方法将返回一个对象,该对象应该被注册到spring容器中。
@ConfigurationProperties(prefix=“net”) //Application.properties下的net参数会覆盖原有配置
有关于实例化bean的注解:
@ConditionalOnBean //仅在当前上下文中存在某个bean时,才会实例化这个Bean。
@ConditionalOnClass //某个class位于类路径上,才会实例化这个Bean。
@ConditionalOnExpression //当表达式为true的时候,才会实例化这个Bean。
@ConditionalOnMissingBean //仅在当前上下文中不存在某个bean时,才会实例化这个Bean。
@ConditionalOnMissingClass //某个class在类路径上不存在的时候,才会实例化这个Bean。
@ConditionalOnNotWebApplication //不是web应用时才会实例化这个Bean。
@AutoConfigureAfter //在某个bean完成自动配置后实例化这个bean。
@AutoConfigureBefore //在某个bean完成自动配置前实例化这个bean。
现在,我们写一个从网上爬取图片的小demo,没有别的,就是为了用一下注解实现一下stater的原理:
三、stater实现网络图片爬取工具包
1.目的:一个网络图片爬取工具;
2.功能:引入后使用AutoWrite或Resource注解调用其装配类,使用其爬取方法;
3.参数:三个参数,img.url(爬取目标网址) img.num(图片数量) img.downPath(本地保存地址)
4.参数配置:当我们直接调用方法时,使用stater的默认配置参数,分别为百度官网,10,E:// ;当我们在application.properties文件配置后,新参数会覆盖默认配置;
废话不多说,我们开始吧:
1.新建一个项目(maven)
引进一下maven依赖
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>${jsoup.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<!-- 自定义starter依赖此jar包 没有这个,你将无法使用stater相关依赖,因为这是基于springboot的-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
2.项目中新建一个实体类,用来存放我们的参数字段
/**
* 参数存储实体
* @author mansuosuo
*/
public class GetImgPO {
/**
* 访问的网址
*/
private String url;
/**
* 获取的图片数量
*/
private Integer num;
/**
* 下载到本地的路径
*/
private String downPath;
public GetImgPO(String u, Integer n, String d) {
this.num = n;
this.url = u;
this.downPath = d;
}
}
//get set方法需补全
3.新建配置类,这里面存放的是我们默认装配的参数
//如果配置文件配置了以下某属性,则默认属性值会被覆盖
@ConfigurationProperties(prefix = "img")
public class ImgProperties {
/**
* 访问的网址
*/
private String url="https://www.baidu.com/";
/**
* 获取的图片数量
*/
private Integer num = 10;
/**
* 下载到本地的路径
*/
private String downPath = "E://";
}
//get set方法需补全
4.新建一个类,装配类
@Configuration
@EnableConfigurationProperties(ImgProperties.class)
public class GetImgAutoConfiguration {
@Resource
private ImgProperties imgProperties;
@Bean
//在该bean不存在的情况下执行此方法
@ConditionalOnMissingBean
public GetImgPO initGetImgPO(){
GetImgPO getImgPO = new GetImgPO(imgProperties.getUrl(),imgProperties.getNum(),imgProperties.getDownPath());
return getImgPO;
}
public void getImg(GetImgPO getImgPO) throws IOException{
// 创建httpclient实例
CloseableHttpClient httpclient = HttpClients.createDefault();
// 创建httpget实例
HttpGet httpget = new HttpGet(getImgPO.getUrl());
// 执行get请求
CloseableHttpResponse response = httpclient.execute(httpget);
HttpEntity entity = response.getEntity();
// 获取返回实体
String content = EntityUtils.toString(entity,"UTF-8");
// 解析网页 得到文档对象
Document doc = (Document) Jsoup.parse(content);
// 获取指定的 <img />
//Elements elements = doc.select(".img_box img");
// 获取tag是a的所有DOM元素,数组
Elements elements =doc.getElementsByTag("img");
if (getImgPO.getNum()>elements.size()){
getImgPO.setNum(elements.size());
}
for (int i = 0; i < getImgPO.getNum(); i++) {
Element element = elements.get(i);
// 获取 <img /> 的 src
String url = element.attr("src");
// 再发请求最简单了,并由于该链接是没有 https:开头的,得人工补全
HttpGet PicturehttpGet = new HttpGet("https:"+url);
System.out.println("getURL:"+PicturehttpGet);
CloseableHttpResponse pictureResponse = httpclient.execute(PicturehttpGet);
HttpEntity pictureEntity = pictureResponse.getEntity();
InputStream inputStream = pictureEntity.getContent();
// 使用 common-io 下载图片到本地,注意图片名不能重复
FileUtils.copyToFile(inputStream, new File(getImgPO.getDownPath() + i + ".jpg"));
pictureResponse.close(); // pictureResponse关闭
}
response.close(); // response关闭
httpclient.close(); // httpClient关闭
}
}
总共就三个类,很简单,已经在尽力补救代码格式了,这个类里面你只需要知道前面的配置即可,整个类就一个方法,就是爬取图片的方法,我们在其他项目调用的话也是调用这个方法。详细描述如下:
最后,也是最重要的一步,我们需要在 resources 路径下新建一个文件 spring.factories,路径如下:
这里我们需要配置一个路径,也就是我们的自动装配类路径,我的配置如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.jd.imggets.GetImgAutoConfiguration
最后,打包项目即可,这里我推荐使用maven打包, 命令执行mvn install ; 打包地址就是你的maven本地仓库地址下,你可以在maven日志看到,现在整个过程已经完成,接下来讲讲核心的。
我们的程序执行流程,如何实现自动装配:
我们的项目在启动时,入口处有这个注解:@SpringBootApplication,查看@SpringBootApplication源码,我们能发现其底层有其他注解,其中@ComponentScan注解只能扫描spring-boot项目包内的bean并注册到spring容器中,注解@EnableAutoConfiguration用来扫描我们上面配置的文件spring.factories;在文件中,我们定义了待扫描的路径:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=
com.jd.imggets.GetImgAutoConfiguration
当扫描此路径下的类时,我们的注解就起作用了,
@Configuration //这个不多说,是标注一个bean的实例化工厂
@EnableConfigurationProperties(ImgProperties.class) //这个注解将会扫描我们的默认配置文件类,在ImgProperties.class中的参数如果没有被application.properties文件中的参数覆盖,则会被加载并注入到spring容器里面去。接着我们加载了以下注解:
@Resource
private ImgProperties imgProperties; //装配我们配置参数类的bean
@Bean
@ConditionalOnMissingBean //在该bean不存在的情况下执行此方法,这里使用了我们的配置参数对象,并把实例化的GetImgPO对象注入到springIoc容器中
public GetImgPO initGetImgPO(){
GetImgPO getImgPO = new GetImgPO(imgProperties.getUrl(),imgProperties.getNum(),imgProperties.getDownPath());
return getImgPO;
}
现在,只要我们在其他地方使用@AutoWrite注解取到GetImgPO 对象,那么它里面的参数都是有默认值的,但是如果我们在application.properties里面进行配置,那么默认参数就会改变,这里是通过这个注解实现的
@ConfigurationProperties(prefix = “img”) //如果配置文件配置了以下某属性,则默认属性值会被覆盖
比如说,我配置 img.num=15;那么原有配置10就会被改变。
到这里,你是否会说,我直接把参数传进方法就可以,或者我new出一个对象并set参数值就可以,为什么要做这些麻烦的配置呢,想一想,如果你做了一个很复杂的工具包,别人如果要使用它就需要做很多参数配置和文件配置,而且一旦某个参数配置错误就可能导致工具包无法运行,那么还有人会使用这个工具吗,所以使用了stater原理配置后,只要注入依赖,其他人不管你里面如何配置,他只需要取出对象调用方法即可,就算什么参数都不配置,你的工具包依然加载默认配置完美运行,这才是一个好的工具。因此我们会发现,springboot之所以好用,stater自动装配很重要。感谢观看_