SpringBoot
这里写目录标题
- 1.入门程序
- 1.1 spring-boot-starter-parent
- 1.2 启动器
- 1.3 @EnableAutoConfiguration(重要)
- 1.4 如何注册多个Controller?
- 1.5 引导类
- 2.完整的SpringBoot项目
- 2.1 启动类
- 2.1.1 创建一个启动类
- 2.1.2 扩展: @SpringBootConfiguration
- 2.2 使用配置类定义组件
- 2.3 SpringBoot的属性注入
- 3.整合SpirngMvc
- 3.1 注册DispatcherServlet(了解)
- 3.1.1 配置DispatcherServlet映射路径
- 3.1.2 设置端口号
- 3.1.3 访问静态资源
- 3.2 添加拦截器
- 4.整合连接池
- 4.1 HikariCP连接池
- 4.2 Druid连接池
- 5.整合Mybatis
- 5.1 mybatis
- 5.2 通用mapper(基础的CRUD操作)
- 6.整合事务
- 7.SpringBoot项目快速启动
- 8.yaml
- 8.1 语法
- 8.1.1 yaml数组数据
- 8.1.2 yaml数据读取和注入
- 8.2 多环境开发配置
- 8.2.1 多环境启动命令格式(运维人员)
- 8.2.2 Maven与SpringBoot多环境兼容
- 8.3 配置文件读取优先级
- 9.SpringBoot整合Junit
1.入门程序
入门程序相当简单,只要三步
- 创建一个普通工程
- 引入依赖
- 编写controller
一、创建一个普通工程
二、引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>cn.itcast.springboot</groupId><artifactId>itcast-springboot</artifactId><version>1.0-SNAPSHOT</version><!-- 所有的springboot的工程都以spring父工程为父工程 --><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.6.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
</project>
三、编写controller
@RestController
@EnableAutoConfiguration
public class HelloController {@GetMapping("show")public String test(){return "hello Spring Boot!";}public static void main(String[] args) {SpringApplication.run(HelloController.class, args);}
}
1.1 spring-boot-starter-parent
所有SpringBoot项目要继承的项目,定义了若干个坐标版本号(依赖管理,而非依赖),以达到减少依赖冲突的目的
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.6.RELEASE</version>
</parent>
它的作用是对常用的依赖进行版本管理,以便引入依赖时可以省略版本号,需要注意: spring-boot-starter-parent(2.5.0)与 spring-boot-starter-parent(2.4.6)共计57处坐标版本不同
1.2 启动器
Springboot包含许多启动项目并快速运行所需的依赖项
,并且具有一组受支持的被管理的传递性依赖项,所有的正式starter都遵循类似的命名模式spring-boot-starter-*
。
starter启动器是一组方便的依赖项描述符
,可以在pom中引入其依赖,免去了自己需要引用很多依赖类,并且SpringBoot会自动进行类的自动配置。
例如我们引入spring-boot-starter-web(web启动器)
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
实际上我们可以看到这一个启动器中就包含了这么多的依赖
想了解更多的启动器,可以参考:Spring Boot启动器
1.3 @EnableAutoConfiguration(重要)
之前我们如果要访问一个Controller,是比较麻烦的.要配置DispatchServlet,还要去初始化SpringMvc容器,后期到了Spring3.0版本后,我们有了注解配置,但依旧需要配置不少东西
官网翻译
开启spring应用程序的自动配置,SpringBoot基于你所添加的依赖和你自己定义的bean,试图去猜测并配置你想要的配置。比如我们引入了spring-boot-starter-web,而这个启动器中帮我们添加了tomcat、SpringMVC的依赖。此时自动配置就知道你是要开发一个web应用,所以就帮你完成了web及SpringMVC的默认配置了!
总结,SpringBoot内部对大量的第三方库或Spring内部库进行了默认配置,这些配置是否生效,取决于我们是否引入了对应库所需的依赖,如果有那么默认配置就会生效。
@EnableAutoConfiguration会开启SpringBoot的自动配置,并且根据你引入的依赖来生效对应的默认配置。那么问题来了:
- 这些默认配置是怎么配置的,在哪里配置的呢?
- 为何依赖引入就会触发配置呢?
- 这些默认配置的属性来自哪里呢?
其实在我们的项目中,已经引入了一个依赖:spring-boot-autoconfigure,其中定义了大量自动配置类:
我们来看一个我们熟悉的,例如SpringMVC,查看mvc 的自动配置类:
打开WebMvcAutoConfiguration:
我们看到这个类上的4个注解:
@Configuration
声明这个类是一个配置类
@ConditionalOnWebApplication(type = Type.SERVLET)
ConditionalOn,翻译就是在某个条件下,此处就是满足项目的类是是Type.SERVLET类型,也就是一个普通web工程,显然我们就是
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
这里的条件是OnClass,也就是满足以下类存在:Servlet、DispatcherServlet、WebMvcConfigurer,其中Servlet只要引入了tomcat依赖自然会有,后两个需要引入SpringMVC才会有。这里就是判断你是否引入了相关依赖,引入依赖后该条件成立,当前类的配置才会生效!
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
这个条件与上面不同,OnMissingBean,是说环境中没有指定的Bean这个才生效。其实这就是自定义配置的入口,也就是说,如果我们自己配置了一个WebMVCConfigurationSupport的类,那么这个默认配置就会失效!
接着,我们查看该类中定义了什么:
视图解析器:
处理器适配器(HandlerAdapter):
另外,这些默认配置的属性来自哪里呢?
我们看到,这里通过@EnableAutoConfiguration注解引入了两个属性:WebMvcProperties和ResourceProperties。
我们查看这两个属性类:
找到了内部资源视图解析器的prefix和suffix属性。
ResourceProperties中主要定义了静态资源(.js,.html,.css等)的路径:
如果我们要覆盖这些默认属性,只需要在application.properties中定义与其前缀prefix和字段名一致的属性即可。
总结:
SpringBoot为我们提供了默认配置,而默认配置生效的条件一般有两个:
- 你引入了相关依赖
- 你自己没有配置
一、启动器
之所以,我们如果不想配置,只需要引入依赖即可,而依赖版本我们也不用操心,因为只要引入了SpringBoot提供的stater(启动器),就会自动管理依赖及版本了。
因此,玩SpringBoot的第一件事情,就是找启动器,SpringBoot提供了大量的默认启动器,参考课前资料中提供的《SpringBoot启动器.txt》
二、全局配置
另外,SpringBoot的默认配置,都会读取默认属性,而这些属性可以通过自定义application.properties文件来进行覆盖。这样虽然使用的还是默认配置,但是配置中的值改成了我们自定义的。
因此,玩SpringBoot的第二件事情,就是通过application.properties来覆盖默认属性值,形成自定义配置。我们需要知道SpringBoot的默认属性key,非常多,参考课前资料提供的:《SpringBoot全局属性.md》
1.4 如何注册多个Controller?
如果我们有另一个controller,应该怎么访问呢?难道要在每一个Controller中都添加一个main方法和@EnableAutoConfiguration注解,这样启动一个springboot程序也太麻烦了。
也无法同时启动多个Controller,因为每个main方法都监听8080端口。所以,一个springboot程序应该只有一个springboot的main方法。
所以,springboot程序引入了一个全局的引导类。
1.5 引导类
通常请求下,我们在一个springboot工程中都会在基包下创建一个引导类,一些springboot的全局注解(@EnableAutoConfiguration注解)以及springboot程序的入口main方法都放在该类中。
一、在根目录下, 创建引导类
我们还需要添加@ComponentScan
来扫描
@EnableAutoConfiguration
@ComponentScan
public class TestApplication {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}
}
官网描述:
配置组件扫描的指令。提供了类似与context:component-scan标签的作用
通过basePackageClasses或者basePackages属性来指定要扫描的包。如果没有指定这些属性,那么将从声明这个注解的类所在的包开始,扫描包及子包
而我们的@ComponentScan注解声明的类就是main函数所在的启动类,因此扫描的包是该类所在包及其子包。一般启动类会放在一个比较浅的包目录中。
二、并修改HelloController
@RestController
public class HelloController {@GetMapping("show")public String test(){return "hello Spring Boot!";}
}
2.完整的SpringBoot项目
2.1 启动类
2.1.1 创建一个启动类
启动类上添加@SpringBootApplication
@SpringBootApplication
public class TestApplication {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}}
@SpringBootApplication
= @EnableAutoConfiguration
+ @ComponentScan
+ @SpringBootConfiguration
- @EnableAutoConfiguration:开启自动配置
- @ComponentScan:开启注解扫描
- @SpringBootConfiguration ???
2.1.2 扩展: @SpringBootConfiguration
@Configuration这个注解的作用就是声明当前类是一个配置类,然后Spring会自动扫描到添加了@Configuration的类,并且读取其中的配置信息。
而@SpringBootConfiguration是来声明当前类是SpringBoot应用的配置类
,项目中只能有一个。所以一般我们无需自己添加。
2.2 使用配置类定义组件
springboot的默认配置方式和我们之前玩的配置方式不太一样,没有任何的xml, 例如数据库连接池,之前是这么配的
<!-- 配置连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"init-method="init" destroy-method="close"><property name="url" value="${jdbc.url}" /><property name="username" value="${jdbc.username}" /><property name="password" value="${jdbc.password}" />
</bean>
现在我们可以使用更优雅的java配置方式
一、引入依赖
<dependency><groupId>com.github.drtrang</groupId><artifactId>druid-spring-boot2-starter</artifactId><version>1.1.10</version>
</dependency>
二、添加jdbc.properties
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/leyou
jdbc.username=root
jdbc.password=123
三、配置数据源
之前配置的@ComponentScan
此时就可以通过@Configuration
注解扫描到此配置类
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfiguration {@Value("${jdbc.url}")String url;@Value("${jdbc.driverClassName}")String driverClassName;@Value("${jdbc.username}")String username;@Value("${jdbc.password}")String password;@Beanpublic DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(url);dataSource.setDriverClassName(driverClassName);dataSource.setUsername(username);dataSource.setPassword(password);return dataSource;}
}
- @Configuration:声明为配置类
- 配置类的作用就是替代application.xml,我们使用配置类来定位bean,交给容器管理
- @PropertySource:引入属性文件
- 通过
@Value
+${}
可以在Spring容器的所有位置(配置类、bean)中注入值
- 通过
- @Bean:相当于以前的bean标签
- Spring会自动调用该方法,将方法的返回值加入Spring容器中
- @Bean支持直接在传参中注入对象(按类型注入)
然后就可以在任意位置通过@Autowired注入DataSource了!
2.3 SpringBoot的属性注入
上面案例中,我们注入属性使用了@Value注解,这种方式不够强大,在SpringBoot中,提供了一种新的属性注入方式,支持java基本类型以及复杂类型注入
- 创建属性读取类
- 在配置类(在JdbcConfiguratio)中使用这个属性
一、创建属性读取类
@ConfigurationProperties(prefix = "jdbc")
@Data
public class JdbcProperties {private String url;private String driverClassName;private String username;private String password;
}
- @ConfigurationProperties 注解声明当前类为属性读取类
- prefix="jdbc"读取属性文件中,前缀为jdbc的值。
- 在类上定义各个属性,名称必须与属性文件中jdbc.后面部分一致,并且必须具有getter和setter方法
二、在配置类(在JdbcConfiguratio)中使用这个属性
@Configuration
@PropertySource("classpath:jdbc.properties")
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcConfiguration {@Autowiredprivate JdbcProperties jdbcProperties;@Beanpublic DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl(jdbcProperties.getDriverClassName());dataSource.setDriverClassName(jdbcProperties.getUrl());dataSource.setUsername(jdbcProperties.getUsername());dataSource.setPassword(jdbcProperties.getPassword());return dataSource;}
}
- @EnableConfigurationProperties 声明要使用指定属性读取类
三、@Bean方法的参数注入(更推荐)
@Configuration
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcConfiguration {@Beanpublic DataSource dataSource(JdbcProperties jdbcProperties) {dataSource.setUrl(jdbcProperties.getDriverClassName());dataSource.setDriverClassName(jdbcProperties.getUrl());dataSource.setUsername(jdbcProperties.getUsername());dataSource.setPassword(jdbcProperties.getPassword());return dataSource;}
}
四、扩展内容:默认读取的资源文件(之后会改为.yml文件)
以我们把jdbc.properties名称改为application.properties, 此时我们不用指定属性文件
五、最优雅的方式
随着Spring容器初始化Bean后, SpringBoot就会自动调用这个Bean(此处是DataSource)的set方法
,然后完成注入。
使用前提:该类(此处是DataSource)必须有对应属性的set方法!
@Configuration
@PropertySource("classpath:jdbc.properties")
public class JdbcConfiguration {@Bean// 声明要注入的属性前缀,SpringBoot会自动把相关属性通过set方法注入到DataSource中@ConfigurationProperties(prefix = "jdbc")public DataSource dataSource() {DruidDataSource dataSource = new DruidDataSource();return dataSource;}
}
3.整合SpirngMvc
3.1 注册DispatcherServlet(了解)
只要有SpringMvc的依赖后,SpringBoot会自动帮我们定义和注册Dispatcher
一、Spring2.0 回顾XML配置
在Spring2.0时代,我们使用XML的配置方式,在web.xml中配置DispatcherServlet,当web应用启动时,会解析这个文件
<servlet><!-- 在web应用中注册这个Servlet --><servlet-name>springmvc</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!-- 指定读取SpringMvc配置文件的地址 --><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:springmvc-servlet.xml</param-value></init-param><!-- 标记容器是否在启动的时候就加载这个servlet --><load-on-startup>1</load-on-startup>
</servlet><!-- 设置拦截路径 -->
<servlet-mapping><servlet-name>springmvc</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>
二、Spring 3.0 java配置
第一步:SpringMvc配置类
@Configuration
@ComponentScan("com.itheima.controller")
// 用来开启支持SpringMvc的一些配置,常配置实现WebMvcConfigurer接口使用,底层是继承了WebMvcConfigurationSupport
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {}
第二步:继承AbstractAnnotationConfigDispatcherServletInitializer
public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {// 初始化Spring容器protected Class<?>[] getRootConfigClasses() {return new Class[]{SpringConfig.class};}// 初始化SpringMvc容器protected Class<?>[] getServletConfigClasses() {return new Class[]{SpringMvcConfig.class};}protected String[] getServletMappings() {return new String[]{"/"};}
}
原理:
- AbstractAnnotationConfigDispatcherServletInitializer是WebApplicationInitializer的子孙类,当web应用启动时,会调用onStartup方法
- 在AbstractDispatcherServletInitializer(父类)中不仅执行onStartup,还执行了registerDispatcherServlet,在这个方法中,我们注册了DispatchServlet
三、SpringBoot DispatcherServlet的注册
-
1.当我们开启@EnableAutoConfiguration(自动装配)后,会根据扫描到的Configuration来判断是否能自动装备(依赖是否引入依赖)
-
2.WebMvcAutoConfiguration作为一个Configuration,我们运行启动类后会被扫描到,它是基于DispatcherServletAutoConfiguration的装配完成后执行
-
3.DispatcherServletAutoConfiguration中定义了DispatcherServlet
-
4.完成了Dispatcher的定义后,在此处将注册到了web容器中
3.1.1 配置DispatcherServlet映射路径
一、SpringBoot编程式
@Bean
public ServletRegistrationBean dispatherRegistration(DispatcherServlet dispatcherServlet) {return new ServletRegistrationBean(dispatcherServlet, "/api/*");
}
二、SpringBoot配置文件
server.servlet.path=/api/*
3.1.2 设置端口号
# 映射端口
server.port=80
3.1.3 访问静态资源
回顾我们上面看的源码,有一个叫做ResourceProperties的类,里面就定义了静态资源的默认查找路径:
默认的静态资源路径为:
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/
- classpath:/public/
只要静态资源放在这些目录中任何一个,SpringMVC都会帮我们处理。
我们习惯会把静态资源放在classpath:/static/目录下。我们创建目录,并且添加一些静态资源:
3.2 添加拦截器
- 定义拦截器类
- 注册拦截器
一、定义拦截器类
@Component
public class MyInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("preHandle method is running!");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("postHandle method is running!");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("afterCompletion method is running!");}
}
回顾:XML的配置 Spring2.0时代
<!-- 注册自定义拦截器 -->
<mvc:interceptors><mvc:interceptor><!-- 拦截所有请求 --><mvc:mapping path="/**"/><!-- <mvc:mapping path="/hello/"/> --><!-- 自定义拦截器的全路径 --><bean class="cn.itcast.springmvc.interceptors.MyInterceptor"/></mvc:interceptor>
</mvc:interceptors>
回顾:java的配置 Spring3.0时代
- 第一步:在SpringMvc的配置类上添加
@EnableWebMvc注解
同时实现WebMvcConfigurer接口
- 第二步:复写addInterceptors方法
@Configuration
@ComponentScan({"com.itheima.controller"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {// 注入拦截器@Autowiredprivate HandlerInterceptor myInterceptor;// 设置拦截器(如果是拦截器链则按顺序执行),一个拦截器可配置多个拦截路径@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/books/**","/books");}
}
但是随着SpringBoot的到来,SpringBoot不需要我们自定义SpringMvc配置类,它的内部帮我们提供了默认的SpringMvc配置类,只需要我们有对应的依赖
二、SpringBoot 注册拦截器类
如果你想要保持Spring Boot 的一些默认MVC特征,同时又想自定义一些MVC配置(包括:拦截器,格式化器, 视图控制器、消息转换器 等等),你应该让一个类实现WebMvcConfigurer,并且添加@Configuration注解,但是千万不要加@EnableWebMvc注解。
如果你想要自定义HandlerMapping、HandlerAdapter、ExceptionResolver等组件, 你可以创建一个WebMvcRegistrationsAdapter实例 来提供以上组件。
- 保留@Configuration注解,让引导类可以读取到
- 删除@ComponentScan,不需要通过SpringMvcConfig来扫描了
- 删除@EnableWebMvc,会跟SpringBoot的功能冲突
- 保留WebMvcConfigurer ,实现Mvc特征
@Configuration
public class SpringMvcConfig implements WebMvcConfigurer {@Autowiredprivate HandlerInterceptor myInterceptor;/*** 重写接口中的addInterceptors方法,添加自定义拦截器* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(myInterceptor).addPathPatterns("/**");}
}
4.整合连接池
两者二选一即可
- HikariCP连接池
- Druid连接池
SpringBoot版本低于2.4.3(不含),Mysql驱动版本大于8.0时,需要在url连接串中配置时区,或在MySQL数据库端配置时区解决此问题
jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
4.1 HikariCP连接池
HikariCP连接池是jdbc的默认使用的连接池,只有引入jdbc的依赖即可
<!--jdbc的启动器,默认使用HikariCP连接池-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency><!--不要忘记数据库驱动,因为springboot不知道我们使用的什么数据库,这里选择mysql-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
# 连接四大参数
spring.datasource.url=jdbc:mysql://localhost:3306/heima
spring.datasource.username=root
spring.datasource.password=root
# 可省略,SpringBoot自动推断
spring.datasource.driverClassName=com.mysql.jdbc.Driverspring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.minimum-idle=10
4.2 Druid连接池
<!-- Druid连接池 -->
<dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.6</version>
</dependency><!--不要忘记数据库驱动,因为springboot不知道我们使用的什么数据库,这里选择mysql-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
# 连接四大参数
spring.datasource.url=jdbc:mysql://localhost:3306/heima
spring.datasource.username=root
spring.datasource.password=root
# 可省略,SpringBoot自动推断
spring.datasource.driverClassName=com.mysql.jdbc.Driver#初始化连接数
spring.datasource.druid.initial-size=1
#最小空闲连接
spring.datasource.druid.min-idle=1
#最大活动连接
spring.datasource.druid.max-active=20
#获取连接时测试是否可用
spring.datasource.druid.test-on-borrow=true
#监控页面启动
spring.datasource.druid.stat-view-servlet.allow=true
5.整合Mybatis
5.1 mybatis
SpringBoot官方并没有提供Mybatis的启动器,不过Mybatis官方自己实现了:
<!--mybatis -->
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version>
</dependency>
配置,基本没有需要配置的:
# mybatis 别名扫描
mybatis.type-aliases-package=cn.itcast.pojo
# mapper.xml文件位置,如果没有映射文件,请注释掉
mybatis.mapper-locations=classpath:mappers/*.xml
需要注意,这里没有配置mapper接口扫描包,因此我们需要给每一个Mapper接口添加@Mapper
注解,才能被识别。
@Mapper
public interface UserMapper {
}
5.2 通用mapper(基础的CRUD操作)
通用Mapper的作者也为自己的插件编写了启动器,我们直接引入即可:
<!-- 通用mapper -->
<dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>2.0.2</version>
</dependency>
不需要做任何配置就可以使用了。
@Mapper
public interface UserMapper extends tk.mybatis.mapper.common.Mapper<User>{
}
6.整合事务
一、回顾之前,我们是怎么引入事务的
- xml时代
<!-- druid连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://127.0.0.1:3306/my_database"/><property name="username" value="root"/><property name="password" value="root"/></bean><!-- 第一步:定义具体的平台事务管理器(DataSource事务管理器) --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!-- 注入数据源 --><property name="dataSource" ref="dataSource"/></bean>
- java配置时代
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {// 不同的持久化框架,选择不同的事务管理器DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource);return transactionManager;
}
二、SpringBoot的事务管理
当我们引入了jdbc
或者web
的启动器后,就已经引入事务相关的依赖及默认配置了spring-tx
至于添加事务,SpringBoot中通过注解来控制。就是我们熟知的@Transactional
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public User queryById(Long id){return this.userMapper.selectByPrimaryKey(id);}@Transactionalpublic void deleteById(Long id){this.userMapper.deleteByPrimaryKey(id);}
}
7.SpringBoot项目快速启动
一、引入maven插件
jar支持命令行启动需要依赖maven插件支持,请确认打包时是否具有SpringBoot对应的maven插件。
<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>
二、对SpringBoot项目打包(执行Maven构建指令package)
要先clean后package,打包成功后在target文件夹下
三、执行启动指令
进入target文件夹下,cmd进入命令行界面,输入
java -jar springboot-demo-1.0-SNAPSHOT.jar # 项目的名称根据实际情况修改
SpringBoot启动成功
8.yaml
yml和yaml是同一种格式,只是在运算速度上有区别
SpringBoot配置文件加载顺序(了解)
application.properties > application.yml > application.yaml
8.1 语法
- 大小写敏感
- 属性层级关系使用多行描述,每行结尾使用冒号结束
- 使用缩进表示层级关系,同层级左侧对齐,只允许使用空格(不允许使用Tab键)
- 属性值前面添加空格(属性名与属性值之间使用冒号+空格作为分隔)
- 核心规则:数据前面要加
空格
与冒号
隔开
8.1.1 yaml数组数据
8.1.2 yaml数据读取和注入
一、使用@Value读取单个数据
属性名引用方式:${一级属性名.二级属性名……}
二、将数据封装到Environment对象
三、自定义对象封装指定数据(最常用)
public class Enterprise {private String name;private Integer age;private String tel;private String[] subject;//自行添加getter、setter、toString()等方法
}
自定义对象封装数据警告解决方案
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>
8.2 多环境开发配置
方式一:同一个yaml中配置多环境
在实际开发中,项目的开发环境、测试环境、生产环境的配置信息是否会一致?如何快速切换?
在yaml文件中通过加 ---
来区分多种环境
通过spring.profiles.active来指定环境
方式二:不同环境使用单位yaml(了解)
格式:application-环境名称.yml
启动时指定环境名称(不指定环境名称,默认读取application.yml)
方式三:共性内容写到主配置中,特性内容写到独立环境中,根据当前需要,在主配置中指向某个环境(常用)
- 共性内容写在主配置文件
(application.yml)
中 - 非共性的内容(例如数据库连接信息、kafka等),我们写到独立的
application-环境.yml
- 在主配置文件中,指向独立环境
8.2.1 多环境启动命令格式(运维人员)
一、解决yaml文件中因为存在中文,打包失败的情况
将这几处改为UTF-8
二、多环境启动命令格式
java –jar springboot.jar --spring.profiles.active=test
java –jar springboot.jar --server.port=88
java –jar springboot.jar --server.port=88 --spring.profiles.active=test
8.2.2 Maven与SpringBoot多环境兼容
一、在Maven中设置多环境属性
此处的<profile.active>dev</profile.active>只需要有application-dev.yml即可(不用在application-dev.yml中设置spring.profiles:dev)
<profiles><!-- 环境dev --><profile><id>dev_env</id><properties><profile.active>dev</profile.active></properties><activation><activeByDefault>true</activeByDefault></activation></profile><!-- 环境test --><profile><id>test_env</id><properties><profile.active>test</profile.active></properties></profile>
</profiles>
添加了后,在maven的profiles中会显示配置的环境
二、对资源文件开启默认占位符的解析
解析${}占位符
<build><plugins><plugin><artifactId>maven-resources-plugin</artifactId><configuration><encoding>utf-8</encoding><useDefaultDelimiters>true</useDefaultDelimiters></configuration></plugin></plugins>
</build>
三、SpringBoot中引用Maven属性
在主文件application.yml中引入maven属性
四、勾选对应的环境,启动
五、使用Maven打包
Maven指令执行完毕后,生成了对应的包,其中类参与编译,但是配置文件并没有编译,而是复制到包中,生会根据我们勾选的环境,加载环境
8.3 配置文件读取优先级
- SpringBoot中4级配置文件
- 1级 同级目录: config/application.yml 【最高】
- 2级 同级目录: application.yml
- 3级 classpath:config/application.yml
- 4级 classpath:application.yml 【最低】
同级目录指的是与jar包在同一级目录
同样的配置,会采用等级高的
作用:
- 1级与2级留做系统打包后设置通用属性
- 3级与4级用于系统开发阶段设置通用属性
9.SpringBoot整合Junit
一、添加依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
二、编写测试类,默认自动生成了一个
@SpringBootTest
class Springboot07JunitApplicationTests {@Autowiredprivate BookService bookService;@Testpublic void testSave() {bookService.save();}
}
相关文章:
SpringBoot
这里写目录标题1.入门程序1.1 spring-boot-starter-parent1.2 启动器1.3 EnableAutoConfiguration(重要)1.4 如何注册多个Controller?1.5 引导类2.完整的SpringBoot项目2.1 启动类2.1.1 创建一个启动类2.1.2 扩展: SpringBootConfiguration2.2 使用配置类定义组件2.3 SpringBo…...
python--turtle
前言 就随便练练,学习一下turtle库的使用 正文 1.语法学习 import turtle #导入库 turtle.showturtle() #画笔显示箭头 turtle.write("我是大帅逼") #写下字符串 turtle.forward(300) …...
NodeJS的后端Express项目部署到Ubuntu服务器,为前端提供API服务
之前参与的web3项目后端是用NodeJS开发的,因为可以共用NPM库,采用的Express框架,第一次弄,记录下大致的部署过程如下: 1、服务器上安装NodeJS sudo apt-get install nodejs 2、安装全局NPM工具,node_mod…...
作为研发如何使用Github Api?
文章目录使用步骤账号创建进行开发者相关设置API操作演示Github API好处推荐的Github API🌟个人主页: 个人主页 🚵♀️个人介绍:每天进步一点点,生活变得好一点点。 📌作为一位开发,不管是非工作的还是工作中的人士&…...
Java volatile学习
面试题: 1、请谈谈你对volatile的理解? volatile是Java虚拟机提供的轻量级的同步机制1.保证可见性2.不保证原子性3.禁止指令重排 2、JMM你谈谈?Java内存模型 3、你在哪些地方用到过volatile?单例模式CAS底层代码 目录 一、概述 1、可见性 2、原子性…...
用神经网络分类上和下
( A, B )---3*30*2---( 1, 0 )( 0, 1 ) 做一个网络,输入为3个点,训练集A,B各有4张图片。让B的4张图片全是0.排列组合A,记录迭代次数平均值的变化。收敛误差为7e-4,每个网络收敛199次。 其中得到一组数据 差值结构 1-A-B 迭代次…...
VS Code 1.75 发布!
欢迎使用 2023 年 1 月版的 Visual Studio Code。希望您喜欢此版本中的许多更新,其中一些主要亮点包括:配置文件、VS Marketplace 签名、辅助功能改进、更轻松地调整多视图大小、树视图搜索历史、新的 Git 命令等等。让我们一起看看吧! 配置文…...
Vue2仿网易云风格音乐播放器(附源码)
Vue2仿网易云风格音乐播放器1、整体效果2、使用技术3、实现内容4、源码5、使用图片1、整体效果 2、使用技术 使用了HTML5 CSS3进行页面布局及美化使用Vue2进行数据渲染与页面交互使用Axios发送http请求获取数据 3、实现内容 实现了搜索歌曲功能,输入歌手或歌曲关…...
Spring相关面试题
文章目录请谈一下你对 spring 的理解?说一下 Spring 的核心是什么?请谈 一下你对 Spring IOC 和 和 AOP 的理解?请说一下 Spring 的 的 Bean 作用域?请谈一下Spring中bean对象的生命周期?Spring中的事务是如何实现的 &…...
操作符详解(上篇)
前言小伙伴们大家好,随着对c的不断学习今天我们将来学习操作符。在初始c语言中也介绍过操作符但也只是点到即可,今天我们将详细了解操作符。操作符分类:算术操作符移位操作符位操作符赋值操作符单目操作符关系操作符逻辑操作符条件操作符逗号…...
采样电路的3个组成部分
采样电路的使用实际上是电路的一个闭环控制过程,也可以理解为一个负反馈过程,采集的信号被传送到主控制芯片进行调整。今天就来为您介绍一下采样电路的三个组成部分分析!一起来看看吧! 这里的采样实际上分为电流采样、电压采样、…...
ffmpeg硬解码与软解码的压测对比
文章目录ffmpeg硬解码与软解码的压测一、基本知识二、压测实验1. 实验条件及工具说明2. 压测脚本3. 实验数据结果ffmpeg硬解码与软解码的压测 一、基本知识 本文基于intel集显进行压测 软解码:cpu对视频进行解码硬解码:显卡或者多媒体处理芯片对视频进…...
操作符——“C”
各位CSDN的uu们你们好呀,今天,总算是要到我们的操作符啦,在C语言中,操作符是一个极为复杂的东西,下面,就让我们进入操作符的世界吧 算术操作符 移位操作符 位操作符 赋值操作符 单目操作符 关系操作符…...
YSP的UI界面设计
文章目录一、准备工作二、UI设计1.QPushButton:三、遇到的bug一、准备工作 1.MSVC和MinGW上编译的项目,不能用另一个编译器进行编译 2.若要使用MSVC编译器,需要下载对应版本的VS 见此篇:https://blog.csdn.net/Copperxcx/article…...
干货 | 什么是磁传感器?最常用的磁传感器类型及应用
1、什么是磁传感器?磁传感器通常是指将磁场的大小和变化转换成电信号。磁场,以地球磁场(地磁)或磁石为例的磁场是我们熟悉但不可见的现象。将不可见的磁场转化为电信号,以及转化为可见效应的磁传感器一直以来都是研究的主题。从几十年前使用电…...
操作符(运算符)详解
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀 目录 🐰算数操作符: - * / % 🐰移位操作符&#x…...
【LeetCode每日一题】【2023/2/9】1797. 设计一个验证系统
文章目录1797. 设计一个验证系统方法1:哈希表代码总体1797. 设计一个验证系统 LeetCode: 1797. 设计一个验证系统 中等\color{#FFB800}{中等}中等 你需要设计一个包含验证码的验证系统。每一次验证中,用户会收到一个新的验证码,这个验证码在…...
计算机图形学:改进的中点BH算法
作者:非妃是公主 专栏:《计算机图形学》 博客地址:https://blog.csdn.net/myf_666 个性签:顺境不惰,逆境不馁,以心制境,万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、改进缘由二、…...
【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放
系列文章目录 【SQL开发实战技巧】系列(一):关于SQL不得不说的那些事 【SQL开发实战技巧】系列(二):简单单表查询 【SQL开发实战技巧】系列(三):SQL排序的那些事 【SQL开发实战技巧…...
十分钟利用环信WebIM-vue3-Demo,打包上线一个即时通讯项目【含音视频通话】
这篇文章无废话,只教你如果接到即时通讯功能需求,十分钟利用环信WebIM-vue3-Demo,打包上线一个即时通讯项目【包含音视频通话功能】。 写这篇文章是因为,结合自身情况,以及所遇到的有同样情况的开发者在接到即时通讯&a…...
pandas——DataFrame基本操作(二)【建议收藏】
pandas——DataFrame基本操作(二) 文章目录pandas——DataFrame基本操作(二)一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.修改数据2.缺失值3.合并1.concat合并2.使用append方法合并3.使用merge进行合并4.使用…...
PostgreSQL查询引擎——General Expressions Grammar之restricted expression
General expressions语法规则定义在src/backend/parser/gram.y文件中,其是表达式语法的核心。有两种表达式类型:a_expr是不受限制的类型,b_expr是必须在某些地方使用的子集,以避免移位/减少冲突。例如,我们不能将BETWE…...
从某种程度上来看,产业互联网是一次对于互联网的弥补和修正
如果对当下我们正在经历的这样一个时代进行一次定义的话,我更加愿意将其划归到产业互联网的范畴里。可能有人会说,这与产业互联网并无联系,因为从本质上来看,当下我们所经历的这样一个时代,其实是与互联网并没有太多联…...
【C#Unity题】1.委托和事件在使用上的区别是什么?2.C#中 == 和 Equals 的区别是什么?
1.委托和事件在使用上的区别是什么? 委托和事件是C#中的重要概念,通俗来讲,委托是一个可以指向特定方法的指针,可以将委托分配给不同的脚本,使它们能够完成不同的任务。而事件则是一种使用委托实现的通知机制ÿ…...
FFmpeg5.0源码阅读——内存池AVBufferPool
摘要:FFmpeg中大多数数据存储比如AVFrame,AVPacket都是通过AVBufferRef管理的,而承载数据的结构为AVBuffer。本文主要通过FFmpeg源码来分析下FFmpeg中AVBuffer相关的实现。 关键字:AVBuffer、AVBufferPool、AVBufferPool 1. AVBufferRef 1.…...
Python学习------起步7(字符串的连接、删除、修改、查询与统计、类型判断及字符串字母大小写转换)
目录 前言: 1.字符串的连接 join() 函数 2.字符串的删除&取代 replace()函数 3.字符串的修改&切割 (1)strip() 函数 (2)lstrip()函数 和 rstrip()函数 (3)split()函数-->…...
雪花算法snowflake
snowflake中文的意思是 雪花,雪片,所以翻译成雪花算法。它最早是twitter内部使用的分布式环境下的唯一ID生成算法。在2014年开源。雪花算法产生的背景当然是twitter高并发环境下对唯一ID生成的需求,得益于twitter内部高超的技术,雪…...
Part 4 描述性统计分析(占比 10%)——上
文章目录【后续会持续更新CDA Level I&II备考相关内容,敬请期待】【考试大纲】【考试内容】【备考资料】1、统计基本概念1.1、统计学的含义及应用1.1.1、统计学的含义1.2.1、统计学的应用1.2、统计学的基本概念1.2.1、数据及数据的分类1.2.2、总体和样本1.2.3、…...
Linux系统安全:安全技术和防火墙
目录 一、安全技术 1、安全技术 2、防火墙分类 二、防火墙 1、iptables五表五链 2、黑白名单 3、iptables基本语法 4、iptables选项 5、控制类型 6、隐藏扩展模块 7、显示扩展模块 8、iptables规则保存 9、自定义链使用 一、安全技术 1、安全技术 ①入侵检测系统…...
【干货】Python:turtle库的用法
【干货】Python:turtle库的用法1. turtle库概述2. turtle库与基本绘图2.1 导入库的三种方式2.1.12.1.22.1.32.2 窗体函数2.2 画笔状态函数2.2.1 seed(s)2.2.2 random()2.2.3 randint(a, b)2.2.4 getrandbits(k)2.2.5 randrange(start, stop[ , step])2.2.6 uniform(…...
开通网站必须做域名空间/seo培训中心
1.FastDFS介绍 FastDFS是用c语言编写的一款开源的分布式文件系统。FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载…...
做海南旅游网站的初衷/线下推广活动策划方案
1背景转眼已经过了33岁生日。作为一个大龄程序媛,昨天又收到了阿里技术直接打过来的面试电话,照例客气的回答不考虑机会之后,算算今年下来阿里技术直接打过来的面试至少也有十几次了。每次都问你是多久不考虑机会呢?我回答几年吧。…...
上海技术做网站/福州seo兼职
我的日食标志着每个带有惊叹号的新项目.我能够删除java 1.7并添加旧1.6但现在我收到此错误:java.lang.UnsupportedClassVersionError: klasse : Unsupported major.minor version 51.0at java.lang.ClassLoader.defineClass1(Native Method)at java.lang.ClassLoade…...
wordpress 仿站/企业营销网站制作
背景:在做项目时,经常会遇到这样的表结构在主表的中有一列保存的是用逗号隔开ID。如,当一个员工从属多个部门时、当一个项目从属多个城市时、当一个设备从属多个项目时,很多人都会在员工表中加入一个deptIds VARCHAR(1000)列(本文…...
wordpress代码安装畅言/汽车seo是什么意思
概要 分析如何使用微软提供的ASP.NET来对动态产生的URL地址进行网址重写。 网址重写是实现一种截取网址请求并将其进行处理后重新指向到一个指定的网址的过程。作者本人在对各种实现网址重写的技术进行研究和探讨后得出的经验和方法,希望能对您有所帮助。 内容简…...
wordpress构架都是模板/seo全国最好的公司
1、业务场景:在开发业务时,有一个对象数组,对象数组有一个字段是数字,我需要筛选出这个数组对应的数字字段的最大值,于是用到了如下代码: Math.max.apply(Math,mayArr.map((item:{score:number})> retu…...