spring中使用拦截器WebMvcConfigurer读取redis缓存、使用ResponseBodyAdvice存放redis数据

2 篇文章 0 订阅

1、创建项目

2、添加依赖


    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.0.RELEASE</version>
    </parent>

    <dependencies>
	     <dependency>
	         <groupId>org.springframework.boot</groupId>
	         <artifactId>spring-boot-starter-web</artifactId>
	     </dependency>
	     <dependency>
	         <groupId>com.graphql-java</groupId>
	         <artifactId>graphql-java</artifactId>
	         <version>14.0</version>
	     </dependency>
	     <!--thymeleaf 模板引擎-->
	     <dependency>
	         <groupId>org.springframework.boot</groupId>
	         <artifactId>spring-boot-starter-thymeleaf</artifactId>
	     </dependency>
	     <dependency>
	         <groupId>org.springframework.boot</groupId>
	         <artifactId>spring-boot-starter-data-redis</artifactId>
	     </dependency>
	     <!-- redis依赖commons-pool 这个依赖一定要添加 -->
	     <dependency>
	         <groupId>org.apache.commons</groupId>
	         <artifactId>commons-pool2</artifactId>
	     </dependency>
	     <dependency>
	         <groupId>redis.clients</groupId>
	         <artifactId>jedis</artifactId>
	         <!--<version>2.7.2</version>-->
	     </dependency>
	     <dependency>
	         <groupId>commons-io</groupId>
	         <artifactId>commons-io</artifactId>
	         <version>2.6</version>
	     </dependency>
	     <dependency>
	         <groupId>commons-codec</groupId>
	         <artifactId>commons-codec</artifactId>
	     </dependency>
	     <dependency>
	         <groupId>org.projectlombok</groupId>
	         <artifactId>lombok</artifactId>
	         <!--需要注意传递依赖中、如果需要使用、请显示引入-->
	         <optional>true</optional>
	     </dependency>
	     <dependency>
	         <groupId>com.baomidou</groupId>
	         <artifactId>mybatis-plus-boot-starter</artifactId>
	         <version>3.0.5</version>
	         <optional>true</optional>
	     </dependency>
	     <dependency>
	         <groupId>mysql</groupId>
	         <artifactId>mysql-connector-java</artifactId>
	         <version>5.1.47</version>
	     </dependency>
	 </dependencies>

3、创建user表

CREATE TABLE user3(
	id INT KEY AUTO_INCREMENT,
	name VARCHAR(20),
	age INT,
	email VARCHAR(50)
)
//随便添加点数据
 INSERT INTO user3(name,age,email) VALUES("张三",123,"645531@qq.com"),("李三",23,"6475531@qq.com"),("张阿三打",13,"647731@qq.com"),("网页",33,"644561@qq.com"),("哈哈",73,"64781@qq.com")

4、编写application.properties文件

# Spring boot application
spring.application.name = haoke-manage-dubbo-server-house-resources

# ?????
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://你的ip地址:3306/haoke?useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true&useSSL=false
spring.datasource.username=root
spring.datasource.password=root



# redis集群配置
# 接池最大阻塞等待时间(使用负值表示没有限制) 默认-1
spring.redis.jedis.pool.max-wait = 500
# 连接池中的最大空闲连接 默认8
spring.redis.jedis.pool.max-Idle = 100
# 连接池中的最小空闲连接 默认8
spring.redis.jedis.pool.min-Idle = 8
#集群地址
spring.redis.cluster.nodes = 你的ip地址:6380,你的ip地址:6382,你的ip地址:6381
#最大重定向没有是使用
spring.redis.cluster.max-redirects=5
#最大连接数量
spring.redis.jedis.pool.max-active=100

5、编写启动类

package cn.lfd.redis;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.SpringApplication;

@SpringBootApplication
public class Provider {

    public static void main(String[] args) {
        SpringApplication.run(Provider.class,args);
    }
}

6、编写controller

package cn.lfd.redis.controller;

import cn.lfd.redis.pojo.User;
import cn.lfd.redis.service.UserService;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.Map;

@RequestMapping("hello")
@RestController
public class UserController {

    @Autowired
    UserService userService;

    @GetMapping
    public List<User> getStr(HttpServletRequest request) {
        //获取请求参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        for(String key:parameterMap.keySet()){
            System.out.println(key);
            System.out.println(parameterMap.get(key)[0]);
        }
        List<User> str = userService.getStr();
        return str;
    }

    @PostMapping
    public List<User> postStr(HttpServletRequest request) {
        List<User> str = userService.getStr();
        return str;
    }
}

7、编写service

7.1编写UserService

package cn.lfd.redis.service;


import cn.lfd.redis.pojo.User;

import java.util.List;

public interface UserService {
    List<User> getStr();


}

7.2编写BaseServiceimpl

package cn.lfd.redis.service;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public abstract class BaseServiceimpl<T> {
	//使用mybatisplus
    @Autowired
    private BaseMapper<T> mapper;

    //查询所有数据
    public List<T> queryAll() {
        return this.mapper.selectList(null);
    }
}

7.3编写UserService实现类

package cn.lfd.redis.service.impl;

import cn.lfd.redis.pojo.User;
import cn.lfd.redis.service.BaseServiceimpl;
import cn.lfd.redis.service.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
@Transactional  //开启事务
public class UserImpl extends BaseServiceimpl<User> implements UserService {


    @Override
    public List<User> getStr() {
        return super.queryAll();
    }
}

8、编写User类

package cn.lfd.redis.pojo;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)    //使用链式编程return this
@TableName("user")    //指定表名
public class User {

    private int id;
    private String name;
    private int age;
    private String email;


}

9、创建Mapper文件夹

package cn.lfd.redis.mapper;

import cn.lfd.redis.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface UserMapper extends BaseMapper<User> {

}

10、创建Interceptor文件夹

10.1、创建ResponseBodyAdvice 类

package cn.lfd.redis.Interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.time.Duration;

@ControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice {
    //ResponseBodyAdvice是对请求响应后对结果的处理,一般使用环境是处理加密的json串。
    //需要在controller层中调用方法上加入@RequstMapping和@ResponseBody;后者若没有,则ResponseBodyAdvice实现方法不执行。
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private ObjectMapper mapper = new ObjectMapper();

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
   		 //判断哪些请求需要进行拦截
        if (returnType.hasMethodAnnotation(GetMapping.class)) {
            return true;
        }


        return false;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    	//重写需要拦截请求的返回值、或者在返回之前存到redis
        try {
            String redisKey = RedisCacheInterceptor.createRedisKey(((ServletServerHttpRequest) request).getServletRequest());
            String redisValue;
            if(body instanceof String){
                redisValue = (String)body;
            }else{
                redisValue = mapper.writeValueAsString(body);
            }
            //key、val、超时时间
            this.redisTemplate.opsForValue().set(redisKey,redisValue , Duration.ofHours(1));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return body;
    }
}

10.2创建HandlerInterceptor

package cn.lfd.redis.Interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
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 org.thymeleaf.util.StringUtils;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@Component
public class RedisCacheInterceptor implements HandlerInterceptor {

    private static ObjectMapper mapper = new ObjectMapper();

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

	//在业务处理器处理请求之前被调用。预处理,可以进行编码、安全控制、权限校验等处理;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        if (!StringUtils.equalsIgnoreCase(request.getMethod(),"OPTIONS")) {
//            return true;
//        }

        //判断请求方式:get、post还是其他
        if (!StringUtils.equalsIgnoreCase(request.getMethod(), "GET")) {
            //非get请求、如果不是graphql请求、放行
            if (!StringUtils.equalsIgnoreCase(request.getRequestURI(), "/graphql")) {
                return true;
            }
        }
        //通过缓存做命中、查询redis,redisKey? 组成:md5(请求url+请求参数)
        String redisKey = createRedisKey(request);
        String data = this.redisTemplate.opsForValue().get(redisKey);
        if (StringUtils.isEmpty(data)) {
            // 缓存未命中
            return true;
        }

        //将data数据进行相映
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");

        // 支持跨域
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        //将结果返回到前端
        response.getWriter().write(data);
        //直接返回结果
        return false;
    }

    public static String createRedisKey(HttpServletRequest request) throws Exception {
        String paramStr = request.getRequestURI();
        //getParameterMap()返回的是一个Map类型的值,该返回值记录着前端(如jsp页面)所提交请求中的请求参数和请求参数值的映射关系
        //这个返回值有个特别之处——只能读。不像普通的Map类型数据一样可以修改。这是因为服务器为了实现一定的安全规范,所作的限制。
        // 比如WebLogic,Tomcat,Resin,JBoss等服务器均实现了此规范。
        Map<String, String[]> parameterMap = request.getParameterMap();
        for(String key:parameterMap.keySet()){
            System.out.println(key);
            System.out.println(parameterMap.get(key)[0]);
        }
        if (parameterMap.isEmpty()) {
            //IOUtils.toString:可以从输入流读取所有内容:
            paramStr += IOUtils.toString(request.getInputStream(), "UTF-8");
        } else {
            //使用jackon的ObjectMapper的writeValueAsString方法可以把java对象转化成json字符串
            paramStr += mapper.writeValueAsString(request.getParameterMap());
        }
        //把String字符串进行md5加密
        String redisKey = "WEB_DATA_" + DigestUtils.md5Hex(paramStr);
        return redisKey;
    }


}

11、编写各种配置文件

11.1、redis配置文件

package cn.lfd.redis.config;

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.List;

@Component
@ConfigurationProperties(prefix = "spring.redis.cluster")
@Data
public class ClusterConfigurationProperties {

    private List<String> nodes;
    //最大重定向次数
    private Integer maxRedirects;
    //刷新时间
    private Integer refreshTime;
    //最大空闲连接数
    @Value("#{${spring.redis.jedis.pool.max-Idle}}")
    private Integer maxIdle;
    //最小空闲连接
    @Value("#{${spring.redis.jedis.pool.min-Idle}}")
    private Integer minIdle;
    //最大连接数量
    @Value("#{${spring.redis.jedis.pool.max-active}}")
    private Integer maxActive;
    //最大等待毫秒数
    @Value("#{${spring.redis.jedis.pool.max-wait}}")
    private Integer maxWait;
}

package cn.lfd.redis.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisClusterConfiguration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisClusterConfig {
    @Autowired
    private ClusterConfigurationProperties clusterProperties;
    @Bean
    public RedisConnectionFactory connectionFactory() {
        RedisClusterConfiguration configuration = new
                RedisClusterConfiguration(clusterProperties.getNodes());
        configuration.setMaxRedirects(clusterProperties.getMaxRedirects());
        return new JedisConnectionFactory(configuration);
    }

    @Bean
    public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory redisConnectionfactory) {
        RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionfactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
}

11.2拦截器配置文件

package cn.lfd.redis.config;


import cn.lfd.redis.Interceptor.RedisCacheInterceptor;
import org.mybatis.spring.annotation.MapperScan;
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;

//使用拦截器WebMvcConfigurer
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private RedisCacheInterceptor redisCacheInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //设置拦截请求地址
        registry.addInterceptor(this.redisCacheInterceptor).addPathPatterns("/**");
    }
}

11.3mybatisplus配置文件

package cn.lfd.redis.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@MapperScan({"cn.lfd.redis.mapper"})
@Configuration
public class MyBatisConfig {

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值