Redis
NOSql介绍与好处
NOSql介绍
Not Only Sql 不仅仅是sql, 泛指非关系型数据库
非关系型数据库里面有一个很重要类型数据库: 缓存数据库, 因为里面存储的数据没有任何关系
非关系与关系型数据库的区别
关系型数据库
优点:
是磁盘数据库,数据永久保存在磁盘上,所以数据安全缺点:
就是慢
原因1: 磁盘数据库的续写是IO的读写
原因2: 关系型数据库有各种约束、检查、事务操作等逻辑控制
非关系型数据库
优点
就是快, 因为是内存的操作
缺点
数据不安全,会容易丢失部分数据
使用哪种类型数据库
关系型和非关系型都使用
NOSql产品-Redis介绍与安装
非关系型数据库的产品
java领域最重要的非关系数据库产品Redis
redis存储数据特点
以key-value键值对存储
redis安装与目录介绍
- 下载
windows版本,适合开发,https://github.com/MSOpenTech/redis/tags 微软提供的
linux版本,适合正式环境,官方提供的http://redis.io/download
- 解压完成安装
- 介绍redis的目录结构
使用redis存储数据体验步骤
-
双击运行redis服务器端redis-server.exe(服务器启动后会根据电脑内存相等的大小占用磁盘空间)
-
双击运行redis客户端redis-cli.exe
-
在客户端上进行存取数据
常见问题
问题: 双击服务器端打不开?
解决方案:redis服务器启动会占用当前磁盘系统内存相等大小的空间, 例如电脑内存16G, 启动时就会占磁盘16G的空间, 如果当前磁盘不够16G, 服务器就不能启动起来
如果上面方案解决不了: 重启电脑,再次打开
五种数据类型结构介绍
类型介绍
key的使用原则
- key的长度不要超过1024个字节,否则会影响查询的性能
- key的名字要有含义和可读性
数据类型1—String命令
介绍
字符串类型是 Redis 中最为基础的数据存储类型,它在 Redis 中以二进制保存,没有编码和解码的过程。无论存入的是字符串、整数、浮点类型都会以字符串写入。在 Redis 中字符串类型的 Value 最多可以容纳的数据长度是 512M。这是最常用的数据类型。
操作命令语法
String操作命令
redis适合操作的数据
查询频率高, 修改频率低
原因: 因为数据在2个地方缓存数据库中和磁盘数据库中都有, 需要保持2个地方的数据一致, 如果修改频率高, 那么数据同步会消耗很多资源
数据类型2—hash命令
介绍
Redis 中的 Hash 类型可以看成具 String 的键和 String 的值 Map 容器,每一个 Hash 可以存储 40(42 亿 9千多个)亿个键值对。
string类型存储的value大小限制512MB
操作命令语法
操作
扩展命令
hlen 获取hash类型指定key的字段数
语法: hlen key
HEXISTS 判断hash中指定key的指定字段是否存在
语法: HEXISTS key field1
Hincrby 命令用于为哈希表中的字段值加上指定增量值。
语法: HINCRBY key field 增量值
存储数据(hash类型的应用场景):
存储购物车数据
例如
用户1:user1
商品1 id=p001 购物数量=2
商品2 id=p002 购物数量=1
用户2:user2
商品1 id=p003 购物数量=2
商品2 id=p004 购物数量=1
命令
hmset user1 p001 2 p002 1
hmset user2 p003 2 p004 1
数据类型3—list命令
list介绍
在 Redis 中,List 类型是按照插入顺序排序的字符串链表。和数据结构中的普通链表(java的LinkedList)一样,可以在其左部(left)和右部(right)添加新的元素。在插入时,如果该键并不存在,Redis 将为该键创建一个新的链表,如果这个键已经存在,则是向 list 添加元素。与此相反,如果链表中所有的元素均被移除,那么该键也将会被从数据库中删除。List 中可以包含的最大元素数量是 40 亿个。可以实现队列(先进先出)和栈(先进后出)
添加元素语法
操作
效果
查询数据语法
效果
删除元素语法
效果
查看列表的长度
扩展命令
1、查询指定位置的元素
lindex key 位置
2、修改指定位置元素值
lset key 位置 元素新值
3、给指定元素前后插入数据,从左到右匹配第一个符合的元素插入
LINSERT key BEFORE|AFTER 已有元素值 新元素值
4、删除指定元素值数据命令
LREM KEY COUNT 元素值
- count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT 。
- count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值。
- count = 0 : 移除表中所有与 VALUE 相等的值。
list应用场景
定时排行榜
list类型的lrange命令可以分页查看队列中的数据。可将每隔一段时间计算一次的排行榜存储在list类型中,如京东每日的手机销量排行、学校每次月考学生的成绩排名、斗鱼年终盛典主播排名等,下图是酷狗音乐“K歌擂台赛”的昨日打擂金曲排行榜,每日计算一次,存储在list类型中,接口访问时,通过page和size分页获取打擂金曲。
举例: 将一个表中大量的数据进行降序排序计算(数据量不同,计算时间不等),将计算结果按照顺序写入redis中list类型里面
数据类型4—set命令
介绍
在 Redis 中,可以将 Set 类型看作为没有排序的字符集合,和 List 类型一样,也可以在该类型的数据值上执行添加、删除或判断某一元素是否存在等操作。Set 可包含的最大元素数量是 40 亿,和 List 类型不同的是,Set 集合中不允许出现重复的元素。
操作命令语法
存储数据特点:不可重复,无序
注意:set没有修改数据命令
效果
应用场景
数据去重:存储不重复的数据,就可以使用set
不能操作大量数据
数据类型5—zset命令
介绍
sorted set 是有序并且不可重复(value值不可以重复)
Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复,每个集合可存储40多亿个成员。
Sorted Set(zset)常用命令
zrange myZSet 0 -1 withscores 升序查询指定索引范围的数据,并显示值的分数
zrevrange myZSet 0 -1 withscores 降序查询指定索引范围的数据,并显示值的分数
zrevrank 键 值 降序查询指定元素的索引
注意:zset没有修改数据命令
命令演示
-
添加键country,分数是10,值是Japan
-
添加键country,分数是5,值是USA
-
添加键country,分数是1,值是China,分数是120,值是Korea
-
查询country中所有的元素
-
查询Japan的索引号(从0开始)
-
删除值为USA的元素
-
查询country中还有多少个元素
效果
应用场景
各种实时排行榜
扩展资料
了解其他类型:
http://www.runoob.com/redis/redis-sorted-sets.html
扩展命令资料
http://doc.redisfans.com/
客户端图形工具与通用命令
客户端软件
直接安装提供的客户端软件即可,双击桌面图标执行。
启动后出现如下登录界面:
注意:这个软件显示数据方面有问题,偶尔会出现服务器是有数据但是图形界面客户端显示null
操作命令语法
ttl的说明
set key value ex 秒数: 设置键存活指定的秒数
扩展命令:setnx key value
将
key
的值设为value
,当且仅当key
不存在。若给定的
key
已经存在,则 SETNX不做任何动作。SETNX是『SET if Not eXists』(如果不存在,则 SET)的简写。
作用
防止数据覆盖或重复设置数据
效果
redis持久化方式1-RDB策略
问题
-
redis服务器关闭所有内存数据都会丢失吗?
答: 不会全部丢失, 只会丢失部分数据
原因: redis有持久化机制, 可以在符合条件的时候将内存中的数据持久化到磁盘上保存;
-
为什么要保存到磁盘?
答: 防止redis服务器突然崩溃, redis可以重启之后立刻恢复磁盘的数据用于缓存; 这就是redis的持久化机制
如果没有redis持久化机制, 所有缓存数据丢失, 会造成磁盘数据库mysql瞬间压力增大, 有可能导致mysql崩溃
RDB策略介绍(快照策略)
Redis DataBase(RDB),是redis的默认开启的持久化策略。在符合持久化条件时会将这一时刻内存所有数据进行持久化到磁盘文件上dump.rdb,由于持久化的是某一时刻所有内存数据又叫快照策略。
RDB策略的配置
在配置文件redis.windows.conf文件中有配置的持久化条件
save 900 1
如果有1个以上的key发生改变(增删改), 那么900秒(15分钟)持久化一次数据到dump.rdb文件中
save 300 10
如果有10个以上的key发生改变(增删改), 那么300秒(5分钟)持久化一次数据到dump.rdb文件中
save 60 10000
如果有10000个以上的key发生改变(增删改), 那么60秒(1分钟)持久化一次数据到dump.rdb文件中
示例:采用RDB策略持久化数据测试
-
需求
修改rdb持久化策略方案,设置20秒内修改3个键进行持久化数据到dump.rdb文件中
-
实现步骤
-
关闭redis服务器
-
编辑文件redis.windows.conf增加如下命令, 保存文件
-
进入dos命令并且进入redis服务器目录
打开dos命令如图
-
执行命令如下
-
redis-server.exe redis.windows.conf
注意:
双击redis-server.exe启动redis服务器,这样启动服务器一切采用默认配置;如果配置文件修改了,必须使用dos命令启动redis服务器并且指明配置文件,这样才可以应用修改后的配置文件数据
-
双击启动redis-cli.exe启动客户端
-
输入3次命令,观察输入后和到达20秒就立即持久化操作
dump.rdb文件数据内容
上面不是乱码,是redis自己的持久化数据格式
redis持久化方式2-AOF策略
AOF(append only file)策略介绍
介绍
这个策略没有开启, 这个策略默认是每一秒将一秒内的增删改的命令持久化追加到appendonly.aof文件中
配置
需要修改配置文件redis.windows.conf进行开启AOF策略,如下操作
开启AOF后,持久化策略有3个
AOF默认是采用的策略是每秒持久化一次,会导致持久化文件随着时间不断增大,AOF会记录每一个key所有修改操作的过程。
appendfsync no:含义不进行强制持久化,而是交给操作系统与redis自己决定持久化的频率;在aof里面性能最好,但是安全性最不好
示例:采用AOF策略持久化数据测试
-
需求
开启AOF策略进行持久化数据测试,观察其持久化数据的过程
-
实现步骤
-
开启AOF, 保存文件
-
关闭redis服务器与客户端
-
启动dos命令方式启动redis服务器端, 输入如下命令
redis-server.exe redis.windows.conf
- 双击启动客户端, 每秒输入一次命令查看持久化效果
问题:每秒都持久化会导致日志文件过大,那么文件过大怎么办?需要做什么优化吗?
答:不需要做任何事情,redis对于aof策略有日志过大重写机制(如下信息都在配置文件中)
重写机制:在日志文件大小达到一定条件下,redis会将aof文件原有的全部数据删除,并且redis会将内存中所有数据生成写入命令重新写到aof文件中,达到清除所有冗余命令
小贴士
如果rdb与aof同时恢复的时候,出现冲突以谁为准? 答:以aof为准
2种是否可以同时使用? 可以,但是要观测cpu负载,如果cpu负载过大强烈建议关闭AOF
-
请说出redis常用的数据类型与应用场景
string:验证码, 还有查询频率高, 修改频率低, 数据量少
hash:购物车
list:定时排行榜
set:数据去重
zset:各种实时排行榜
-
redis的持久化机制请介绍下
有2种持久化策略
RDB策略介绍
是redis默认开始的持久化策略, 又叫快照策略, 在符合持久化条件时会将这一时刻内存全部数据写入磁盘文件dump.rdb中;
AOF策略介绍
是追加方式持久化策略, 默认是没有开启 , 开启后默认每秒将1秒内的增删改的命令追加到appendonly.aof文件中;
Jedis的使用:基本使用
Jedis(java redis)介绍
是官方推荐的操作redis的java客户端
Jedis的api方法
jedis的使用步骤
- 需要导入jedis的jar包
- 利用jedis的api操作redis
jedis基本使用代码
public class JedisTest1 {
public static void main(String[] args) {
//1.创建Jedis连接池对象
//1.1 创建一个连接池配置对象
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(10); //最大连接数
config.setMaxWaitMillis(30000); //最大等待超时时间
//1.2 根据配置对象创建连接池对象
JedisPool jedisPool = new JedisPool(config,"localhost",6379);
//2.从连接池获取Jedis连接对象
Jedis jedis = jedisPool.getResource();
//3.操作数据
//字符串数据
jedis.set("username","小明");
String username = jedis.get("username");
System.out.println("username="+username);
//list类型数据
jedis.lpush("mylist2","a","b","c");
List<String> mylist2 = jedis.lrange("mylist2", 0, -1);
System.out.println("mylist2:"+mylist2);
//4.关闭连接
jedis.close();
jedisPool.close();
}
}
常见错误
客户端命令查询
Jedis的使用:工具类优化操作
配置文件
jedis.properties配置文件内容
maxTotal=10
maxWaitMillis=30000
host=localhost
port=6379
使用工具类优化连接池操作代码
public class JedisUtil {
private static JedisPool jedisPool;
static {
//目标:初始化连接池对象
//1.读取配置文件内容
//ResourceBundle 专门用于读取类路径下properties文件,根据文件名即可读取
ResourceBundle resourceBundle = ResourceBundle.getBundle("jedis");
int maxTotal = Integer.parseInt(resourceBundle.getString("maxTotal"));
int maxWaitMillis = Integer.parseInt(resourceBundle.getString("maxWaitMillis"));
String host = resourceBundle.getString("host");
int port = Integer.parseInt(resourceBundle.getString("port"));
//2.创建一个连接池配置对象
JedisPoolConfig config = new JedisPoolConfig();
config.setMaxTotal(maxTotal); //最大连接数
config.setMaxWaitMillis(maxWaitMillis); //最大等待超时时间,单位毫秒
//3.根据配置对象创建连接池对象
jedisPool = new JedisPool(config,host,port);
}
//对外提供Jedis连接资源
public static Jedis getJedis(){
return jedisPool.getResource();
}
}
使用工具类测试代码
public class JedisTest2_JedisUtil {
public static void main(String[] args) {
//1.通过工具类获取Jedis连接
Jedis jedis = JedisUtil.getJedis();
//2.操作数据
//字符串数据
jedis.set("username","小民");
String username = jedis.get("username");
System.out.println("username="+username);
//list类型数据
jedis.lpush("mylist2","a","b","c");
List<String> mylist2 = jedis.lrange("mylist2", 0, -1);
System.out.println("mylist2:"+mylist2);
//3.关闭连接
jedis.close();
}
}
示例:异步加载联系人1-环境搭建
需求
访问index.html页面,点击页面上的加载所有联系人按钮,使用ajax请求异步加载所有联系人列表。用户第一次访问从数据库中获取数据,以后都从redis缓存里面获取。
服务器输出控制器信息
项目分析
数据库表数据准备
-- 联系人
create database test charset utf8;
use test;
create table contact (
id int primary key auto_increment,
name varchar(20) not null, -- 姓名
phone varchar(20), -- 电话
email varchar(50), -- 邮箱
birthday date -- 生日
);
insert into contact (name,phone,email,birthday) values
('小明','13423431234','xiaoming@xxx.com', '1996-12-01'),...
;
select * from contact;
创建实体类
public class Contact {
private Integer id;
private String name;
private String phone;
private String email;
private String birthday;
public Contact() {
}
public Contact(Integer id, String name, String phone, String email, String birthday) {
this.id = id;
this.name = name;
this.phone = phone;
this.email = email;
this.birthday = birthday;
}
/**
* 获取
* @return id
*/
public Integer getId() {
return id;
}
/**
* 设置
* @param id
*/
public void setId(Integer id) {
this.id = id;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return phone
*/
public String getPhone() {
return phone;
}
/**
* 设置
* @param phone
*/
public void setPhone(String phone) {
this.phone = phone;
}
/**
* 获取
* @return email
*/
public String getEmail() {
return email;
}
/**
* 设置
* @param email
*/
public void setEmail(String email) {
this.email = email;
}
/**
* 获取
* @return birthday
*/
public String getBirthday() {
return birthday;
}
/**
* 设置
* @param birthday
*/
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String toString() {
return "Contact{id = " + id + ", name = " + name + ", phone = " + phone + ", email = " + email + ", birthday = " + birthday + "}";
}
}
添加包、配置文件、工具类
jdbc.properties数据库名修改
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8
username=root
password=root
poolMaximumActiveConnections=10
示例:异步加载联系人2-后端处理
实现代码
IContactDao
public interface IContactDao {
//查询联系人列表
@Select("select * from contact")
List<Contact> findAll();
}
ContactService
public class ContactService {
//目标:从缓存获取联系人列表数据
public String findAllByRedis()throws Exception{
//1.从缓存获取数据jsonData
//获取jedis连接
Jedis jedis = JedisUtil.getJedis();
//读取数据
String jsonData = jedis.get("contacts");
//2.判断jsonData是否有效
if(jsonData==null || jsonData.equals("{}")) {
//3.无效
//3.1调用数据库获取数据List<Contact>
SqlSession sqlSession = MybatisUtils.getSession();
IContactDao contactDao = sqlSession.getMapper(IContactDao.class);
List<Contact> contactList = contactDao.findAll();
//3.2将列表数据转换为json字符串写入到缓存中
jsonData = new ObjectMapper().writeValueAsString(contactList);
jedis.set("contacts",jsonData);
}
jedis.close();
//4.有效,直接返回
return jsonData;
}
}
ContactServlet
@WebServlet(name = "ContactServlet", urlPatterns = "/ContactServlet")
public class ContactServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
//实例业务类
private ContactService contactService = new ContactService();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
//目标:处理异步请求获取联系人列表数据
//1.调用业务获取数据
String jsonData = contactService.findAllByRedis();
//2.输出给前端
response.setContentType("application/json;charset=utf8");
response.getWriter().print(jsonData);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e); //抛给前端异步错误回调函数
}
}
}
示例:异步加载联系人3-前端处理
index.html实现代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>通讯录管理</title>
<link href="css/bootstrap.min.css" rel="stylesheet">
<script src="js/jquery-3.3.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<br>
<input id="btnLoad" type="button" class="btn btn-primary" value="加载联系人列表">
<input id="btnClear" type="button" class="btn btn-danger" value="清空联系人列表">
<hr>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr class="success">
<th>编号</th>
<th>姓名</th>
<th>电话</th>
<th>邮箱</th>
<th>生日</th>
</tr>
</thead>
<tbody id="contacts">
</tbody>
</table>
</div>
</body>
<script type="text/javascript">
//1.给“加载联系人列表”按钮注册点击事件
$("#btnLoad").click(function () {
//2.提交异步请求获取联系人列表json数据
$.post({
url:"ContactServlet",
success:function (contactList) {
//contactList=[{id:xx,name:xx,...}...]
//3.将数据更新到页面上显示
//定义拼接字符串变量
var html='';
//循环contactList列表,拼接每一个联系人的html代码
for(var contact of contactList){
html+=`<tr>
\t\t\t\t\t<td>${contact.id}</td>
\t\t\t\t\t<td>${contact.name}</td>
\t\t\t\t\t<td>${contact.phone}</td>
\t\t\t\t\t<td>${contact.email}</td>
\t\t\t\t\t<td>${contact.birthday}</td>
\t\t\t\t</tr>`;
}
//将html代码设置到tbody(id="contacts")标签体里面
$("#contacts").html(html);
},
error:function (errorObj) {
console.log(errorObj);
alert("服务器忙。。。");
}
});
});
//目标:实现按钮清空联系人功能
$("#btnClear").click(function () {
$("#contacts").empty();
});
</script>
</html>
Jquery验证码插件介绍
代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>
<title>jquery验证码插件verify.js</title>
<link href="http://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="css/htmleaf-demo.css">
<link rel="stylesheet" type="text/css" href="css/verify.css">
</head>
<body>
<div class="htmleaf-container">
<div class="container">
<div class="row">
<div class="col-md-offset-4 col-md-4">
<h3>普通验证码</h3>
<div id="mpanel2" ></div>
<button type="button" id="check-btn" class="verify-btn">确定</button>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-offset-4 col-md-4">
<h3>数字计算验证码</h3>
<div id="mpanel3" style="margin-top: 20px"></div>
<button type="button" id="check-btn2" class="verify-btn">确定</button>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-offset-4 col-md-4">
<h3>滑动验证码</h3>
<p>滑动滑块到最右侧完成验证</p>
<div id="mpanel1" ></div>
<p style="margin-top:50px;">拖动方块到空白处完成验证</p>
<div id="mpanel4" ></div>
</div>
</div>
<hr>
<div class="row">
<div class="col-md-offset-4 col-md-4">
<h3>点选验证码</h3>
<div id="mpanel5" style="margin-top:50px;"></div>
<div id="mpanel6" style="margin-top:50px;"></div>
</div>
</div>
</div>
</div>
<script src="js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="js/verify.js" ></script>
<script type="text/javascript">
$('#mpanel2').codeVerify({
type : 1,
width : '400px',
height : '50px',
fontSize : '30px',
codeLength : 6,
btnId : 'check-btn',
ready : function() {
},
success : function() {
alert('验证匹配!');
},
error : function() {
alert('验证码不匹配!');
}
});
$('#mpanel3').codeVerify({
type : 2,
figure : 100, //位数,仅在type=2时生效
arith : 0, //算法,支持加减乘,不填为随机,仅在type=2时生效
width : '200px',
height : '50px',
fontSize : '30px',
btnId : 'check-btn2',
ready : function() {
},
success : function() {
alert('验证匹配!');
},
error : function() {
alert('验证码不匹配!');
}
});
$('#mpanel1').slideVerify({
type : 1, //类型
vOffset : 5, //误差量,根据需求自行调整
barSize : {
width : '80%',
height : '40px',
},
ready : function() {
},
success : function() {
alert('验证成功,添加自己的代码!');
//......后续操作
},
error : function() {
// alert('验证失败!');
}
});
$('#mpanel4').slideVerify({
type : 2, //类型
vOffset : 5, //误差量,根据需求自行调整
vSpace : 5, //间隔
imgName : ['1.jpg', '2.jpg'],
imgSize : {
width: '400px',
height: '200px',
},
blockSize : {
width: '40px',
height: '40px',
},
barSize : {
width : '400px',
height : '40px',
},
ready : function() {
},
success : function() {
alert('验证成功,添加自己的代码!');
//......后续操作
},
error : function() {
// alert('验证失败!');
}
});
$('#mpanel5').pointsVerify({
defaultNum : 4, //默认的文字数量
checkNum : 2, //校对的文字数量
vSpace : 5, //间隔
imgName : ['1.jpg', '2.jpg'],
imgSize : {
width: '600px',
height: '200px',
},
barSize : {
width : '600px',
height : '40px',
},
ready : function() {
},
success : function() {
alert('验证成功,添加自己的代码!');
//......后续操作
},
error : function() {
// alert('验证失败!');
}
});
$('#mpanel6').pointsVerify({
defaultNum : 4, //默认的文字数量
checkNum : 2, //校对的文字数量
vSpace : 5, //间隔
imgName : ['1.jpg', '2.jpg'],
imgSize : {
width: '600px',
height: '200px',
},
barSize : {
width : '600px',
height : '40px',
},
ready : function() {
},
success : function() {
alert('验证成功,添加你自己的代码!');
//......后续操作
},
error : function() {
// alert('验证失败!');
}
});
</script>
</body>
</html>