SpringBoot
一、SpringBoot常用注解
1、@Configuration注解与 @Bean
(1)@configuration spring配置注解,贴有这个注解的类,表示该类为配置类
作用:把普通类变为配置类
功能等价于:// applicationContext.xml
(2)@Bean 是spring bean 实例标签,贴有该注解的方法,表示该方法为实例方法
作用:作用:把普通方法变成实例方法,创建对象,并把实例方法对象交由spring容器管理
功能等价于://<bean name="someBean" class="cn.wolfcode._02_ioc_config.SomeBean" ></bean>
举栗子:
@Configuration
public class AppConfig {
/**
* 1>someBean对象可以从容器中获取
* 2>otherBean可以从容器中获取
* 3>someBean对象通过getOtherBean()方法获得的bean应该==从容器获取的otherBean对象。
*
* 需要注意的是 在调用 otherBean()方法 的时候 不可以去new
* 还有就是不管调用了多少次的 otherBean()方法 在spring容器中都是执行一次 otherBean构建的
* 对象
* 原因: 因为 otherBean()方法 是由spring 容器管理的,每一次的调用都会到spring容器中
* 检查bean,如果发现容器中已经存在了,他就会直接的调用不会再去创建了,
* 没有他才会去执行方法,而且返回到容器中
*/
@Bean
public SomeBean someBean() {
SomeBean someBean = new SomeBean();
someBean.setOtherBean(otherBean());
return someBean;
}
@Bean
public OtherBean otherBean() {
return new OtherBean();
}
}
2、@Componentscan注解
@Componentscan
作用:扫描指定包路径下,所有贴有版型标签的类,创建对象并交给spring容器管理
默认的情况下:如果不指定包的路径,会扫描当前类所在包及其子类
(1)、在bean的扫描组件中常用的4个版型标签:
1)@Controller //标在控制层
2)@Service //标在服务层
3)@Repository //标在持久层
4)@Component //当不知使用上面的哪个注解时使用它标注
@Component //版型标签
public class SomeBean {
}
举栗子:
/**
* @ComponentScan spring组件扫描配置注解
* 作用:扫描指定包下,所有贴了版型标签的类,创建对象,并把对象返回给spring容器管理
*/
@Configuration
@ComponentScan(basePackages = "cn.wolfcode.demo05._03_scan")
public class AppConfig {
@Bean
public SomeBean someBean() {
return new SomeBean();
}
}
3、@Scope注解
@Scope: bean范围注解,指定创建的bean是单例的还是多例的
public class SomeBean {
public SomeBean() {
System.out.println("SomeBean创建······");
}
public void init() {
System.out.println("SomeBean初始化······");
}
public void destroy() {
System.out.println("SomeBean销毁······");
}
}
@Configuration
public class AppConfig {
/**
* @Scope spring 范围注解
* 作用:指定创建的bean 是单例还是多例
*/
@Scope("singleton") // singleton 单例模式
@Bean(value = "someBean", initMethod = "init", destroyMethod = "destroy")
public SomeBean someBean() {
return new SomeBean();
}
}
4、@Import 注解
@Import:spring配置类导入注解
作用:将某个配置类合并到另一个配置类中(配置类与配置类间的导入)
等价于:<import resource="xxx配置.xml"></import>标签
举栗子:
@Configuration
public class OtherConfig {
@Bean
public OtherBean otherBean() {
return new OtherBean();
}
}
/**
*@Import spring配置类导入注解
* 作用:将某一个配置类合并到另一个配置类中,就是两个配置类之间的互导
*/
@Configuration
@Import(OtherConfig.class)
public class AppConfig {
@Bean
public SomeBean someBean() {
return new SomeBean();
}
}
5、@ImportResource 注解
@ImportResource:spring配置文件导入注解,
作用:将某个配置文件,合并到配置类中(配置文件与配置类间导入)
等价于:<import resource="xxx配置.xml"></import>标签
/**
* @ImportResource spring配置文件导入注解
* 作用:将某一个配置文件导到一个配置类中,就是配置类与配置文件之间的导入
*/
@Configuration
@ImportResource("classpath:applicationContext.xml")
public class AppConfig {
@Bean
public SomeBean someBean() {
return new SomeBean();
}
}
6、@PropertySource 注解
@PropertySource:spring资源文件的导入注解,
作用:将资源文件导入到spring容器中
等价于: <context:property-placeholder location="classpath:xxx.perperties"/>
/**
* @PropertySource spring 资源文件导入注解
* 作用:将资源文件导入到spring容器中
*/
@Configuration
@PropertySource("classpath:db.properties")
public class AppConfig {
(方式一)
@Value("${jdbc.driverClassName}")
private String driverClassName;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public MyDataSource myDataSource() {
MyDataSource myDataSource = new MyDataSource();
myDataSource.setDriverClassName(driverClassName);
myDataSource.setUrl(url);
myDataSource.setUsername(username);
myDataSource.setPassword(password);
return myDataSource;
}
(方式二)
/*
@Autowired
private Environment env;
@Bean
public MyDataSource myDataSource() {
MyDataSource myDataSource = new MyDataSource();
myDataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
myDataSource.setUrl(env.getProperty("jdbc.url"));
myDataSource.setUsername(env.getProperty("jdbc.username"));
myDataSource.setPassword(env.getProperty("jdbc.password"));
return myDataSource;
} */
}
二、自动装配
1、pom.xml文件中继承的spring-boot-starter-paren的作用?
spring-boot-starter-paren 为springboot 提供了工具工程,这个工程是用来收集常见的第三方jar依赖,然后对它们统一的管理,当项目继承这个项目工程时,会自动的生成一个新的springboot项目,同时也继承了这些第三方的jar。在以后的使用中,引入需要的依赖坐标就行,不用去关联依赖的版本。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
//依赖管理标签: 对依赖统一管理,被管理的依赖,后续子项目只要导入 groupId 跟 artifactId ,不用去导入版本号
继承是 Maven 中很强大的一种功能,继承可以使得子POM可以获得 parent 中的部分配置(groupId,version,dependencies,build,dependencyManagement等),可以对子pom进行统一的配置和依赖管理。
parent项目中的dependencyManagement里的声明的依赖 , 只具有声明的作用,并不实现引入,子项目在引用时要进行依赖显示声明,不然无法从父类中继承想要的依赖。
parent项目中的dependencies里声明的依赖会被所有的子项目继承
2、pom.xml文件中导入的依赖spring-boot-starter-web的作用
对 spring-boot-starter-paren收集好的第三方jar 在特点、解决问题的场景上进行一个分类、整合、重新封装,弄成一个新的依赖工具,将这些依赖工具称为:启动器(组件),命名规则: spring-boot-starter-xxx。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3、启动类App头顶上的@SpringBootApplication注解做了什么
dependencyManagement 注解:依赖管理标签,对依赖进行同一管理,
用法:@SpringBootApplication注解一般放在项目的一个启动类上
作用:用来把启动类注入到容器中,用来定义容器扫描的范围,用来加载classpath环境中一些bean
例:
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
//一般贴有@SpringBootApplication注解的类称之为启动类,建议放置在根包下。
//一般springboot项目只有唯一一个启动类,启动类都是配置类。
4、自动装配原理
自动装配原理:
在SpringBootApplication类上有一个重要的注解@EnableAutoConfiguration。
它是实现自动装配的重要注解,当SpringBoot项目启动的时候,就会调用@EnableAutoConfiguration来进一步加载系统所需的一些配置信息,
完成自动装配。
@SpringBootApplication注解里3个核心关键注解
1. @SpringBootConfiguration
头上贴了@Configuration --说明了该类是配置类
2. @ComponentScan :扫描类贴了该注解中所在包及其子包所有贴了版型注解的类,创建对象交给spring容器管理
3. @EnableAutoConfiguration
通过选择器导入一堆的springboot 预先准备的配置类(这些配置是全限定类类名), 然后根据导入的依赖激活相应的配置类,创建对象,交由spring 容器管理
5、springboot项目打包部署
springboot 是默认打jar包,打包后的jar可以独立的运行,添加相应的插件即可,点击maven 展开Lifecycle文件,找到package双击它运行,就可以生成jar包
<!-- pom.xml中添加插件 -->
<build>
<plugins>
<!-- SpringBoot打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
三、SpringBoot优缺点
优点:
- 创建独立运行的Spring应用程序
- 内嵌Tomcat,生成的是jar包
- 简化Maven配置
- 自动配置Spring
- 提供生产就绪型功能,如:日志,健康检查和外部配置等
- 不要求配置 XML
缺点:
版本更新较快,可能出现较大变化
四、SpringBoot参数配置
它的文件配置有两种:一种是application.properties;另一种是application.yml。
1、application.properties
//application.properties语法
server.port=80
server.session-timeout=30
server.tomcat.uri-encoding=UTF-8
spring.datasource.url = jdbc:mysql://localhost:3306/crm
spring.datasource.username = root
spring.datasource.password = mymysql
spring.datasource.driverClassName = com.mysql.jdbc.Driver
2、application.yml
//application.yml语法
server:
port: 80
session-timeout: 30
tomcat.uri-encoding: UTF-8
spring:
datasource:
url : jdbc:mysql://localhost:3306/crm
username : root
password : mymysql
driverClassName : com.mysql.jdbc.Driver
当一个项目中存在多个application.properties文件存放在不同目录中,这个时候就出现优先级了,主要是用来解决属性配置冲的一个问题,执行的顺序是由高到低,优先级高的会把优先级低的覆盖掉,如下:
1. 项目/config/application.properties
2. 项目/application.properties
3. classpath:config/application.properties
4. classpath:application.properties
一般都在 classpath:application.properties 做配置,其他方式不使用
3、参数属性绑定
在参数属性绑定中可以用**@value** 来绑定单个属性,同时也可通过 @ConfigurationProperties批量绑定属性 来批量的绑定属性,各自的操作如下:
/* 使用 @value 来绑定单个属性*/
@Component
@Getter
@Setter
@ToString
public class MyData {
// @Value 绑定单个属性
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
}
/**
* @ConfigurationProperties("jdbc") 绑定 @value 可以批量的生成,不用一个一个的去弄
* 它是根据前缀 ("jdbc") 进行识别的, 还可以多级(例如:@ConfigurationProperties("jdbc.sss") )
批量生成获取,要说明前缀是什么,springboot 通过前缀来加载所有的属性配置,然后使用同名匹配原则,设置bean属性中
有两个方案:
方案一:在bean实例方法头上贴
方案二:在实体对象上贴
*/
/* @ConfigurationProperties 批量绑定属性 */
@Component
@Getter
@Setter
@ToString
//@ConfigurationProperties("jdbc")
public class MyData {
private String username;
private String password;
}
五、SpringBoot应用
1、SpringBoot 的 整合
数据库连接池:和之前的操作一样要添加一个SQL 驱动依赖,如果没有导其他的数据源依赖的话,就是使用默认的连接池–Hikari,这个可以不用去添加依赖也能使用。在application.properties 配置文件 四要素,如下:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql:///springboot?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=admin
如果项目中不想用这个,而是用 Druid 来作为连接池也可以,加入相应的依赖就行,DruidDataSourceAutoConfigure自动配置类,会自动创建druid的连接池对象, 所以springboot发现已经有连接池对象了,则不会再使用 Hikari,Druid 依赖如下:
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.5</version>
</dependency>
2、集成MyBatis
在数据库中建好一张员工表,然在springboot项目中添加相关的依赖;逆向工程生成mapper与实体类,在配置文件application.properties 配好 四要素 ,然后就可以在业务层(service)写相应的业务,下一步写控制层(controller),最后写一个启动类来启动springboot项目,相应依赖和启动类如下:
<!--mybatis集成到SpringBoot中的依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
//启动类
@SpringBootApplication
@MapperScan("cn.wolfcode.sb.mapper")
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
//mybatis中的mapper 接口扫描器,指定参数为:mapper所在是的路径
//作用:将路径下所有的接口动态代理,创建mapper接口实现类交给spring容器管理
/*
@MapperScan注解:
作用:指定要变成实现类的接口所在的包,包下面的所有接口在编译之后都会生成相应的实现类
用法:是在Springboot启动类上面添加,
@ComponentScan注解:
作用:扫描指定包下,所有贴了版型标签的类,创建对象,并把对象返回给spring容器管理
用法:贴在配置类上
@ComponentScan注解 与 @MapperScan注解 区别?
@ComponentScan是组件扫描注解,用来扫描@Controller、@Service、
@Repository、@Component 这类版型标签, 主要就是定义扫描的路径从中找出标志了需要装配的类到Spring容器中
@MapperScan 是扫描mapper类的注解,就不用在每个mapper类上加@MapperScan
*/
事务管理
添加一个事物管理的依赖,把注解 @Transactional 贴在业务层的实现类或者其他的方法上,就可以生效
<!-- 支持使用 Spring AOP 和 AspectJ 进行切面编程。 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
3、WEB集成
在soringboot中 static文件是放在resource 资源文件下,同时templates 文件也是resource 资源文件下,那些模板文件再放到templates文件中,不用再建一个webapp文件;
1、默认情况下,Springboot加载静态资源会从classpath下的 /static , /public , /resources , /META-INF/resources下加载
2、修改静态资源加载地址时 可以 在application.properties中配置spring.resources.staticLocations属性来修改
SpringBoot多数用于前后端分离和微服务开发,默认支持RESTFul规范,所以一般都是使用默认匹配 / ,不做改动
#在匹配模式时是否使用后缀模式匹配
spring.mvc.pathmatch.use-suffix-pattern=true
4、集成FreeMarker
整合freeMaker注意问题点:配置时 .ftl 少一个点、依赖没加、templates少了s都会报404错误
使用freeMaker是要添加对应的依赖,
<!-- SpringBoot集成FreeMarker的依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
freeMaker常见的属性配置:
#一般我们会做3个配置,其余默认即可
#暴露session对象的属性
spring.freemarker.expose-session-attributes=true
#配置为传统模式,空值自动处理
spring.freemarker.settings.classic_compatible=true
#重新指定模板文件后缀 springboot 2.2.x 后 默认后缀为 .ftlh
spring.freemarker.suffix=.ftl
5、统一异常处理
SpringBoot默认情况下,会把所有错误都交给BasicErrorController类完成处理,只要把对应的模板文件放到对应路径上 classpath:/static/error/ 和 classpath:/templates/error/,会根据路径找到视图展示出来;
例如:出现404错误 -> classpath:/static/error/404.html 或者 出现5xx类错误 -> classpath:/static/error/5xx.html
@ControllerAdvice 控制器增强 ,自己定义一个类贴在一个类上,用于统一异常处理,一般是处理5xx这一类错误信息;@ControllerAdvice 用于异常处理只是其中不过一个作用;
和 @ControllerAdvice 注解配合使用的其他注解有:
@ExceptionHandler // 自定义的错误处理器
@ModelAttribute // 全局的对所有的controller的Model添加属性
@InitBinder //对表单数据绑定
例如:
@ControllerAdvice //控制器增强器 @ControllerAdvice
public class ExceptionControllerAdvice {
@ExceptionHandler(RuntimeException.class) //处理什么类型的异常 @ExceptionHandler
public String handlException(RuntimeException e, Model model) {
return "errorView"; //错误页面视图名称
}
}
6、添加拦截器
新建一个包,写一个拦截类 CheckLoginInterceptor,然后实现 HandlerInterceptor 接口, 重写 preHandle 这个方法,在这个方法中写拦截逻辑 ;在启动类要实现 webMvcConfigurer 接口, 在启动类创建拦截器 实例对象 、然后重写addInterceptors方法,把需要放行路径写好
public class CheckLoginIntercept implements HandlerInterceptor {
@Autowired
private IUserInfoRedisService userInfoRedisService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (user == null) {
//提示用户没有登陆
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(JSON.toJSONString(JsonResult.noLogin()));
return false;
}
}
return true;
}
}
//需要拦截的资源
@Bean
public CheckLoginInterceptor checkLoginInterceptor() {
return new CheckLoginInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(checkLoginInterceptor())
.addPathPatterns("/**") // 对哪些资源起过滤作用
.excludePathPatterns("/js/**") // 对哪些资源起排除作用
.excludePathPatterns("/css/**")
// .excludePathPatterns("/static/**") //springboot 中 不用static 错误写法
.excludePathPatterns("/images/**");
}
综合案例
springboot 的一个 员工crud
1、新建一个springboot项目
2、在pom.xml 中添加要用到的依赖
3、在resource 根目录下添加 application.properties ,把一些需要配置的写在里边,如:配置数据库四要素、SQL打印日志、freemaker相关等
4、写一个启动类,用于启动项目,(记得贴注解)@SpringBootApplication
@MapperScan(basePackages = "cn.wolfcode.xxx.mapper")
5、把static静态资源目录和 templates模板目录 建好,用于导入静态文件与模板文件,也是在resource 根目录下
6、在数据库建好员工表
7、在resource 根目录下 添加generatorConfig.xml 用于 生成数据模板
8、用逆向工程生成员工的数据模型
9、剩下的一些常规操作跟以前一样,如:service(服务层)、controller(控制层)
系统日志
日志级别,:trace < debug < info < warn < error
默认使用的级别是info,可以自定义,例如:定义了debug ,那么 info 、warn 、error 的信息都可以打印出来,因为 debug 级别比他们低
使用时可以直接用注解 @Slf4j 贴在需要的类上也可以下面这个方式
private static final Logger log = LoggerFactory.getLogger(当前类.class);
日志:重要的信息用info级别,异常信息用error级别,其他不重要的用其他级别,找bug可以用debug级别