zoukankan      html  css  js  c++  java
  • 【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监控页面

  • 相关阅读:
    PAT2019顶级7-2:美丽的序列(线段树+DP)
    ZOJ2112 Dynamic Rank(可持久化线段树套树状数组)
    CF1353E K-periodic Garland(动态规划)
    CF1353D Constructing the array(优先队列)
    HDU2069 Coin Change(基础DP)
    surf(树状数组+DP)
    双倍快乐(回文树)
    ZOJ3591 Nim(博弈论)
    HDU6601 Keep On EveryThing But Triangle(可持久化线段树)
    HDU6599 I Love Palindrome String(回文树)
  • 原文地址:https://www.cnblogs.com/dream-to-pku/p/7463594.html
Copyright © 2011-2022 走看看