美文网首页
使用SpringBoot和Redis构建个人博客(二)

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

作者: 空挡 | 来源:发表于2018-08-06 21:25 被阅读0次

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


    项目结构.jpg
    • BlogWebApplication.java 是启动类
    • configuration 包含spring的配置类
    • utils 包含所有的工具类
    • dto 数据实体类
    • controller,service和dao就不用说了,里面分为接口和实现类。
    • application.properties和logback-spring.xml是springboot默认读取的应用和日志配置文件,放在resource目录下面

    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主要的依赖项如下:

    • spring-boot-starter-web基本上涵盖了所有web开发使用到的依赖包
    • spring-boot-starter-data-redis需要手工引入,用来连接Redis。
    • 比起springboot默认使用的jackson,阿里开源的fastjson api更加简单易用,所以项目中会使用fastjson做http请求的converter。同时放入redis中的数据也使用fastjson来做序列化和反序列化。
    • jsoup是一个开源的html parser工具包,用来在用户提交博客时过滤非法的html标签,防止XSS攻击代码提交。

    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了。不过为了使用起来更方便,我们需要额外做一些配置。

    • Springboot 默认使用java自带的序列化类来序列化value,因为序列化后的value是不可读的,所以我们改成
      使用json序列化。
    • 写一个RedisSupport类封装redis操作,便于Dao中使用
    • 一个Configuration将上面的配置生效

    首先需要实现一个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 ©王赛超

    相关文章

      网友评论

          本文标题:使用SpringBoot和Redis构建个人博客(二)

          本文链接:https://www.haomeiwen.com/subject/cccnvftx.html