我们先创建一个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里面获取信息,不用每次从数据库中获取了。
当你写上用户类后他会自动注入信息。