分布式环境中的登录应用

在分布式环境中使用kapcha和redis完成登录功能。

1.添加jar包

<!-- kaptcha -->  
<dependency>  
    <groupId>com.google.code.kaptcha</groupId>  
    <artifactId>kaptcha</artifactId>  
    <version>2.3.2</version>  
</dependency>
2.在spring-mvc-servlet.xml中添加拦截器和captchaProducer bean
    <mvc:status-controller status-code="200" path="/status"/>
    <mvc:view-controller path="/" view-name="redirect:/login" />
    <!-- 对静态资源文件的访问  restful-->
    <mvc:resources mapping="/static/**" location="/static/" cache-period="31556926"/>
    <mvc:resources location="/favicon.ico" mapping="/favicon.ico" />
    <mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/" />
    <mvc:resources mapping="/swagger-ui.html" location="classpath:/META-INF/resources/" />
    <!-- 访问拦截  -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <mvc:exclude-mapping path="/static/**" />
            <mvc:exclude-mapping path="/favicon.ico"/>
            <mvc:exclude-mapping path="/status"/>
            <mvc:exclude-mapping path="/webjars/**" />
            <mvc:exclude-mapping path="/*/api-docs" />
            <mvc:exclude-mapping path="/swagger-ui.html" />
            <mvc:exclude-mapping path="/configuration/**" />
            <bean class="com.buoumall.common.web.interceptor.EventInterceptor">
                <property name="nextInterceptor">
                    <array>
                        <!-- 登录拦截器 -->
                        <bean class="com.buoumall.front.interceptor.LoginInterceptor">
                            <property name="loginUrl" value="/login"/>
                        </bean>
                    </array>
                </property>
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>

    <!-- 验证码 -->
    <bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">
        <property name="config">
            <bean class="com.google.code.kaptcha.util.Config">
                <constructor-arg>
                    <props>
                        <prop key="kaptcha.border">no</prop>
                        <prop key="kaptcha.border.color">105,179,90</prop>
                        <prop key="kaptcha.textproducer.font.color">red</prop>
                        <prop key="kaptcha.image.width">250</prop>
                        <prop key="kaptcha.textproducer.font.size">90</prop>
                        <prop key="kaptcha.image.height">120</prop>
                        <prop key="kaptcha.session.key">code</prop>
                        <prop key="kaptcha.textproducer.char.length">4</prop>
                        <prop key="kaptcha.textproducer.font.names">宋体,楷体,微软雅黑</prop>
                    </props>
                </constructor-arg>
            </bean>
        </property>
    </bean>
3.生成验证码的controller
	//生成验证码
	@RequestMapping("/captcha-image")
	public void captchaImageCode(@RequestParam Integer bizType,HttpServletRequest request, HttpServletResponse response) throws BizException {
		response.setDateHeader("Expires", 0);
		// Set standard HTTP/1.1 no-cache headers.
		response.setHeader("Cache-Control","no-store, no-cache, must-revalidate");
		// Set IE extended HTTP/1.1 no-cache headers (use addHeader).
		response.addHeader("Cache-Control", "post-check=0, pre-check=0");
		// Set standard HTTP/1.0 no-cache header.
		response.setHeader("Pragma", "no-cache");
		// return a jpeg
		response.setContentType("image/png");
		// create the text for the image
		String capText = captchaProducer.createText();
		//bizType为业务类型,这里为LOGIN
		BizTypeEnum bizTypeEnum = BizTypeEnum.findByBizType(bizType);
		if (bizTypeEnum == null) {
			logger.error("The bizType is illegal!");
			return;
		}
		//客户端保存一个验证码的cookie,GlobalConst.BOM_CAPTCHA_KEY为cookie的name,value为一个随机数
		String captcha_key = CookieUtil.getCookieValue(request,GlobalConst.BOM_CAPTCHA_KEY);
		//如果取出来的为空,这表示是一个新用户,客户端没有这个cookie,就新建一个
		if(StringUtils.isBlank(captcha_key)){
			captcha_key = UuidUtil.get32UUID();
			logger.info("New user coming,captcha_key = {}", captcha_key);
			CookieUtil.addCookie(response, GlobalConst.BOM_CAPTCHA_KEY, captcha_key, CaptchaCodeUtil.CAPTCHA_TIME_OUT);
		}
		//将验证码和客户端cookie的信息存在redis中
		CaptchaCodeUtil.addCaptchaCode(captcha_key,redisService, bizTypeEnum, capText);
		OutputStream out = null;
		try {
			// create the image with the text
			BufferedImage bi = captchaProducer.createImage(capText);
			out = response.getOutputStream();
			// write the data out
			ImageIO.write(bi, "png", out);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			IOUtils.closeQuietly(out);
		}
	}

	//判断验证码是否正确
	//一般是先判断验证码是否正确,如果正确再进行登录判断,不然提示验证码错误。
	@RequestMapping(value = "/checkCaptchaCode")
	@ResponseBody
	public Result<Boolean> checkCaptchaCode(HttpServletRequest request,
			@RequestParam Integer bizType, @RequestParam String captchaCode) {
		//bizType表示业务类型,这里是LOGIN
		BizTypeEnum bizTypeEnum = BizTypeEnum.findByBizType(bizType);
		if (bizTypeEnum == null) {
			logger.error("The bizType is illegal!");
			return super.buildBizErrorResult("验证码bizType不合法");
		}
		//得到客户端cookie的value,redis里的key就是通过这个value生成的
		String captchaKey = CookieUtil.getCookieValue(request, GlobalConst.BOM_CAPTCHA_KEY);
		//在redis中判断验证码是否正确
		boolean captchaCodeOk = CaptchaCodeUtil.captchaCodeOk(captchaKey,redisService, bizTypeEnum, captchaCode);
		if (captchaCodeOk) {
			return super.buildOk(true);
		} else {
			return super.buildBizErrorResult("验证码不正确");
		}
	}
4.图形验证码工具类
/**
 * 图形验证码工具类,目前主要是未登录,基于Cookie的方式。用户已登录的情况,暂时没有。
 */
public class CaptchaCodeUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(CaptchaCodeUtil.class);
	public static final String CAPTCHA_NAMESPACE = "captcha";
	//验证码在redis中保存的时间
	public static final int CAPTCHA_TIME_OUT = 10 * 60;

	//captcha_key为一个随机数,captchaCode为验证码
	//captchaKey为redis中的key,captchaCode为value

	//添加验证码信息到redis
	public static void addCaptchaCode(String captcha_key,RedisService redisService, BizTypeEnum bizType, String captchaCode) throws BizException {
		String captchaKey = buildCaptchaKey(captcha_key, captchaCode, bizType);
		if (StringUtils.isNotBlank(captchaKey)) {
			redisService.add(captchaKey, captchaCode, CAPTCHA_TIME_OUT, TimeUnit.SECONDS);
		}
	}

	// 验证某个业务的验证码,是否正确
	public static boolean captchaCodeOk(String captcha_key,RedisService redisService, BizTypeEnum bizType, String captchaCode) {
		try {
			String captchaKey = buildCaptchaKey(captcha_key,captchaCode, bizType);
			if(StringUtils.isNotBlank(captchaKey)){
				// 验证码
				String captchaCodeRedis = redisService.getString(captchaKey);
				if (StringUtils.equalsIgnoreCase(captchaCodeRedis, captchaCode)) {
					return true;
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}
		return false;
	}

	//重新构建redis中的key
	private static String buildCaptchaKey(String captcha_key,String captchaCode, BizTypeEnum bizType) {
		if(StringUtils.isBlank(captcha_key)){
			return null;
		}
		String captchaKey = CAPTCHA_NAMESPACE + ":" + bizType.getDir() + ":" + captcha_key + ":" + captchaCode;
		return captchaKey;
	}

	//删除redis中验证码的信息
	public static void deleteCaptchaCode(String captcha_key,RedisService redisService, String captchaCode, BizTypeEnum bizType) throws BizException {
		String captchaKey = buildCaptchaKey(captcha_key, captchaCode, bizType);
		if (StringUtils.isNotBlank(captchaKey)) {
			redisService.delete(captchaKey);
		}
	}
}
5.登录和登出
	@ApiOperation(value = "登录", produces = MediaType.APPLICATION_JSON_VALUE)
	@RequestMapping(value = "/doLogin",produces = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public Result<Boolean> doLogin(
			@ApiParam(required = true, value = "登录名") @RequestParam String loginName,
			@ApiParam(required = true, value = "登录密码") @RequestParam String password, 
			@ApiParam(required = true, value = "验证码") @RequestParam String captchaCode,
			HttpServletResponse response, 
			HttpServletRequest request
			){
		try {
			BizTypeEnum bizType = BizTypeEnum.LOGIN;
			//从客户端cookie中得到redis的value
			String captcha_Key = CookieUtil.getCookieValue(request, GlobalConst.BOM_CAPTCHA_KEY);
			boolean captchaCodeOk = CaptchaCodeUtil.captchaCodeOk(captcha_Key, redisService, bizType, captchaCode);
			if(!captchaCodeOk){
				return buildBizErrorResult("验证码错误!");
			}
			// 删除验证码
			CaptchaCodeUtil.deleteCaptchaCode(captcha_Key, redisService, captchaCode, bizType);
			Member member = memberSecurityBizService.login(loginName, password);
			if(member == null){
				logger.info("Login failed,loginName=" + loginName);
				return buildBizErrorResult("用户名和密码信息输入有误!");
			}
			if(!RoleTypeEnum.DESIGNER.getCode().equals(member.getRoleType()) && !RoleTypeEnum.EDITOR.equals(member.getRoleType())){
				return buildBizErrorResult("你无权登录本系统!");
			}
			//用户token的key值
			String login_ut_key = UuidUtil.get32UUID();
			//在客户端添加有关用户信息的Cookie
			CookieUtil.addCookie(response, GlobalConst.BOM_FRONT_UT, login_ut_key, GlobalConst.KEEP_BOM_FRONT_UT_TIME);
			//在redis中添加用户信息
			redisService.add(login_ut_key, member,1,TimeUnit.HOURS);
		    return buildOk(true);
		} catch (Exception e) {
			return buildExceptionResult(e);
		}
	}

	@ApiOperation(value = "登出", produces = MediaType.TEXT_HTML_VALUE)
	@RequestMapping(value = "/logout", produces = MediaType.TEXT_HTML_VALUE)
	public String logout(HttpServletRequest request, HttpServletResponse response) {
		try {
			logger.info("Logout");
			String accessTokenKey = CookieUtil.getCookieValue(request,GlobalConst.BOM_FRONT_UT);
			if(StringUtils.isNotBlank(accessTokenKey)){
				CookieUtil.removeCookie(response, GlobalConst.BOM_FRONT_UT);
				redisService.delete(accessTokenKey);
			}
		} catch (Exception e) {
			logger.error("Logout failed");
			e.printStackTrace();
		}
		return "login/login";
	}
6.登录拦截器LoginInterceptor
package com.front.interceptor;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;

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

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.method.HandlerMethod;

import com.alibaba.fastjson.JSON;
import com.common.web.interceptor.BaseInterceptor;
import com.common.web.util.CommonUtil;
import com.common.web.util.CookieUtil;
import com.common.web.util.RequestUtils;
import com.common.web.util.ResponseUtils;
import com.commonService.service.RedisService;
import com.front.result.Result.ResultCodeEnum;
import com.front.util.FrontLoginUtil;
import com.front.util.GlobalConst;
import com.front.util.NeedRole;
import com.userService.enums.RoleTypeEnum;
import com.userService.model.Member;
import com.userService.model.MemberDetail;
import com.userService.service.MemberDetailService;
import com.google.common.collect.Maps;

public class LoginInterceptor extends BaseInterceptor {

	private String loginUrl;

	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private MemberDetailService memberDetailService;
	@Autowired
	private RedisService redisService;
	
	@Override
	public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
		//将线程中的用户信息清空
		FrontLoginUtil.setCurrentUser(null);
		// User项目也需要响应图片
		boolean b = handler instanceof HandlerMethod;
		if (!b) {
			return true;
		}
		//客户端cookie用户的value
		String accessToken = CookieUtil.getCookieValue(request,GlobalConst.BOM_FRONT_UT);
		
		Member member =null;
		try {
			if(StringUtils.isNotEmpty(accessToken)){
				member = (Member) redisService.getValue(accessToken);
			}
		} catch (Exception e) {
			logger.info(e.getMessage());
			CookieUtil.removeCookie(response, GlobalConst.BOM_FRONT_UT);
		}
		boolean exist = CommonUtil.hasNeedLogin(handler);
		if (!exist) {
			return true;
		}
		boolean isAjaxRequest = RequestUtils.isAjaxRequest(request);
		// 需要登录的
		if (member != null) {
			//刷新redis中用户信息保存的时间,只要操作就不会掉线
			redisService.expire(accessToken, 1, TimeUnit.HOURS);
			if(!RoleTypeEnum.DESIGNER.getCode().equals(member.getRoleType()) && !RoleTypeEnum.EDITOR.equals(member.getRoleType())){
				logger.error("你无权操作本系统!");
				jump(response, isAjaxRequest);
				return false;
			}
			MemberDetail detail = memberDetailService.getByMemberId(member.getId());
			//保存用户信息
			FrontLoginUtil.initCurrentUser(member, detail);
			//判断“角色”
			NeedRole needRole=hasNeedRole(handler);
			if(needRole==null){
				return true;
			}else{
				Integer roleType = member.getRoleType();
				boolean needDesigner=needRole.designer();
				boolean needEditor=needRole.editor();
				//需要设计师权限,但是没有
				if(needDesigner && !RoleTypeEnum.DESIGNER.getCode().equals(roleType)){
					logger.error("权限不足,没有设计师权限");
					jump(response, isAjaxRequest);
					return false;
				}
				//需要编辑权限,但是没有
				if(needEditor && !RoleTypeEnum.EDITOR.getCode().equals(roleType)){
					logger.error("权限不足,没有服务者权限");
					jump(response, isAjaxRequest);
					return false;
				}
			}
			return true;
		} else {
			jump(response, isAjaxRequest);
			return false;
		}
	}

	// 需要登录,但是没有登录
	private void jump(HttpServletResponse response, boolean isAjaxRequest) throws IOException {
		if (isAjaxRequest) {
			// 异步
			jsonLogin(response);
		}else {
			// 同步
			response.sendRedirect(loginUrl);
		}
	}
	
	private static void jsonLogin(HttpServletResponse response) {
		Map<String, Object> map = Maps.newHashMap();
		map.put("code", ResultCodeEnum.NEED_LOGIN.getCode());
		map.put("msg", "会话超时,请重新登录");
		ResponseUtils.renderJson(response, JSON.toJSONString(map));
	}
	
	public String getLoginUrl() {
		return loginUrl;
	}

	public void setLoginUrl(String loginCenterUrl) {
		this.loginUrl = loginCenterUrl;
	}
	
	public static NeedRole hasNeedRole(Object handler) {
		if(!(handler instanceof HandlerMethod)){
			return null;
		}
		HandlerMethod handlerMethod = (HandlerMethod) handler;
		Class<?> type = handlerMethod.getBeanType();
	
		// 判断是否有NeedRole注解
		NeedRole needRole = type.getAnnotation(NeedRole.class);
		if (needRole == null) {
			needRole = type.getSuperclass().getAnnotation(NeedRole.class);
		}
		if (needRole == null) {
			needRole = handlerMethod.getMethodAnnotation(NeedRole.class);
		}
		return needRole;
	}
}
7.前端用的登录工具,保存用户信息
package com.front.util;

import com.front.model.UserInfo;
import com.userService.model.Member;
import com.userService.model.MemberDetail;

public class FrontLoginUtil {

	private static ThreadLocal<UserInfo> currentUser = null;

	private FrontLoginUtil(){
	}
	
	public static void setCurrentUser(UserInfo userInfo) {
		if(currentUser == null){
			currentUser = new ThreadLocal<UserInfo>();
		}
		currentUser.set(userInfo);
	}

	public static UserInfo getCurrentUser() {
		return currentUser.get();
	}

	public static void initCurrentUser(Member member,MemberDetail memberDetail) {
		if (member != null) {
			UserInfo userInfo = new UserInfo();
			userInfo.setId(member.getId());
			userInfo.setName(member.getName());
			userInfo.setMobile(member.getMobile());
			userInfo.setRoleType(member.getRoleType());
			userInfo.setNickname(memberDetail.getNickname());
			userInfo.setAvatar(memberDetail.getAvatar());
			setCurrentUser(userInfo);
		}
	}
}
8.cookie工具类CookieUtil
package com.common.web.util;

import java.util.Map;

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import com.google.common.collect.Maps;

public class CookieUtil {
	/**
	 * 写入一个Cookie
	 * @param response
	 * @param name
	 * @param path
	 * @param value
	 * @param maxAge
	 */
	public static void addCookie(HttpServletResponse response, String name, String value, String path, int maxAge) {       
        Cookie cookie = new Cookie(name, value);
        if(StringUtils.isNotBlank(path)){
        	cookie.setPath(path);	
        }       
        if (maxAge>0) {
        	cookie.setMaxAge(maxAge);
        }
        response.addCookie(cookie);
    }
	
	/**
	 * 写入一个Cookie
	 * @param response
	 * @param name
	 * @param value
	 * @param maxAge
	 *
	 */
	public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {       
		addCookie(response, name, value,"/", maxAge);
	}
	
	/**
	 * 根据名称获得value
	 * @param request
	 * @param name
	 * @return
	 */
	public static String getCookieValue(HttpServletRequest request, String name) {
		Cookie[] cookies=request.getCookies();
        if(cookies != null){
        	for (Cookie cookie : cookies) {
        		if(cookie.getName().equalsIgnoreCase(name)){
        			return cookie.getValue();
        		}
			}
        }
        return null;
    }
	
	/**
	 * 删除某个cookie
	 * 
	 * @param response
	 * @param name
	 * @param path
	 */
	public static void removeCookie(HttpServletResponse response,String name,String path) {		
		Cookie cookie = new Cookie(name,null);
		cookie.setMaxAge(0);
		cookie.setPath(path);
		response.addCookie(cookie);		
	}
	
	/**
	 * 删除某个cookie
	* 
	* @param response
	* @param name
	*
	 */
	public static void removeCookie(HttpServletResponse response,String name) {	
		removeCookie(response, name, "/");
	}
	  
	/**
	 * 读取全部Cookie到Map
	 * @param request
	 * @return
	 */
	public static Map<String, Cookie> readCookieToMap(HttpServletRequest request) {
        Map<String, Cookie> cookieMap = Maps.newHashMap();
        Cookie[] cookies = request.getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
              cookieMap.put(cookie.getName(), cookie);
			}
        }
        return cookieMap;
    }
    
    /**
     * 清除所有Cookie
     * @param request
     * @param response
     */
    public static void clear(HttpServletRequest request,HttpServletResponse response) {
		Cookie[] cookies = request.getCookies();
		if(cookies!=null){
			for(Cookie cookie:cookies) {
				cookie.setValue(null);
				cookie.setMaxAge(0);
				response.addCookie(cookie);
			}	
		}		
	}
    
    /**
	 * 获得cookie
	 * 
	 * @param request
	 *            HttpServletRequest
	 * @param name
	 *            cookie name
	 * @return if exist return cookie, else return null.
	 */
	public static Cookie getCookie(HttpServletRequest request, String name) {
		Assert.notNull(request);
		Cookie[] cookies = request.getCookies();
		if (cookies != null && cookies.length > 0) {
			for (Cookie cookie : cookies) {
				if (cookie.getName().equalsIgnoreCase(name)) {
					return cookie;
				}
			}
		}
		return null;
	}
}
9.redis的工具类

一、接口

package com.commonService.service;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import com.commonService.exception.BizException;

/**
 * 缓存数据服务
 */
public interface RedisService {

	/**
	 * 加入缓存
	 * 
	 * @param key 加入缓存
	 * @param value 缓存的数据
	 * @return
	 * @throws BizException 
	 */
	public abstract void add(String key, Serializable value) throws BizException;

	/**
	 * 加入缓存,并设置缓存时间
	 * 
	 * @param key 缓存的key
	 * @param value 缓存的值
	 * @param timeout 缓存时间
	 * @param unit 缓存时间类型枚举
	 * @throws BizException 
	 *
	 */
	public abstract void add(String key, Serializable value, long timeout,
			TimeUnit unit) throws BizException;

	/**
	 * 如果这个key不在缓存中就设置
	 * 
	 * @param key 缓存的key
	 * @param value 缓存的对象
	 * @return true/false
	 * @throws BizException 
	 *
	 */
	public abstract boolean setIfAbsent(String key, Serializable value) throws BizException;

	/**
	 * 获取缓存字符串
	 * 
	 * @param key 缓存的key
	 * @return 缓存的字符串
	 * @throws BizException 
	 *
	 */
	public String getString(String key) throws BizException;
	/**
	 * 获取缓存的对象
	 * 
	 * @param key 缓存的key
	 * @return 缓存的对象
	 * @throws BizException 
	 *
	 */
	public abstract Serializable getValue(String key) throws BizException;

	/**
	 * 获取指定时间之内redis自增序列
	 * 
	 * @param key 缓存的key
	 * @param timeout 时间
	 * @param timeUnit 时间类型
	 * @return 自增值
	 * @throws BizException 
	 *
	 */
	public abstract Long getSequence(String key, long timeout, TimeUnit timeUnit) throws BizException;

	/**
	 * 删除缓存的对象
	 * 
	 * @param key 缓存的key
	 * @return
	 * @throws BizException 
	 */
	public abstract void delete(String key) throws BizException;

	/**
	 * 批量删除缓存对象
	 * 
	 * @param keys 缓存的key集合
	 * @return
	 * @throws BizException 
	 */
	public abstract void delete(Collection<String> keys) throws BizException;

	/**
	 * 判断key是否存在
	 * 
	 * @param key 缓存的key
	 * @return 是否存在
	 * @throws BizException 
	 */
	public abstract boolean exists(String key) throws BizException;

	/**
	 * 设置指定key的过期时间
	 * 
	 * @param key 参数key
	 * @param timeout 时间
	 * @param unit 时间类型
	 * @return 是否成功
	 * @throws BizException 
	 *
	 */
	public abstract boolean expire(String key, long timeout, TimeUnit unit) throws BizException;

	/**
	 * 设置指定key的过期日期
	 * 
	 * @param key 参数key
	 * @param date 日期
	 * @return 是否成功
	 * @throws BizException 
	 *
	 */
	public abstract boolean expireAt(String key, Date date) throws BizException;

	/**
	 * 获取key过期剩余时间,单位是秒
	 * 
	 * @param key 缓存的key
	 * @return 时间
	 * @throws BizException 
	 *
	 */
	public abstract Long getExpire(String key) throws BizException;

	/**
	 * 获取key过期剩余时间
	 * 
	 * @param key 获取过期
	 * @param unit 时间类型
	 * @return 时间
	 * @throws BizException 
	 *
	 */
	public abstract Long getExpire(String key, TimeUnit unit) throws BizException;

	/**
	 * 获取所有匹配的key对象列表
	* 
	* @param pattern 例如  KEYS w3c* 获取以 w3c 为开头的 key的值
	* @return 对象列表
	 * @throws BizException 
	*
	 */
	public <T> List<T> getByPattern(String pattern) throws BizException;
}
二、实现类
package com.commonService.service.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;

import com.commonService.exception.BizException;
import com.commonService.service.RedisService;
import com.google.common.collect.Lists;

public class RedisServiceImpl implements RedisService {

	private RedisTemplate<String, Serializable> redisTemplate;

	public RedisTemplate<String, Serializable> getRedisTemplate() {
		return redisTemplate;
	}

	public void setRedisTemplate(RedisTemplate<String, Serializable> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	private String redisKeyNamespace;
	
	public String getRedisKeyNamespace() {
		return redisKeyNamespace;
	}

	public void setRedisKeyNamespace(String redisKeyNamespace) {
		this.redisKeyNamespace = redisKeyNamespace;
	}

	// 加入缓存
	@Override
	public void add(String key, Serializable value) throws BizException {
		key = buildKey(key);
		ValueOperations<String, Serializable> valueops = redisTemplate.opsForValue();
		valueops.set(key, value);
	}
	
	// 加入缓存,并设置缓存时间
	@Override
	public void add(String key, Serializable value, long timeout, TimeUnit unit) throws BizException {
		key = buildKey(key);
		ValueOperations<String, Serializable> valueops = redisTemplate.opsForValue();
		valueops.set(key, value, timeout, unit);
	}

	// 如果这个key不在redis中就设置
	@Override
	public boolean setIfAbsent(String key, Serializable value) throws BizException {
		key = buildKey(key);
		ValueOperations<String, Serializable> valueops = redisTemplate.opsForValue();
		boolean result = valueops.setIfAbsent(key, value);
		return result;
	}

	// 获取缓存的对象
	@Override
	public String getString(String key) throws BizException {
		key = buildKey(key);
		ValueOperations<String, Serializable> valueops = redisTemplate.opsForValue();
		String value =  (String) valueops.get(key);
		return value;
	}
	// 获取缓存的对象
	@Override
	public Serializable getValue(String key) throws BizException {
		key = buildKey(key);
		ValueOperations<String, Serializable> valueops = redisTemplate.opsForValue();
		Serializable value = valueops.get(key);
		return value;
	}
	//获取所有匹配的key 例如  KEYS w3c* 获取以 w3c 为开头的 key 的值
	@Override
	public <T> List<T> getByPattern(String pattern) throws BizException {
		pattern = buildKey(pattern);
		Set<String> keys = redisTemplate.keys(pattern);
		ValueOperations<String, Serializable> valueops = redisTemplate.opsForValue();
		@SuppressWarnings("unchecked")
		List<T> list = (List<T>) valueops.multiGet(keys);
		return list;
	}
	
	// 获取一段时间自增序列
	@Override
	public Long getSequence(String key, long timeout, TimeUnit timeUnit) throws BizException {
		key = buildKey(key);
		ValueOperations<String, Serializable> valueOperations = redisTemplate.opsForValue();
		Long sequence = null;
		if(redisTemplate.hasKey(key)){
			 sequence = valueOperations.increment(key, 1l);
		}else{
			 sequence = valueOperations.increment(key, 1l);
			 redisTemplate.expire(key, timeout, timeUnit);
		}
		return sequence;
	}

	// 单个删除
	@Override
	public void delete(String key) throws BizException {
		key = buildKey(key);
		redisTemplate.delete(key);
	}

	@Override
	public void delete(Collection<String> keys) throws BizException {
		if (CollectionUtils.isEmpty(keys)) {
			throw new BizException("key 不能为空!");
		}
		List<String> list = Lists.newArrayList();
		for (String key : keys) {
			list.add(buildKey(key));
		}
		redisTemplate.delete(list);
	}

	// 判断key是否存在
	@Override
	public boolean exists(String key) throws BizException {
		key = buildKey(key);
		Boolean b = redisTemplate.hasKey(key);
		return b.booleanValue();
	}

	// 设置指定key的过期时间
	@Override
	public boolean expire(String key, long timeout, TimeUnit unit) throws BizException {
		key = buildKey(key);
		return redisTemplate.expire(key, timeout, unit);
	}

	// 设置指定key的过期时间
	@Override
	public boolean expireAt(String key, Date date) throws BizException {
		key = buildKey(key);
		return redisTemplate.expireAt(key, date);
	}

	// 获取key过期剩余时间,单位是秒
	@Override
	public Long getExpire(String key) throws BizException {
		key = buildKey(key);
		return redisTemplate.getExpire(key);
	}

	// 获取key过期剩余时间
	@Override
	public Long getExpire(String key, TimeUnit unit) throws BizException {
		key = buildKey(key);
		return redisTemplate.getExpire(key, unit);
	}
	
	private String buildKey(String key) throws BizException {
		if (StringUtils.isEmpty(key)) {
			throw new BizException("key 不能为空!");
		}
		if (StringUtils.hasText(redisKeyNamespace)) {
			key = redisKeyNamespace + ":" + key;
		}
		return key;
	}
}

kaptcha验证码组件的使用可以参考http://chenzhou123520.iteye.com/blog/1987636

http://www.open-open.com/lib/view/open1395238908947.html





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值