什么是springboot
springboot是简化spring应用开发,是J2EE一站式解决方案,降低了对配置文件的要求。整合了整个spring的应用技术栈。
什么是微服务
微服务是一种架构风格,是由一组小型服务组成,每一个小型服务都运行在自己的进程上,通过http方式进行沟通,微服务是把应用中的每一个功能元素都独立出来,通过动态组合的方式进行使用,每一个功能元素最终都是一个可独立替换和独立升级的软件单元。区别于传统单体应用,所有的功能单元都写着一个应用里面,打包成一个war。
@SpirngBootApplication注解
(默认扫描同包,或者子包下的类,不然可能会404)
是一个组合注解主键,由以下组成
1.@springbootconfiguration:标注在某个类上,表示这个类是配置类,并注入容器中,底层由@configuration实现。
2.@EnableAutoConfiguration:开启自动配置功能,把以前需要配置的东西交给springboot自动配置,告诉springboot开启自动配置功能。底层由@AutoconfigurationPackage实现,作用是给容器中导入一个组件,底层由@impor来导入这个组件,(真正作用)这个主键可以将@SpirngBootApplication所在的包和子包里面的组件加载到spring容器中,实现自动配置。
3.@import:给容器中导入组件选择器,将需要的组件以全类名的方式返回,返回的组件就回到容器中(真正作用)会给容器中导入场景(小型服务)所需要的所有组件(类),并配置好这些组件。
4.自动配置功能组件的原理:
springboot在启动的时候会通过EnableAutoconfiguration.class的selectimports方法从META-INF/spring.factories中获取properties文件中的全路径类名,将这些类名主动导入容器中,自动配置类就生效了。
package com.zxh.test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/*
* @SpirngBootApplication
* 作用:用来标注一个主程序类,说明这这是一个springboot应用
*
* */
@SpringBootApplication
public class springbootTest {`在这里插入代码片`
public static void main(String[] args) {
//让spring应用启动起来
SpringApplication.run(springbootTest.class,args);
}
}
springboot的简化部署
1.导入插件
<build>
<!--这个配置,可以将应用打包成一个可执行的jar包-->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.打包成jar架包
3.复制到桌面,拿到jar架包的位置
5.启动cmd,输入位置
6.使用 java -jar springbootfirst.jar命令部署架包
springboot运行探索
spring-boot-starter是spring-boot场景启动器,
springboot将所有功能都抽取出来,做成一个个的staters(小型服务),只需要在项目中引入需要的场景,就能够帮我们导入相关的依赖
一.pom.xml
1.spring-boot-starter-parent父项目
依赖于spring-boot-dependencies父项目,作用是用来管理springboot应用里面的所有依赖版本。
2.spring-boot-starter-web依赖
spring-boot-starter-web帮我们导入了web模块正常运行所依赖的项目。
二.主程序类
1.@SpirngBootApplication:作用是用于说明springboot的主配置类,需要自动配置的包和自动配置的组件(场景或者小型服务)。spring boot会运行这个主配置类的main方法来启动springboot运用
springboot的配置文件
springboot使用一个全局配置文件,采用application.properties或者application.yml,配置文件名称是固定的。
yml介绍
作用:修改springboot自动配置的默认值
yml是什么:是一种标记语言,跟xml文件一样都是标记语言,但是yml是以数据为中心
yml语法格式:
不用大量的解析标签,关注内容数据。
如修改服务器端口号
server:
port:8081
而传统的xml语法格式是:
把大量的处理浪费在了解析标签上
<server>
<port>8081</port>
</server>
yml语法格式:
yml语法:
1.基本语法
k:(空格)v:表示一对键值对(空格必须有)
以空格的缩进来控制层级关系,只要是左对齐的一列标签,都是同一层级的,属性和值都是大小写敏感的
server:
port: 8081
path: /hello
2.值的写法
基本类型和string类型
写法 K: V(字符串默认不用加上引号)
加双引号会转义字符串里面的特殊字符
加单引号不会转义特殊字符,直接输出。
int: 100
String: zxh111
JavaBean对象,map,(键值对):
写法一:K: v
User:
name: zxh
passwod: 111
price: 666
写法二:行内写法
User: {name: zxh,password: 111,price: 666}
List,Set:
写法一:- (空格)值表示数组中的一个元素
price:
- 777
- 888
- 999
- 1000
写法二:行类写法
price:{777,888,999,1000}
properties文件的使用格式
采用key=value的形式
//javabean对象写法
user.password=zxh //基本类型写法
user.books.math=111 //map类型写法
user.books.music=muisc
user.days=1,2,3,4 //list集合类型写法
***@ConfigurationProperties:***默认从全局配置文件中获取值(application.yml)
告诉springboot,将yml配置或者properties配置映射到pojo的bean对象属性中,写在bean实体类上面,前提是这个bean在spring的容器中(使用@Commnent注解)。
属性:prefix=“ ”指定配置文件中的属性对象。
对比:
他的功能比@Value注解要强大一些,他可以从配置文件中注入Javabean类型,集合类型,map类型到实体类中,@Value只能注入基本类型和字符串,但支持spEL表达式。
@PropertySource 作用:加载指定的配置文件,一般写在配置类上
属性:value={“classpath:xxxx.properties”,"",…}
@ImportResource作用:加载指定的spring配置文件,一般写在配置类上(不用)
属性:location={“classpath:xxxx.xml”,"",…}
springboot推荐使用配置类的方式给与容器添加组件
1.声明配置spring的配置类
2.使用@Bean给容器添加注解
package com.zxh.springbootinit.config;
import com.zxh.springbootinit.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*
* @Configuration:作用是声明这是一个配置类,用于替代spring配置文件
*
*
* */
@Configuration
public class Springcofig {
/*
* @Bean:将方法的返回值添加到容器中,默认id是方法名
* */
@Bean
public User returnUser(){
return new User();
}
}
配置文件占位符:
1.随机数占位符int,uuid,long,value…
2.获取之前配置的值,如果没有就把配置的占位符当作字符串返回
使用方法
${}
user.password=zxh
user.books.math=111
user.books.music=${user.password}muisc
user.days=1,2,3,${random.int}
Profile
作用:给不同的开发环境(测试,开发,运行,发布等)提供功能的支持
1.多Profile文件方式
配置文件名称编写格式:application-{profile}.properties/yml默认使用application.properties/yml
激活方式:在对应的application-{profile}.properties/yml配置文件中指定:springprofiles.active=dev ,就可激活
springprofiles.active=dev
2.yml支持多文档块方式
server:
port: 8081
spring:
profiles:
active: dev
---
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8083
profiles: prod
激活对应的代码块方式:
spring:
profiles:
active: dev
怎么查看自动配置源码中组件是否被配置和配置的组件有哪些?
1.@Conditional
用途:用于判断容器中有没有这个类的组件,有的话返回true,没有就返回false,来决定@Conditional后的代码是否执行。
打开autoconfigure中的spring.factories文件,点击相应的全路径类名查看
@Conditional中的配置是否存在。
2.可以通过在application.properties中启用debug=true属性,让控制台打印那些自动配置组件生效
debug=true
生效配置
Positive matches:
-----------------
AopAutoConfiguration matched:
- @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)
.......
.........
.........
springboot与日志
1.传统方式,通过System.out.println(“”):将关键数据打印在控制台,当需要修改和维护时十分不方便
2.用框架来记录系统的一些运行时的信息:日志框架
市面上的日志框架:
JUL,JCL,Jboss-logging,logback,log4j,log4j2,slf4j
对应关系:
日志接口层 | 日志实现 |
---|---|
JCL ,slf4j,jboss-logiing | log4j,jul,log4j2,logback |
用法:在左边选择一个接口,在右边选择一个实现。
日志门面-----选择slf4j,日志实现选择----logback
springboot默认选择的日志框架:slf4j+logback
斜体样式
slf4j的使用:
使用原理:调用slf4j接口,实际上真正实现日志记录的是实现类logback。(就像去奶茶店买奶
茶,你购买时,看着菜单购买之后,就可以拿到奶茶,但实际生产奶茶的是机器。)
调用日志记录方法时要调用的是接口层—slf4j,不应该调用实现类logback
1.给系统中导入slf4j和logback的jar包
2.slf4j配置文件使用日志实现类的配置文件,因为实质上是实现类实现了日志记录。
3.日志接口方法调用
存在的问题:
当一个系统使用不同的框架开发时,框架本身会有不同的日志记录,需要把日志记录进行统一,都统一使用slf4j和logback。
解决的方法:
1.将系统中其他日志框架先排除出去
2.用中间包来替换原有的日志框架
3.然后把中间包都面向slf4j进行统一管理
4.slf4j通过调用logback来具体实现日志记录
Springboot能够自动适配所有的日志,底层采用slf4j+logback的日志记录方式,我们需要使用其他框架时,只需要移除该框架的日志框架即可,剩下的适配会由springboot完成。
springboot日志记录的使用
package com.zxh.logg;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
class LoggApplicationTests {
//生成记录器
Logger logger= LoggerFactory.getLogger(getClass());
@Test
void contextLoads(){
//日志的级别
//由低到高 trace<debug<info<warn<error
//级别用途是:用过调整日志级别,不打印低级别的日志,只打印高级别及更高级别的日志
logger.trace("这是运行信息");//用于跟踪信息,跟Sout作用一样
logger.debug("这是调试信息");
//springboot默认给我们使用的是info级别的
logger.info("info信息,自己定义的一些信息");
logger.warn("这是警告信息");
logger.error("这是错误信息");//记录异常信息
}
}
sprigboot日志的基本调整
在application中修改
#日志级别调整
#logging.level关键字 + 需要调整级别的包如 com.zxh = 调整的级别(trace,debug,info.....)
logging.level.com.zxh=trace
#logging.file和logging.path默认会输出在控制台,如果指定了文件名就会输出到指定的文件里
#会在当前项目在生成这个文件
#logging.file=springboot.log
#会在当前项目根目录的磁盘下生成这个文件
#logging.path=/spring/springboot.log
# 指定在控制台输出的日志格式
logging.pattern.console=%d{yyyy-MM-dd}[%thread] %-5level %logger{50} -%msg%n
# 指定文件中日志输出的格式
#logging.pattern.file=%d{yyyy-MM-dd}===[%thread] === %-5level %logger{50} ===%msg%n
静态资源存放地址和thymeleaf
1.springboot的静态资源存放地址有4个
calsspath:/META-INF/resource/
calsspath:/resource/
calsspath:/static/
calsspath:/public/
/ 指当前项目根目录
可以用于存放js,css,图片,页面等文件
首页的存放地,只要是静态资源文件夹且名为index.html的页面即可
图片的存放地址,只要是在静态资源文件夹下即可
还可以自定义静态资源文件夹
spring.resources.static-locations=classpath:/file/,classpath:/boot/
2.由于springboot不支持jsp,所以我们需要模板引擎
模板引擎的作用:负责把数据 ,填充到,模板页面表达式中。
可以使用jsp,Velocity,Freemarker,Thymeleaf,springmvc推荐我们使用Thymeleaf
Thymeleaf的使用:
1.引入Thymeleaf依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2.thymeleaf的存放地址
只需要把html页面放在classpath:/templates/ 中,thymeleaf就可以帮我启用模板引擎的作用
原因如下:
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
标签的使用:
如:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--th:text作用 可以替换原本文本内容的值
th:id作用 可以替换原来id的值
th:class作用 可以替换原来class的值-->
<div id="success" class="success" th:id="${test}" th:class="${test}" th:text="${test}">成功页面</div>
</body>
</html>
表达式的使用:
lombok应用
lomoke作用:应用lomoke的注解简化pojo类,提供了@Data,@Getter等这些注解简化实体
类中get/set方法等方法的编写
1.在IDEA中安装lombok插件
2.添加lombok依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
3.在POJO上使用lombok注解
package com.zxh.springbootlombok.pojo;
import lombok.Data;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import java.io.Serializable;
/*
* @Data :在编译阶段会根据注解生成自动的方法
* 包含,get/set,hashcode,equals,toString。
* @Getter:
* @Setter:
* 可以写在类名上,也可以写在属性上,自动提供get/set方法
* @Slf4j:提供一个log的属性,进行日志记录
* * */
@Data
public class Account implements Serializable {
private int id;
private String name;
private int price;
/*
传统方式
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", price=" + price +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}*/
}
springboot整合springmvc拦截器
1.编写拦截器(实现handlerinterceptor接口)
package com.zxh.springbootlombok.comfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class interceptor implements HandlerInterceptor {
@Override
//预处理方法,返回false表示后面被拦截的方法不执行。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("前置拦截器");
return true;
}
@Override
//后处理方法,在controller请求执行后,return之前执行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
log.info("后置拦截器");
}
@Override
//完成时方法,再整个请求流程完成后执行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
log.info("完成拦截器");
}
}
2.编写配置类实现WebMvcConfigurer接口,然后声明为配置类@Configuration
package com.zxh.springbootlombok.comfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class Configinterceptor implements WebMvcConfigurer {
//注册拦截器
@Bean
public interceptor interceptor(){
return new interceptor();
}
//添加拦截器到 spring mvc拦截器链
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor()).addPathPatterns("/test");
}
}
package com.zxh.springbootlombok.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class testcontroller {
@RequestMapping(path = "/test")
public String Test(){
System.out.println("Test方法");
return "success";
}
}
springboot整合事务和连接池
1.添加事务和mysql的相关依赖
</dependency>
<!--jdbc依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
2.编写业务类AccountService,使用事务注解@Transactional
package com.zxh.springbootlombok.service;
import com.zxh.springbootlombok.pojo.Account;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AccountService {
//根据id查询
public Account byid(int id){
return new Account();
}
//创建
@Transactional
public void insert(Account account){
System.out.println("创建");
}
}
数据库连接池hikari配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/spring
username: root
password: root
springboot整合事务mybatis
1.添加springboot整合mybatis依赖
<!--springboot整合mybatis依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.2</version>
</dependency>
2.配置mybatis
mybatis:
#对实体类起别名
type-aliases-package: com.zxh.pojo
#配置日志实现类
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.配置mapperScan,需要在启动引导器类中配置。
package com.zxh;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
//扫描mybatis所有的业务mapper接口
@MapperScan(value = "com.zxh.mapper")
public class SpringbootlombokApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootlombokApplication.class, args);
}
}
springboot整合通用mapper
通用mapper:可以实现自动拼接sql语句
1.添加依赖
<!--通用mapper依赖-->
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
<version>2.1.5</version>
</dependency>
2.改造AccountMapper继承mapper中的接口
package com.zxh.springbootlombok.mapper;
import com.zxh.springbootlombok.pojo.Account;
import tk.mybatis.mapper.common.Mapper;
public interface AccountMapper extends Mapper<Account> {
}
3.修改启动引导类中的mapper扫描注解:
作用就是将mapper包中的类注入到spring容器中
package com.zxh;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import tk.mybatis.spring.annotation.MapperScan;
@SpringBootApplication
//扫描mybatis所有的业务mapper接口
//@MapperScan(value = "com.zxh.mapper")
//注意这是引入的:import tk.mybatis.spring.annotation.MapperScan;
@MapperScan(value = "com.zxh.mapper")
public class SpringbootlombokApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootlombokApplication.class, args);
}
}
4.修改Account实体类添加 jpa注解
@Data
//对应的数据库中的表名
@Table(name = "account")
public class Account implements Serializable {
//声明这是一个主键
@Id
//必须使用包装类,不然无法识别这个属性。
private Integer id;
/*
* 将数据库中的字段名和实体类的名称映射起来
@Column(name="数据库字段名")
*
* */
private String name;
private Integer price;
/*
}
5.改造AccountSerivce实现具体业务功能
package com.zxh.springbootlombok.service;
import com.zxh.springbootlombok.pojo.Account;
import com.zxh.springbootlombok.mapper.AccountMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AccountService {
@Autowired
private AccountMapper accountMapper;
//根据id查询
public Account byid(int id){
return accountMapper.selectByPrimaryKey(id);
}
//创建
@Transactional
public void insert(Account account){
System.out.println("创建");
accountMapper.insertSelective(account);
}
}
springboot整合redis
1.添加redis依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2.可以在application.yml中修改redis的参数
redis:
host: localhost
port: 6379
3.编写测试类应用redisTemplate操作redis的5种数据类型(string/hash/list/set/sorted set)
package com.zxh.redis;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import java.util.Set;
@RunWith(SpringRunner.class)
@SpringBootTest
public class redistest {
Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private RedisTemplate redisTemplate;
@Test
public void test(){
//string
redisTemplate.opsForValue().set("str","zhzxhzxhzxh");//给redis种存入一个str字符串
logger.info((String) redisTemplate.opsForValue().get("str"));//输出redis中的字符串
//hash
redisTemplate.opsForHash().putIfAbsent("hash","name","hashname");//给hash中存入数据
redisTemplate.opsForHash().putIfAbsent("hash","age","12");
redisTemplate.opsForHash().putIfAbsent("hash","gender","man");
Set set = redisTemplate.opsForHash().keys("hash");
List values = redisTemplate.opsForHash().values("hash");
logger.info(String.valueOf(set));//输出hash中的值
logger.info(String.valueOf(values));
//list 列表
redisTemplate.opsForList().set("list",1,"zz");
redisTemplate.opsForList().set("list",2,"xx");
redisTemplate.opsForList().set("list",3,"hh");
List list= redisTemplate.opsForList().range("list",0,-1);
logger.info(String.valueOf(list));
//set 集合
redisTemplate.opsForSet().add("set","a","b","c");
Set set1 = redisTemplate.opsForSet().members("set");
logger.info(String.valueOf(set1));
//sorted set 有序集合
redisTemplate.opsForZSet().add("zset","a",10);
redisTemplate.opsForZSet().add("zset","b",20);
redisTemplate.opsForZSet().add("zset","c",30);
Set set2 = redisTemplate.opsForZSet().range("zset",0,-1);
logger.info(String.valueOf(set2));
}
}