医院设置swagger接口:http://localhost:8201/swagger-ui.html
注意点
data: searchObj
表示对象会以 json 传递
不用json传递 params
npm run dev
启动时报错Found bindings for the following environments: - Windows 64-bit with Node.js
需要重装node-sass包
npm rebuild node-sass
springboot 2.2.1.RELEASE
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.2.1.RELEASEversion>
<relativePath/>
parent>
<groupId>com.cngroupId>
<artifactId>yyghm_parentartifactId>
<packaging>pompackaging>
<version>0.0.1-SNAPSHOTversion>
<name>yyghm_parentname>
<description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
<cloud.version>Hoxton.RELEASEcloud.version>
<alibaba.version>2.2.0.RELEASEalibaba.version>
<mybatis-plus.version>3.3.1mybatis-plus.version>
<mysql.version>5.1.46mysql.version>
<swagger.version>2.7.0swagger.version>
<jwt.version>0.7.0jwt.version>
<fastjson.version>1.2.29fastjson.version>
<httpclient.version>4.5.1httpclient.version>
<easyexcel.version>2.2.0-beta2easyexcel.version>
<aliyun.version>4.1.1aliyun.version>
<oss.version>3.9.1oss.version>
<jodatime.version>2.10.1jodatime.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>${mybatis-plus.version}version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
<version>${swagger.version}version>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
<version>${swagger.version}version>
dependency>
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwtartifactId>
<version>${jwt.version}version>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
<version>${httpclient.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
<version>${fastjson.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>${easyexcel.version}version>
dependency>
<dependency>
<groupId>com.aliyungroupId>
<artifactId>aliyun-java-sdk-coreartifactId>
<version>${aliyun.version}version>
dependency>
<dependency>
<groupId>com.aliyun.ossgroupId>
<artifactId>aliyun-sdk-ossartifactId>
<version>${oss.version}version>
dependency>
<dependency>
<groupId>joda-timegroupId>
<artifactId>joda-timeartifactId>
<version>${jodatime.version}version>
dependency>
dependencies>
dependencyManagement>
project>
2 搭建common模块 及common模块下的两个子模块common-util
和 service-util
common 配置文件中添加依赖
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
<scope>provided scope>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<scope>provided scope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger2artifactId>
dependency>
<dependency>
<groupId>io.springfoxgroupId>
<artifactId>springfox-swagger-uiartifactId>
dependency>
dependencies>
common-util
<dependencies>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>fastjsonartifactId>
dependency>
<dependency>
<groupId>io.jsonwebtokengroupId>
<artifactId>jjwtartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
dependency>
<dependency>
<groupId>joda-timegroupId>
<artifactId>joda-timeartifactId>
dependency>
dependencies>
模块model 实体类 VO类
https://gitee.com/shixumin/yyghm_parent.git
localhost:8201/swagger-ui.html
//1. 查询医院设置表所有信息
@ApiOperation(value = "获取所有医院设置信息")
@GetMapping("findAll")
public Result findAllHospitalSet(){
//调用service的方法
List<HospitalSet> list = hospitalSetService.list();
// Result> ok = Result.ok(list);
return Result.ok(list);
}
//2. 逻辑删除医院设置
@ApiOperation(value = "逻辑删除医院设置信息")
@DeleteMapping("{id}")
public Result removeHospSer(@PathVariable long id){
boolean flag = hospitalSetService.removeById(id);
if (flag){
return Result.ok();
}else {
return Result.fail();
}
}
注意:@RequestBody
的使用 :接收前端传递给后端的 json
串
//3.条件查询分页
// @RequestBody(required = false)//json形式传递,required=false可以为空 post提交才能得到requestbody传来的值
@PostMapping("findPage/{current}/{limit}")
public Result findPageHospSet(@PathVariable long current,
@PathVariable long limit,
@RequestBody(required = false) HospitalSetQueryVo hospitalSetQueryVo){
//创建page对象,传递当前页,每页记录数
Page<HospitalSet> page = new Page<>(current, limit);
//构建条件
QueryWrapper<HospitalSet> wrapper = new QueryWrapper<>();
//先对条件值进行判断,有的话设置
String hosname = hospitalSetQueryVo.getHosname();//医院名称
String hoscode = hospitalSetQueryVo.getHoscode();//医院编号
if (!StringUtils.isEmpty(hosname)){
wrapper.like("hosname", hospitalSetQueryVo.getHosname());
}
if (!StringUtils.isEmpty(hoscode)){
wrapper.eq("hoscode", hospitalSetQueryVo.getHoscode());
}
//调用方法实现分页查询
Page<HospitalSet> hospitalSetPage = hospitalSetService.page(page, wrapper);
return Result.ok(hospitalSetPage);
}
//4.添加医院设置
@PostMapping("saveHospitalSet")
public Result saveHospitalSet(@RequestBody HospitalSet hospitalSet){
//设置状态 1 使用 ; 2 不能使用
hospitalSet.setStatus(1);
//签名密钥 与医院接口对接时使用
Random random = new Random();
//根据当前时间和一个随机数
hospitalSet.setSignKey(MD5.encrypt(System.currentTimeMillis()+""+random.nextInt(1000)));
//调用service
boolean save = hospitalSetService.save(hospitalSet);
if (save){
return Result.ok();
}else {
return Result.fail();
}
}
添加测试数据
{
"apiUrl": "http://localhost:8999",
"contactsName": "张三",
"contactsPhone": "1291012",
"hoscode": "1000_01",
"hosname": "北京人民医院",
"isDeleted": 0
}
//5.根据id获取医院设置
@ApiOperation(value = "根据id获取医院设置")
@GetMapping("getHospSet/{id}")
public Result getHospSet(@PathVariable Long id){
HospitalSet hospitalSet = hospitalSetService.getById(id);
return Result.ok(hospitalSet);
}
//6.修改医院设置
@ApiOperation(value = "修改医院设置")
@PostMapping("updateHospitalSet")
public Result updateHospitalSet(@RequestBody HospitalSet hospitalSet){
boolean flag = hospitalSetService.updateById(hospitalSet);
if (flag){
return Result.ok();
}else {
return Result.fail();
}
}
//7.批量删除医院设置
@ApiOperation(value = "批量删除医院设置")
@DeleteMapping("batchRemove")
public Result batchRemoveHospitalSet(@RequestBody List<Long> idList){
hospitalSetService.removeByIds(idList);
return Result.ok();
}
//8 医院设置 锁定与解锁
@PutMapping("lockHospitalSet/{id}/{status}")
public Result lockHospitalSet(@PathVariable Long id,
@PathVariable Integer status){
//根据id查询医院设置信息
HospitalSet hospitalSet = hospitalSetService.getById(id);
//设置状态
hospitalSet.setStatus(status);
//调用方法
hospitalSetService.updateById(hospitalSet);
return Result.ok();
}
异常时出现统一的提示
添加全局异常处理类 GlobalExceptionHandler
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class) //指定什么异常
@ResponseBody //使结果以json形式输出
public Result error(Exception e){
e.printStackTrace();
return Result.fail();
}
}
自定义异常需要手动 抛出
/**
* 自定义全局异常类
*
* @author qy
*/
@Data
@ApiModel(value = "自定义全局异常类")
public class YyghException extends RuntimeException {
@ApiModelProperty(value = "异常状态码")
private Integer code;
/**
* 通过状态码和错误消息创建异常对象
* @param message
* @param code
*/
public YyghException(String message, Integer code) {
super(message);
this.code = code;
}
/**
* 接收枚举类型对象
* @param resultCodeEnum
*/
public YyghException(ResultCodeEnum resultCodeEnum) {
super(resultCodeEnum.getMessage());
this.code = resultCodeEnum.getCode();
}
@Override
public String toString() {
return "YyghException{" +
"code=" + code +
", message=" + this.getMessage() +
'}';
}
}
日志等级
OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
设置日志级别
在相应的项目配置文件中加入
logging.level.root=DEBUG
如何把日志输出到硬盘文件
spring boot内部使用Logback
作为日志实现的框架。
Logback和log4j非常相似
在resource下创建配置文件 logback-spring.xml
将压缩文件解压到工作区
打开终端
# 安装依赖
npm install
# 启动。执行后,浏览器自动弹出并访问http://localhost:9527/
npm run dev
前端项目端口号9528,后端接口端口号8201 ,端口号不同 ,不允许访问
<template>
<div class="app-container">
医院设置列表
</div>
</template>
<script>
import hospset from '@/api/hospset'
export default{
//定义变量和初始值
data(){
return{
current:1, //当前页
limit:3, //每页显示记录数
searchObj:{}, //条件封装对象
list:[], //每页数据集合
total:0 //总记录数
}
},
created(){ //在页面渲染之前进行
//一般调用methods定义方法,得到数据
this.getList() //只能调用当前vue方法
},
methods:{ //定义方法,进行请求接口调用
//医院设置列表
getList(){
hospset.getHospSetList(this.current,this.limit,this.searchObj)
.then(response=>{ //请求成果response是接口返回数据
//返回集合赋值list
this.list=response.data.records
//总记录数
this.total=response.data.total
// console.log(response)
}) //请求成功
.catch(error=>{
console.log(error)
})
}
}
}
</script>
<template>
<div class="app-container">
医院设置列表
<el-table :data="list" stripe style="width: 100%">
<el-table-column type="index" width="50" lable="序号"/>
<el-table-column prop="hosname" label="医院名称"/>
<el-table-column prop="hoscode" label="医院编号"/>
<el-table-column prop="apiUrl" label="api基础路径"width="200"/>
<el-table-column prop="contactsName" label="联系人姓名"/>
<el-table-column prop="contactsPhone" label="联系人手机"/>
<el-table-column label="状态" width="80">
<template slot-scope="scope">
{{ scope.row.status === 1 ? '可用' : '不可用' }}
template>
el-table-column>
el-table>
div>
template>
<el-pagination
:current-page="current"
:page-size="limit"
:total="total"
style="padding: 30px 0; text-align: center;"
layout="total, prev, pager, next, jumper"
@current-change="getList" />
医院设置列表
<el-form :inline="true" class="demo-form-inline">
<el-form-item>
<el-input v-model="searchObj.hosname" placeholder="医院名称"/>
el-form-item>
<el-form-item>
<el-input v-model="searchObj.hoscode" placeholder="医院编号"/>
el-form-item>
<el-button type="primary" icon="el-icon-search" @click="getList()">查询el-button>
el-form>
hospset.js
文件定义操作的接口路径1.在页面利用element-ui添加删除按钮
<el-table-column label="操作" width="280" align="center">
<template slot-scope="scope">
<el-button
type="danger"
size="mini"
icon="el-icon-delete"
@click="removeDataById(scope.row.id)">
el-button>
template>
el-table-column>
2.在list.vue编写调用删除的方法,得到删除id的值
点击按钮,弹窗 确定or取消
确定 调用删除接口,刷新页面(此为刷新到第一页)
//删除医院设置 的方法
removeDataById(id) {
// alert(id)
this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
//确定执行then
//调用接口
hospset.deleteHospSet(id).then(response => {
//提示
this.$message({
type: "success",
message: "删除成功!"
})
//刷新页面
this.getList(1)
})
})
}
3.在api文件夹的 hospset.js
文件定义操作的接口路径
在每条数据前加一个复选框 ,将选择的id传入到方法中
如何得到选中的 id 值?
在复选框位置绑定事件
添加成功,跳转到列表页面
//设置id查询
getHospSet(id){
return request({
url: `/admin/hosp/hospitalSet/getHospSet/${id}`,
method: 'get'
})
},
//修改设置
updateHosplSet(hospitalSet){
return request({
url: `/admin/hosp/hospitalSet/updateHospitalSet`,
method: 'post' ,
data:hospitalSet
})
},
add.vue
//根据id查询
getHospitalSet(id){
hospset.getHospSet(id)
.then(response=>{
this.hospitalSet=response.data
})
},
//修改
update(){
hospset.updateHosplSet(this.hospitalSet)//要用当前变量和它的值要加this
.then(response=>{
//
this.$message({
type:'success',
message:'修改成功!'
})
//跳转
this.$router.push({path:'/hospSet/list'})
})
},
//判断添加还是修改 没有id做添加,有id做修改操作
saveOrUpdate(){
if(!this.hospitalSet.id){
this.save()
}else{
this.update()
}
}
问题:vue-router导航切换 时,如果两个路由都渲染同个组件,
组件的生命周期方法(created或者mounted)不会再被调用, 组件会被重用,显示上一个路由渲染出来的自建
解决方案:可以简单的在 router-view上加上一个唯一的key,来保证路由切换时都会重新触发生命周期方法,确保组件被重新初始化。
参照 service-hosp
修改
端口号为8202
,数据库yygh_cmn
@Api("数据字典接口")
@RestController
@CrossOrigin
@RequestMapping("/admin/cmn/dict")
public class DictController {
@Autowired
private DictService dictService;
//根据数据id查询子数据列表
@ApiOperation(value = "根据数据id查询子数据列表")
@GetMapping("findChildData/{id}")
public Result findChildData(@PathVariable Long id){
List<Dict> list =dictService.findChlidData(id);
return Result.ok(list);
}
}
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
//MP已经实现注入
根据数据id查询子数据列表
@Override
public List<Dict> findChlidData(Long id) {
QueryWrapper<Dict> wrapper = new QueryWrapper<>();
wrapper.eq("parent_id", id);
List<Dict> dictList = baseMapper.selectList(wrapper);
/*
遍历list集合,根据每个对象中的id值查询其下面有没有子节点或子数据
将其返回值 setHasChildren(isChild)
*/
for (Dict dict : dictList) {
Long dictId = dict.getId();
boolean isChild=this.isChildren(dictId);
dict.setHasChildren(isChild);
}
return dictList;
}
//判断id下面是否有子节点
private boolean isChildren(Long id) {
QueryWrapper<Dict> wrapper = new QueryWrapper<>();
wrapper.eq("parent_id", id);
Integer count = baseMapper.selectCount(wrapper);//值>0 , 有数据
// >0 返回true
return count>0;
}
}
创建api文件dict.js 和视图文件
api/dict.js
import request from '@/utils/request'
export default{
//数据字典列表
dictList(id){
return request({
url: `/admin/cmn/dict/findChildData/${id}`,
method: 'get',
})
},
}
dict/list.vue
<template>
<div class="app-container">
<el-table
:data="list"
style="width: 100%"
row-key="id"
border
lazy
:load="getChildrens"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column label="名称" width="230" align="left">
<template slot-scope="scope">
<span>{{ scope.row.name }}</span>
</template>
</el-table-column>
<el-table-column label="编码" width="220">
<template slot-scope="{row}">
{{ row.dictCode }}
</template>
</el-table-column>
<el-table-column label="值" width="230" align="left">
<template slot-scope="scope">
<span>{{ scope.row.value }}</span>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center">
<template slot-scope="scope">
<span>{{ scope.row.createTime }}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import dict from '@/api/dict'
export default{
data(){
return{
list:[] //数据字典列表数组
}
},
created(){
this.getDictList(1)
},
methods:{
//数据字典列表
getDictList(id){
dict.dictList(id)
.then(response=>{
this.list=response.data
})
},
getChildrens(tree,treeNode,resolve){
dict.dictList(tree.id).then(response => {
resolve(response.data)
})
}
}
}
</script>
注意前端页面若在没有报错的情况下 也没有展示出来分级菜单 -->升级下element-ui的版本
<dependencies>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.1.1version>
dependency>
dependencies>
@Data
public class UserData {
@ExcelProperty("用户编号")
private int uid;
@ExcelProperty("用户名称")
private String username;
}
public class TestWrite {
public static void main(String[] args) {
//构建数据list集合
List<UserData> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
UserData data = new UserData();
data.setUid(i);
data.setUsername("lucy"+i);
list.add(data);
}
//设置excel文件路径和文件名称
String fileName="D:\\excel\\01.xlsx";
//调用方法实现写操作
EasyExcel.write(fileName,UserData.class).sheet("用户信息")
.doWrite(list);
}
}
需要写一个监听器
public class ExcelListener extends AnalysisEventListener<UserData> {
//一行一行的读取excel内容,从第二行读取
@Override
public void invoke(UserData userData, AnalysisContext analysisContext) {
System.out.println(userData);
}
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表头信息"+headMap);
}
//读取后执行
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
public class TestRead {
public static void main(String[] args) {
//设置excel文件路径和文件名称
String fileName="D:\\excel\\01.xlsx";
//调用方法实现读取操作
EasyExcel.read(fileName,UserData.class,new ExcelListener()).sheet().doRead();
}
}
添加导出实体
package com.cn.yygh.vo.cmn;
@Data
public class DictEeVo {
@ExcelProperty(value = "id" ,index = 0)
private Long id;
@ExcelProperty(value = "上级id" ,index = 1)
private Long parentId;
@ExcelProperty(value = "名称" ,index = 2)
private String name;
@ExcelProperty(value = "值" ,index = 3)
private String value;
@ExcelProperty(value = "编码" ,index = 4)
private String dictCode;
}
controller
//导出数据字典接口
@GetMapping("exportData")
public void exportDict(HttpServletResponse response){
dictService.exportDictData(response);
}
service方法
//导出数据字典接口
@Override
public void exportDictData(HttpServletResponse response) {
//设置下载信息
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = "dict";
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
//查询数据库
List<Dict> dictList = baseMapper.selectList(null);
//Dict ---> DictEeVo 遍历dictList后得到Dict对象,把每个Dict对象中的内容复制到DictEeVo中
List<DictEeVo> dictVoList = new ArrayList<>();
for (Dict dict : dictList) {
DictEeVo dictEeVo = new DictEeVo();
// dictEeVo.setId(dict.getId());
BeanUtils.copyProperties(dict,dictEeVo,DictEeVo.class);
dictVoList.add(dictEeVo);
}
//调用方法进行写操作
try {
EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("dict")
.doWrite(dictVoList);
} catch (IOException e) {
e.printStackTrace();
}
}
<div class="el-toolbar">
<div class="el-toolbar-body" style="justify-content: flex-start;">
<a href="http://localhost:8202/admin/cmn/dict/exportData" target="_blank">
<el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
</a>
<el-button type="text" @click="importData"><i class="fa fa-plus"/> 导入</el-button>
</div>
</div>
添加导出方法
exportData() {
window.location.href = 'http://localhost:8202/admin/cmn/dict/exportData'
}
创建回调监听器
public class DictListener extends AnalysisEventListener<DictEeVo> {
private DictMapper dictMapper;
public DictListener(DictMapper dictMapper) {
this.dictMapper = dictMapper;
}
//一行一行读取
@Override
public void invoke(DictEeVo dictEeVo, AnalysisContext analysisContext) {
//调用方法添加数据库
Dict dict = new Dict();
BeanUtils.copyProperties(dictEeVo,dict);
dictMapper.insert(dict);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
controller
//导入数据字典
@PostMapping("importData")
public Result importDict(MultipartFile file){
dictService.importDictData(file);
return Result.ok();
}
service
//导入数据字典
@Override
public void importDictData(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(baseMapper)).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
<!-- 导入弹出层 -->
<el-dialog title="导入" :visible.sync="dialogImportVisible" width="480px">
<el-form label-position="right" label-width="170px">
<el-form-item label="文件">
<el-upload
:multiple="false"
:on-success="onUploadSuccess"
:action="'http://localhost:8202/admin/cmn/dict/importData'"
class="upload-demo">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传excel文件,且不超过500kb</div>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogImportVisible = false">
取消
</el-button>
</div>
</el-dialog>
添加方法
//导入数据字典
importData(){
this.dialogImportVisible = true
},
//上传成功调用
onUploadSuccess(){
//关闭弹窗
this.dialogImportVisible = false
//刷新页面
this.getDictList(1)
},
package com.cn.yygh.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
import java.time.Duration;
@Configuration
@EnableCaching //开启缓存
public class RedisConfig {
/**
* 自定义key规则 redis结构 k,v
* @return
*/
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 设置RedisTemplate规则
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//序列号key value
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 设置CacheManager缓存规则
* @param factory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
#reids 配置
spring.redis.host=192.168.64.128
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0