# 快速开发
很方便的开发框架,只需要很少的配置,提供一站式 starter
依赖项,简化 maven
配置,内置 tomcat,没有 xml 配置要求,大幅度提高开发效率。
这么爽的开发框架,几乎是傻瓜式上手即用,所以会用点框架是拿不上台面的。我们更应该注重基础,以及算法,不要过多沉迷于框架。
# 新建项目
几乎不用选择什么,新建项目选择 Spring Initializr
如果是 web 项目,勾选上 spring web 就差不多了(小辣椒也可以选,毕竟真的很方便):
进去之后就会看到启动类,该类有 @SpringBootApplication
注解, springboot
项目启动时,会通过启动类去 "扫描" 其他的类,所以我们写的 service 类,controller 类不能放在启动类的父目录,只能放在同级目录或同级目录的子目录里面。
现在你可以什么都不写,直接 run,也不会报错(没有配置文件默认就是 8080 端口)。
# 整合 web 框架
配置文件:可以是 .properties
文件,也可以是 .yml
文件,区别只是两个文件内容书写格式不同,前者通过 .
引用,后者通过缩进。
# mybatis
导入依赖:
<dependency> | |
<groupId>org.mybatis.spring.boot</groupId> | |
<artifactId>mybatis-spring-boot-starter</artifactId> | |
<version>2.2.0</version> | |
</dependency> | |
<dependency> | |
<groupId>mysql</groupId> | |
<artifactId>mysql-connector-java</artifactId> | |
</dependency> |
在 resource
目录配置文件指定数据源(我这里用的就是.yaml 文件):
spring: | |
datasource: | |
url: jdbc:mysql://localhost:3306 | |
username: root | |
password: 123456 | |
driver-class-name: com.mysql.cj.jdbc.Driver |
starter
会自动扫描项目中 @Mapper
注解的接口,注册为 Bean,不需要任何配置:
@Mapper | |
public interface MainMapper { | |
@Select("select * from users where username = #{username}") | |
UserData findUserByName(String username); | |
} |
SpringBoot
会自动为 Mybatis 配置数据源,默认使用的就是 HikariCP
数据源。
# Thymeleaf
导入依赖:
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-thymeleaf</artifactId> | |
</dependency> |
然后直接用就可以了
@RequestMapping("/index") | |
public String index(){ | |
return "index"; | |
} |
html
文件放在 template
目录下,css,js 文件放在 static
目录下,甚至你可能还特意分了一下 css 目录之类的,所以我们愮在配置文件中指定一下静态资源的访问前缀:
spring: | |
mvc: | |
static-path-pattern: /static/** |
# 日志
先了解两个概念:
日志实现:之前学习的 JUL 其实就是日志实现,实现了具体细节和操作。
日志门面:如 Slf4j,把不同日志系统实现进行具体的抽象化,只提供统一的日志使用接口,使用时直接调用接口即可。但是最终日志实现的格式,输出方式等需要绑定具体日志系统来实现。
Springboot 为了统一日志框架,做了以下的事情:
- 将其他依赖以前的日志框架剔除。
- 导入对应日志框架的 Slf4j 中间包。
- 导入自己官方指定的日志实现。
可以选择 Logback 日志框架:
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-logging</artifactId> | |
</dependency> |
# Redis
你需要有一些 redis 的预备知识。
# Java 与 Redis 交互
需要用到 Jedis 框架,实现 Java 与 Redis 数据库的交互
<dependency> | |
<groupId>redis.clients</groupId> | |
<artifactId>jedis</artifactId> | |
<version>4.0.0</version> | |
</dependency> |
最基本的操作(前提是启动 redis 服务器)
public static void main(String[] args) { | |
// 创建 Jedis 对象 | |
Jedis jedis = new Jedis("localhost", 6379); | |
// 使用之后关闭连接 | |
jedis.close(); | |
} |
之后就是通过 Jedis 调用命令的同名方法来执行 redis 命令:
try(Jedis jedis = new Jedis("192.168.10.3", 6379)){ | |
jedis.set("test", "lbwnb"); // 等同于 set test lbwnb 命令 | |
System.out.println(jedis.get("test")); // 等同于 get test 命令 | |
} |
# SpringBoot 整合 Redis
对应依赖,该依赖底层没有使用 Jedis
,而是 Lettuce
:
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-data-redis</artifactId> | |
</dependency> |
starter 提供的默认配置会去连接本地的 Redis 服务器,并使用 0 号数据,也可以手动修改:
spring: | |
redis: | |
#Redis 服务器地址 | |
host: 192.168.10.3 | |
#端口 | |
port: 6379 | |
#使用几号数据库 | |
database: 0 |
starter 已经提供了两个默认的模板类: RedisTemplate
和 SteingRedisTemplate
,我们可以直接注入这两个类使用:
@SpringBootTest | |
class SpringBootTestApplicationTests { | |
@Resource | |
StringRedisTemplate template; | |
@Test | |
void contextLoads() { | |
ValueOperations<String, String> operations = template.opsForValue(); | |
operations.set("c", "xxxxx"); // 设置值 | |
System.out.println(operations.get("c")); // 获取值 | |
template.delete("c"); // 删除键 | |
System.out.println(template.hasKey("c")); // 判断是否包含键 | |
} | |
} |
所有的值的操作都被封装到了 ValueOperations
对象中,而普通的键操作直接通过模板对象就可以使用了,大致使用方式其实和 Jedis 一致。
事务管理:Spring 没有专门的 Redis 事务管理,可以借助 JDBC 的:
<dependency> | |
<groupId>org.springframework.boot</groupId> | |
<artifactId>spring-boot-starter-jdbc</artifactId> | |
</dependency> | |
<dependency> | |
<groupId>mysql</groupId> | |
<artifactId>mysql-connector-java</artifactId> | |
</dependency> |
然后在配置文件中配置一下 datasource
:
spring: | |
datasource: | |
url: jdbc:mysql://localhost:3306:study | |
username: root | |
password: 123456 |
就可以写 service 了:
@Service | |
public class RedisService { | |
@Resource | |
StringRedisTemplate template; | |
// 构造,注入后调用该方法 | |
@PostConstruct | |
public void init(){ | |
template.setEnableTransactionSupport(true); // 需要开启事务 | |
} | |
@Transactional // 需要添加此注解 | |
public void test(){ | |
template.multi(); | |
template.opsForValue().set("d", "xxxxx"); | |
template.exec(); | |
} | |
// 也可以将对象存进去,1. 使用序列化 2. 使用 json,需要导入 Jaskson 依赖 | |
// 使用 json,还需要设置一下 | |
// template.setValueSerializer(new Jaskson2JsonRedisSerializer<>(Object.class)) | |
@Test | |
void contextLoad2() { | |
// 注意 Student 需要实现序列化接口才能存入 Redis | |
template.opsForValue().set("student", new Student()); | |
System.out.println(template.opsForValue().get("student")); | |
} | |
} |
# Redis 用作缓存
在项目中,将 Redis 作为 Mybatis 的二级缓存,Mybatis 自带的二级缓存的缺点在于是 Mapper 级别的,对于多台服务器连接,各自二级缓存是隔离的,之前讲 Mybatis 的时候也提到过。
我们需要手动实现 Mybatis 提供的 Cache 接口,直接给代码了:
// 实现 Mybatis 的 Cache 接口 | |
public class RedisMybatisCache implements Cache { | |
private final String id; | |
private static RedisTemplate<Object, Object> template; | |
// 注意构造方法必须带一个 String 类型的参数接收 id | |
public RedisMybatisCache(String id){ | |
this.id = id; | |
} | |
// 初始化时通过配置类将 RedisTemplate 给过来 | |
public static void setTemplate(RedisTemplate<Object, Object> template) { | |
RedisMybatisCache.template = template; | |
} | |
@Override | |
public String getId() { | |
return id; | |
} | |
@Override | |
public void putObject(Object o, Object o1) { | |
// 这里直接向 Redis 数据库中丢数据即可,o 就是 Key,o1 就是 Value,60 秒为过期时间 | |
template.opsForValue().set(o, o1, 60, TimeUnit.SECONDS); | |
} | |
@Override | |
public Object getObject(Object o) { | |
// 这里根据 Key 直接从 Redis 数据库中获取值即可 | |
return template.opsForValue().get(o); | |
} | |
@Override | |
public Object removeObject(Object o) { | |
// 根据 Key 删除 | |
return template.delete(o); | |
} | |
@Override | |
public void clear() { | |
// 由于 template 中没封装清除操作,只能通过 connection 来执行 | |
template.execute((RedisCallback<Void>) connection -> { | |
// 通过 connection 对象执行清空操作 | |
connection.flushDb(); | |
return null; | |
}); | |
} | |
@Override | |
public int getSize() { | |
// 这里也是使用 connection 对象来获取当前的 Key 数量 | |
return template.execute(RedisServerCommands::dbSize).intValue(); | |
} | |
} |
缓存类编写完成后,我们接着来编写配置类(Spring):
@Configuration | |
public class MainConfiguration { | |
@Resource | |
RedisTemplate<Object, Object> template; | |
@PostConstruct | |
public void init(){ | |
// 把 RedisTemplate 给到 RedisMybatisCache | |
RedisMybatisCache.setTemplate(template); | |
} | |
} |
在 Mapper 直接使用即可:
// 只需要修改缓存实现类 implementation 为我们的 RedisMybatisCache 即可 | |
@CacheNamespace(implementation = RedisMybatisCache.class) | |
@Mapper | |
public interface MainMapper { | |
// 会将查询结果放到 redis 里面 | |
@Select("select name from student where sid = 1") | |
String getSid(); | |
} |
# 多环境配置
写好多个环境的配置文件,进行自由切换。
SpringBoot
只会读取 application.properties
或者 application.yml
文件,所以要实现自由切换,需要在配置文件中指定:
spring:
profiles:
active: dev
这样就会读取 application-dev.yml
配置文件。
# 参考
https://www.yuque.com/qingkongxiaguang/spring/xzo445