实现流程
1. 实现缓存文章 1.1 实体类 package com.intehel.demo.domain;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;@Data @NoArgsConstructor @AllArgsConstructor public class Article implements Serializable { private Integer id; private Integer num; }
1.2 数据库持久层 package com.intehel.demo.mapper;import com.intehel.demo.domain.Article;import org.apache.ibatis.annotations.*;import org.springframework.stereotype.Repository;@Repository @Mapper public interface ArticleMapper { Article findArticleById (Long id) ; Long updateArticle (@Param("lviews") Long lviews, @Param("lid") Long lid) ; }
1.3 mybatis映射文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.intehel.demo.mapper.ArticleMapper" > <resultMap id ="BaseResultMap" type ="com.intehel.demo.domain.Article" > <id column ="id" property ="id" jdbcType ="INTEGER" /> <result column ="num" property ="num" jdbcType ="BIGINT" /> </resultMap > <select id ="findArticleById" resultMap ="BaseResultMap" parameterType ="java.lang.Long" > select * from article where id = #{id} </select > <update id ="updateArticle" parameterType ="java.lang.Long" > update article set num = #{lviews} where id = #{lid} </update > </mapper >
1.4 实现服务层的缓存设置 package com.intehel.demo.service;import com.intehel.demo.domain.Article;import com.intehel.demo.mapper.ArticleMapper;import org.apache.ibatis.annotations.Param;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.cache.annotation.CacheConfig;import org.springframework.cache.annotation.CachePut;import org.springframework.cache.annotation.Cacheable;import org.springframework.stereotype.Service;@Service @CacheConfig(cacheNames = "articleService") public class ArticleService { @Autowired private ArticleMapper articleMapper; @Cacheable(key = "#id") public Article findArticleById (Long id) { return articleMapper.findArticleById(id); } @CachePut(key = "#lid") public Article updateArticle (@Param("lviews") Long lviews, @Param("lid") Long lid) { articleMapper.updateArticle(lviews,lid); return articleMapper.findArticleById(lid); } }
1.5 配置redis package com.intehel.demo.config;import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.CachingConfigurerSupport;import org.springframework.cache.interceptor.KeyGenerator;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.*;import java.lang.reflect.Method;import java.time.Duration;@Configuration public class RedisConfig extends CachingConfigurerSupport { @Override @Bean public KeyGenerator keyGenerator () { return new KeyGenerator () { @Override public Object generate (Object target, Method method, Object... params) { StringBuilder sb = new StringBuilder (); sb.append(target.getClass().getName()); sb.append(method.getName()); for (Object obj : params) { sb.append(obj.toString()); } return sb.toString(); } }; } @SuppressWarnings("rawtypes") @Bean public CacheManager cacheManager (RedisConnectionFactory connectionFactory) { RedisSerializer<String> strSerializer = new StringRedisSerializer (); Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer (Object.class); ObjectMapper om = new ObjectMapper (); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jacksonSeial.setObjectMapper(om); RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofDays(1 )) .serializeKeysWith(RedisSerializationContext.SerializationPair .fromSerializer(strSerializer)) .serializeValuesWith(RedisSerializationContext.SerializationPair .fromSerializer(jacksonSeial)) .disableCachingNullValues(); RedisCacheManager cacheManager = RedisCacheManager .builder(connectionFactory).cacheDefaults(config).build(); return cacheManager; } @Bean public RedisTemplate<String,Object> redisTemplate (RedisConnectionFactory factory) { RedisTemplate<String, Object> template = new RedisTemplate <>(); template.setConnectionFactory(factory); Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer (Object.class); ObjectMapper om = new ObjectMapper (); om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); template.setDefaultSerializer(jackson2JsonRedisSerializer); return template; } @Bean public StringRedisTemplate stringRedisTemplate (RedisConnectionFactory factory) { StringRedisTemplate stringRedisTemplate = new StringRedisTemplate (); stringRedisTemplate.setConnectionFactory(factory); return stringRedisTemplate; } private RedisSerializer<?> keySerializer() { return new StringRedisSerializer (); } private RedisSerializer<?> valueSerializer() { return new GenericJackson2JsonRedisSerializer (); } }
2. 实现统计点击量 package com.intehel.demo.controller;import com.intehel.demo.domain.Article;import com.intehel.demo.service.ArticleService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/article") public class ArticleController { @Autowired private ArticleService articleService; @Autowired private RedisTemplate<String,Object> redisTemplate; @RequestMapping("/{id}") public Article testPathVariable (@PathVariable("id") Integer id) { Article article = articleService.findArticleById(Long.valueOf(id)); System.out.println(article); if (article.getNum()>0 ){ if (redisTemplate.opsForValue().get("num::" +id)!=null ){ redisTemplate.opsForValue().increment("num::" +id, 1 ); }else { redisTemplate.boundValueOps("num::" +id).increment(article.getNum()+1 ); } }else { redisTemplate.boundValueOps("num::" +id).increment(1 ); } return article; } }
3.实现定时同步 package com.intehel.demo.config;import com.intehel.demo.service.ArticleService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.scheduling.annotation.Scheduled;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.util.ArrayList;import java.util.List;import java.util.Set;@Component public class CountScheduledTasks { @Autowired private ArticleService articleService; @Resource private RedisTemplate<String,Object> redisTemplate; @Scheduled(cron = "0/10 * * * * ?" ) public void syncPostViews () { Long StartTime = System.nanoTime(); List dtolist = new ArrayList (); Set<String> keySet = redisTemplate.keys("num::*" ); System.out.println(keySet); for (String key : keySet) { String view = redisTemplate.opsForValue().get(key).toString(); String sid = key.replaceAll("num::" , "" ); Long lid = Long.valueOf(sid); Long lviews = Long.valueOf(view); articleService.updateArticle(lviews,lid); redisTemplate.delete(key); } } }
同时要在启动类中添加注解,开启redis缓存和定时任务:
@SpringBootApplication @EnableCaching @EnableScheduling @MapperScan("com.intehel.demo")