在Java项目中配置Redis拦截器
在javaWeb项目中,免不了使用Redis作为缓存,但是在开始学习时,会在每个请求前进行拦截进行是否有缓存判断,这样十分没有效率。通常方法应该是利用RedisKey进行缓存命中判断,来进行统一的拦截判断。
一、在Redis中存入RedisKey以及相应的Data
RedisKey:为相应的请求参数进行MD5加密后生成的字符串。
Data:为相应请求的返回结果。
二、编写拦截器以及RedisKey生成方法
package com.dbh123.interceptor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@Component
public class RedisCacheInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, String> redisTemplate;
private static ObjectMapper mapper = new ObjectMapper();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断请求方法只有get方法才拦截 因为只有在请求结果时才会用到缓存
if (!StringUtils.equals(request.getMethod() , "get")){
//当不为get方法时 因为这里用到graphQL,所以还需在post中拦截graphql请求
if (!StringUtils.equals(request.getRequestURI() , "/graphql")){
return true;
}
}
//创建Rediskey
String redisKey = createRedisKey(request);
//从Redis获取数据
String data = this.redisTemplate.opsForValue().get(redisKey);
if (StringUtils.isEmpty(data)) {
//若为空则缓存未命中 通过
return true;
}
//命中填加缓存数据 返回
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
response.getWriter().write(data);
return false;
}
/**
* ReidsKey 创建方法
* @param request
* @return
* @throws Exception
*/
public static String createRedisKey(HttpServletRequest request) throws
Exception {
//1.获取url
String paramStr = request.getRequestURI();
//2.获取参数
Map<String, String[]> parameterMap = request.getParameterMap();
if (parameterMap.isEmpty()) {
//参数为空,及为post方法并通过输入流获取数据 加入参数
paramStr += IOUtils.toString(request.getInputStream(), "UTF-8");}
else {
//将参数加入url中
paramStr += mapper.writeValueAsString(request.getParameterMap());
}
//调用MD5方法将url生成Rediskey
String redisKey = "WEB_DATA_" + DigestUtils.md5Hex(paramStr);
return redisKey;
}
}
三、注册拦截器
package com.dbh123.configuration;
import cn.itcast.haoke.dubbo.api.interceptor.RedisCacheInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private RedisCacheInterceptor redisCacheInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(this.redisCacheInterceptor).addPathPatterns("/**");
}
}
特别要注意:这里若是post请求,会报400请求参数错误,因为由于在拦截器中读取了输入流的数据,在request中的输入流只能读取一次,请求进去Controller时,输入流中已经没有数据了,导致获取不到数据。解决方法详见下一篇文章。