Spring4.X + Spring MVC + Mybatis3 零配置应用开发框架搭建详解(5) - Redis缓存配置

来源:互联网 发布:vs运行c语言 编辑:程序博客网 时间:2024/05/23 18:44

Spring4.X + Spring MVC + Mybatis3 零配置应用开发框架搭建详解(5) - Redis缓存配置

对于缓存管理,其实就是四个步骤

  • 第一,在【cache】组件中的pom.xml中加入redis的第三方java客户端jedis的jar包
  • 第二,通过编写一个缓存配置类,来管理连接池
  • 第三,编写缓存服务,提供缓存操作接口
  • 第四,在需要使用缓存服务的【back】服务中,加入项目依赖,其他任何服务需要使用缓存服务,都可以配置类似的依赖
  • 第五,在【back】服务启动配置中加入缓存配置类,以保障缓存服务能再服务启动的时候初始化
  • 第六,在需要使用缓存服务的模块中,编写业务代码,完成缓存操作。

1. 加入缓存jar包依赖配置

<?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">    <parent>        <artifactId>web</artifactId>        <groupId>com.aitongyi.web</groupId>        <version>1.0-SNAPSHOT</version>    </parent>    <modelVersion>4.0.0</modelVersion>    <artifactId>cache</artifactId>    <properties>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    </properties>    <dependencies>        <!-- CacheService缓存服务中需要用到的对象依赖    -->        <dependency>            <groupId>com.aitongyi.web</groupId>            <artifactId>bean</artifactId>            <version>${project.version}</version>        </dependency>        <!-- Redis依赖    -->        <dependency>            <groupId>redis.clients</groupId>            <artifactId>jedis</artifactId>            <version>2.7.2</version>        </dependency>    </dependencies></project>


2. 创建配置对象

  

import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableAspectJAutoProxy;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;@Configuration@EnableAspectJAutoProxy@ComponentScan(basePackages = {"com.aitongyi.web.cache"})public class CacheConfig {    /** redis缓存服务器地址    */    @Value("${redis.host}")    private String host;    /** redis缓存服务器端口    */    @Value("${redis.port}")    private Integer port;    /** redis缓存服务器连接超时时间    */    @Value("${redis.timeout}")    private Integer timeout;    @Bean(name = "jedisPool")    public JedisPool jedispool() {        JedisPoolConfig config = new JedisPoolConfig();        config.setMaxWaitMillis(30000); //  最大等待时间        config.setMaxTotal(32);         //  最大连接数        config.setMinIdle(6);           //  允许最小的空闲连接数        config.setTestOnBorrow(false);  //  申请到连接时是否效验连接是否有效,对性能有影响,建议关闭        config.setTestOnReturn(false);  //  使用完连接放回连接池时是否效验连接是否有效,对性能有影响,建议关闭        config.setTestWhileIdle(true);  //  申请到连接时,如果空闲时间大于TimeBetweenEvictionRunsMillis时间,效验连接是否有效,建议开启,对性能有效不大        config.setTimeBetweenEvictionRunsMillis(30000); //TestWhileIdle的判断依据        return new JedisPool(config, host, port, timeout);    }}


3. 创建缓存服务

/** * 缓存服务 * Created by admin on 16/8/18. */@Componentpublic class CacheService {    @Autowired    private JedisPool jedisPool;    /**     * 设置缓存对象     * @param key     * @param value     */    public void set(String key,String value){        Jedis jedis = null;        try{            jedis = jedisPool.getResource();            jedis.set(key, value);        }finally{            if(jedis != null){                jedis.close();            }        }    }    /**     * 获取缓存对象     * @param key     * @return     */    public String get(String key){        Jedis jedis = null;        try{            jedis = jedisPool.getResource();            return jedis.get(key);        }finally{            if(jedis != null){                jedis.close();            }        }    }    /**     * 删除缓存对象     * @param key     */    public void del(String key){        Jedis jedis = null;        try{            jedis = jedisPool.getResource();            jedis.del(key);        }finally{            if(jedis != null){                jedis.close();            }        }    }}

4. 对缓存服务的依赖管理

在【back】服务中的pom.xml中加入【cache】模块的依赖

<dependencies>        <dependency>            <groupId>com.aitongyi.web</groupId>            <artifactId>dao</artifactId>            <version>${project.version}</version>        </dependency>        <dependency>            <groupId>com.aitongyi.web</groupId>            <artifactId>bean</artifactId>            <version>${project.version}</version>        </dependency>        <dependency>            <groupId>com.aitongyi.web</groupId>            <artifactId>service</artifactId>            <version>${project.version}</version>        </dependency>        <dependency>            <groupId>com.aitongyi.web</groupId>            <artifactId>task</artifactId>            <version>${project.version}</version>        </dependency>        <!--  缓存模块  -->        <dependency>            <groupId>com.aitongyi.web</groupId>            <artifactId>cache</artifactId>            <version>${project.version}</version>        </dependency>

5. 缓存配置加入项目启动配置中

在【back】项目中的com.aitongyi.web.back.conf.WebApplicationInitializer类中加入缓存项目的配置类【CacheConfig.class】

import com.aitongyi.web.cache.conf.CacheConfig;import com.aitongyi.web.dao.conf.DatabaseConfig;import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;import javax.servlet.Filter;/** * 项目启动基类 * -- 整个项目的入口 */public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {/** * 获取配置信息 * @return */@Overrideprotected Class<?>[] getRootConfigClasses() {return new Class[] { BackConfig.class, DatabaseConfig.class, SecurityConfig.class, CacheConfig.class};}@Overrideprotected Class<?>[] getServletConfigClasses() {return new Class[] { MvcConfig.class };}@Overrideprotected String[] getServletMappings() {return new String[] { "/" };}@Overrideprotected Filter[] getServletFilters() {return null;}}


6. 缓存业务操作代码

在操作业务代码时,需要一些工具类,比如json操作的fastjson,需要在pom.xml中加入依赖,

        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>fastjson</artifactId>            <version>1.2.6</version>        </dependency>

然后在用户控制器中加入处理逻辑

import com.aitongyi.web.bean.User;import com.aitongyi.web.cache.CacheService;import com.aitongyi.web.service.UserService;import com.alibaba.fastjson.JSON;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.access.prepost.PreAuthorize;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;/** * 用户请求处理器 * Created by admin on 16/8/6. */@Controllerpublic class UserController {    private static final Logger logger = LoggerFactory.getLogger(UserController.class);    @Autowired    private UserService userService;    @Autowired    private CacheService cacheService;    @RequestMapping(value = "/home", method = RequestMethod.GET)    @PreAuthorize("isAuthenticated()")// isAuthenticated 如果用户不是匿名用户就返回true    public String showHomePage() {        try {                        User user = userService.loadUserByUsername("admin");//            测试缓存服务//            缓存用户对象到redis,以用户ID区分            cacheService.set("LOGIN_USER_" + user.getId(), JSON.toJSONString(user));//            从缓存中取出            String userStr = cacheService.get("LOGIN_USER_" + user.getId());//            进行反序列化            User u = JSON.parseObject(userStr, User.class);            if(u != null){                logger.info("user:{}", u);            }            logger.info("load user ");        }catch (Exception e){            logger.error(e.getLocalizedMessage(), e);        }        return "/index/index";    }}

当然,直接打印user会出现 @45sd3sdf这样的情况,需要重写User的toString方法

import java.util.Date;/** * Created by admin on 16/8/8. */public class User {    private Integer id;    private String username;    private String password;    private boolean enabled;    private Date createDate;    public Date getCreateDate() {        return createDate;    }    public void setCreateDate(Date createDate) {        this.createDate = createDate;    }    public boolean isEnabled() {        return enabled;    }    public void setEnabled(boolean enabled) {        this.enabled = enabled;    }    public Integer getId() {        return id;    }    public void setId(Integer id) {        this.id = id;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    @Override    public String toString() {        final StringBuffer sb = new StringBuffer("User{");        sb.append("id=").append(id);        sb.append(", username='").append(username).append('\'');        sb.append(", password='").append(password).append('\'');        sb.append(", enabled=").append(enabled);        sb.append(", createDate=").append(createDate);        sb.append('}');        return sb.toString();    }}

7. 加入数据库配置

在【back】项目的back.properties中,增加redis和mysql的连接配置

#redisredis.host = 127.0.0.1redis.port = 6380redis.timeout = 2000#========= Mysql ============jdbc.driver = com.mysql.jdbc.Driverdb.url = jdbc:mysql://127.0.0.1/web?useUnicode=true&characterEncoding=UTF-8db.username = webdb.password = 123456db.maxtotal = 150db.minidle = 40db.maxidle = 60
这两个配置意味着你需要在本机安装一个redis服务器(默认端口6379),端口是6380,本机安装一个mysql,并创建一个名称为web的库,使用utf-8这个字符集,并且创建一个web的用户,密码是123456,另外需要在数据库中创建两张表,一个是【users】表,用来存储用户信息,另外一个是【authorities】表,用来存储权限信息

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;/*!40101 SET NAMES utf8 */;/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;# Dump of table authorities# ------------------------------------------------------------DROP TABLE IF EXISTS `authorities`;CREATE TABLE `authorities` (  `username` varchar(50) NOT NULL,  `authority` varchar(50) NOT NULL,  UNIQUE KEY `ix_auth_username` (`username`,`authority`),  CONSTRAINT `fk_authorities_users` FOREIGN KEY (`username`) REFERENCES `users` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;LOCK TABLES `authorities` WRITE;/*!40000 ALTER TABLE `authorities` DISABLE KEYS */;INSERT INTO `authorities` (`username`, `authority`)VALUES('admin','ROLE_ADMIN');/*!40000 ALTER TABLE `authorities` ENABLE KEYS */;UNLOCK TABLES;# Dump of table users# ------------------------------------------------------------DROP TABLE IF EXISTS `users`;CREATE TABLE `users` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `username` varchar(50) NOT NULL,  `password` varchar(50) NOT NULL,  `enabled` tinyint(1) NOT NULL,  `create_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,  PRIMARY KEY (`id`),  UNIQUE KEY `ix_username` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;LOCK TABLES `users` WRITE;/*!40000 ALTER TABLE `users` DISABLE KEYS */;INSERT INTO `users` (`id`, `username`, `password`, `enabled`, `create_date`)VALUES(1,'admin','e10adc3949ba59abbe56e057f20f883e',1,'2016-08-18 14:51:06');/*!40000 ALTER TABLE `users` ENABLE KEYS */;UNLOCK TABLES;

表创建完成,数据写入完成,启动服务器,运行back这个web项目,就可以看到登录页面,输入用户名admin,密码123456,登录,完成我们的操作。

然后看看日志,就可以看到存储缓存和打印缓存数据的日志了。如果你有兴趣,还可以在代码上打上断点,用debug模式启动,然后一步步的看运行状态!



8. 缓存KEY管理最佳实践

到此,缓存就说完了,这里要提一下这个redis的key,很多时候我们开发,定义redis中的缓存key很随意,也不规范,结果导致最终key管理混乱,代码管理难度加大。通过我们的项目,可以看到,每个功能基本是分模块的,在缓存中,需要定义一个公共的KEY管理类,所有的key都通过这个公共类来声明,如果要看缓存中定义了那些Key,就可以从这个类中一目了然。

下面我们就用【UserController】中的一个缓存KEY来做例子说明一下:

原来的key是这样的:

//            缓存用户对象到redis,以用户ID区分            cacheService.set("LOGIN_USER_" + user.getId(), JSON.toJSONString(user));//            从缓存中取出            String userStr = cacheService.get("LOGIN_USER_" + user.getId());


通过统一管理,我们要再【cache】模块下创建一个CacheKey:

/** * 缓存Key统一管理类 * Created by admin on 16/8/18. */public class CacheKey {    /**     * <pre>     * 登录用户缓存Key     * 格式 :  str.login.user.{userId}     * </pre>     */    public static final String LOGIN_USER_KEY = "str.login.user.";}

然后将原来的代码改为:

//            缓存用户对象到redis,以用户ID区分            cacheService.set(CacheKey.LOGIN_USER_KEY + user.getId(), JSON.toJSONString(user));//            从缓存中取出            String userStr = cacheService.get(CacheKey.LOGIN_USER_KEY + user.getId());

通过这样的管理,所有用户都统一的缓存Key的使用,如果要查看redis中用了那些缓存key,缓存中的key代表什么意思,就一目了然了。


目录

        (一)基本介绍    
        (二)基础框架搭建
        (三)实现最基本的登录处理        
        (四)任务调度管理   
        (五)Redis缓存配置
        (六)安全框架集成

        (七) git版本源代码下载


0 0
原创粉丝点击