在一个完整的项目中,可能有许多微服务需要集成Feign和Redis来提高效率。
我们正常的想法就是,哪个服务需要就去那个服务集成,这样我们会发现那样不好,大量的重复代码,造成了性能下降,也不便于管理。
有要重复使用的代码,抽取成公共方法;
有重复使用的类,抽取成为公共类;
微服务也一样
总结一个字-- 抽
我们将Redis和Feign抽取出来,成为一个redis-server模块。需要集成那么直接依赖redis-server服务即可
Redis是需要用Tomcat跑起来的,所以需要添加端口;而feign则不需要
Feign配置中需要自定义接口,那微服务怎么使用Feign呢?
真正的是微服务(如课程服务)集成feign,我们只是抽取接口成为公共模块
配置类上打feign客户端标签@EnableFeignClients(“填接口所在包”) 开启feign即可 (哪个服务需要谁就开启)
步骤略过,这里有详细集成步骤
Eureka集成和集群:
https://blog.csdn.net/weixin_45561263/article/details/104347501
Ribbon负载均衡器/Feign/Hystrix断路器/Zuul网关/config 分布式配置:
https://blog.csdn.net/weixin_45561263/article/details/104349726
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.io.IOException;
import java.util.Properties;
/**
* 获取连接池对象
*/
public enum RedisUtils {
INSTANCE;
static JedisPool jedisPool = null;
static {
//1 创建连接池配置对象
JedisPoolConfig config = new JedisPoolConfig();
//2 进行配置-四个配置
config.setMaxIdle(1);//最小连接数
config.setMaxTotal(11);//最大连接数
config.setMaxWaitMillis(10 * 1000L);//最长等待时间
config.setTestOnBorrow(true);//测试连接时是否畅通
//3 通过配置对象创建连接池对象
Properties properties = null;
try {
properties = new Properties();
properties.load(RedisUtils.class.getClassLoader().getResourceAsStream("redis.properties"));
} catch (IOException e) {
e.printStackTrace();
}
String host = properties.getProperty("redis.host");
String port = properties.getProperty("redis.port");
String password = properties.getProperty("redis.password");
String timeout = properties.getProperty("redis.timeout");
jedisPool = new JedisPool(config, host, Integer.valueOf(port),Integer.valueOf(timeout), password);
}
//获取连接
public Jedis getSource() {
return jedisPool.getResource();
}
//关闭资源
public void closeSource(Jedis jedis) {
if (jedis != null) {
jedis.close();
}
}
/**
* 设置字符值
*
* @param key
* @param value
*/
public void set(String key, String value) {
Jedis jedis = getSource();
jedis.set(key, value);
closeSource(jedis);
}
/**
* 设置
* @param key
* @param value
*/
public void set(byte[] key, byte[] value) {
Jedis jedis = getSource();
jedis.set(key, value);
closeSource(jedis);
}
/**
*
* @param key
* @return
*/
public byte[] get(byte[] key) {
Jedis jedis = getSource();
try {
return jedis.get(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeSource(jedis);
}
return null;
}
/**
* 设置字符值
*
* @param key
*/
public String get(String key) {
Jedis jedis = getSource();
try {
return jedis.get(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
closeSource(jedis);
}
return null;
}
}
redis.host=127.0.0.1
redis.port=6379
redis.password=123456
redis.timeout=10000
import cn.itsource.hrm.util.AjaxResult;
import cn.itsource.redis.utils.RedisUtils;
import org.springframework.web.bind.annotation.*;
@RequestMapping("/redis")
@RestController
public class RedisController {
@PostMapping("/set")// 从请求中获取值,将值设置给对应参数key
public AjaxResult set(@RequestParam("key") String key,@RequestParam("value") String value){
RedisUtils.INSTANCE.set(key,value );
return AjaxResult.me();
}
@GetMapping("/get/{key}")//PathVariable:将参数key值设置给uri中的key
public AjaxResult get(@PathVariable("key") String key){
String result = RedisUtils.INSTANCE.get(key);
//通过setResultObj方法返回到前台对象
return AjaxResult.me().setResultObj(result);
}
}
<dependency>
<groupId>cn.itsourcegroupId>
<artifactId>hrm-redis-feignartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
@EnableFeignClients("cn.xxx.redis.feignclients")//开启服务集成feign
缓存更新
思路:
在添加,修改,删除的时候重置缓存
即操作完数据之后同步一份到Redis
/**
*
* 课程目录 服务实现类
*
*
* @author rjm
* @since 2020-02-17
*/
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {
@Autowired
private RedisFeignClient redisFeignClient;
//操作也使用Redis
//controller用什么方法就覆写什么方法
//覆写删除、修改、添加方法
@Override
public boolean insert(CourseType entity) {
//先对数据库执行操作
boolean result = super.insert(entity);
//重置Redis
resetRedis();
return result;
}
@Override
public boolean deleteById(Serializable id) {
boolean result= super.deleteById(id);
//重置Redis
resetRedis();
return result;
}
@Override
public boolean updateById(CourseType entity) {
boolean result = super.updateById(entity);
//重置Redis
resetRedis();
return result;
}
//自定义重置Redis的方法
public List<CourseType> resetRedis(){
//Redis没数据,从数据库中查询
List<CourseType> courseTypes = baseMapper.selectList(null);
//将courseTypes数据转换成string类型,同步一份到Redis
redisFeignClient.set("course_type", JSON.toJSONString(courseTypes));
return courseTypes;
}
@Override
public List<CourseType> treeData() {
//查询使用Redis
//集成feign使用Redis
List<CourseType> courseTypes = null;
//先查询Redis,
AjaxResult result = redisFeignClient.get("course_type");
if (result.isSuccess() && result.getResultObj() != null) {//存在数据且不为空
//获取json的数据字符串
String coursetypes = result.getResultObj().toString();
//返回CourseType类型的数据
courseTypes = JSON.parseArray(coursetypes, CourseType.class);
} else {
courseTypes = resetRedis();
}
//先查所有课程分类 wrapper:条件
//在通用impl里有basemapper,上面泛型放什么就是谁的basemapper,直接调用里面的方法
// List courseTypes = baseMapper.selectList(null);
/*---------------下面是获取课程多级分类的代码-------------------*/
//准备集合装所有 顶级父亲
List<CourseType> topLevelParentCourseTypes = new ArrayList<>();
//遍历所有课程分类
for (CourseType courseType : courseTypes) {
//判断pid,为0即为顶级父亲
//Java里面定义的id是Long包装类型,转成long来和0比较是最准确的
if(courseType.getPid().longValue() == 0){
//将顶级课程分类放入集合中的CourseType中
topLevelParentCourseTypes.add(courseType);
} else {//非顶级课程分类,即pid不为0
//遍历非顶级课程分类
//核心思路:各自找各自的父,找到后装进各自父课程类型中的children中
for (CourseType currentCourseTypes : courseTypes) {
//当前分类的id和某个分类的pid相等那么这一对就是父子
if(currentCourseTypes.getId().longValue() == courseType.getPid().longValue()){
//父 currentCourseTypes 子 courseType
//将子装进父中children里
currentCourseTypes.getChildren().add(courseType);
//成功找到一对父子并装好结构,结束该循环。
break;
}
}
}
//break后,开始下一次循环找其他的父子并组装
}
//返回已经组装好的结构
return topLevelParentCourseTypes;
}
}