Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
最根本的原因我还不太清楚,可能是错综复杂的bug
因此,展示我因为这个bug所进行的一些改动
先说明一下,我一开始打算将以下代码抽取成一个方法。
/**
* 根据id查询病患信息
* @param id
* @return
*/
@Override
public Result<Patient> getById1(Long id) {
//Patient patient = cacheClient.queryWithPAssThrough(RedisConstants.CACHE_PATIENT_KEY,id,Patient.class,this::getById,RedisConstants.CACHE_PATIENT_TTL, TimeUnit.MINUTES);
// Patient patient = patientMapper.getById(id);
// return patient;
String key = RedisConstants.CACHE_PATIENT_KEY + id;
//1.从redis查询缓存
String json = stringRedisTemplate.opsForValue().get(key);
//2.判断是否存在
if (StrUtil.isNotBlank(json)) {
//3.存在,直接返回
Patient patient = JSONUtil.toBean(json, Patient.class);
return Result.success(patient);
}
//判断命中的是否是空值
if (json != null) {
//返回一个错误信息
return null;
}
//4.不存在,根据id查询数据库
Patient patient = patientMapper.getById(id);
//5.不存在,返回错误
if(patient == null){
//将空值写入redis
stringRedisTemplate.opsForValue().set(key,"", RedisConstants.CACHE_NULL_TTL,TimeUnit.MINUTES);
//返回错误信息
return null;
}
//6.存在,写入redis
stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(patient),RedisConstants.CACHE_NULL_TTL,TimeUnit.MINUTES);
return Result.success(patient);
}
以下方法。
package com.sky.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.sky.utils.RedisConstants;
import com.sky.utils.RedisData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
@Slf4j
@Component
public class CacheClient {
@Resource
private StringRedisTemplate stringRedisTemplate;
public void set(String key, Object value, Long time, TimeUnit unit){
stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(value),time,unit);
}
public void setWithLogicalExpire(String key,Object value,Long time,TimeUnit unit){
//设置逻辑过期
RedisData redisData = new RedisData();
redisData.setData(value);
redisData.setExpireTime(LocalDateTime.now().plusSeconds(unit.toSeconds(time)));
//写入redis
stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(redisData));
}
public <R,ID> R queryWithPAssThrough
(String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit) {
String key = keyPrefix + id;
//1.从redis查询缓存
String json = stringRedisTemplate.opsForValue().get(key);
//2.判断是否存在
if (StrUtil.isNotBlank(json)) {
//3.存在,直接返回
return JSONUtil.toBean(json, type);
}
//判断命中的是否是空值
if (json != null) {
//返回一个错误信息
return null;
}
//4.不存在,根据id查询数据库
R r = dbFallback.apply(id);
//5.不存在,返回错误
if(r == null){
//将空值写入redis
stringRedisTemplate.opsForValue().set(key,"", RedisConstants.CACHE_NULL_TTL,TimeUnit.MINUTES);
//返回错误信息
return null;
}
//6.存在,写入redis
this.set(key,r,time,unit);
return r;
}
}
于是就出现了这个bug
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.StackOverflowError] with root cause
1.循环注入问题
可能是我的代码太乱了出现的。
2.导包导错了,我猜这个是最重要的。以下是手动代码的,不是idea那些自带的。但是自从我尝试用mybatisplus之后,他就莫名奇怪给我弄了一个一模一样的result
而为了避免用那个奇奇怪怪的代码,idea就给了我一些方法
1.在Result前添加com.sky.result,准确说明这个Result是谁的Result
2.以防万一,将getById改为getById1,避免奇奇怪怪的事情发生。
记录一下!