SpringBoot
1、初始SpringBoot
——SpringBoot是一个开发基于Spring框架的应用的快速开发框架。
1.1、SpringBoot的理解
-
SpringBoot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化 Spring 应用的初始搭建以及开发过程。
-
简化了传统的spring项目的开发,不需要再去写很多xml配置文件(或配置类)。
-
导入即配置,我们导入包之后,springboot默认启动会启用自动装配,并且会有默认的配置,我们可以直接使用。(如MybatisConfig、JDBCConfig、SpringMvcConfig等)
-
如果需要自定义配置
- 可以新建@Configration配置类,结合@Bean注解完成自定义的配置,替换了以前传统的xml
- 也可以@Bean交给Spring容器管理,在@Import导入配置类
-
springboot大大的提升了我们的开发效率
1.2、SpringBoot特性
- 起步依赖
- 也就是我们常见的starter依赖,本质上就是一个Maven坐标,整合了完成一个功能需要的所有坐标。
- 自动装配
- SpringBoot启动应用时,会检测引入的Spring模块或第三方库(Web库或Mysql相关库),当条件满足时自动加载Spring模块或第三方库的组件到IOC容器中,不需要手动声明,简化开发。
- 内嵌了Tomcat、Jetty(Web容器)
- 直接将SpringBoot程序打成一个Jar即可,使用java -jar命令即可运行。
- 外部化配置
- 当配置需要修改时,只需要修改外部化配置重启即可,而无需再重新打包。
- 不需要XML配置
- 只需要在.properties或者.yml后缀的配置文件中编写配置即可。
1.3、SpringBoot自动装配原理
- 启动类会有一个入口注解@SpringBootApplication
- 该注解中有三个核心注解
- @SpringBootConfiguration 标注该类为springboot核心配置类
- @EnableAutoConfiguration 启动自动装配
- 该注解组合了@Import注解,通过@Import注解导入了一个AutoConfigurationImportSelector接口实现类。
- 这个实现类中重写了selectImports这样一个方法,这个方法经过层层调用,最终会读取META-INF目录下的后缀名为imorts的文件,当然了,boot2.7以前的版本,读取的是spring.factories文件。
- 通过文件读取到全类名之后,会解析注册条件,也就是@Conditional及其衍生的注解,把满足注册条件的Bean对象自动注入到IOC容器中,从而实现自动装配。
- @ComponentScan 扫描指定路径下有哪些bean需要管理
- 当没有指定扫描包时,会默认扫描添加了这个注解的类所在的包及其子包,所以SpringBoot默认扫描启动类所在的包及其子包
- 特别注意:一旦自己添加了@ComponentScan并设置了路径,则会以你添加了的为主。
2、SpringBoot快速入门(重点)
步骤1:选择 Spring Initializr(一种快速构建方式,实际上也是maven工程),用来创建SpringBoot工程
注意:打包方式这里需要设置为 Jar,Java版本选择8。
-
选中 Web,然后勾选 Spring Web
由于我们需要开发一个 web程序,使用到了 SpringMVC 技术,所以按照下图红框进行勾选
注意:
1、在创建好的工程中不需要创建配置类
2、创建好的项目会自动生成其他的一些文件,而这些文件目前对我们来说没有任何作用,所以可以将这些文件删除。
可以删除的目录和文件如下:
.mvn
.gitignore
HELP.md
mvnw
mvnw.cmd
版本特别特别注意:
步骤2:创建 Controller
@RestController
@RequestMapping("/books")
public class BookController {
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println("id ==> "+id);
return "hello , spring boot!";
}
}
步骤3:启动服务器
-
运行 SpringBoot工程不需要使用本地的 Tomcat和 插件,只运行Application类(启动类)
-
特别注意:SpringBoot启动类一定要与你扫描的文件同级,不然扫描不到。
3、命令行启动SpringBoot工程
打包
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
所以我们只需要使用 Maven 的 package 指令打包就会在 target 目录下生成对应的 Jar包。
特别注意:(1)该插件必须配置,不然打好的 jar 包也是有问题的。
(2)必须先使用clean命令清除缓存才能打包
启动
进入 jar
包所在位置,在 命令提示符
中输入如下命令
java -jar jar包名称
例:java -jar springboot_01_quickstart-0.0.1-SNAPSHOT.jar
执行上述命令就可以看到 SpringBoot
运行的日志信息
注意:运行后可以ctrl+c让程序结束。
4、SpringBoot概述
starter
- SpringBoot中常见依赖名称,该依赖定义了当前项目需要使用的所有依赖坐标,以达到减少依赖配置的目的。
parent
- 所有 SpringBoot 项目要继承的项目,定义了若干个依赖版本号(依赖管理,而非依赖),以达到减少依赖冲突的目的
实际开发
-
使用任意坐标时,仅书写GAV中的G和A,V由SpringBoot提供
G:groupid
A:artifactId
V:version
-
如发生坐标错误,再指定version(要小心版本冲突)
4.1、起步依赖(starter依赖)
我们使用 Spring Initializr方式创建的Maven工程的的 pom.xml配置文件中自动生成了很多包含 starter的依赖,这些依赖就是启动依赖。接下来我们探究一下它是如何实现的。
4.1.1、父工程依赖
注意:由标签写的就是父标签
再进入到该父工程中,在该工程中我们可以看到配置内容结构如下图所示
上图中的 properties 标签中定义了各个技术软件依赖的版本,避免了我们在使用不同软件技术时考虑版本的兼容问题。在 properties中我们找servlet和 mysql的版本如下图
dependencyManagement标签是进行依赖版本锁定,但是并没有导入对应的依赖;如果我们工程需要那个依赖只需要引入依赖的 groupid和 artifactId不需要定义version。
而 build标签中也对插件的版本进行了锁定,如下图
看完了父工程中 pom.xml
的配置后不难理解我们工程的的依赖为什么都没有配置 version
。
4.1.2、引入依赖
在我们创建的工程中的 pom.xml
中配置了如下依赖
进入到该依赖,查看 pom.xml
的依赖会发现它引入了如下的依赖
里面的引入了 spring-web
和 spring-webmvc
的依赖,这就是为什么我们的工程中没有依赖这两个包还能正常使用 springMVC
中的注解的原因。
而依赖 spring-boot-starter-tomcat
,从名字基本能确认内部依赖了 tomcat
,所以我们的工程才能正常启动。
结论:以后需要使用技术,只需要引入该技术对应的起步依赖即可。
4.1.3、自定义starter
4.2、SpringBoot启动类
@SpringBootApplication
public class Springboot01QuickstartApplication {
public static void main(String[] args) {
SpringApplication.run(Springboot01QuickstartApplication.class, args);
}
}
-
SpringBoot的引导类是项目的入口,运行main方法就可以启动项目
-
特别注意:所有需要被扫描的Bean都需要放在与启动类同一个目录下,否者需要手动添加@CompentScan(basePackages=“”)去指定扫描。
4.3、切换web服务器
问题提出:
现在我们启动工程使用的是 tomcat服务器,那能不能不使用 tomcat使用 jett服务器呢?(jetty在我们 maven高级时讲 maven私服使用的服务器。)
解决方法:
步骤1:使用 exclusion 标签(排除依赖)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
步骤2:在 pom.xml
中导入 jetty
的起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
接下来再次运行引导类,在日志信息中就可以看到使用的是 jetty
服务器
小结:
通过切换服务器,我们不难发现在使用 SpringBoot
换技术时只需要导入该技术的起步依赖即可。
4.4、关于springboot项目静态资源放置问题
情况一:将HTML页面存放在resources/static的目录下,可以直接访问
情况二:将HTML页面存放在**resource/templates或resource/****,需要设置静态资源映射
@Slf4j
@Configuration
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 设置静态资源映射
* @param registry
*/
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始进行静态资源映射...");
//当访问/backend/????时候,从/backend目录下查找内容
//需要哪些静态资源就需要配置
registry.addResourceHandler("/backend/**").addResourceLocations("classpath:/backend/");
registry.addResourceHandler("/front/**").addResourceLocations("classpath:/front/");
}
}
5、配置文件
——在SpringBoot中,配置文件只能是 .properties文件或 .yml/.yaml文件。
5.1、配置文件格式
- application.properties
server.port=80
- application.yml(主流)
server:
port: 80
- application.yaml
server:
port: 80
特别注意:
-
SpringBoot程序的配置文件名必须是 application,只是后缀名不同而已。
-
三种配置文件的优先级是:application.properties> application.yml > application.yaml
配合文件没提示解决方法
-
点击
File
选中Project Structure
-
弹出如下窗口,按图中标记红框进行选择
-
通过上述操作,会弹出如下窗口
- 点击上图的
+
号,弹出选择该模块的配置文件
通过上述几步后,就可以看到如下界面。properties
类型的配合文件有一个,ymal
类型的配置文件有两个
5.2、yaml格式
——一种数据序列化格式。
5.2.1、yaml格式详解
xml格式:
<enterprise>
<name>itcast</name>
<age>16</age>
<tel>4006184000</tel>
</enterprise>
properties格式:
enterprise.name=itcast
enterprise.age=16
enterprise.tel=4006184000
yaml格式:
server:
port: 80 #配置端口
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印SQL日志到控制台
global-config:
banner: off # 关闭mybatisplus启动图标
优点:容易阅读、容易与脚本语言交互、以数据为核心(重数据轻格式,yaml更注重数据,而 xml 更注重格式)
语法规则(严格)
-
大小写敏感
-
属性层级关系使用多行描述,每行结尾使用冒号结束
-
使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(空格的个数并不重要,只要保证同层级的左侧对齐即可。)
-
属性值前面添加空格(核心规则:数据前面要加空格与冒号隔开)
-
‘#’ 表示注释
-
数组数据表示方法:数组数据在数据书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔
enterprise:
name: itcast
age: 16
tel: 4006184000
subject:
- Java
- 前端
- 大数据
5.2.2、yaml配置文件数据读取
编写实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Enterprise {
private String name;
private int age;
private String tel;
private String[] subject;
}
编写配置文件
lesson: SpringBoot
server:
port: 80
enterprise: #这是一个对象数据
name: itcast
age: 16
tel: 4006184000
subject: #数组表示法
- Java
- 前端
- 大数据
subject:Java,前端,大数据 #集合表示法
方法一:使用 @Value注解
使用 @Value("表达式")
注解可以从配合文件中读取数据,注解中用于读取属性名引用方式是:${一级属性名.二级属性名……}
@RestController
@RequestMapping("/books")
public class BookController {
@Value("${lesson}")
private String lesson;
@Value("${server.port}")
private Integer port;
@Value("${enterprise.subject[0]}")
private String subject_00;
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println(lesson);
System.out.println(port);
System.out.println(subject_00);
return "hello , spring boot!";
}
}
- 缺点:读取到的数据特别零散。
方法二:Environment对象
- 使用 @Autowired注解注入Environment对象的方式读取数据。
- 这种方式 SpringBoot会将配置文件中所有的数据封装到Environment对象中,通过getProperty(String name)方法获取。
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired
private Environment env;
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println(env.getProperty("lesson"));
System.out.println(env.getProperty("enterprise.name"));
System.out.println(env.getProperty("enterprise.subject[0]"));
return "hello , spring boot!";
}
}
缺点:框架内容巨大,使用Environment对象数据太多,不好使用
方法三:自定义对象(重点)
——SpringBoot提供了将配置文件中的数据封装到我们自定义的实体类对象中的方式。
-
在实体类上添加
@Component
注解,交给 Spring管理。 -
使用
@ConfigurationProperties
注解表示加载配置文件- 在该注解中也可以使用
prefix
属性指定只加载指定前缀的数据
- 在该注解中也可以使用
-
在
BookController
中进行注入
具体代码如下:
步骤一:创建Enterprise实体类:
@Component //将实体类bean的创建交给Spring管理。
@ConfigurationProperties(prefix = "enterprise") //加载配置文件,注意属性名称都要与配置文件命名保持一致
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Enterprise {
private String name;
private int age;
private String tel;
private String[] subject;
}
步骤二:BookController内容如下:
@RestController
@RequestMapping("/books")
public class BookController {
@Autowired //注入Enterprise类对象
private Enterprise enterprise;
@GetMapping("/{id}")
public String getById(@PathVariable Integer id){
System.out.println(enterprise.getName());
System.out.println(enterprise.getAge());
System.out.println(enterprise.getSubject());
System.out.println(enterprise.getTel());
System.out.println(enterprise.getSubject()[0]);
return "hello , spring boot!";
}
}
注意:使用第三种方式,在实体类上有如下警告提示
这个警告提示解决是在 pom.xml
中添加如下依赖即可
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
5.3、多环境配置
问题提出:
以后在工作中,对于开发环境、测试环境、生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql
,连接自己电脑上的 mysql
即可,但是项目开发完毕后要上线就需要该配置,将环境的配置改为线上环境的,这样来回的修改配置会很麻烦。
解决方法:
而 SpringBoot给开发者提供了多环境的快捷配置,需要切换环境时只需要改一个配置即可。
5.3.1、yaml多环境(重点)
#设置启用的环境
spring:
profiles:
active: dev
---
#开发
spring:
profiles: dev #给开发环境起的名字
server:
port: 80
---
#生产
spring:
profiles: pro #给生产环境起的名字
server:
port: 81
---
#测试
spring:
profiles: test #给测试环境起的名字
server:
port: 82
---
细节解释:(1)在 application.yml
中使用 ---
来分割不同的配置(要靠在最最左边的位置)
(2)spring.profiles
是用来给不同的配置起名字的
(3)spring.profiles.active
用于告知 SpringBoot
使用哪段配置,设置启用环境
注意:在上面配置中给不同配置起名字的 spring.profiles
配置项已经过时。最新用来起名字的配置项是 (两个使用都可以)
#开发
spring:
config:
activate:
on-profile: dev
5.3.2、properties多环境(了解即可)
properties
类型的配置文件配置多环境需要定义不同的配置文件
-
application-dev.properties
是开发环境的配置文件。我们在该文件中配置端口号为80
server.port=80
-
application-test.properties
是测试环境的配置文件。我们在该文件中配置端口号为81
server.port=81
-
application-pro.properties
是生产环境的配置文件。我们在该文件中配置端口号为82
server.port=82
SpringBoot
只会默认加载名为 application.properties
的配置文件,所以需要在 application.properties
配置文件中设置启用哪个配置文件,配置如下:
spring.profiles.active=pro
5.3.3、命令行启动参数设置
问题提出:使用 SpringBoot
开发的程序以后都是打成 jar
包,通过 java -jar xxx.jar
的方式启动服务的。配置文件打到的jar包中了,该如何切换环境呢?
解决方法:
SpringBoot
提供了在运行 jar
时设置开启指定的环境的方式,如下:
java –jar xxx.jar --spring.profiles.active=test
临时修改端口号:
java –jar xxx.jar --server.port=88
也可以同时设置多个配置,比如即指定启用哪个环境配置,又临时指定端口,如下:
java –jar springboot.jar --server.port=88 –-spring.profiles.active=test
注意:测试后会发现命令行设置的端口号优先级高(也就是使用的是命令行设置的端口号)
配置的优先级在SpringBoot
官网已经进行了说明,参见 :
https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-external-config
进入上面网站后会看到如下页面
如果使用了多种方式配合同一个配置项,优先级高的生效。
5.3.4、扩展:Maven与SpringBoot多环境兼容
问题提出:如果Maven和Spring都配置了多环境,应该如何让它们兼容呢?(因为SpringBoot最终是打包成jar包用命令运行的,所以SpringBoot应该听从Maven)
5.4、配置文件优先级
问题提出:我们开发完毕后需要测试人员进行测试,由于测试环境和开发环境的很多配置都不相同,所以测试人员在运行我们的工程时需要临时修改很多配置,该怎么优化呢?
解决方法:SpringBoot
定义了配置文件不同的放置的位置(放在不同位置的优先级是不同的)
扩展:
企业开发一般会先在application.yml写配置文件,到真正投入使用时会将application.yml放在config文件夹下。
5.4.1、验证
在 resources下创建一个名为 config的目录,在该目录中创建 application.yml配置文件,而在该配置文件中将端口号设置为 81
server:
port: 81
而在 resources下创建的application.yml配置文件中并将端口号设置为80
server:
port: 80
验证3级和4级的优先级
——说明类路径下的config下的配置文件优先于类路径下的配置文件。
验证2级和4级的优先级
-
将工程打成 jar包,到 jar包所在位置
-
在jar包所在位置创建config文件夹,在该文件夹下创建 application.yml配置文件,而在该配合文件中将端口号设置为 82
-
或者是直接将临时配置 application.yml配置文件放在jar包所在位置
-
在命令行使用以下命令运行程序
java -jar springboot_06_config_file-0.0.1-SNAPSHOT.jar
运行后日志信息如下
通过这个结果可以得出file:
config
下的配置文件优先于类路径下的配置文件。
注意:
SpringBoot 2.5.0版本存在一个bug,我们在使用这个版本时,需要在
jar
所在位置的config
目录下创建一个任意名称的文件夹
6、SpringBoot整合junit
基本步骤:
- 在测试类上添加
@SpringBootTest
注解 - 使用
@Autowired
注入要测试的资源 - 定义测试方法进行测试
编写测试类
@SpringBootTest
class Springboot07TestApplicationTests {
@Autowired
private BookService bookService;
@Test
public void save() {
bookService.save();
}
}
如果不满足这个要求的话,就需要在使用 @SpringBootTest
注解时,使用 classes
属性指定引导类的字节码对象。如
@SpringBootTest(classes = Springboot07TestApplication.class)
@RunWith(SpringRunner.class)
class Springboot07TestApplicationTests {
@Autowired
private BookService bookService;
@Test
public void save() {
bookService.save();
}
}
7、SpringBoot整合mybatis(重点)
选择当前模块需要使用的技术集(MyBatis、MySQL)
- 特别注意:在模块选择了mybatis时,当使用的是jdk8版本时,需要更改版本和依赖才能使用,特别注意这两个依赖。
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
定义实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private Integer id;
private String name;
private String type;
private String description;
}
定义dao接口,注意要加上@Mapper
- 或者在启动类添加
@MapperScan
注解,其属性为所要扫描的Dao所在包
@Mapper
public interface BookDao {
@Select("select * from tbl_book where id = #{id}")
public Book getById(Integer id);
}
特别注意:凡是加了@Mapper的接口,SpringBoot都会自动为它开启自动代理。
定义测试类
@SpringBootTest
class Springboot08MybatisApplicationTests {
@Autowired
private BookDao bookDao;
@Test
void testGetById() {
Book book = bookDao.getById(1);
System.out.println(book);
}
}
编写配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false #使用druid需要配置时区
username: root
password: root
扩展:使用Druid数据源
注意:我们常用的数据源是Druid,所以一般我们都会指定使用Druid数据源
-
导入
Druid
依赖<dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.23</version> </dependency>
-
在
application.yml
配置文件配置spring: datasource: type: com.alibaba.druid.pool.DruidDataSource #引入druid数据源 url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useUnicode=true&useSSL=false #使用druid需要配置时区 username: root password: 232104 driver-class-name: com.mysql.cj.jdbc.Driver
8、Bean注册
8.1、注册自定义Bean
8.2、注册第三方Bean
通过@Bean注解
-
假设在第三方配置包下有一个Resolver类,我们需要注册该Bean并使用
-
可以在启动类下直接配置(不推荐,启动类专门启动进行了,别弄复杂)
@SpringBootApplication public class SpringBootRegisterApplication { public static void main(String[] args) { SpringApplication.run(SpringbootTestApplication.class, args); } @Bean //将方法返回值交给IOC容器管理,成为IOC容器的bean对象 public Country country(){ return new Country(); } }
-
自己建一个配置类专门注册第三方的Bean。(需要注意配置类需要放在启动类同包或者子包下)
@Configuration public class CommonConfig { @Bean //将方法返回值交给IOC容器管理,成为IOC容器的Bean对象 public Country country(){ return new country(); } //对象默认的名字是:方法名 ,也可以自己指定 //如果方法的内部需要使用到IOC容器中已经存在的Bean对象,那么只需要在方法上声明即可,Spring会自动的注入 @Bean public Province province(Country country){ System.out.println("province: "+country); //方法参数需要country,Spring会自动的注入Country对象 return new Province() ; } }
8.3、@Import注解的使用
- 实际上SpringBootApplication中的@EnableAutoConfiguration内部就有一个@Import注解,默认扫描启动类的当前类或子类。
- 负责将一个或多个外部配置类导入到当前的配置类中,以便在Spring应用程序上下文中注册额外的Bean或配置。
用法1:导入配置类(当配置类太多时就不优雅了)
@Import(CommonConfig.class) 或者 @Import({CommonConfig.class})
用法2:导入ImportSelector接口实现类(重点,是SpringBoot自动装配的原理)
- 创建ImportSelector接口实现类
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"com.itheima.config.CommonConfig"};
}
}
//只需要返回一个字符串数组,数组里每一个字符串就是你要注入到IOC容器类的全类名
//SpringBoot会自动调用selectImports方法得到全类名的数组,把这些类的对象自动注入到IOC容器中去。
- 导入ImportSelector接口实现类
@Import(CommonImportSelector.class)
8.4、优化代码
8.4.1、优化1:通过流的方式读取文件路径
- String数组中的数据应该写在文件中
- 在resources文件夹下建立文件common.imports,编写要注入到IOC容器类的全类名,以流的方式读写。
com.haoyu.config.MyConfig //一行一个路径
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//读取配置文件的内容
List<String> imports = new ArrayList<>();
InputStream is = CommonImportSelector.class.getClassLoader().getResourceAsStream("common.imports");
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
try {
while ((line = br.readLine()) != null) {
imports.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
return imports.toArray(new String[0]);
}
}
优化2:配置组合注解
- 自定义组合注解(类似于自定义注解)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(CommonImportSelector.class)
public @interface EnableCommonConfig{
}
- 此时在启动类上添加自定义组合注解即可
@EnableCommonConfig
@SpringBootApplication
public class SpringbootTestApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootTestApplication.class, args);
}
}
8.5、Bean注册条件(源码中经常使用)
案例:
country:
name: china
system: socialism
@Configuration
public class CommonConfig {
//如果配置文件中配置了指定的信息,则注入,否则不注入
@ConditionalOnProperty(prefix = "country",name = {"name", "system"})
@Bean
public Country country(@Value("${country.name}")String name,@Value("${country.system}" String system){
Country country=new Country(name,system);
return country;
}
}
9、Springboot接受与发送文件
9.1、接收文件
——springboot内部封装了MultipartFile接口,用于接收和处理前端发送过来的文件。
设置上传文件大小
spring:
servlet:
multipart:
# 设置 上传文件的大小
max-file-size: 10MB
# 设置 整个请求的大小
max-request-size: 15MB
或者:
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB
前端核心代码(发送文件)
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="multipartfile" accept="image/png" value="请选择文件">
<input type="submit" value="上传">
</form>
注意事项:编码方式enctype必须是"multipart/form-data",指表单数据中由多部分构成,既有文本数据,又有文件等二进制数据。multipart/form-data是将文件以二进制的形式上传,这样可以实现多种类型的文件上传。
Controller类接收文件
@RestController
public class uploadcontroller {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
@PostMapping("/upload")
public String upload(MultipartFile multipartfile, HttpServletRequest request){
String realPath = request.getSession().getServletContext().getRealPath("/update/");
String format=sdf.format(new Date());
File folder=new File(realPath+format);
if(!folder.isDirectory()){
folder.mkdirs();
}
String oldname = multipartfile.getOriginalFilename();
String newname = UUID.randomUUID().toString()+oldname.substring(oldname.lastIndexOf("."),oldname.length());
try {
multipartfile.transferTo(new File(folder, newname));
System.out.println(new File(folder, newname).getAbsolutePath());//输出(上传文件)保存的绝对路径
String filePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/update/"+format+newname;
return filePath+"上传成功";
}
catch (IOException e){
e.printStackTrace();
}
return "上传失败!";
}
}
form-data是将文件以二进制的形式上传,这样可以实现多种类型的文件上传。**
Controller类接收文件
@RestController
public class uploadcontroller {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
@PostMapping("/upload")
public String upload(MultipartFile multipartfile, HttpServletRequest request){
String realPath = request.getSession().getServletContext().getRealPath("/update/");
String format=sdf.format(new Date());
File folder=new File(realPath+format);
if(!folder.isDirectory()){
folder.mkdirs();
}
String oldname = multipartfile.getOriginalFilename();
String newname = UUID.randomUUID().toString()+oldname.substring(oldname.lastIndexOf("."),oldname.length());
try {
multipartfile.transferTo(new File(folder, newname));
System.out.println(new File(folder, newname).getAbsolutePath());//输出(上传文件)保存的绝对路径
String filePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/update/"+format+newname;
return filePath+"上传成功";
}
catch (IOException e){
e.printStackTrace();
}
return "上传失败!";
}
}