1. 安装redis
https://redis.io/download
根据官网的教程就行操作:
$ wget http://download.redis.io/releases/redis-3.2.9.tar.gz $ tar xzf redis-3.2.9.tar.gz $ cd redis-3.2.9 $ make
可能会遇到的问题是你的服务器上没有装 gcc编译器,导致make命令不能使用。解决办法:yum install gcc即可。
如果服务器没有装yum,那还需要安装一下yum。
redis的几个命令./redis-server 按照默认的配置启动redis-server
./redis-cli -p 6379 shutdown 关闭redis服务
redis-conf 的解释:
配置文件中会包括如下信息(简单列举需要的):
port 6379 指定redis运行的端口
bind 127.0.0.1 绑定可以访问redis服务的ip,如果需要所有的机器都能访问的话,注释掉这个就行。
protected-mode no 这个是指定的redis 服务器是否是保护状态访问,如果是yes的话需要配置身份信息,这里设置no表示的是不启用保护状态访问。
设置完 redis的配置文件,需要重启启动redis,并且使用redis-server redis.conf
这个命令,刚才的配置项才起作用。
redis 安装大体完成。
2.Spring集成redis
maven的方式加载依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.1.RELEASE</version>
</dependency>
redis.clients: 相当于 JDBCConnection驱动
org.springframework.data:对redis的封装底层依赖redis.clients,spring
这个一个非常需要重要的注意事项:org.springframework.data 的不同版本对应的不同版本的spring,比如1.7.1依赖的spring是3.2.8及以上,官网文档:
3. Requirements Spring Data Redis 1.2.x binaries requires JDK level 6.0 and above, and Spring Framework 3.2.8 and above. In terms of key value stores, Redis 2.6.x or higher is required. Spring Data Redis is currently tested against the latest 2.6 and 2.8 releases.
现在官网spring data redis GA的版本是1.8.4,这个需要spring 4.3.9版本。
这里我遇到一个问题是:
我的spring是4.0.2版本,那怎么去找到对应版本的spring data redis。最后找到了他们的服务器上的地址:http://docs.spring.io/autorepo/docs/spring-data-redis/
在这个网址中我找到了对应的是1.7.1, 需注意1.7.11版本对应的是4.2.9
这个是官网的截图,右上角可以查看对应的api 和 文档,但是最低是1.7.11版本。
接下来java代码测试是否可用:
import redis.clients.jedis.Jedis; import redis.clients.jedis.exceptions.JedisConnectionException; public class RedisTest { private Jedis jedis = null; private String key1 = "key1"; private String key2 = "key2"; public RedisTest() { jedis = new Jedis("123.56.87.101",6379); } public static void main(String[] args) { RedisTest redisTest = new RedisTest(); redisTest.isReachable(); redisTest.testData(); redisTest.delData(); redisTest.testExpire(); } public boolean isReachable() { boolean isReached = true; try { jedis.connect(); jedis.ping(); // jedis.quit(); } catch (JedisConnectionException e) { e.printStackTrace(); isReached = false; } System.out .println("The current Redis Server is Reachable:" + isReached); return isReached; } public void testData() { jedis.set("key1", "data1"); System.out.println("Check status of data existing:" + jedis.exists(key1)); System.out.println("Get Data key1:" + jedis.get("key1")); long s = jedis.sadd(key2, "data2"); System.out.println("Add key2 Data:" + jedis.scard(key2) + " with status " + s); } public void delData() { long count = jedis.del(key1); System.out.println("Get Data Key1 after it is deleted:" + jedis.get(key1)); } public void testExpire() { long count = jedis.expire(key2, 5); try { Thread.currentThread().sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } if (jedis.exists(key2)) { System.out .println("Get Key2 in Expire Action:" + jedis.scard(key2)); } else { System.out.println("Key2 is expired with value:" + jedis.scard(key2)); } } }
Next:(Spring+redis)推荐一篇文章:http://www.cnblogs.com/jianwei-dai/p/5741753.html写的非常好。
1)redis.properties
redis.hostName=************* redis.port=6379 redis.timeout=15000 redis.usePool=true redis.maxIdle=6 redis.minEvictableIdleTimeMillis=300000 redis.numTestsPerEvictionRun=3 redis.timeBetweenEvictionRunsMillis=60000
同时别忘在在spring中导入配置文件,如果有多个配置文件需要导入请按照下面方式导入,不要一个一个导入否则报错:
<!-- 加载配置 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:sys-dev.properties</value> <value>classpath:redis.properties</value> </list> </property> </bean>
2)spring-redis.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd "> <!--<bean > <constructor-arg index="0" value="mymaster" /> <constructor-arg index="1"> <set> <value>${redis.sentinel}</value> </set> </constructor-arg> <constructor-arg index="2" ref="jedisPoolConfig" /> </bean>--> <bean > <property name="maxIdle" value="${redis.maxIdle}"></property> <property name="minEvictableIdleTimeMillis" value="${redis.minEvictableIdleTimeMillis}"></property> <property name="numTestsPerEvictionRun" value="${redis.numTestsPerEvictionRun}"></property> <property name="timeBetweenEvictionRunsMillis" value="${redis.timeBetweenEvictionRunsMillis}"></property> </bean> <bean > <property name="poolConfig" ref="jedisPoolConfig"></property> <property name="hostName" value="${redis.hostName}"></property> <property name="port" value="${redis.port}"></property> <property name="timeout" value="${redis.timeout}"></property> <property name="usePool" value="${redis.usePool}"></property> </bean> <!-- redis模板类 --> <bean > <property name="connectionFactory" ref="jedisConnectionFactory" /> </bean> <!-- redisService 实现类 --> <bean > <property name="redisTemplate" ref="redisTemplate" /> </bean> </beans>
这里使用的是bean标签的方式注入RedisServiceImpl,这里不能在类中用@Autowired的方式注入,因为在主的spring配置文件中会先扫描component 完成注入,此时如果在类中用Autowired 这时候RedisTemplate是null,
<!-- 注解扫描目录 -->
<context:component-scan base-package="com.space" />
接下来编写RedisService 接口,封装redis的操作
import org.springframework.stereotype.Service; import com.space.entity.RedisKeyDto; @Service public interface RedisService { void addData(RedisKeyDto redisKeyDto); void delete(RedisKeyDto redisKeyDto); RedisKeyDto redisGet(RedisKeyDto redisKeyDto); void addRedisData(RedisKeyDto redisKeyDto,int outTime); }
RedisService的实现类:
import java.io.Serializable; import java.util.concurrent.TimeUnit; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import com.space.entity.RedisKeyDto; @Service public class RedisServiceImpl implements RedisService { private RedisTemplate<String, Object> redisTemplate; @Override public void addData(final RedisKeyDto redisKeyDto) { redisTemplate.opsForValue().set(redisKeyDto.getKeys(), redisKeyDto.getValues()); } @Override public void delete(RedisKeyDto redisKeyDto) { redisTemplate.delete(redisKeyDto.getKeys()); } @Override public RedisKeyDto redisGet(RedisKeyDto redisKeyDto) { RedisKeyDto re=new RedisKeyDto(); Object ob = redisTemplate.opsForValue().get(redisKeyDto.getKeys()); if(null != ob){ re.setKeys(redisKeyDto.getKeys()); re.setValues((String)ob); return re; } return null; } @Override public void addRedisData(RedisKeyDto redisKeyDto, int outTime) { addData(redisKeyDto); redisTemplate.expire(redisKeyDto.getKeys(), outTime, TimeUnit.MILLISECONDS); } public RedisTemplate<String, Object> getRedisTemplate() { return redisTemplate; } public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) { this.redisTemplate = redisTemplate; } }
这个实现类与下边这篇文章中的实现不一样。
这里介绍一篇文章:http://blog.csdn.net/wenbo20182/article/details/62037747
3 发送验证码
用的是阿里大于的发送验证码
首先下载两个jar包:taobao-sdk-java-auto_1455552377940-20160607.jar,taobao-sdk-java-auto_1455552377940-20160607-source.jar
将这两个jar包放到WEB_INF下的lib下,将本地的jar包添加到maven仓库的步骤:
1)右击项目->import->Maven(Install or deploy ...)
2)填写表格
选择WEB_INF下lib下的这两个jar包即可,group id=com.test,artifactid = alidayu,version =1.0;group id=com.test,artifactid = alidayu-resource,version =1.0
3)pom.xml中加载
<dependency> <groupId>com.test</groupId> <artifactId>alidayu</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>com.test</groupId> <artifactId>alidayu_resource</artifactId> <version>1.0</version> </dependency>
定义三个common类
SMSConstants.java
public class SMSConstants { //公共参数:正式环境请求地址http格式 public static String URL="http://gw.api.taobao.com/router/rest"; //公共参数:正式环境请求地址https格式 //public static String URL2 = "https://eco.taobao.com/router/rest"; //TOP分配给应用的AppKey,即阿里大于账户创建的应用 public static String APP_KEY=""; //公共参数:签名的摘要算法,可选值为:hmac,md5。 public static String SIGN_METHOD_MD5="md5"; //公共参数:签名的摘要算法,可选值为:hmac,md5。 public static String SIGN_METHOD_HMAC="hmac"; //请求参数:短信签名,传入的短信签名必须是在阿里大于“管理中心-短信签名管理”中的可用签名 public static String SMS_SIGN=""; //请求参数:公共回传参数 public static String EXTEND="123456"; //请求参数:短信类型,传入值请填写normal public static String SMS_TYPE="normal"; //请求参数:短信模板ID,传入的模板必须是在阿里大于“管理中心-短信模板管理”中的可用模板。示例:SMS_585014 //验证码模板 public static String SMS_TEMPLATE_CODE=""; //短信通知模板 public static String SMS_TEMPLATE_CODE_ACK=""; //请求参数:签名的App Secret值 public static String SECRET = ""; //返回信息编码为utf-8 public static String CHARSET_UTF8="utf-8"; //短信通知模板类型:1验证码类2通知类 //千匠用户注册发送短信验证码 public static final String SMS_MODEL_TYPE1="1"; //千匠用户下发订单发送订单通知 public static final String SMS_MODEL_TYPE2="2"; //千匠用户商品价格变动通知1 public static final String SMS_MODEL_TYPE21="21"; //千匠用户商品价格变动通知2 public static final String SMS_MODEL_TYPE211="211"; //千匠用户商品到货通知1 public static final String SMS_MODEL_TYPE212="212"; //千匠用户商品到货通知2 public static final String SMS_MODEL_TYPE213="213"; }
SmsParam.java
public class SmsParam { //短信模板变量:模板内容中的变量${product} private String product; //短信模板变量:模板内容中的变量${number},手机验证码 private String number; //短信模板变量:模板内容中的变量${ordernumber},订单号 private String ordernumber; //短信模板变量:模板内容中的变量${disname},关注商品地区 private String disname; //短信模板变量:模板内容中的变量${goodsinfoname},货品名称 private String goodsinfoname; //短信模板变量:模板内容中的变量${ofollowprice},关注商品收藏的价格 private String ofollowprice; //短信模板变量:模板内容中的变量${nfollowprice},降低以后的新价格 private String nfollowprice; //短信模板变量:模板内容中的变量${bsetname},站点名称 private String bsetname; public SmsParam() { super(); } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getProduct() { return product; } public void setProduct(String product) { this.product = product; } public String getOrdernumber() { return ordernumber; } public void setOrdernumber(String ordernumber) { this.ordernumber = ordernumber; } public String getDisname() { return disname; } public void setDisname(String disname) { this.disname = disname; } public String getGoodsinfoname() { return goodsinfoname; } public void setGoodsinfoname(String goodsinfoname) { this.goodsinfoname = goodsinfoname; } public String getOfollowprice() { return ofollowprice; } public void setOfollowprice(String ofollowprice) { this.ofollowprice = ofollowprice; } public String getNfollowprice() { return nfollowprice; } public void setNfollowprice(String nfollowprice) { this.nfollowprice = nfollowprice; } public String getBsetname() { return bsetname; } public void setBsetname(String bsetname) { this.bsetname = bsetname; } }
SMSUtils.java
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.taobao.api.DefaultTaobaoClient; import com.taobao.api.TaobaoClient; import com.taobao.api.request.AlibabaAliqinFcSmsNumSendRequest; import com.taobao.api.response.AlibabaAliqinFcSmsNumSendResponse; /** * @Description:短信验证工具类 */ public class SMSUtils { //请求地址 private static String URL = SMSConstants.URL; //TOP分配给应用的AppKey private static String APP_KEY = SMSConstants.APP_KEY; //短信签名AppKey对应的secret值 private static String SECRET = SMSConstants.SECRET; //短信类型,传入值请填写normal private static String SMS_TYPE = SMSConstants.SMS_TYPE; //阿里大于账户配置的短信签名 private static String SMS_SIGN = SMSConstants.SMS_SIGN; //阿里大于账户配置的短信模板ID private static String SMS_TEMPLATE_CODE = SMSConstants.SMS_TEMPLATE_CODE; /** * @param phone 必填参数,手机号码 * @return * @throws Exception */ public String sendMsgCode(String phone) throws Exception { //随机生成6位数字作为验证码 int code = getCode(1,999999); //获得第三方阿里云短信通知接口 TaobaoClient client = new DefaultTaobaoClient(URL, APP_KEY, SECRET); //获得短信通知请求头 AlibabaAliqinFcSmsNumSendRequest req = new AlibabaAliqinFcSmsNumSendRequest(); //短信通知类型 req.setSmsType(SMS_TYPE); //短信通知签名 req.setSmsFreeSignName(SMS_SIGN); //短信接收号码:传入号码为11位手机号码不能加0或+86,最多传入200个号码,多个号码以逗号分隔 req.setRecNum(phone); //短信通知参数json格式 SmsParam smsParamVo = new SmsParam(); smsParamVo.setNumber(String.valueOf(code)); String smsParam = JSONObject.toJSONString(smsParamVo); System.out.println("短信通知参数smsParam:"+smsParam); //短信模板变量,传参规则{"key":"value"},key的名字须和申请模板中的变量名一致,多个变量之间以逗号隔开 req.setSmsParamString(smsParam); //短信模板ID req.setSmsTemplateCode(SMS_TEMPLATE_CODE); AlibabaAliqinFcSmsNumSendResponse rsp = client.execute(req); JSONObject json = JSON.parseObject(rsp.getBody()); String jsonStr = json.getString("alibaba_aliqin_fc_sms_num_send_response"); if (jsonStr!=null&&!jsonStr.isEmpty() ) { json = JSON.parseObject(jsonStr); String result = json.getString("result"); if (result!=null && !result.isEmpty()) { json = JSON.parseObject(result); System.out.println("json:"+json); String errorCode = json.getString("err_code"); if ("0".equals(errorCode)) { //发送成功 return String.valueOf(code); } else { //发送失败 return null; } } } //发送失败 return null; } /** * 随机生成6位数字作为验证码 * @return */ public static int getCode(int min, int max){ int randNum = min + (int)(Math.random() * ((max - min) + 1)); return randNum; } /*//测试 public static void main(String[] args) { try { JSONObject modelParam=new JSONObject(); modelParam.put("code", getCode(1,999999)); SMSUtils m = new SMSUtils(); String result=m.sendMsgCode(""); System.out.println(result); System.out.println("发送成功"); } catch (Exception e) { e.printStackTrace(); System.out.println("发送失败"); } } */ }
这里介绍一篇文章:
http://blog.csdn.net/u014079773/article/details/52873150
接下来在编写发送验证码的service类:
SmsVerificationCodeService.java
import org.springframework.stereotype.Service; @Service public interface SmsVerificationCodeService { /*** * 发送验证码 * @param phoneName * @return */ String sendMessage(String phoneName); /** * 判断验证码是否正确 * @param phone * @param code * @return */ boolean checkIsCorrectCode(String phone,String code); }
SmsVerificationCodeServiceImpl.java 实现类
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.space.common.SMSUtils; import com.space.entity.RedisKeyDto; @Service public class SmsVerificationCodeServiceImpl implements SmsVerificationCodeService{ private static Logger LOGGER = LoggerFactory.getLogger(SmsVerificationCodeService.class); @Autowired RedisServiceImpl redisService; @Transactional @Override public String sendMessage(String phoneName) { SMSUtils smsu = new SMSUtils(); String returnCode=""; try { String checkCode = smsu.sendMsgCode(phoneName); RedisKeyDto cc = new RedisKeyDto(); cc.setKeys(phoneName); cc.setValues(checkCode); RedisKeyDto exsitCC = redisService.redisGet(cc); if(exsitCC != null){ redisService.delete(exsitCC); } redisService.addRedisData(cc, 600000); returnCode = checkCode; } catch (Exception e) { e.printStackTrace(); } return returnCode; } @Override public boolean checkIsCorrectCode(String phone, String checkcode) { RedisKeyDto cc = new RedisKeyDto(); cc.setKeys(phone); cc.setValues(checkcode); RedisKeyDto cc2 = redisService.redisGet(cc); if(cc2!=null && cc2.getValues().equals(checkcode)){ return true; } return false; } }
最后在编写Controller了...