使用SpringBoot和Redis构建个人博客(二)

2018-08-06  本文已影响0人  空挡

上一篇讲了redis sentinel环境的搭建,这一篇进入正题,搭建SpringBoot环境。首先看下搭建完成后的项目结构,再分解讲解一下。


项目结构.jpg

POM文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.github.blog</groupId>
    <artifactId>redis-blog</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>redis-blog</name>
    <url>http://maven.apache.org</url>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring.boot.version>1.5.2.RELEASE</spring.boot.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!-- 加入redis支持 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
       <!-- 引入fastjson -->
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.47</version>
      </dependency>
      <!-- 工具包 -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.7</version>
        </dependency>
    <!-- 引入jsoup解析html -->
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.11.3</version>
        </dependency>
    </dependencies>
    <build>
        <finalName>redis-blog</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

POM主要的依赖项如下:

POM写好后就可以导入自己熟悉的IDE里面了,idea可以使用File->New -> Project From Source 从pom导入, 或者Project->New->Project From Version Control->Git。
Eclipse建议先使用mvn eclipse:eclipse生成eclipse工程,然后import project。详细步骤可上网查询。

application.properties

springboot的配置项如下:

spring.profiles.active=dev   #表示dev环境

#redis,下面注释的两项单机模式时配置
#spring.redis.hostName=localhost
#spring.redis.port=6379
spring.redis.password=Blog2018dev$            #redis密码,在上一章的redis.conf中有配置
spring.redis.sentinel.master=master001        #master组的名字,在上一章的redis.conf中有配置
spring.redis.sentinel.nodes=127.0.0.1:26379   #sentinel的ip和密码,多个的话使用逗号隔开

#Redis连接池配置,2.0之前springboot默认使用jedis连接池
spring.redis.pool.max-active=200              
spring.redis.pool.max-idle=10
spring.redis.pool.min-idle=0
spring.redis.pool.max-wait=5000
spring.redis.timeout=30000

#http默认编码,貌似不配也可以
spring.http.encoding.charset=UTF-8
app.log.path=logs    # 日志文件路径,logback-spring.xml中有用到

以上的配置文件中redis相关配置是必须的,连接池springboot会有默认配置,可根据自己需要选择修改其中一个或者多个

Redis Template基础配置

springboot配置中加入redis配置后,spring会默认生成一个RedisTemplate的Bean,只要业务代码里将这个Bean注入就可以使用redis了。不过为了使用起来更方便,我们需要额外做一些配置。

首先需要实现一个RedisSerializer

public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>{
    private static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");

    private Class<T> clazz;

    public FastJson2JsonRedisSerializer(Class<T> clazz) {
        super();
        this.clazz = clazz;
    }
    
    //使用fastjson做序列化,同时带上class name,便于反序列化
    @Override
    public byte[] serialize(T t) throws SerializationException {
        if (t == null) {
            return new byte[0];
        }
        return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
    }

    @Override
    public T deserialize(byte[] bytes) throws SerializationException {
        if (bytes == null || bytes.length <= 0) {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);

        return JSON.parseObject(str, clazz);
    }
}

Configuration类,做两件事情,定义RedisSupport Bean,将RedisTemplate序列化类改成我们上面写的使用fastjson的实现。

@Configuration
public class RedisConfiguration {
    @Bean
    @Primary
    public RedisTemplate<String, Object> createRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new FastJson2JsonRedisSerializer<>(Object.class));    //普通value
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(new FastJson2JsonRedisSerializer<>(Object.class)); //Hash结构的Value
//        redisTemplate.setEnableTransactionSupport(true); //这里不要打开事务支持,原因后面单独写一篇文章来解释
        return redisTemplate;
    }

    /**
     * 定义RedisSupport bean 
     */
    @Bean(name = "redisSupport")
    public RedisSupport createRedisSupport(RedisTemplate<String, Object> redisTemplate) {
        return new RedisSupport(redisTemplate);
    }

}

RedisSupport类,封装了RedisTemplate的操作。这里只截取一个片段,详细的请到git上查看。

public class RedisSupport {

    private RedisTemplate<String, Object> redisTemplate;
    /**
     * 根据key 获取过期时间
     * @param key 键 不能为null
     * @return 时间(秒) 返回0代表为永久有效
     */
    public long getExpire(String key){
        return redisTemplate.getExpire(key,TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true 存在 false不存在
     */
    public boolean hasKey(String key){
        return exists(key);
    }
    public boolean exists(String key) { return redisTemplate.hasKey(key);}

    /**
     * 删除缓存
     * @param key 可以传一个值 或多个
     */
    @SuppressWarnings("unchecked")
    public void del(String ... key){
        if(key!=null&&key.length>0){
            if(key.length==1){
                redisTemplate.delete(key[0]);
            }else{
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }
}

好了,redis的配置到这里就结束了,后面就可以在Dao里愉快的使用RedisSupport了,具体用法就是在Dao中注入RedisSupport就可以了。
比如ArticleDao中获取一篇文章的属性,详细的代码见Git上

@Repository
public class ArticleDaoImpl implements ArticleDao {
      private final Logger log = LoggerFactory.getLogger(ArticleDao.class);
    
    @Autowired
    private RedisSupport redisSupport;  //注入RedisSupport
    
    @Override
    public ArticleDto getSummary(Long id) {
        Assert.notNull(id, "id must not be null");
        
        //从redis中取一篇文章的属性,文章使用Hash类型存储
        Map<Object,Object> result = redisSupport.hmget("article:"+id);
        if(MapUtils.isNotEmpty(result)){
            ArticleDto article = BeanUtils.mapToBean(result, ArticleDto.class);
            if(NumberUtils.zeroOnNull(article.getStatus()) <= 1)
                return article;
        }
        return null;
    }
}

Spring mvc 配置

spring mvc的配置我们只干一件事,使用fastjson代替jackson来转换http的request和将reponse转成json。实现方式很简单,fastjson已经提供了一个converter类的实现FastJsonHttpMessageConverter,
只需要用它作为默认的converter就可以了。修改Spring mvc的配置一般是通过继承WebMvcConfigurationSupport,并重写其中的方法来实现的。

@Configuration
public class WebConfiguration extends WebMvcConfigurationSupport{
  @Override
    protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
    //SerializerFeature.PrettyFormat reponse返回的json做format,带回车和缩进,如果为了节省流量可在发正式环境时去掉
    //SerializerFeature.WriteDateUseDateFormat  转json时将日期转成yyyy-MM-dd HH:mm:ss的格式
        fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat, SerializerFeature.WriteDateUseDateFormat);
        fastConverter.setFastJsonConfig(fastJsonConfig);
        fastConverter.setDefaultCharset(Charset.forName("UTF-8"));
    //content-type未application/json的请求将会使用这个converter
        fastConverter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8,MediaType.APPLICATION_JSON));
        HttpMessageConverter<Object> converter = fastConverter;
    //将converter放在第一个,优先匹配
        converters.add(0, converter);
    }
}

SpringBoot+Redis配置已经讲完了,下一章将讲使用Redis存储个人博客系统的数据结构设计,并跑通一个完整的请求。

参考文章:https://blog.csdn.net/qq_34021712/article/details/75949706 ©王赛超

上一篇下一篇

猜你喜欢

热点阅读