【Spring Boot&&Spring Cloud系列】提高数据库访问性能

前言

使用关系型数据库的应用系统的性能瓶颈最终还是数据库。随着业务的迅速增长,数据量会不断增大,会逐渐暴露关系型数据库的弱点,性能会大幅度的降低

项目地址:https://github.com/AndyFlower/Spring-Boot-Learn/tree/master/spring-boot-dbup

一、使用Druid

Druid是一个关系型数据库连接池,它是阿里巴巴的一个开源项目。Druid支持所有JDBC兼容的数据库,包括,Oracle,MySql,Derby,PostgreSQL,SQL Server,H2等。Druid在监控、可扩展性、稳定性和性能方面具有明显的优势。通过Druid提供的监控功能,可以实时观察数据库连接池和SQL查询的工作状况。使用Druid连接池,在一定程度上可以提高数据库的访问性能。使用Druid连接池,在一定程度上可以提高数据库的访问性能。

1、配置Druid依赖

1 <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
2 <dependency>
3     <groupId>com.alibaba</groupId>
4     <artifactId>druid</artifactId>
5     <version>1.0.29</version>
6 </dependency>

2、使用XML配置

使用Spring开发框架时,XML配置是经常使用的一种配置方法,其中数据源配置就是使用XML配置的一种。使用Spring Boot框架也能使用XML配置,只要在程序入口使用一个注解即@ImportResource({"classpath:spring-datasource.xml"}),即可导入XML配置,但是Spring Boot更推荐使用application.properties或application.yum文件来进行配置

 1 server.port=80
 2 server.tomcat.uri-encoding=utf-8
 3 
 4 spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
 5 spring.datasource.driver-class-name=com.mysql.jdbc.Driver
 6 spring.datasource.url=jdbc:mysql://localhost:3306/dev?characterEncoding=utf-8
 7 spring.datasource.username=root
 8 spring.datasource.password=123456
 9 #初始化大小
10 spring.datasource.initial-size=5
11 #最小
12 spring.datasource.min-idle=5
13 #最大
14 spring.datasource.max-active=20
15 #配置获取连接等待超时的时间
16 spring.datasource.max-wait=60000
17 #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
18 spring.datasource.time-between-eviction-runs-millis=60000
19 #配置一个连接在池中最小生存的时间,单位是毫秒
20 spring.datasource.min-evictable-idle-time-millis=300000
21 spring.datasource.validation-query=SELECT 1 FROM DUAL
22 spring.datasource.test-while-idle=true
23 spring.datasource.test-on-borrow=false
24 spring.datasource.test-on-return=false
25 #打开PSCache,并且指定每个连接上的PSCache的大小
26 spring.datasource.pool-prepared-statements=true
27 spring.datasource.max-pool-prepared-statement-per-connection-size=20
28 #配置监控统计拦截的filters,去掉后监控界面sql无法统计 wall用于防火墙
29 spring.datasource.filters=stat,wall,log4j
30 spring.datasource.connection-properties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
31 
32 
33 spring.jpa.database=mysql
34 spring.jpa.show-sql=true
35 spring.jpa.hibernate.ddl-auto=update
36 spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.ImprovedNamingStrategy
37 spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
38 
39 spring.redis.host=localhost
40 spring.redis.port=6379
41 spring.redis.pool.max-idle=8
42 spring.redis.pool.min-idle=0
43 spring.redis.pool.max-active=8
44 spring.redis.pool.max-wait=-1

3、开启监控功能

开启Druid的监控功能可以在应用运行的过程中,通过监控提供的多维度数据来分析使用数据库的运行情况。从而调整程序设计,以优化数据库的访问性能。

设置访问连接地址为“/druid/*”,设定访问数据库的白名单和黑名单,即通过访问者的IP来控制访问员,增加了数据库的安全设置,还配置了用于登陆的用户名和密码。

 1 package com.slp.dbexpand;
 2 
 3 import com.alibaba.druid.support.http.StatViewServlet;
 4 import com.alibaba.druid.support.http.WebStatFilter;
 5 import org.springframework.boot.context.embedded.FilterRegistrationBean;
 6 import org.springframework.boot.context.embedded.ServletRegistrationBean;
 7 import org.springframework.context.annotation.Bean;
 8 import org.springframework.context.annotation.Configuration;
 9 
10 /**
11  * Created by sangliping on 2017/9/1.
12  */
13 @Configuration
14 public class DruidConfiguration {
15     @Bean
16     public ServletRegistrationBean statViewServlet(){
17         ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
18         //白名单
19         servletRegistrationBean.addInitParameter("allow","127.0.01");
20         //IP黑名单(共同存在时,deny优先于allow)
21         servletRegistrationBean.addInitParameter("deny","192.168.1.100");
22         //登陆查看新的是账户密码
23         servletRegistrationBean.addInitParameter("loginUsername","druid");
24         servletRegistrationBean.addInitParameter("loginPassword","123456");
25         //是否能够重置数据
26         servletRegistrationBean.addInitParameter("resetEnable","false");
27         return servletRegistrationBean;
28     }
29 
30     @Bean
31     public FilterRegistrationBean statFilter(){
32         FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
33         //添加过滤规则
34         filterRegistrationBean.addUrlPatterns("/*");
35         //添加不需要忽略的格式信息
36         filterRegistrationBean.addInitParameter("exclusions","*.js.*.gif,*.png,*.css,*.ico,/druid/*");
37         return filterRegistrationBean;
38     }
39 }

4、扩展JPA实现

4.1首先创建一个接口,继承与JpaRepository,并将接口标记为@NoRepositoryBean以防被当做一般的Repository调用,该接口不仅扩展了原来的findOne、findAll、count等方法而且增加了deleteById、getEntityClass、nativeQuery4Map等方法,其中nativeQuery4Map用于执行原生的复杂的SQL查询语句。

 1 package com.slp.dbexpand.jpa.repository;
 2 
 3 import com.slp.dbexpand.jpa.parameter.Operator;
 4 import com.slp.dbexpand.jpa.parameter.Predicate;
 5 import org.springframework.data.domain.Page;
 6 import org.springframework.data.domain.Pageable;
 7 import org.springframework.data.domain.Sort;
 8 import org.springframework.data.jpa.repository.JpaRepository;
 9 import org.springframework.data.repository.NoRepositoryBean;
10 
11 import java.io.Serializable;
12 import java.util.List;
13 import java.util.Map;
14 /**
15  * Created by sangliping on 2017/9/1.
16  */
17 @NoRepositoryBean
18 public interface ExpandJpaRepository <T, ID extends Serializable> extends JpaRepository<T,ID> {
19     T findOne(String condition, Object... objects);
20 
21     List<T> findAll(String condition, Object... objects);
22 
23     List<T> findAll(Iterable<Predicate> predicates, Operator operator);
24 
25     List<T> findAll(Iterable<Predicate> predicates, Operator operator, Sort sort);
26 
27     Page<T> findAll(Iterable<Predicate> predicates, Operator operator, Pageable pageable);
28 
29     long count(Iterable<Predicate> predicates, Operator operator);
30 
31     List<T> findAll(String condition, Sort sort, Object... objects);
32 
33     Page<T> findAll(String condition, Pageable pageable, Object... objects);
34 
35     long count(String condition, Object... objects);
36 
37     void deleteByIds(Iterable<ID> ids);
38 
39     Class<T> getEntityClass();
40 
41     List<Map<String,Object>> nativeQuery4Map(String sql);
42 
43     Page<Map> nativeQuery4Map(String sql, Pageable pageable);
44 
45     Object nativeQuery4Object(String sql);
46 }
package com.slp.dbexpand.jpa.repository;

import com.slp.dbexpand.jpa.Exception.DataException;
import com.slp.dbexpand.jpa.parameter.Operator;
import com.slp.dbexpand.jpa.parameter.Predicate;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.query.QueryUtils;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.*;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.util.*;

import static org.apache.commons.lang3.StringUtils.*;

/**
 * Created by sangliping on 2017/9/1.
 */
public class ExpandJpaRepositoryImpl<T,ID extends Serializable> extends SimpleJpaRepository<T,ID> implements ExpandJpaRepository<T,ID> {

    private final EntityManager entityManager;
    private final JpaEntityInformation<T, ?> entityInformation;

    public ExpandJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityManager = entityManager;
        this.entityInformation = entityInformation;
    }

    @Override
    public T findOne(String condition, Object... values) {
        if(isEmpty(condition)){
            throw new NullPointerException("条件不能为空!");
        }
        T result = null;
        try {
            result = (T) createQuery(condition, values).getSingleResult();
        } catch (NoResultException e) {
            e.printStackTrace();
        }
        return result;

    }

    @Override
    public List<T> findAll(Iterable<Predicate> predicates, Operator operator) {
        return new JpqlQueryHolder(predicates,operator).createQuery().getResultList();
    }

    @Override
    public List<T> findAll(Iterable<Predicate> predicates, Operator operator, Sort sort) {
        return new JpqlQueryHolder(predicates,operator,sort).createQuery().getResultList();
    }

    @Override
    public Page<T> findAll(Iterable<Predicate> predicates, Operator operator, Pageable pageable) {
        if(pageable==null){
            return new PageImpl<T>((List<T>) findAll(predicates,operator));
        }

        Long total = count(predicates,operator);

        Query query = new JpqlQueryHolder(predicates,operator,pageable.getSort()).createQuery();
        query.setFirstResult(pageable.getOffset());
        query.setMaxResults(pageable.getPageSize());

        List<T> content = total > pageable.getOffset() ? query.getResultList() : Collections.<T> emptyList();

        return new PageImpl<T>(content, pageable, total);
    }

    @Override
    public List<T> findAll(String condition, Object... objects) {
        return createQuery(condition, objects).getResultList();
    }


    @Override
    public List<T> findAll(String condition, Sort sort, Object... objects) {
        return createQuery(condition, sort, objects).getResultList();
    }

    @Override
    public Page<T> findAll(String condition, Pageable pageable, Object... objects) {

        if(pageable==null){
            return new PageImpl<T>((List<T>) findAll(condition,objects));
        }

        Long total = count(condition,objects);

        Query query = createQuery(condition, pageable.getSort(), objects);
        query.setFirstResult(pageable.getOffset());
        query.setMaxResults(pageable.getPageSize());

        List<T> content = total > pageable.getOffset() ? query.getResultList() : Collections.<T> emptyList();

        return new PageImpl<T>(content, pageable, total);
    }

    @Override
    public Page<T> findAll(Pageable pageable) {
        return this.findAll("", pageable);
    }

    @Override
    public List<T> findAll(Iterable<ID> ids) {
        return this.findAll("x."+getIdName()+" in ?1",ids);
    }


    @Override
    public long count(String condition, Object... objects) {
        return new JpqlQueryHolder(condition,objects).createCountQuery().getSingleResult();
    }

    @Override
    public long count(Iterable<Predicate> predicates, Operator operator) {
        return new JpqlQueryHolder(predicates,operator).createCountQuery().getSingleResult();
    }

    @Override
    public void deleteByIds(Iterable<ID> ids) {
        List<T> tlist = super.findAll(ids);
        super.deleteInBatch(tlist);
    }


    @Override
    public Class<T> getEntityClass() {
        return entityInformation.getJavaType();
    }

    public String getIdName(){
        Class<?> entityClass = getEntityClass();
        do{
            Field[] fields = entityClass.getDeclaredFields();
            for(Field field:fields){
                if(field.getAnnotation(Id.class)!=null){
                    return field.getName();
                }
            }
            entityClass = entityClass.getSuperclass();
        }while (entityClass != Object.class);
        throw new DataException("未设置主键",DataException.noID);
    }

    @Override
    public List<Map<String, Object>> nativeQuery4Map(String sql) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        return nativeQuery.getResultList();
    }

    @Override
    public Page<Map> nativeQuery4Map(String sql, Pageable pageable) {
        Query nativeQuery = entityManager.createNativeQuery(sql);
        nativeQuery.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
        nativeQuery.setFirstResult(pageable.getOffset());
        nativeQuery.setMaxResults(pageable.getPageSize());

        Query countNativeQuery = entityManager.createNativeQuery("select count(*) from ("+sql+") a");
        long total = Long.valueOf(String.valueOf(countNativeQuery.getSingleResult()));

        return new PageImpl<Map>(nativeQuery.getResultList(),pageable,total);
    }

    @Override
    public Object nativeQuery4Object(String sql) {
        Query nativeQuery = entityManager.createNativeQuery(sql);

        List results=nativeQuery.getResultList();
        if(results==null || results.size()==0){
            return null;
        }
        try{
            if(results.size()>1){
                throw new RuntimeException("结果应当只有一个,但是发现了"+results.size()+"个。");
            }
            return results.get(0);
        }catch (NoResultException e){
            return null ;
        }

    }

    private TypedQuery createCountQuery(String condition, Object[] objects){

        JpqlQueryHolder queryHolder = new JpqlQueryHolder(condition,objects);

        return queryHolder.createCountQuery();
    }

    /**
     * 声明entityClass的查询
     */
    private Query createQuery(String condition, Sort sort, Object[] objects) {

        JpqlQueryHolder queryHolder = new JpqlQueryHolder(condition,sort,objects);

        return queryHolder.createQuery();
    }

    /**
     * 声明entityClass的查询
     */
    private Query createQuery(String condition, Object[] objects) {
        return createQuery(condition, null, objects);
    }


    private class JpqlQueryHolder {

        //别名
        private final String ALIAS = "x";

        //QUERY ALL
        private final String FIND_ALL_QUERY_STRING = "from %s "+ALIAS;

        //传入的condition 排除列表
        private final String[] IGNORE_CONSTAINS_CHARSEQUENCE = {"where","WHERE","from","FROM"};

        private String condition = null;
        private Sort sort;
        private Object[] objects;
        private Iterable<Predicate> predicates;
        private Operator operator = Operator.AND;

        private JpqlQueryHolder(Iterable<Predicate> predicates, Operator operator, Sort sort) {
            this.predicates = predicates;
            this.operator = operator;
            this.sort = sort;
        }

        private JpqlQueryHolder(Iterable<Predicate> predicates , Operator operator ) {
            this.operator = operator;
            this.predicates = predicates;
        }

        private JpqlQueryHolder(String condition, Sort sort, Object[] objects) {
            this(condition,objects);
            this.sort = sort;
        }

        private JpqlQueryHolder(String condition, Object[] objects) {

            if(startsWithAny(condition,IGNORE_CONSTAINS_CHARSEQUENCE)){
                throw new DataException("查询条件中只能包含WHERE条件表达式!",DataException.noPermission);
            }
            this.condition = trimToNull(condition);
            this.objects = objects;
        }

        private Query createQuery(){
            StringBuilder sb = new StringBuilder();
            // select x from table
            sb.append(QueryUtils.getQueryString(FIND_ALL_QUERY_STRING, entityInformation.getEntityName()))
                    //where
                    .append(applyCondition());

            Query query = entityManager.createQuery(QueryUtils.applySorting(sb.toString(), sort, ALIAS));
            applyQueryParameter(query);
            return query;
        }

        private TypedQuery<Long> createCountQuery(){
            String ql = String.format(QueryUtils.COUNT_QUERY_STRING, ALIAS, "%s");
            ql = QueryUtils.getQueryString(ql, entityInformation.getEntityName());
            ql += applyCondition();

            TypedQuery<Long> query = entityManager.createQuery(ql,Long.class);
            applyQueryParameter(query);
            return query;
        }

        private List<String> map2Conditions(){
            if(predicates==null||!predicates.iterator().hasNext()){
                return new ArrayList<String>();
            }
            List<String> conditions = new ArrayList<String>();

            Iterator<Predicate> iterator = predicates.iterator();
            int index = 0 ;
            while (iterator.hasNext()){
                Predicate predicate = iterator.next();
                if(predicate.getKey()==null){
                    continue;
                }
                conditions.add(predicate.toCondition(String.valueOf(index)));
                index++ ;
            }
            return conditions;
        }

        private String applyCondition(){
            List<String> conditions = map2Conditions();
            if(condition!=null) {
                conditions.add(condition);
            }
            condition = join(conditions, " " + operator.name() + " ");
            return isEmpty(condition)?"":" where "+condition;
        }

        private void applyQueryParameter(Query query){
            if(objects!=null){
                int i = 0;
                for(Object value:objects){
                    i++;
                    query.setParameter(i,value);
                }
            }
            if(predicates!=null&&predicates.iterator().hasNext()){
                int index = 0 ;
                Iterator<Predicate> iterator = predicates.iterator();
                while (iterator.hasNext()){
                    Predicate predicate = iterator.next();
                    predicate.setParameter(query,String.valueOf(index));
                    index++ ;
                }
            }
        }
    }

}

4.2、装配自定义的扩展接口

自定义的接口必须在程序启动的时候装配,才能正常使用。首先创建一个ExpandJpaRepositoryFactoryBean继承于JpaRepositoryFactoryBean,用于加载自定义的扩展接口,其中getTargetRepository返回自定义的接口实现ExpandJpaRepositoryImpl:

package com.slp.dbexpand.jpa.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactoryBean;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;

import javax.persistence.EntityManager;
import java.io.Serializable;

/**
 * Created by sangliping on 2017/9/1.
 */
public class ExpandJpaRepositoryBean<R extends JpaRepository<T, ID>, T, ID extends Serializable>extends JpaRepositoryFactoryBean<R, T, ID> {
    protected RepositoryFactorySupport createRepositoryFactory(
            EntityManager entityManager) {
        return new ExpandJpaRepositoryFactory<T, ID>(entityManager);
    }

    private static class ExpandJpaRepositoryFactory<T, ID extends Serializable>
            extends JpaRepositoryFactory {

        private final EntityManager entityManager;

        public ExpandJpaRepositoryFactory(EntityManager entityManager) {

            super(entityManager);
            this.entityManager = entityManager;
        }

        protected Object getTargetRepository(RepositoryMetadata metadata) {
            JpaEntityInformation<T, Serializable> entityInformation = (JpaEntityInformation<T, Serializable>) getEntityInformation(metadata.getDomainType());
            return new ExpandJpaRepositoryImpl<T, ID>(entityInformation, entityManager);
        }

        protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
            return ExpandJpaRepositoryImpl.class;
        }
    }
}

4.3在jpa配置类中通过@EnableJpaRepository加载定义的装配类ExpandJpaRepositoryFactoryBean

 1 package com.slp.dbexpand;
 2 
 3 import com.slp.dbexpand.jpa.repository.ExpandJpaRepositoryBean;
 4 import org.springframework.boot.orm.jpa.EntityScan;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.core.Ordered;
 8 import org.springframework.core.annotation.Order;
 9 import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
10 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
11 import org.springframework.transaction.annotation.EnableTransactionManagement;
12 
13 /**
14  * Created by sangliping on 2017/9/1.
15  */
16 @Order(Ordered.HIGHEST_PRECEDENCE)
17 @Configuration
18 @EnableTransactionManagement(proxyTargetClass = false)
19 @EnableJpaRepositories(basePackages = "com.slp.repository",repositoryFactoryBeanClass = ExpandJpaRepositoryBean.class)
20 @EntityScan(basePackages = "com.slp.entity")
21 public class JpaConfiguration {
22     @Bean
23     PersistenceExceptionTranslationPostProcessor persistenceExceptionTranslationPostProcessor(){
24         return new PersistenceExceptionTranslationPostProcessor();
25     }
26 }

4.3、使用Redis做缓存

在数据库使用中,数据查询是最大的性能开销。如果能借助Redis作为辅助缓存,将可以极大的提高数据库的访问性能。使用Redis做缓存,一方面可以调用,另一方面可以使用注解的方式调用。

值得注意的是,Redis是一个具有持久化功能的数据库系统,若使用默认配置,存取的数据就会永久的保存在磁盘中。如果只是使用Redis做缓存的话可以设定Redis保存数据的期限来实现,这样,过期的数据会自动清除。

1)使用spring cache注解

 1 package com.slp.dbexpand.jpa;
 2 import com.fasterxml.jackson.annotation.JsonAutoDetect;
 3 import com.fasterxml.jackson.annotation.PropertyAccessor;
 4 import com.fasterxml.jackson.databind.ObjectMapper;
 5 import org.springframework.cache.CacheManager;
 6 import org.springframework.cache.annotation.CachingConfigurerSupport;
 7 import org.springframework.cache.annotation.EnableCaching;
 8 import org.springframework.cache.interceptor.KeyGenerator;
 9 import org.springframework.context.annotation.Bean;
10 import org.springframework.context.annotation.Configuration;
11 import org.springframework.data.redis.cache.RedisCacheManager;
12 import org.springframework.data.redis.connection.RedisConnectionFactory;
13 import org.springframework.data.redis.core.RedisTemplate;
14 import org.springframework.data.redis.core.StringRedisTemplate;
15 import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
16 
17 import java.lang.reflect.InvocationTargetException;
18 import java.lang.reflect.Method;
19 /**
20  * Created by sangliping on 2017/9/1.
21  */
22 @Configuration
23 @EnableCaching
24 public class RedisConfig extends CachingConfigurerSupport{
25     @Bean
26     public KeyGenerator simpleKey(){
27         return new KeyGenerator() {
28             @Override
29             public Object generate(Object target, Method method, Object... params) {
30                 StringBuilder sb = new StringBuilder();
31                 sb.append(target.getClass().getName()+":");
32                 for (Object obj : params) {
33                     sb.append(obj.toString());
34                 }
35                 return sb.toString();
36             }
37         };
38     }
39 
40     @Bean
41     public KeyGenerator objectId(){
42         return new KeyGenerator() {
43             @Override
44             public Object generate(Object target, Method method, Object... params){
45                 StringBuilder sb = new StringBuilder();
46                 sb.append(target.getClass().getName()+":");
47                 try {
48                     sb.append(params[0].getClass().getMethod("getId", null).invoke(params[0], null).toString());
49                 }catch (NoSuchMethodException no){
50                     no.printStackTrace();
51                 }catch(IllegalAccessException il){
52                     il.printStackTrace();
53                 }catch(InvocationTargetException iv){
54                     iv.printStackTrace();
55                 }
56                 return sb.toString();
57             }
58         };
59     }
60 
61     @Bean
62     public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate redisTemplate) {
63         RedisCacheManager manager = new RedisCacheManager(redisTemplate);
64         manager.setDefaultExpiration(43200);//12小时
65         return manager;
66     }
67 
68     @Bean
69     public RedisTemplate<String, String> redisTemplate(
70             RedisConnectionFactory factory) {
71         StringRedisTemplate template = new StringRedisTemplate(factory);
72         Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
73         ObjectMapper om = new ObjectMapper();
74         om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
75         om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
76         jackson2JsonRedisSerializer.setObjectMapper(om);
77         template.setValueSerializer(jackson2JsonRedisSerializer);
78         template.afterPropertiesSet();
79         return template;
80     }
81 
82 }

2)使用RedisTemplate

 1 package com.slp.redis;
 2 import com.google.gson.Gson;
 3 import com.google.gson.reflect.TypeToken;
 4 import com.slp.entity.User;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.data.redis.core.RedisTemplate;
 7 import org.springframework.stereotype.Repository;
 8 import org.springframework.util.StringUtils;
 9 
10 import java.util.List;
11 import java.util.concurrent.TimeUnit;
12 /**
13  * Created by sangliping on 2017/9/1.
14  */
15 @Repository
16 public class UserRedis {
17     @Autowired
18     private RedisTemplate<String, String> redisTemplate;
19 
20 
21     public void add(String key, Long time, User user) {
22         Gson gson = new Gson();
23         redisTemplate.opsForValue().set(key, gson.toJson(user), time, TimeUnit.MINUTES);
24     }
25 
26     public void add(String key, Long time, List<User> users) {
27         Gson gson = new Gson();
28         redisTemplate.opsForValue().set(key, gson.toJson(users), time, TimeUnit.MINUTES);
29     }
30 
31 
32     public User get(String key) {
33         Gson gson = new Gson();
34         User user = null;
35         String json = redisTemplate.opsForValue().get(key);
36         if(!StringUtils.isEmpty(json))
37             user = gson.fromJson(json, User.class);
38         return user;
39     }
40 
41     public List<User> getList(String key) {
42         Gson gson = new Gson();
43         List<User> ts = null;
44         String listJson = redisTemplate.opsForValue().get(key);
45         if(!StringUtils.isEmpty(listJson))
46             ts = gson.fromJson(listJson, new TypeToken<List<User>>(){}.getType());
47         return ts;
48     }
49 
50     public void delete(String key){
51         redisTemplate.opsForValue().getOperations().delete(key);
52     }
53 }

二、部署并访问应用

http://localhost/druid/index.html:访问Druid监控页面

posted @ 2017-09-01 15:50  霓裳梦竹  阅读(5042)  评论(4编辑  收藏  举报