SpringBoot 是一个快速开发的框架, 封装了Maven常用依赖、能够快速的整合第三方框架;简化XML配置,全部采用注解形式,内置Tomcat、Jetty、Undertow,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringBoot原理介绍:
1. 能够帮助开发者实现快速整合第三方框架 (原理:Maven依赖封装)
2. 去除xml配置 完全采用注解化 (原理:Spring体系中内置注解方式)
3. 无需外部Tomcat、内部实现服务器(原理:Java语言支持创建Tomcat服务器)
SpringBoot 是一个快速开发的框架,能够快速的整合第三方框架,简化XML配置,全部采用注解形式,内置Tomcat容器,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringMVC是控制层。
SpringBoot 是一个快速开发的框架,能够快速的整合第三方框架,简化XML配置,全部采用注解形式,内置Tomcat容器,帮助开发者能够实现快速开发,SpringBoot的Web组件 默认集成的是SpringMVC框架。
SpringCloud依赖与SpringBoot组件,使用SpringMVC编写Http协议接口,同时SpringCloud是一套完整的微服务解决框架。
编写一个http接口,实现访问/hello,在页面上输出hello SpringBoot字符串?
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-parentartifactId>
<version>2.3.8.RELEASEversion>
parent>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
1.spring-boot-starter-parent作用
在pom.xml中引入spring-boot-start-parent,spring官方的解释叫什么stater poms,它可以提供dependency management,也就是说依赖管理。
2.spring-boot-starter-web作用
springweb 核心组件
/**
* 项目的启动类
*/
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class,args);
}
}
@Controller
public class DemoController {
@RequestMapping("/hello")
@ResponseBody
public String hello(){
return "Hello SpringBoot!";
}
}
2.9.1 在pom.xml文件中添加打包插件
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
2.9.2 在命令行窗口执行mvn package
2.9.3 进入jar所在的目录–>cmd -->java -jar xxxx.jar
/**
* @SpringBootApplication 表示他是一个SpringBoot程序
*/
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
//表示运行一个被@SpringBootApplication注解标注的Spring程序
SpringApplication.run(DemoApplication.class, args);
}
}
@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}
)}
)
public @interface SpringBootApplication {
@SpringBootConfiguration :SpringBoot配置
@Configuration 使用这个注解标注的类是一个配置类 作用相当于我们之前学习的xxxx.xml
@EnableAutoConfiguration :启动SpringBoot自动配置
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
1. @AutoConfigurationPackage:自动配置包
@Target({
ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({
Registrar.class})
public @interface AutoConfigurationPackage {
String[] basePackages() default {
};
Class<?>[] basePackageClasses() default {
};
}
@Import({Register.class})
//注册bean的定义信息 到spring的IOC容器
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));
}
选中(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames() -->右键 -->Evaluate Expression 得出的结果为 项目启动类所在的包 ,也就是说和启动类在同一个包以及子包下定义的类会被注册到Spring的IOC容器中,也就解释了我们没有配置扫描某个包,却能注册bean到SpringIOC容器中
结论:我们创建的包必须是和启动类在同一个包或者子包内
2. @Import({AutoConfigurationImportSelector.class}) 导入自动配置导入选择器
在这个AutoConfigurationImportSelector中有一个方法
```java
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return NO_IMPORTS;
} else {
AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
在这个方法中调用了getAutoConfigurationEntry(annotationMetadata)
```java
protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!this.isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
} else {
AnnotationAttributes attributes = this.getAttributes(annotationMetadata);
List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
configurations = this.removeDuplicates(configurations);
Set exclusions = this.getExclusions(annotationMetadata, attributes);
this.checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = this.getConfigurationClassFilter().filter(configurations);
this.fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);
}
}
调试List configurations 或者的结果是127个xxxAutoConfiguration自动配置类,这些配置类在META-INF/spring.factories定义的
#### 3.2、SpringBoot配置文件
1. springboot的配置文件有2种:
yaml application.yml
properties application.properties
文件的名称必须叫以上2种,不能叫其他的
2. 配置文件优先级
properties的优先级高于yml
3. yaml的语法
1. yaml的基本语法:
使用缩进表示层级关系,缩进时不允许使用Tab键,只允许使用空格(例如:k:(空格) v),缩进的空格数目不重要,但是相同层级的元素左对齐即可,大小写敏感
2. YAML 支持的三种数据结构
- 字面量:单个的、不可再分的值
使用k: v 直接写
字符串类型的v默认不用双引号或者单引号;
“”:双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思
eg: name: "zhangsan \n lisi" 输出:zhangsan 换行 lisi
‘’:单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据
eg: name: "zhangsan \n lisi" 输出:zhangsan \n lisi
- 对象:键值对的集合
k: v 在下一行来写对象的属性和值的关系;注意缩进
1.还是k: v的方式
eg:
friends:
lastName: zhangsan
age: age
2.行内写法:
eg:
friends: {lastName: zhangsan,age: 18}
- 数组
一组按次序排列的值
1.用-值表示数组中的一个元素
eg:
pets:
-cat
-dog
-pig
2.行内写法:
pets: “cat,dog,pig”
4. properties的编码配置
![](\img\properties.jpg)
#### 3.3、SpringBoot配置文件中属性的读取
在需要读取yml文件中属性值的类添加2个注解@ConfigurationProperties(prefix="前缀")、@Configuration/@Component
```java
/**
* @author lrg on 2021/7/23
* @since 1.0.0
* @ConfigurationProperties(prefix = "user") 读取配置文件中前缀为user的数据,
* 然后就可以按照属性名称设置属性值,但是使用这个注解标注的类必须是一个组件或者是能扫描到这个类,
* 或者是一个配置类,也就是在类上添加一个@Configuration注解
*/
@Data
@Component
@ConfigurationProperties(prefix = "person")
@ToString
public class User {
private String name;
private String email;
private String address;
添加依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
在测试类上添加注解
@RunWith(SpringRunner.class)
@SpringBootTest
@RunWith(SpringRunner.class)
@SpringBootTest
class Springboot02ApplicationTests {
@Autowired
private User user;
@Test
void contextLoads() {
System.out.println(user.toString());
}
}
@propertysource 用于引入指定的属性文件
案例:
1. 在resources下创建一个user.properties属性文件
在属性文件中添加如下内容
person.name=zhangsan
[email protected]
person.address=北京市
person.dog.name=旺财
person.dog.strain=中华田园犬
person.aihao=[kanshu,xiezi,qiaodaima]
创建实体类User.java,如下:
@Data
@ToString
@Component
@PropertySource("classpath:user.properties") //导入属性文件
@ConfigurationProperties(prefix = "person")
public class User {
private String name;
private String email;
private String address;
private Dog dog;
private List<String> aihao;
}
@ImportResource 导入Spring的配置文件
@Bean 配置Spring IOC中的Bean
案例:
@Configuration
public class DruidConfiguration {
/*
* 类似于在Spring的配置文件中做了如下配置
*
*
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource(){
return new DruidDataSource();
}
步骤:
找到自己喜欢的banner
地址:https://www.bootschool.net/ascii
下载banner.txt
默认方式是将banner.txt放在resources下
不是默认方式就需要在SpringBoot的配置文件中去进行配置
例如:我将banner.txt文件放在resources/banner.txt,就需要在SpringBoot的配置文件中去做如下的配置
#设置banner
spring:
banner:
location: banner/banner.txt
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境
application-dev.properties、application-prod.properties
多profile文档模式:在主配置文件中指定多个环境
例如:
spring:
profiles:
active: test #指定使用的时哪一个环境
---
#开发环境dev
spring:
profiles: dev
server:
port: 8082
---
#测试环境
spring:
profiles: test
server:
port: 8083
激活方式:
-配置文件 spring.profiles.active=dev
-命令行 --spring.profiles.active=dev
-jvm参数 -Dspring.profiles.active=dev
注意:第二种一般时项目已经写好并且已经打包好,在运行jar文件的时候去指定使用哪一个配置文件如:
java -jar springboot-02-0.0.1-SNAPSHOT.jar --spring.profiles.active=test
spring boot启动会扫描以下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件
-file:./config/
-file:./
-classpath:/config/
-classpath:/
以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。 互补配置
我们也可以通过配置spring.config.location来改变默认配置。
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar xxx.jar -Dspring.config.location=E:/application.yml
在我们开发Web应用的时候,需要引用大量的js、css、图片等静态资源。
默认配置
Spring Boot默认提供静态资源目录位置需置于classpath下,目录名需符合如下规则:
/static
/public
/resources
/META-INF/resources
举例:我们可以在src/main/resources/目录下创建static,在该位置放置一个图片文件。启动程序后,尝试访问http://localhost:8080/D.jpg。如能显示图片,配置成功。
通过@RestController来处理请求,所以返回的内容为json对象。那么如果需要渲染html页面的时候,要如何实现呢?
模板引擎
在动态HTML实现上Spring Boot依然可以完美胜任,并且提供了多种模板引擎的默认配置支持,所以在推荐的模板引擎下,我们可以很快的上手开发动态网站。
Spring Boot提供了默认配置的模板引擎主要有以下几种:
Thymeleaf
FreeMarker
Velocity
Groovy
Mustache
Spring Boot建议使用这些模板引擎,避免使用JSP,若一定要使用JSP将无法实现Spring Boot的多种特性。
当你使用上述模板引擎中的任何一个,它们默认的模板配置路径为:src/main/resources/templates。当然也可以修改这个路径,具体如何修改,可在后续各模板引擎的配置属性中查询并修改。
@ExceptionHandler 表示拦截异常
@ControllerAdvice 是 controller 的一个辅助类,最常用的就是作为全局异常处理的切面类
@ControllerAdvice 可以指定扫描范围
@ControllerAdvice 约定了几种可行的返回值,如果是直接返回 model 类的话,需要使用 @ResponseBody 进行 json 转换
返回 String,表示跳到某个 view
返回 modelAndView
返回 model + @ResponseBody
@ControllerAdvice
public class MayiktExceptionHandler {
/**
* 拦截运行异常出现的错误~~~
*
* @return
*/
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public Map<Object, Object> exceptionHandler() {
Map<Object, Object> map = new HashMap<>();
map.put("error", "500");
map.put("msg", "系统出现错误~");
return map;
}
}
在pom.xml文件中添加依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
这里要加MySQL的版本号
dependency>
在SpringBoot的配置文件application.yml文件中配置数据源
spring:
#配置数据源
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/smbms?serverTimezone=GMT%2B8&useSSL=true
username: root
password: root
springboot默认给我们添加的数据源是:
com.zaxxer.hikari.HikariDataSource //这个数据源号称是效率最高的数据源
另外还提供了很多的数据源:如下
org.apache.tomcat.jdbc.pool.DataSource
org.apache.commons.dbcp2.BasicDataSource
如果这些数据源我们不想要,还可以通过如下方法自定义数据源
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(DataSource.class)
@ConditionalOnProperty(name = "spring.datasource.type")
static class Generic {
@Bean
DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
可以使用JdbcTemplate来操作数据库了
@Controller
public class JdbcController {
@Autowired
private JdbcTemplate template;
@RequestMapping("/index")
@ResponseBody
public List<Map<String, Object>> index(){
List<Map<String, Object>> maps = template.queryForList("select * from smbms_user");
return maps;
}
}
4. 访问测试
在pom.xml文件中添加如下依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.2.2version>
dependency>
在配置文件application.yml文件中添加如下依赖
#以下配置是发送电子邮件的配置
spring:
#以下是数据源的配置
datasource:
url: jdbc:mysql://192.168.1.223:3306/itrip_db? useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 #注意修改
driver-class-name: com.mysql.cj.jdbc.Driver
username: root #注意修改
password: root #注意修改
type: com.alibaba.druid.pool.DruidDataSource #指定数据源的类型
#以下是alibaba数据源的配置
initialSize: 5 #初始化大小
minIdle: 5 #最小连接数
maxActive: 20 #最大连接数
maxWait: 60000 #获取连接等待超时时间
timeBetweenEvictionRunsMillis: 60000 #间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
minEvictableIdleTimeMillis: 300000 #一个连接在池中最小生存的时间,单位是毫秒
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
编写Druid的配置类
/**
* DruidDataSource配置类
*
*/
@Configuration
public class DruidConfiguration {
/*
* 类似于在Spring的配置文件中做了如下配置
*
*
*/
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource(){
return new DruidDataSource();
}
//配置Druid的监控
//1、配置一个管理后台的Servlet
//访问的地址为:http://ip:port/上下文/druid
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
initParams.put("loginUsername","admin");
initParams.put("loginPassword","admin");
initParams.put("allow","");//配置允许哪一个IP地址访问 默认就是允许所有访问
initParams.put("deny","192.168.15.21");/*拒绝后面的这个IP地址访问*/
bean.setInitParameters(initParams);
return bean;
}
//2、配置一个web监控的filter
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(new WebStatFilter());
Map<String,String> initParams = new HashMap<>();
//设置不拦截的路径
initParams.put("exclusions","*.js,*.css,/druid/*");
bean.setInitParameters(initParams);
//设置拦截的路径
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
}
编写控制器来测试
@RestController
public class DruidController {
@Autowired
private JdbcTemplate jdbcTemplate;
@GetMapping(value="/index")
public List<Map<String,Object>> index(){
List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from smbms_user");
return list;
}
}
访问测试
http://localhost:8080/index
http://localhost:8080/druid
步骤:
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>1.1.1version>
dependency>
在SpringBoot的配置文件中做如下配置
#mybatis的配置
mybatis:
type-aliases-package: com.kgc.demo.entity
mapper-locations: classpath:mapper/*.xml
configuration:
log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl #mybatis日志输出
spring:
#配置数据源
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/smbms?serverTimezone=GMT%2B8&useSSL=true
username: root
password: root
在resources下创建mapper文件夹用来存放mybatis的映射文件
在启动类上去添加扫描mybatis接口的直接如下:
方式一:直接在启动类上添加注解@MapperScan(basePackages = “com.kgc.demo.mapper”)
@SpringBootApplication
@MapperScan(basePackages = "com.kgc.demo.mapper")
public class DemoApplication {
public static void main(String[] args) {
//表示运行一个被@SpringBootApplication注解标注的Spring程序
SpringApplication.run(DemoApplication.class, args);
}
}
方式二:和启动类在同一个包或者子包中去创建一个配置类如下:
@Configuration
@MapperScan(basePackages = "com.kgc.demo.mapper")
public class MyBatisConfiguration {
}
启动测试
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.2.0version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.2.0version>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.2version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>1.2.47version>
dependency>
mybatis-plus:
configuration:
map-underscore-to-camel-case: true #是否开启驼峰命名
auto-mapping-behavior: full #自动映射级别
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #mybatis日志输出
mapper-locations: classpath*:mapper/**/*Mapper.xml #映射文件路径配置
global-config:
db-config: # 逻辑删除配置
logic-not-delete-value: 1 # 删除前
logic-delete-value: 0 # 删除后
/**
* 配置分页插件
*
*/
@Configuration
@MapperScan(backPackage="com.java.test.mapper")
public class MybatisPlusConfiguration {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.Scanner;
public class CodeGenerator {
/**
*
* 读取控制台内容
*
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.checkValNotNull(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(scanner("请输入你的项目路径") + "/src/main/java");
gc.setAuthor("lrg");
gc.setOpen(false);//生成之后是否打开资源管理器
gc.setSwagger2(true); //实体属性 Swagger2 注解
gc.setFileOverride(false);//重新是否自动覆盖文件
gc.setServiceName("%sService");//%sService 为占位符,用于生成service层代码,默认生成名称第一个字符是有I
gc.setIdType(IdType.AUTO);//设置主键成成策略 自动增长
gc.setDateType(DateType.ONLY_DATE);//设置日期类型 只是用java.util.date 代替
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/auth_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8");
// dsc.setSchemaName("public");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
dsc.setDbType(DbType.MYSQL);//设置是用的是什么数据库
mpg.setDataSource(dsc);
// 包配置
PackageConfig pc = new PackageConfig();
pc.setModuleName(scanner("请输入模块名"));
pc.setParent("com.lyh.pro");
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setEntity("entity");
pc.setXml("mapper");
mpg.setPackageInfo(pc);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));//设置那些表需要自动生成
strategy.setNaming(NamingStrategy.underline_to_camel);//设置驼峰命令
strategy.setColumnNaming(NamingStrategy.underline_to_camel);//设置_转驼峰命令
strategy.setEntityLombokModel(true);//设置实体类使用lombok
strategy.setRestControllerStyle(true);//设置controller的api风格 使用RestController
strategy.setControllerMappingHyphenStyle(true);//驼峰装连接符
strategy.setTablePrefix("tb_");//设置忽略tb_开头的前缀
mpg.setStrategy(strategy);
mpg.execute();
}
}
application.yml
spring:
datasource:
###会员数据库
member:
jdbc-url: jdbc:mysql://localhost:3306/user
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
###订单数据库
order:
jdbc-url: jdbc:mysql://localhost:3306/order
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
备注:如果是SpringBoot2配置多数据源 ,报如下错误:
“jdbcUrl is required with driverClassName.”或者Cause: java.lang.IllegalArgumentException: dataSource or dataSourceClassName or jdbcUrl is required.] with root cause
解决方案:
spring.datasource.url 和spring.datasource.driverClassName,换成
spring.datasource.jdbc-url和spring.datasource.driver-class-name
数据库数据源相关配置
会员数据库:
@Configuration
@MapperScan(basePackages = "com.java.member.mapper", sqlSessionFactoryRef = "memberSqlSessionFactory")
public class MemberDataSourceConfig {
/**
* 将会员db注册到容器中
*
* @return
*/
@Bean(name = "memberDataSource")
@ConfigurationProperties(prefix = "spring.datasource.member")
public DataSource memberDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 将会员SqlSessionFactory注册到容器中
*
* @param dataSource
* @return
* @throws Exception
*/
@Bean(name = "memberSqlSessionFactory")
public SqlSessionFactory memberSqlSessionFactory(@Qualifier("memberDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(memberDataSource());
return sqlSessionFactoryBean.getObject();
}
/**
* 创建会员管理器
*
* @param dataSource
* @return
*/
@Bean(name = "memberTransactionManager")
public DataSourceTransactionManager memberTransactionManager(@Qualifier("memberDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* 创建会员sqlSesion模版
*
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean(name = "memberSqlSessionTemplate")
public SqlSessionTemplate menberSqlSessionTemplate(
@Qualifier("memberSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
订单数据源:
@Configuration
@MapperScan(basePackages = "com.java.order.mapper", sqlSessionFactoryRef = "orderSqlSessionFactory")
public class OrderDataSourceConfig {
/**
* 将订单db注册到容器中
*
* @return
*/
@Bean(name = "orderDataSource")
@ConfigurationProperties(prefix = "spring.datasource.order")
public DataSource orderDataSource() {
return DataSourceBuilder.create().build();
}
/**
* 将订单SqlSessionFactory注册到容器中
*
* @param dataSource
* @return
* @throws Exception
*/
@Bean(name = "orderSqlSessionFactory")
public SqlSessionFactory orderSqlSessionFactory(@Qualifier("orderDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(orderDataSource());
return sqlSessionFactoryBean.getObject();
}
/**
* 创建订单管理器
*
* @param dataSource
* @return
*/
@Bean(name = "orderTransactionManager")
public DataSourceTransactionManager orderTransactionManager(@Qualifier("orderDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
/**
* 创建订单sqlSesion模版
*
* @param sqlSessionFactory
* @return
* @throws Exception
*/
@Bean(name = "orderSqlSessionTemplate")
public SqlSessionTemplate menberSqlSessionTemplate(
@Qualifier("orderSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
会员Mapper:
public interface MemberMapper {
@Insert("insert into users values(null,#{name},#{age});")
public int addUser(@Param("name") String name, @Param("age") Integer age);
}
订单Mapper:
public interface OrderMapper {
@Insert("insert into order_number values(null,#{number});")
int inserOrder(@Param("number") String number);
}
CREATE TABLE `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL COMMENT '用户名称',
`age` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
CREATE TABLE order_number (
`id` int(11) NOT NULL AUTO_INCREMENT,
`order_name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
在maven项目的pom.xml
中引入Knife4j的依赖包,代码如下:
<dependency>
<groupId>com.github.xiaoymingroupId>
<artifactId>knife4j-spring-boot-starterartifactId>
<version>2.0.9version>
dependency>
添加Knife4j的配置类
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfiguration {
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
Docket docket=new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
//.title("swagger-bootstrap-ui-demo RESTful APIs")
.description("# swagger-bootstrap-ui-demo RESTful APIs")
.termsOfServiceUrl("http://www.xx.com/")
.contact("[email protected]")
.version("1.0")
.build())
//分组名称
.groupName("2.X版本")
.select()
//这里指定Controller扫描包路径
.apis(RequestHandlerSelectors.basePackage("com.github.xiaoymin.knife4j.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
}
DruidController.java
包含一个简单的RESTful接口,代码示例如下:
@Api(tags = "首页模块")
@RestController
public class DruidController {
@Autowired
private JdbcTemplate jdbcTemplate;
@ApiOperation(value = "查询所有用户数据",
protocols = "http",
httpMethod="GET",
consumes="application/json",
response=List.class,
notes = "code:200 表示成功")
@GetMapping(value="/index")
public List<Map<String,Object>> index(){
List<Map<String, Object>> list = jdbcTemplate
.queryForList("select * from smbms_user");
return list;
}
}
http://localhost:17790/doc.html
JUL(java.util.logging)、JCL、Jboss-logging、logback、log4j、log4j2、slf4j…
SLF4J(Simple Logging Facade for Java):是一个简单日志门面抽象框架,它本身只提供了日志Facade API 和一个简单的日志类实现,一般常配合Log4j,Logback,java.util.logging使用。Slf4j作为应用层的Log 接入时,程序可以根据实际应用场景动态调整底层的日志实现框架(Log4j/Logback/JdkLog…)
Logback:Logback是一个日志框架,它与Log4j可以说是同出一源,都出自Ceki Gülcü之手,他是slf4j的 实现类。
SpringBoot底层是Spring,Spring选用的是JCL,SpringBoot对日志进行了封装选用的是slf4j和logback。
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-loggingartifactId>
<version>2.3.8.RELEASEversion>
<scope>compilescope>
dependency>
1. 默认配置:springboot已经帮我们配置好了日志框架,我们使用就行
@SpringBootTest
class SpringbootApplicationLoggingTests {
//定义日志记录器
private Logger log = LoggerFactory.getLogger(SpringbootApplicationLoggingTests.class);
@Test
void loggingTest(){
//日志的级别由低到高:trace
//可以调整输出的日志级别:日志就会在这个级别以后的高级别生效
log.info("这是info日志");
log.warn("这是warn日志");
log.debug("这是debug日志");
log.trace("这是trace日志");
log.error("这是error日志");
}
}
上面程序运行之后只输出类info、warn、error的日志信息,没有输出trace,debug类型的级别,也就是说SpringBoot日志默认输出的日志级别为info,info级别之前的日志级别不能输出出来。
修改日志级别
在springboot的配置文件,application.properties或者是application.yml文件中添加如下配置:
修改logback日志输出的级别,其中com.kgc.springboot是指什么包下的日志输出级别,
没有指定日志输出级别的包那就使用springboot默认指定输出的级别,也就是root级别
logging:
level:
com:
kgc:
springboot: trace
其他日志的的设置
logging:
file:
#不指定路径,在当前目录下生成springboot.log日志
#可以指定完整的路径,那么就是在指定的路径下创建日志文件
name: springboot.log
#在当前磁盘下的根路径下创建spring文件夹和里面的log文件夹:使用spring.log作为默认文件
#path: D:/idea_kgc_13/log
#logging.file.name和logging.file.path设置只能2选一如果2者都设置这是以logging.file.name为准
pattern:
#定义日志输出在控制台的格式
console: -%d -%LOG_LEVEL -%msg%n
#定义日志输出在文件中的格式
file:
自定义配置
在类路径下放上每个日志框架自己的配置文件即可,SpringBoot就不在使用默认的配置了
在resources下去创建一个logback-spring.xml文件文件的内容,如下:
<configuration scan="true" scanPeriod="10 seconds">
<contextName>logbackcontextName>
<property name="log.path" value="G:/logs/pmp" />
<property name="appName" value="kgc-springboot">property>
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debuglevel>
filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}Pattern>
<charset>UTF-8charset>
encoder>
appender>
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/web_debug.logfile>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/web-debug-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>debuglevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/web_info.logfile>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/web-info-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>infolevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/web_warn.logfile>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/web-warn-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warnlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/web_error.logfile>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%npattern>
<charset>UTF-8charset>
encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/web-error-%d{yyyy-MM-dd}.%i.logfileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MBmaxFileSize>
timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15maxHistory>
rollingPolicy>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERRORlevel>
<onMatch>ACCEPTonMatch>
<onMismatch>DENYonMismatch>
filter>
appender>
<springProfile name="dev">
<logger name="com.sdcm.pmp" level="debug"/>
springProfile>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
root>
configuration>
总结:
如果日志文件的名称为:
logback.xml:直接就被日志框架识别了;
logback-spring.xml:日志框架就不直接加载日志的配置项,由SpringBoot去加载,好处在于可以使用logback扩展功能,在帮助文档中有记载
不同的邮件服务器配置方式大同小异,一下以QQ邮件为例:
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-mailartifactId>
dependency>
spring:
mail:
protocol: smtp #配置QQ发送邮件的协议
host: smtp.qq.com #配置QQ发送邮件的主机
port: 587 #配置QQ发送邮件的端口
username: [email protected] #配置发送邮件的账户
password: xxxxxxxx #配置发送邮件的授权码
@SpringBootTest
class SpringbootApplicationTests {
@Autowired
private JavaMailSenderImpl mailSender;
/**
* 发送普通的电子邮件
*/
@Test
void sendSimpleMail() {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom("[email protected]");//设置发送者
message.setTo("[email protected]");//设置发送给谁
message.setSubject("今晚打老虎");//邮件主题
message.setText("今晚子时西门大官人有情,不见不散");//邮件内容
mailSender.send(message);//发送邮件
}
/**
* 发送带附件的电子邮件
* @throws MessagingException
*/
@Test
void sendMineMail() throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
//MimeMessageHelper 并设置是一个带附件的邮件
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setFrom("[email protected]");//设置发送者
helper.setTo("[email protected]");//设置发送给谁
helper.setSubject("今晚打老虎");//邮件主题
helper.setText("今晚子时西门大官人有情,不见不散");//邮件内容
helper.addAttachment("meinv.jpg",
new File("C:\\Users\\Administrator\\Desktop\\test\\234.jpg"));//设置附件
mailSender.send(mimeMessage);
}
/**
* 发送HTML格式的邮件
* @throws MessagingException
*/
@Test
void sendHtmlMail() throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
//MimeMessageHelper 并设置是一个带附件的邮件
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setFrom("[email protected]");//设置发送者
helper.setTo("[email protected]");//设置发送给谁
helper.setSubject("今晚打老虎");//邮件主题
String html="\n" +
"\n" +
"\n" +
" \n" +
" \n" +
"\n" +
"\n" +
"\n" +
"true表示发送的是一个HTML格式的邮件
\n"+
"\n" +
"\n" +
"";
helper.setText(html,true);//邮件内容 true表示发送的是一个HTML格式的邮件
mailSender.send(mimeMessage);
}
}
说明: 这里使用的是Freemarker来做模板(模板引擎有很多)
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-freemarkerartifactId>
dependency>
尊敬的${name},您好!
欢迎成为爱旅行家族成员的一份子,您此次账户注册的激活码为:${code},该激活码用于注册用户激活账户使用,请妥善保管!
请于30分钟内输入激活!
#以下是Freemarker的配置
spring:
freemarker:
template-loader-path: classpath:/templates/mail/ #配置模板路径
suffix: .ftl #配置模板后缀
cache: false #配置模板是否缓存
charset: UTF-8 #配置模板字符编码
@SpringBootTest
class SpringbootApplicationTests {
@Autowired
private JavaMailSenderImpl mailSender;
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
/**
* 使用模板发送电子邮件
* @throws IOException
* @throws TemplateException
* @throws MessagingException
*/
@Test
void sendTemplateMail() throws IOException, TemplateException, MessagingException {
String templateName = "account_active.ftl";//模板名称
//用于设置你要替换模板中的哪个一个占位符,以及值
Map<String,Object> model = new HashMap<>();
model.put("name","张三");
model.put("code","5566");
model.put("datetime","2021-07-26");
// 获得模板对象
Template mailTemplate = freeMarkerConfigurer.getConfiguration().getTemplate(templateName);
// 传入数据模型到模板,替代模板中的占位符,并将模板转化为html字符串
String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(mailTemplate,model);
// 该方法本质上还是发送html邮件,调用之前发送html邮件的方法
MimeMessage mimeMessage = mailSender.createMimeMessage();
//MimeMessageHelper 并设置是一个带附件的邮件
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);
helper.setFrom("[email protected]");//设置发送者
helper.setTo("[email protected]");//设置发送给谁
helper.setSubject("测试HTML模板邮件");//邮件主题
helper.setText(templateHtml,true);//邮件内容 true表示发送的是一个HTML格式的邮件
mailSender.send(mimeMessage);
}
}
MailTools:
/**
* 发送电子邮件的工具类
* @author lyh 2021/7/26
* @since 1.0.0
*/
@Component
@ConfigurationProperties(prefix = "spring.mail")
@Data
public class MailTools {
@Resource
private JavaMailSenderImpl mailSender;
@Resource
private FreeMarkerConfigurer freeMarkerConfigurer;
private String subject;
private String from;
/**
* 发送普通的电子邮件
* @param mailContent 邮件内容
* @param to 发送给谁 可以设置多个
* @return 成功或者失败
*/
public void sendSimpleEmail(String mailContent,String...to){
this.sendSimpleEmail(subject,mailContent,to);
}
/**
* 发送普通的电子邮件
* @param subject 邮件主题
* @param mailContent 邮件内容
* @param to 发送给谁 可以设置多个
* @return 成功或者失败
*/
public void sendSimpleEmail(String subject,String mailContent,String...to){
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setSubject(subject);//设置邮件主题
mailMessage.setTo(to);//设置发送给谁
mailMessage.setFrom(from);//设置谁发送的邮件
mailMessage.setText(mailContent);//设置邮件内容
mailSender.send(mailMessage);
}
/**
* 发送带附件和html格式的邮件
* @param subject 主题
* @param mailContent 邮件内容
* @param to 发送给谁
* @throws MessagingException 邮件异常对象
*/
public void sendMimeMail(String subject,String mailContent,String...to) throws MessagingException {
this.sendMimeMail(subject,mailContent,null,to);
}
/**
* 发送带附件和html格式的邮件
* @param mailContent 邮件内容
* @param to 发送给谁
* @throws MessagingException 邮件异常对象
*/
public void sendMimeMail(String mailContent,String...to) throws MessagingException {
this.sendMimeMail(this.subject,mailContent,null,to);
}
/**
* 发送带附件和html格式的邮件
* @param subject 主题
* @param mailContent 邮件内容
* @param files 附件文件
* @param to 发送给谁
* @throws MessagingException 邮件异常对象
*/
public void sendMimeMail(String subject,String mailContent,File[] files,String...to) throws MessagingException {
MimeMessage mimeMessage = mailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage,true);//这个true表示发送带附件的邮件
helper.setFrom(from);
helper.setTo(to);
//设置主题
helper.setSubject(subject);
helper.setText(mailContent,true);//表示html类型的邮件
//设置附件
if(files!=null && files.length>0){
for (File file:files){
if(file!=null){
String filename = file.getName();//获取上传文件名称
helper.addAttachment(filename,file);
}
}
}
mailSender.send(mimeMessage);
}
/**
* 发送模板邮件
* @param subject 邮件主题
* @param model 用于替换模板中需要替换的内容的map集合
* @param templatePath 模板名称
* @param to 发送给谁
* @throws IOException
* @throws TemplateException
* @throws MessagingException
*/
public void sendTemplateMail(String subject, Map<String,Object> model, String templatePath, String...to) throws IOException, TemplateException, MessagingException {
// 获得模板
Template mailTemplate = freeMarkerConfigurer.getConfiguration().getTemplate(templatePath);
// 传入数据模型到模板,替代模板中的占位符,并将模板转化为html字符串
String templateHtml = FreeMarkerTemplateUtils.processTemplateIntoString(mailTemplate,model);
// 该方法本质上还是发送html邮件,调用之前发送html邮件的方法
this.sendMimeMail(subject,templateHtml,to);
}
}
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-redisartifactId>
dependency>
spring:
#以下时redis的配置
redis:
host: 192.168.1.133 #连接的主机地址
port: 6379 #配置连接的端口号
password: root #配置redis连接的密码
database: 0 #配置redis连接数据库索引
timeout: 5000 #配置连接超时间
jedis:
pool: #使用jedis连接池去管理连接数
max-active: 8 #配置最大激活数
max-idle: 4 #最大的空闲数
min-idle: 4 #最小的空闲数
max-wait: -1 #最大等待时间
整合之后SpringBoot提供了2个操作Redis的模板类给我们操作redis
RedisTemplate中定义了5种数据结构操作
redisTemplate.opsForValue(); //操作字符串
redisTemplate.opsForHash(); //操作hash
redisTemplate.opsForList(); //操作list
redisTemplate.opsForSet(); //操作set
redisTemplate.opsForZSet(); //操作有序set
3.3 StringRedisTemplate和RedisTemplate区别
RedisTemplate使用的是JdkSerializationRedisSerializer 存入数据会将数据先序列化成字节数组然后在存入Redis数据库。
StringRedisTemplate使用的是StringRedisSerializer
当你的redis数据库里面本来存的是字符串数据或者你要存取的数据就是字符串类型数据的时候,那么你就使用StringRedisTemplate即可。
但是如果你的数据是复杂的对象类型,而取出的时候又不想做任何的数据转换,直接从Redis里面取出一个对象,那么使用RedisTemplate是更好的选择。
redisTemplate 中存取数据都是字节数组。当redis中存入的数据是可读形式而非字节数组时,使用redisTemplate取值的时候会无法获取导出数据,获得的值为null。可以使用 StringRedisTemplate 试试
面试题
Redis中有几种数据类型?分别是什么?
Redis和Memcached的区别和使用场景?
使用StringRedisTemplate操作Redis:
@SpringBootTest
class SpringbootApplicationRedisTests {
@Autowired
private StringRedisTemplate stringRemplate;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Test
void testStringRedisTemplate(){
//stringRemplate.opsForValue().set("name","jack");
//向redis里存入数据和设置缓存时间
stringRemplate.opsForValue()
.set("test", "100",60*10, TimeUnit.SECONDS);
//将key为test的value减1
stringRemplate.boundValueOps("test").increment(-1);//val做-1操作
//根据key获取缓存中的val
String testValue = stringRemplate.opsForValue().get("test");
System.out.println("testValue:"+testValue);
//将key为test的value减1
stringRemplate.boundValueOps("test").increment(1);//val +1
//根据key获取过期时间
Long testExpire = stringRemplate.getExpire("test");
System.out.println("testExpire:"+testExpire);
//根据key获取过期时间并换算成指定单位
Long expire = stringRemplate.getExpire("test", TimeUnit.MILLISECONDS);
System.out.println("testExpire:"+expire+"ms");
//根据key删除缓存
//stringRemplate.delete("test");
Boolean isExists = stringRemplate.hasKey("546545");//检查key是否存在,返回boolean值
System.out.println("546545是否存在:"+isExists);
//向指定key中存放set集合
stringRemplate.opsForSet().add("red_123", "1","2","3");
//设置过期时间
stringRemplate.expire("red_123",1000 , TimeUnit.SECONDS);
//根据key查看集合中是否存在指定数据
stringRemplate.opsForSet().isMember("red_123", "1");
//根据key获取set集合
stringRemplate.opsForSet().members("red_123");
}
@Configuration
public class RedisConfiguration {
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer
= new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
//objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 设置value的序列化规则和 key的序列化规则
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
}
@SpringBootTest
class SpringbootApplicationRedisToolsTests {
@Autowired
private RedisTools redisTools;
@Test
public void redisToolsTest(){
//使用RedisTools向redis中存入String类型的K,V
redisTools.set("test","张三");
//使用RedisTools向redis中存入一个对象
User user = new User(1,"张三","[email protected]");
redisTools.set("user",user);
//使用RedisTools根据Key获取一个Object类型的值
Object user1 = redisTools.get("user");
System.out.println(user1);
//使用RedisTools根据Key获取一个User类型的值
User user_1 = redisTools.getObject("user", User.class);
System.out.println(user_1);
//使用RedisTools存入一个List集合
List<User> userList = new ArrayList<>();
userList.add(new User(1,"张三","[email protected]"));
userList.add(new User(2,"李四","[email protected]"));
redisTools.set("listUser",userList,60);
//使用RedisTools根据Key获取一个Object类型的值
Object listUser = redisTools.get("listUser");
//将上一步获取的值转换成一个集合
List<User> users = JSONArray.parseArray(
JSONArray.toJSONString(listUser),
User.class);
for (User us : users) {
System.out.println(us.getName()+"\t"+us.getEmail());
}
}
}
声明:有大部分笔记作者是:刘仁贵老师
如有侵权,请联系我,谢谢!