springboot
一:多环境配置
//表示当前启用的环境
spring:
profiles:
active: dev
用两种方式进行多环境的配置
1、在单文件中进行多环境配置
使用 — 进行多环境进行区分
spring:
profiles:
active: dev
#第一个环境配置
---
server:
port: 8081
spring:
profiles: dev
#第二个环境配置
---
server:
port: 8082
spring:
profiles: test
#第三个环境配置
---
server:
port: 8083
spring:
profiles: prod
2、创建多个文件进行多环境的配置
命名格式为application-*.yaml
一般创建三个文件,分别为application-dec.yaml application-prod.yaml application-test.yaml
以application-dec.yaml为例
server:
port: 8080
# servlet:
# context-path: /fy22
env:
name: 开发环境
# 等等等
二:thymeleaf
导入maven依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
用处不多,都是前后端分离开发,去百度查询怎么使用
三:valid验证
1、创建实体类,并在实体类中添加对应的属性限制
package com.example.fy22_springboot.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;
/**
* @author : panghuhu-Li
* @date : Created in 2022/5/31 15:52
* @description: no
* @modified By: lxz
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class Book {
private int id;
@NotEmpty(message = "书名不能为空")
@Size(min = 2,max = 20,message = "书名长度必须在1~20之间")
private String name;
@Min(value = 1,message = "价格至少一元")
@Max(value = 100,message = "价格不能查过100元")
private int price;
private String author;
private String publish;
}
在controller层对注入的属性进行验证
@RequestMapping("path")
public String testValid(@Valid Book){
return "";
}
四:异常捕获
//专门用来处理异常的类,也叫全局异常监听类
//相当于切面
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(value = {Exception.class})//申明捕获哪个异常类
public String exceptionDemo() {
return "自定义异常返回";
}
}
五:mybatis—springboot整合
1、依赖项导入
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
2、yaml文件配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/fy_ssm?serverTimezone=UTC&characterEncoding=UTF-8&useSSL=false
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
type-aliases-package: 包所在位置
六:redis缓存数据库的使用
卸载服务:redis-server --service-uninstall
开启服务:redis-server --service-start
停止服务:redis-server --service-stop
1、String使用
设置值
set [key] [value]
set 1001 zhangsan
获取值
get [key]
get 1001
获取并重新赋值
getset [key] [newValue]
getset 1001 pangliu
变量+1
incr [key]
incr count
变量-1
decr [key]
decr count
追加内容
append [key] [valux]
批量插入
mset [k1] [v1] [k2] [v2]
批量读取
mget [k1] [k2]
2 、list使用
向list中添加一条数据 左加
lpush [key] [values] //lpush每次都会将数据填加到数据的头部 是left push的缩写
lpush mylist zhangsan
查询指定范围内的数据
lrange [key] [fromIndex] [endIndex]
向list中插入一条数据 右插(保证list中的数据和插入的顺序一致,使用该命令)
rpush [key] [values]
rpush mylist sunwukong
根据下标获取list中的元素
lindex [key] [index]
lindex mylist 2 (取出下标是2的数据,下标是从0开始的)
获取截取的内容 其余删除
ltrim [key] [index1] [index2]
ltrim mylist 1 3 (只保留1-3这几个位置的数据,其他的都删掉)
从list头部拿出一个数据
lpop [key]
lpop mylist
从list尾部拿出一个数据
rpop [key]
rpop mylist
3、hash结构使用
hash结构 数据很多的话存放在hash结构里 数据量较少的话存放在string结构里
每个hash的key里是有多个键值对的
hset [key] [field] [value]
hset myhash 1001 sunwukong
根据key和field从hash中取值
hget [key] [field]
hget myhash 1001
判断hash中是否存在filed
hexists [key] [field]
hexists myhash 1001
删除一个field
格式: hdel [key] [field]
例: hdel myhash 1001
获取hash里面的field的数量
格式: hlen [key]
例: hlen myhash
获取hash里所有的field
格式: hkeys [key]
例: hkeys myhash
获取hash里所有的value
格式: hvals [key]
例: hvals myhash
获取hash里所有的键值对
格式: hgetall [key]
例: hgetall myhash
5、springboot中redis使用
在使用redis时我们要确保redis服务器一直处于开启状态
1)引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
2)yaml配置
spring:
redis:
database: 0
host: 127.0.0.1
port: 6379
timeout: 1000
jedis:
pool:
max-idle: 8
min-idle: 4
max-active: 8
3)配置序列化格式
由于将内容存入到redis编码格式不同,我们需要对存入和取出的编码进行配置。需要对字符串,对象等进行序列化和反序列化。
@Configuration
public class BeanConfig {
/* @Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
//创建字符串类型的序列化对象
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//在java中想要让redis存储对象,就需要把对象进行序列化,转换一定格式的字符串然后进行存储
//创建一个支持任意类型序列化的对象
Jackson2JsonRedisSerializer json=new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om=new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
json.setObjectMapper(om);
//解决key前面有一串乱码的问题
template.setKeySerializer(stringRedisSerializer);
//值的序列化方式选择json的形式
template.setValueSerializer(json);
return template;
}*/
@Bean
@ConditionalOnClass(RedisOperations.class)
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
//序列化包括类型描述 否则反向序列化实体会报错,一律都为JsonObject
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(mapper.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(mapper);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
// key采用 String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的 key也采用 String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用 jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的 value序列化方式采用 jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
4)基本操作
通过查询的缓存业务逻辑来演示其基本使用
基本流程
1、从缓存中查询图书列表
2、如果查到了,则直接返回给调用方
3、如果没有查到,则去数据库中查询
4、如果没有查到,则去数据库中查询
5、如果数据库查到了,则需要把数据添加到缓存中一份,方便下次从缓存中查
查询业务
public List<Book> selectAll() {
//查询里加缓存的业务逻辑
/*
1、从缓存中查询图书列表
2、如果查到了,则直接返回给调用方
3、如果没有查到,则去数据库中查询
4、如果没有查到,则去数据库中查询
5、如果数据库查到了,则需要把数据添加到缓存中一份,方便下次从缓存中查
*/
String key = "book_list";
Object book_list = redisTemplate.opsForValue().get(key);
if (book_list != null) {
System.out.println("缓存命中");
return (List<Book>) book_list;
}
List<Book> books = bookDao.selectAll();
if (books != null) {
System.out.println("从数据库中查询并添加到缓存里");
redisTemplate.opsForValue().set(key, books);
}
return books;
}
@Transactional
public int add(Book book) {
//添加数据库的时候需要删除缓存,否则数据库和缓存会发生不一致的问题
redisTemplate.delete("book_list");
book.setId(AI.incrementAndGet());
System.out.println("添加了" + bookDao.insert(book));
return 1;
}
public int delete(int id) {
//删除数据库的时候需要删除缓存,否则数据库和缓存会发生不一致的问题
redisTemplate.delete("book_list");
return bookDao.deleteById(id);
}
public int update(Book book) {
//修改数据库的时候需要删除缓存,否则数据库和缓存会发生不一致的问题
redisTemplate.delete("book_list");
return bookDao.update(book);
}
public Book getBookById(int id) {
return bookDao.selectById(id);
}
通过set方法也能对加入的key-value设置过期时间
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
七:工具类guava使用
导入以来项
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>22.0</version>
</dependency>
项目中整合swagger3
1、文档接口添加依赖
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
2、在springboot2.6版本以上的需要添加
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
3、在配置类中配置swaggeer的类
@Bean
public Docket createRestApi() {
Docket docket = new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.select()
//设置通过什么方式定位需要自动生成文档的接口,我们这里采用定位方法上的apiOperation注解的方式
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.build();
return docket;
}
private ApiInfo apiInfo() {
ApiInfo info = new ApiInfoBuilder().title("Swagger3接口文档")
.description("自动生成的接口文档,有问题联系开发工程师")
.contact(new Contact("李星泽", "https://www.baidu.com", "abc@anc.com"))
.version("1.0.1")
.build();
return info;
}
4、在启动类中添加注解
//开启swagger文档注解
@EnableOpenApi
5、在需要添加注释信息的类上添加
@Api(tags = "学生管理api接口")
@RestController
public class StudentController {
@ApiOperation(value = "通过学号查询学生")
//这个注解的作用是对请求参数的解释
@ApiImplicitParam(name = "no", value = "学号", required = true, dataType = "String")
@GetMapping("selectByNo")
public BaseResult<Student> selectByNo(String no) {
Student student = new Student();
student.setNo(no);
student.setName("张三");
student.setAge(21);
student.setEmail("123456789");
student.setPhone("110");
student.setAddress("哈尔滨");
BaseResult<Student> result = new BaseResult<>();
result.setCode(1);
result.setMsg("success");
result.setData(student);
return BaseResult.success(ResultCode.SUCCESS, student);
}
@ApiOperation(value = "添加学生信息")
@PostMapping("insert")
public BaseResult<String> insert(@RequestBody Student student) {
return BaseResult.success(ResultCode.SUCCESS, "ok");
}
@PutMapping("update")
@ApiOperation(value = "修改学生信息")
public BaseResult<String> update(Student student) {
return BaseResult.success(ResultCode.SUCCESS, "ok");
}
@DeleteMapping("delete")
@ApiOperation(value = "删除学生信息")
@ApiImplicitParam(name = "no", value = "学号", required = true, dataType = "String")
public BaseResult<String> delete(String no) {
return BaseResult.success(ResultCode.SUCCESS, "ok");
}
}
注:我们可以设置自己返回前端的基本数据格式,上面代码中的BaseResulet就是自己设置的格式
@Data
public class BaseResult<T> {
@ApiModelProperty(value = "状态码"
, allowableValues = "1001,1002,1003"
, example = "1002"
, required = true
, allowEmptyValue = false)
private int code;
@ApiModelProperty(value = "描述信息",example = "success")
private String msg;
@ApiModelProperty("数据")
private T data;
public static <T> BaseResult<T> success(ResultCode code, T data) {
BaseResult<T> result = new BaseResult<>();
result.setCode(code.getCode());
result.setMsg(code.getMsg());
result.setData(data);
return result;
}
public static BaseResult fail(ResultCode code) {
BaseResult res = new BaseResult<>();
res.setCode(code.getCode());
res.setMsg(code.getMsg());
return res;
}
}
public enum ResultCode {
SUCCESS(1001, "SUCCESS"),
FAIL(2001, "FAIL");
int code;
String msg;
ResultCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
6、访问地址 http://127.0.0.1:8080/swagger-ui/index.html