拦截器中使用redisTemplate获取数据报空指针

​ 今天做了个小项目,使用自定义一个拦截器后使用redisTemplate获取redis缓存数据一直报null空指针。

在这里插入图片描述
​ 随后使用了debug模式查找问题,发现token值获取到了,且redis中存在该缓存,但获取的还是null。

在这里插入图片描述
​ 查看了代码发现没有什么问题:

//如果未登陆 直接访问某个地址时
public class AuthcFilter extends FormAuthenticationFilter {

    @Autowired
    private  RedisTemplate redisTemplate;
    
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //对OPTION请求方式放行  其他的请求方式都拦截。
        HttpServletRequest req= (HttpServletRequest) request;
        HttpServletResponse resp= (HttpServletResponse) response;
        String method = req.getMethod();
        if(RequestMethod.OPTIONS.name().equals(method)){
            return true;
        }
        return false;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest req= (HttpServletRequest) request;
        HttpServletResponse resp= (HttpServletResponse) response;
        String token = req.getHeader("token");
        Object o = redisTemplate.opsForValue().get(token);
        if(StringUtils.isBlank(token) || o==null){
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setCharacterEncoding("UTF-8");
            CommonResult result=new CommonResult();
            result.setCode(5000);
            result.setMsg("请先登陆");
            String json = JSON.toJSONString(request);
            httpResponse.getWriter().print(json);
            return false;
        }
        return true;
    }
}

​ 这时我才想起来,过滤器或拦截器在生效时,比你的注入要更快,导致redisTemplate还没注入就使用所以会报空指针异常。

解决方法:自定义一个工具类,,让它在注入容器时就生效,在拦截器中只需要使用该工具类即可

@Component //项目运行时就注入Spring容器
public class RedisUtils {
    @Resource
    private RedisTemplate<String, Object> redis;
    
    //赋值一个静态的redisTemplate
    public static RedisTemplate redisTemplate;

    @PostConstruct //此注解表示构造时赋值
    public void redisTemplate() {
        redisTemplate = this.redis;
    }
}

此时项目中只需要使用RedisUtils中的redisTemplate即可。

 String token = req.getHeader("token");
 Object o = RedisUtils.redisTemplate.opsForValue().get(token);
  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在前后端分离的架构,前端发送的请求会经过后端的拦截器处理后返回数据给前端。如果你想在拦截器获取返回给客户端的数据,可以在拦截器使用 HttpServletResponseWrapper 对象来包装 HttpServletResponse,然后重写 getWriter() 和 getOutputStream() 方法,将返回的数据缓存起来。具体实现如下: ```java public class ResponseWrapper extends HttpServletResponseWrapper { private ByteArrayOutputStream bos = new ByteArrayOutputStream(); private PrintWriter writer = new PrintWriter(bos); public ResponseWrapper(HttpServletResponse response) { super(response); } @Override public PrintWriter getWriter() { return writer; } @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public boolean isReady() { return false; } @Override public void setWriteListener(WriteListener writeListener) { } @Override public void write(int b) throws IOException { bos.write(b); } }; } public byte[] getResponseData() throws IOException { writer.flush(); return bos.toByteArray(); } } ``` 然后在拦截器使用这个 ResponseWrapper 对象,将原始的 HttpServletResponse 替换为它,这样在返回数据时就能够获取到返回给客户端的数据了。具体实现如下: ```java public class MyInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 在请求处理之前进行拦截 ResponseWrapper wrapper = new ResponseWrapper(response); request.setAttribute("responseWrapper", wrapper); return true; } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 在请求处理之后进行拦截 ResponseWrapper wrapper = (ResponseWrapper) request.getAttribute("responseWrapper"); byte[] data = wrapper.getResponseData(); String responseStr = new String(data, response.getCharacterEncoding()); System.out.println(responseStr); } } ``` 需要注意的是,在实际使用,可能会有一些特殊情况需要处理,比如返回的数据是二进制数据等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值