Closed peteryuanpan closed 4 years ago
SpringBoot优点
SpringBoot缺点
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>1.5.9.RELEASE</version>
</dependency>
package com.example;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
@SpringBootApplication来标注一个主程序类,说明这是一个SpringBoot应用 */ @SpringBootApplication public class HelloWorldMainApplication {
public static void main(String[] args) { // 启动Spring应用 SpringApplication.run(HelloWorldMainApplication.class, args); }
}
HelloController.java
```java
package com.example.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/hello")
public String hello() {
return "Hello World!";
}
}
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: Admin
Created-By: Apache Maven 3.6.1
Build-Jdk: 1.8.0_231
预期是有这么一行,但是没有
Main-Class: com.example.HelloWorldMainApplication
尝试了从project structure中添加META-INF/MAINFEST.MF到resources下,再到maven project中运行clean、package,但依然没用 如何让.jar的MANIFEST.MF文件内容拥有Main-Class?
在第二次尝试的时候找到了问题所在 原因是之前在编写pom.xml时做了偷懒
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
</parent>
上面这一段没有写进去,导致maven install时,最终.jar中MANIFEST.MF文件内容不符合预期 添加了上面这段到pom.xml后,重新maven clean,maven install,即可在cmd下运行 java -jar spring-boot-01-helloworld-1.0-SNAPSHOT.jar了,并且还发现上面两个网上的解决方案,实则没有需要
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
</dependencies>
spring boot 将所有的功能场景都抽取出来了,作为一个个的starters(启动器),只需要在项目里面引入这些starter相关场景的所有依赖都会导入进来,要用什么功能就导入什么场景的starter
@SpringBootApplication注解,标注在某个类上,说明该类是SpringBoot的主配置类,SpringBoot应该运行该类的Main方法来启动应用
同样的,按住ctrl,点击@SpringBootApplication,可以进入具体的SpringBootApplication.class中,查看源码 可以看到@SpringBootApplication是一个组合注解,内容如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
)}
)
其中@SpringBootConfiguration,表示一个SpringBoot的配置类,再点进去,可以看到源码如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
其中@Configuration,表示一个Spring的配置类,关联配置文件(这一块知识与Spring原理有关,可深入了解下),配置类也是容器中的一个组件:@Component
还有@EnableAutoConfiguration,表示让SpringBoot对该类开启自动配置功能 代码如下
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({EnableAutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}
其中有@AutoConfigurationPackage,表示自动配置包
其中有如@Import(AutoConfigurationPackages.Registrar.class)形式注解,该具体类,将主配置类(@SpringBootApplication标注的类)的所在包及下面所有子包里的所有组件扫描到Spring容器中
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
Registrar() {
}
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
}
public Set<Object> determineImports(AnnotationMetadata metadata) {
return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
}
}
启动HelloWorld程序,对new AutoConfigurationPackages.PackageImport(metadata)).getPackageName()这一行打个断点,用Evaluate Expression计算一下,包名是叫做com.example,也就是主包
还有注解@Import({EnableAutoConfigurationImportSelector.class}),import(x)的意思是给容器导入组件x,EnableAutoConfigurationImportSelector看源码,再找到AutoConfigurationImportSelector源码,可看到selectImports方法,即是告诉容器具体需要导入哪些组件
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
try {
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
configurations = this.sort(configurations, autoConfigurationMetadata);
Set<String> exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.filter(configurations, autoConfigurationMetadata);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return (String[])configurations.toArray(new String[configurations.size()]);
} catch (IOException var6) {
throw new IllegalStateException(var6);
}
}
}
断点查看List
上面代码中还有getCandidateConfigurations方法,进入后看到SpringFactoriesLoader.loadFactoryNames,再进入看到classLoader.getResources("META-INF/spring.factories") 总结下即是,SpringBoot在启动的时候,从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入到容器中,自动配置类就生效了,然后可进行自动配置工作了。
TODO
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
...
</dependency>
package com.example.demo.controller;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;
/ @ResponseBody // 这个类的所有方法返回的数据值直接写给浏览器(如果是对象转为json数据) @Controller / @RestController // 内置包含了上面2个注解 public class HelloController {
@RequestMapping("/hello")
public String hello() {
return "hello world quick!";
}
}
- run起来,访问http://localhost:8080/hello ,可以得到结果
![image](https://user-images.githubusercontent.com/10209135/88123495-8f538000-cbfd-11ea-93ba-acc4f500272f.png)
- 看java/resources文件夹中,自动创建好了static文件夹、teamplates文件夹、application.properties
- static文件夹用于保存所有静态资源(js、css、teamplate)
- templates文件夹用于保存所有模板页面,SpringBoot默认jar包使用嵌入式的Tomcat,默认不支持JSP页面,但可以使用模板引擎,比如freemarker、thymeleaf
**TODO:这里记一下,不太明白模板引擎具体含义,视频中说后续会再详细说**
- application.properties可以修改SpringBoot默认的应用配置文件,比如填写**server.port=8081**,则会修改端口号,此时需要访问http://localhost:8081/hello ,而非 http://localhost:8080/hello
**TODO:配置文件中参数有哪些,该怎么写?视频中说后续会再详细说**
简介
总结
后续