springboot集成redis,实现高可用,高安全性

我们先创建一个springboot的maven 项目
然后添加redis有关依赖

 
        redis.clients
        jedis
    
    
        com.alibaba
        fastjson
        1.2.47
    

然后在application.properties中添加redis的配置

redis.host=192.168.1.105   
redis.port=6379
redis.timeout=10
redis.password=123456
redis.poolMaxTotal=1000
redis.poolMaxIdle=500
redis.poolMaxWait=500

然后创建redisconfig

package com.xcl.Redis;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
//此注解是读取已reids开头的redis配置
@ConfigurationProperties(prefix="redis")
public class RedisConfig {
	private String host;
	private int port;
	private int timeout;//秒
	private String password;
	private int poolMaxTotal;
	private int poolMaxIdle;
	private int poolMaxWait;//秒
	public String getHost() {
		return host;
	}
	public void setHost(String host) {
		this.host = host;
	}
	public int getPort() {
		return port;
	}
	public void setPort(int port) {
		this.port = port;
	}
	public int getTimeout() {
		return timeout;
	}
	public void setTimeout(int timeout) {
		this.timeout = timeout;
	}
	public String getPassword() {
		return password;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public int getPoolMaxTotal() {
		return poolMaxTotal;
	}
	public void setPoolMaxTotal(int poolMaxTotal) {
		this.poolMaxTotal = poolMaxTotal;
	}
	public int getPoolMaxIdle() {
		return poolMaxIdle;
	}
	public void setPoolMaxIdle(int poolMaxIdle) {
		this.poolMaxIdle = poolMaxIdle;
	}
	public int getPoolMaxWait() {
		return poolMaxWait;
	}
	public void setPoolMaxWait(int poolMaxWait) {
		this.poolMaxWait = poolMaxWait;
	}
}

我们先定义一个keyprefix的接口,里面定义了redis数据的存在时间 和key的前缀

package com.xcl.Redis;

public interface KeyPrefix {
    public int expireSeconds();
    public String getPrefix();
}

然后我们用抽象类实现这个接口

package com.xcl.Redis;

/**
 * BasePrefix
 *
 * @author 徐长乐
 * @date 2019/8/5
 */
public abstract class BasePrefix implements KeyPrefix {
    private  int expireSeconds;

    private String prefix;
    public BasePrefix (String prefix) {
        this(0, prefix);
    }

    public BasePrefix(int expireSeconds, String prefix) {
        this.expireSeconds = expireSeconds;
        this.prefix = prefix;
    }

    @Override
    public int expireSeconds() {
        return expireSeconds;
    }

    @Override
    public String getPrefix() {
        String className=getClass().getSimpleName();
        return className+":"+prefix;
    }
}

然后我们可以定义一些关于redis数据key前缀的类,存储不同用处的数据,例如userkey 定义了关于用户数据的前缀,并定义了过期时间,

package com.xcl.Redis;

/**
 * UserKey
 *
 * @author 徐长乐
 * @date 2019/8/5
 */
public class MiaoshaUserKey extends BasePrefix {
    public  static  final  int TOKEN_EXPIRE=3600*24*2;
    public MiaoshaUserKey(int expireSeconds,String prefix) {
        super(expireSeconds,prefix);
    }
    public static MiaoshaUserKey token= new MiaoshaUserKey(TOKEN_EXPIRE,"tk");
}


然后我们创建RedisPoolFactory ,在里面我们定义 返回JedisPool的工厂Bean

package com.xcl.Redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * JedisFactory
 *
 * @author 徐长乐
 * @date 2019/8/4
 */
@Service
public class RedisPoolFactory {
    @Autowired
    RedisConfig redisConfig;
    @Bean
    public JedisPool JedisPoolFactory(){
        JedisPoolConfig poolConfig=new JedisPoolConfig();
        poolConfig.setMaxIdle(redisConfig.getPoolMaxIdle());
        poolConfig.setMaxTotal(redisConfig.getPoolMaxTotal());
        poolConfig.setMaxWaitMillis(redisConfig.getPoolMaxWait()*1000);
        JedisPool jp=new JedisPool(poolConfig,redisConfig.getHost(),redisConfig.getPort(),redisConfig.getTimeout()*1000,
                redisConfig.getPassword(),0);
        return jp;


    }
}

然后我们开始写RedisService,里面定义了redis的get和set、incr、decr等一系列方法,这些方法可以直接调用。

package com.xcl.Redis;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * RedisService
 *
 * @author 徐长乐
 * @date 2019/8/4
 */
@Service
public class RedisService {
    @Autowired
    JedisPool jedisPool;

    public  T get(KeyPrefix prefix,String key,Class clazz){
        Jedis jedis=null;
        try{
       jedis= jedisPool.getResource();
       String realkey =prefix.getPrefix()+key;
        String str= jedis.get(realkey);
        T t=stringToBean(str,clazz);
        return t;
    }finally {
        returnTOPool(jedis);
    }

    }
    public  boolean set(KeyPrefix prefix,String key,T value){
        Jedis jedis=null;
        try{
          jedis=  jedisPool.getResource();
            String str=beanToString(value);
            if (str==null||str.length()<=0){
                return false;
            }
            String realkey=prefix.getPrefix()+key;
            int seconds=prefix.expireSeconds();
            if (seconds<=0){
                jedis.set(realkey,str);
            }else {
                jedis.setex(realkey,seconds,str);
            }

            return true;
        }finally {
            returnTOPool(jedis);
        }
    }
    public  boolean exists(KeyPrefix prefix,String key){
        Jedis jedis=null;
        try{
            jedis=  jedisPool.getResource();
            String realkey=prefix.getPrefix()+key;
            jedis.exists(realkey);
            return true;
        }finally {
            returnTOPool(jedis);
        }
    }
    public  Long incr(KeyPrefix prefix,String key){
        Jedis jedis=null;
        try{
            jedis=  jedisPool.getResource();
            String realkey=prefix.getPrefix()+key;
          return   jedis.incr(realkey);
        }finally {
            returnTOPool(jedis);
        }
    }
    public  Long decr(KeyPrefix prefix,String key){
        Jedis jedis=null;
        try{
            jedis=  jedisPool.getResource();
            String realkey=prefix.getPrefix()+key;
            return   jedis.decr(realkey);
        }finally {
            returnTOPool(jedis);
        }
    }
    private  String beanToString(T value) {
        if (value==null){
                return  null;
        }
        Class clazz=value.getClass();
         if (clazz==int.class||clazz==Integer.class){
                return ""+value;
        }else if (clazz==String.class){
                return (String)value;
        }else if (clazz==long.class||clazz==Long.class){
                return ""+value;
        }else {
            return JSON.toJSONString(value);
        }

    }

    private  T stringToBean(String str,Class clazz) {
        if (str==null||str.length()<=0||clazz==null){
            return  null;
        }
        if (clazz==int.class||clazz==Integer.class){
         return (T) Integer.valueOf(str);
        }else if (clazz==String.class){
            return (T) str;
        }else if (clazz==long.class||clazz==Long.class){
            return (T) Long.valueOf(str);
        }else {
            return JSON.toJavaObject(JSON.parseObject(str),clazz);
        }

    }

    private void returnTOPool(Jedis jedis) {
        if (jedis!=null){
            jedis.close();
        }
    }



}

reidsservice使用实例

这个是一个登录的功能,我们把用户信息存到redis里,然后把信息的key存到cookie里,(这个时候 相当于我们cookie里面存的是用户信息的key,并且用户信息的key添加了前缀,然后和UUID拼装了起来)当我们需要获取用户信息是可以先从cookie中获取key然后利用RedisService里的get方法获取。

package com.xcl.service;

import com.sun.deploy.net.HttpResponse;
import com.xcl.Exception.GlobalException;
import com.xcl.Redis.MiaoshaUserKey;
import com.xcl.Redis.RedisService;
import com.xcl.VO.LoginVo;
import com.xcl.domain.MiaoshaUser;
import com.xcl.mapper.MiaoshaUserDao;
import com.xcl.result.CodeMsg;
import com.xcl.util.MD5Util;
import com.xcl.util.UUIDutil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

/**
 * MiaoshaUserService
 *登录业务
 * @author 徐长乐
 * @date 2019/8/5
 */
@Service
public class MiaoshaUserService {
//定义用户信息存到 cookie key的名称
    public static final String COOKI_NAME_TOKEN="token";
    @Autowired
    MiaoshaUserDao miaoshaUserDao;
    @Autowired
    RedisService redisService;

    public MiaoshaUser getById(long id){
        return  miaoshaUserDao.getById(id);
    }
//利用token获取redis里面的用户信息
    public  MiaoshaUser getByToken(HttpServletResponse response,String token){
        if (StringUtils.isEmpty(token)){
            return null;
        }
        MiaoshaUser user= redisService.get(MiaoshaUserKey.token,token,MiaoshaUser.class);
        addCookie(response,token,user);
        return user;

    }
    public boolean login(HttpServletResponse response, LoginVo loginVo){
        if (loginVo==null){
            throw  new GlobalException(CodeMsg.SERVER_ERROR);
        }
        String mobile=loginVo.getMobile();
        String password=loginVo.getPassword();
        //判断手机号码是否存在
     MiaoshaUser user= getById(Long.parseLong(mobile));
     if (user==null){
         throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
     }
     //验证密码
     String dbPass=user.getPassword();
     String saltDb=user.getSalt();

     String calcpass=MD5Util.formpassToDBPass(password,saltDb);
     if (!dbPass.equals(calcpass)){
         throw  new GlobalException(CodeMsg.PASSWORD_ERROR);
     }
     String token=UUIDutil.uuid();
         addCookie(response, token,user);
         return true;
    }
    //将用户信息添加到redis里
    private  void  addCookie(HttpServletResponse response, String token,MiaoshaUser user){
                  //给token添加前缀
        redisService.set(MiaoshaUserKey.token,token,user);
        Cookie cookie=new Cookie(COOKI_NAME_TOKEN,token);
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
    }
}

当我们把用户信息存到了redis里面我们如何实现高可用呢?
我们可以将我们的用户信息自动获取注入

package com.xcl.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import java.util.List;

/**
 * WebConfig
 *
 * @author 徐长乐
 * @date 2019/8/6
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Autowired
    UserArgumentsResolver userArgumentsResolver;

    @Override
    public void addArgumentResolvers(List argumentResolvers) {
      argumentResolvers.add(userArgumentsResolver);
    }
}

package com.xcl.config;

import com.xcl.domain.MiaoshaUser;
import com.xcl.service.MiaoshaUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.thymeleaf.util.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * UserArgumentsResolver
 *
 * @author 徐长乐
 * @date 2019/8/6
 */
@Service
public class UserArgumentsResolver implements HandlerMethodArgumentResolver {
    @Autowired
    MiaoshaUserService userService;
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
      Class clazz=  parameter.getParameterType();

        return clazz==MiaoshaUser.class;
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request=webRequest.getNativeRequest(HttpServletRequest.class);
        HttpServletResponse response=webRequest.getNativeResponse(HttpServletResponse.class);

        String paramToken=request.getParameter(MiaoshaUserService.COOKI_NAME_TOKEN);
        String cookieToken=getCookievalue(request,MiaoshaUserService.COOKI_NAME_TOKEN);
        if (StringUtils.isEmpty(cookieToken)&&StringUtils.isEmpty(paramToken)){
            return  null;
        }
        String token=StringUtils.isEmpty(paramToken)?cookieToken:paramToken;

        return userService.getByToken(response,token);
    }

    private String getCookievalue(HttpServletRequest request, String cookiNameToken) {
      Cookie[] cookies= request.getCookies();
        for (Cookie cookie:cookies) {
            if (cookie.getName().equals(cookiNameToken)){
                return cookie.getValue();
            }
        }
        return null;
    }
}

当我们写完上面两个类之后,我们在Controller可以这么写,然后就会自动从cookie里面获取用户的key,然后从redis里面获取信息,不用每次从数据库中获取了。
springboot集成redis,实现高可用,高安全性_第1张图片
当你写上用户类后他会自动注入信息。

你可能感兴趣的:(入门级)