广告类型及广告管理
广告类型:
(1)首页海报(轮播图)
(2)今日推荐
(3)猜你喜欢
(4)楼层广告
构建工程:
广告图片上传:
广告展示:
public List<TbContent> findByCategoryId(Long categoryId) {
//根据广告分类ID查询广告列表
TbContentExample contentExample=new TbContentExample();
Criteria criteria2 = contentExample.createCriteria();
criteria2.andCategoryIdEqualTo(categoryId);
criteria2.andStatusEqualTo("1");//开启状态
contentExample.setOrderByClause("sort_order");//排序
return contentMapper.selectByExample(contentExample);
}
前端三目运算符:{{$index==0?'active':''}}
SpringDataRedis
目前的系统已经实现了广告后台管理和广告前台展示,但是对于首页每天有大量的人访问,每一次访问都要调用数据库查询广告,对数据库造成很大的访问压力,甚至是瘫痪。通常的做法有两种:一种是数据缓存(Redis)、一种是网页静态化。
Redis:
redis是一款开源的Key-Value数据库,运行在内存中,由ANSI C编写。企业开发通常采用Redis来实现缓存。Redis可以持久化数据到本地硬盘,有两种方式RDB和AOF。
Jedis:
Jedis不是数据库,是操作redis的官方API库。
Spring Data Redis:
Spring Data Redis是对redis操作的API库的封装,包含了(Jedis, JRedis, and RJC)
Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现。
spring-data-redis针对jedis提供了如下功能:
1.连接池自动管理,提供了一个高度封装的“RedisTemplate”类
2.针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
ValueOperations:简单K-V操作
SetOperations:set类型数据操作
ZSetOperations:zset类型数据操作
HashOperations:针对map类型的数据操作
ListOperations:针对list类型的数据操作
SpringDataRedis准备工作:
1.pom.xml
<!-- 缓存 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.7.2.RELEASE</version>
</dependency>
2.建立redis-config.properties
redis.host=127.0.0.1
redis.port=6379
redis.pass=
redis.database=0
redis.maxIdle=300
redis.maxWait=3000
redis.testOnBorrow=true
3.创建applicationContext-redis.xml
<context:property-placeholder location="classpath*:properties/*.properties" />
<!-- redis 相关配置 -->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}" />
<property name="maxWaitMillis" value="${redis.maxWait}" />
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean>
<bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="JedisConnectionFactory" />
</bean>
maxIdle :最大空闲数
maxWaitMillis:连接时的最大等待毫秒数
testOnBorrow:在提取一个jedis实例时,是否提前进行验证操作;如果为true,则得到的jedis实例均是可用的;
4.操作:
(1)值类型操作
//存储
public void setValue(){
redisTemplate.boundValueOps("name").set("itcast");
}
//取值
public void getValue(){
String str = (String) redisTemplate.boundValueOps("name").get();
System.out.println(str);
}
//删除
public void deleteValue(){
redisTemplate.delete("name");;
}
(2) Set类型操作
//存值
public void setValue(){
redisTemplate.boundSetOps("nameset").add("曹操");
redisTemplate.boundSetOps("nameset").add("刘备");}
//取值
public void getValue(){
Set nameSet = redisTemplate.boundSetOps("nameSet").members();
System.out.println(nameSet);
}
//移除一个值
public void removeValue(){
redisTemplate.boundSetOps("nameSet").remove("孙权");
}
//全部删除
public void removeAllValue(){
redisTemplate.delete("nameSet");
}
(3)List类型操作
右压栈:后添加的对象排在后边
public void testSetValue1(){
redisTemplate.boundListOps("namelist1").rightPush("刘备");
redisTemplate.boundListOps("namelist1").rightPush("关羽");
redisTemplate.boundListOps("namelist1").rightPush("张飞");
}
//显示右压栈集合
public void testGetValue1(){
List list = redisTemplate.boundListOps("namelist1").range(0, 10);//range(0,-1)是取全部
System.out.println(list);
}
运行结果:
[刘备, 关羽, 张飞]
左压栈:后添加的对象排在前边
public void testSetValue2(){
redisTemplate.boundListOps("namelist2").leftPush("刘备");
redisTemplate.boundListOps("namelist2").leftPush("关羽");
redisTemplate.boundListOps("namelist2").leftPush("张飞");
}
/**
* 显示左压栈集合
*/
@Test
public void testGetValue2(){
List list = redisTemplate.boundListOps("namelist2").range(0, 10);
System.out.println(list);
}
运行结果:
[张飞, 关羽, 刘备]
根据索引查询元素:
//查询集合某个元素
public void testSearchByIndex(){
String s = (String) redisTemplate.boundListOps("namelist1").index(1);
System.out.println(s);
}
//移除集合某个元素
public void testRemoveByIndex(){
redisTemplate.boundListOps("namelist1").remove(1, "关羽");
}
(4)Hash类型操作
//存入值
public void testSetValue(){
redisTemplate.boundHashOps("namehash").put("a", "唐僧");
redisTemplate.boundHashOps("namehash").put("b", "悟空");
redisTemplate.boundHashOps("namehash").put("c", "八戒");
redisTemplate.boundHashOps("namehash").put("d", "沙僧");
}
//提取所有的KEY
public void testGetKeys(){
Set s = redisTemplate.boundHashOps("namehash").keys();
System.out.println(s);
}
运行结果:
[a, b, c, d]
//提取所有的值
public void testGetValues(){
List values = redisTemplate.boundHashOps("namehash").values();
System.out.println(values);
}
运行结果:
[唐僧, 悟空, 八戒, 沙僧]
//根据KEY提取值
public void testGetValueByKey(){
Object object = redisTemplate.boundHashOps("namehash").get("b");
System.out.println(object);
}
运行结果:
悟空
//根据KEY移除值
public void testRemoveValueByKey(){
redisTemplate.boundHashOps("namehash").delete("c");
}
运行后再次查看集合内容:
[唐僧, 悟空, 沙僧]
//获取所有键值对
Map nameHash = redisTemplate.boundHashOps("nameHash").entries();
/*Iterator iterator = nameHash.entrySet().iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}*/
/*Set set = nameHash.entrySet();
for (Object o : set) {
System.out.println(o);
}*/
Set set = nameHash.keySet();
for (Object o : set) {
System.out.println(o+"="+nameHash.get(o));
}
缓存广告数据
@Autowired
private RedisTemplate redisTemplate;
public List<TbContent> findByCategoryId(Long categoryId) {
List<TbContent> contentList= (List<TbContent>) redisTemplate.boundHashOps("content").get(categoryId);
if(contentList==null){
//根据广告分类ID查询广告列表
TbContentExample contentExample=new TbContentExample();
Criteria criteria2 = contentExample.createCriteria();
criteria2.andCategoryIdEqualTo(categoryId);
criteria2.andStatusEqualTo("1");//开启状态
contentExample.setOrderByClause("sort_order");//排序
contentList = contentMapper.selectByExample(contentExample);//获取广告列表
redisTemplate.boundHashOps("content").put(categoryId, contentList);//存入缓存
}
return contentList;
}
广告数据缓存更新
当从数据库查询出来数据,保存到redis之后,数据库就不在查询了,只操作redis的数据,和数据库没有关系了,但是如果数据库的数据更新了,redis是不知道了,这个时候redis中的数据和数据库中的数据就不一致了,所以就会出错,这时在增删改数据库中的数据时都需要重新缓存。
更新redis数据的方案
在数据库增加、更新、删除数据的时候,删除redis中的缓存数据,在重新查询数据库的时候,就会添加到redis中。
新增广告后清除缓存:redisTemplate.boundHashOps("content").delete(content.getCategoryId());
更新广告后清楚缓存:
//查询修改前的分类Id
Long categoryId = contentMapper.selectByPrimaryKey(content.getId()).getCategoryId();
redisTemplate.boundHashOps("content").delete(categoryId);
contentMapper.updateByPrimaryKey(content);
//如果分类ID发生了修改,清除修改后的分类ID的缓存
if(categoryId.longValue()!=content.getCategoryId().longValue()){
redisTemplate.boundHashOps("content").delete(content.getCategoryId());
}
如果这个广告是从分类1改变到分类2,那么这两个分类都进行了更新所以都要删除缓存,要不然酚类2中查询不到新加进来的广告。