SSM(springmvc+spring+mybatis)+Redis实例


最近打算研究一下Redis缓存,于是在本地手动搭建了一个SSM+redis的demo实例,该实例采用的是spring AOP管理日志以及@Transactional注解的方式管理Spring事务和Redis事务

开发环境及工具:jdk1.8,Eclipse,Maven,Tomcat7

spring整合redis需要引入相关jar包,版本需要注意一下,不然会报错:

jedis-2.9.0.jar

spring-data-redis-1.8.4.RELEASE.jar

spring-data-commons-1.8.4.RELEASE.jar

commons-pool2-2.5.0.jar

 

项目结构如下,标红部分分别是Redis工具类和Redis的配置文件:

 

 

Maven依赖文件如下:

pom.xml

<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/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.java</groupId>
  <artifactId>ssm</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>ssm Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <properties>
  
  <spring.version>4.3.3.RELEASE</spring.version>
  <mybatis.version>3.4.5</mybatis.version>
  <mybatis-spring.version>1.3.1</mybatis-spring.version>
  <log4j.version>1.2.17</log4j.version>
  <redis.version>2.9.0</redis.version>
  <spring.data.redis.version>1.8.4.RELEASE</spring.data.redis.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>       
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>${spring.version}</version>     
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-oxm</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>       
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>${mybatis-spring.version}</version>
    </dependency>
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.13</version>
    </dependency>
    <!-- <dependency>
        <groupId>cglib</groupId>
        <artifactId>cglib</artifactId>
        <version>3.2.2</version>
    </dependency> -->
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.21</version>
    </dependency>
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc7</artifactId>
        <version>12.1.0.2</version>
    </dependency>
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-pool2</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.3</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-logging</artifactId>
        <version>1.2</version>
        <type>pom.lastUpdated</type>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.8.10</version>       
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.8.10</version>      
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>${redis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>${spring.data.redis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-commons</artifactId>
        <version>1.8.4.RELEASE</version>
    </dependency>
    <!-- <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-keyvalue</artifactId>
        <version>2.0.0.RELEASE</version>
        <scope>test</scope>
    </dependency> -->
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>5.1.2</version>
    </dependency>
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-email</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>javax</groupId>
        <artifactId>javaee-api</artifactId>
        <version>7.0</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.0-b07</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>ssm</finalName>
  </build>
</project>

 

 

Spring的配置文件,主要配置数据库连接池,Spring事务管理,Mybatis的SqlSession工厂,Spring AOP切面声明,以及Redis的集成。

由于AOP管理Redis的事务无效,所以改用注解的方式实现事务管理, <tx:annotation-driven transaction-manager="txManager"/>

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
    <!-- 扫描包 -->    
    <context:component-scan base-package="com.ssm.service"/>
    <context:component-scan base-package="com.ssm.dao"/>
    <context:component-scan base-package="com.ssm.redis"/>
    <!-- 数据库配置文件 -->
    <context:property-placeholder location="classpath:*.properties"/>
    <!-- 配置数据库连接池 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
      <property name="driverClassName" value="${dbcp.driverClassName}"/>
      <property name="url" value="${dbcp.url}"/>
      <property name="username" value="${dbcp.username}"/>
      <property name="password" value="${dbcp.password}"/>
      <property name="maxActive" value="${dbcp.maxActive}"/>
      <property name="maxIdle" value="${dbcp.maxIdle}"/> 
      <property name="minIdle" value="${dbcp.minIdle}"/> 
      <property name="initialSize" value="${dbcp.initialSize}"/> 
    </bean>    
    
    <!-- sqlsessionFactory配置 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
      <property name="dataSource" ref="dataSource"/>
      <property name="configLocation" value="classpath:mybatis-config.xml"/>
      <property name="mapperLocations" value="classpath:com/ssm/mapper/*.xml"/>
    </bean>    
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
      <property name="basePackage" value="com.ssm.dao"/>
      <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>
    
    <!-- 事务管理 -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
       <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- 事务通知 -->
    <!-- <tx:advice id="txAdvice" transaction-manager="txManager">
       <tx:attributes>
          <tx:method name="insert*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
          <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
          <tx:method name="delete*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
          <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
          <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
          <tx:method name="remove*" propagation="REQUIRED"/>
          <tx:method name="get*" propagation="REQUIRED"/>
          <tx:method name="find*" propagation="REQUIRED"/>
       </tx:attributes>           
    </tx:advice> -->
    
    <!-- AOP事务管理 -->
    <!-- <aop:config>
       <aop:pointcut expression="execution(* com.ssm.service.*.*(..))" id="pointCut"/>
       <aop:advisor advice-ref="txAdvice" pointcut-ref="pointCut"/>   
    </aop:config> -->
    
    <!-- 注解的事务管理  -->
    <tx:annotation-driven transaction-manager="txManager"/>
    
    <!-- 注解的AOP管理 -->
    <aop:aspectj-autoproxy proxy-target-class="true"/>
    <!-- AOP切面 -->
    <bean id="LogAspect" class="com.ssm.aspect.LogAspect"/>
    
    <!-- Jedis连接池配置参数 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
      <property name="maxIdle" value="${redis.maxIdle}"></property>
      <property name="maxTotal" value="${redis.maxTotal}"></property>
      <property name="maxWaitMillis" value="${redis.maxWaitMillis}"></property>
      <property name="testOnBorrow" value="${redis.testOnBorrow}"></property>  
    </bean>
    
    <!--redis连接工厂  -->
    <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
      <property name="hostName" value="${redis.hostName}"></property>
      <property name="port" value="${redis.port}"></property>
      <property name="timeout" value="${redis.timeout}"></property>
      <property name="poolConfig" ref="jedisPoolConfig"></property> 
    </bean>
    
    <!--redis操作模版,使用该对象可以操作redis  -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
      <property name="connectionFactory" ref="jedisConnectionFactory"></property>
      <property name="keySerializer" >
           <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
      </property>
      <property name="hashKeySerializer" >
           <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
      </property>
      <property name="valueSerializer" >
           <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
      </property>
      <property name="hashValueSerializer" >
           <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
      </property> 
      <!--开启事务  -->  
      <property name="enableTransactionSupport" value="true"></property>   
    </bean>
        
</beans>

 

Mybatis配置文件很简单,只需要将实体类声明一个别名就可以了,工厂以及mapper文件扫描都交给spring管理。

mybatis-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration   
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <typeAliases>
      <package name="com.ssm.entity"/>
  </typeAliases>
</configuration>

 

 

接下来是springmvc的配置,主要包括controller层的扫描,视图解析器前后缀,基于注解的处理器映射器和适配器<mvc:annotation-driven/>,拦截器Interceptor,以及自定义全局异常处理器ExceptionResolver

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
        
   <context:component-scan base-package="com.ssm.controller"/>
   
   <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix" value="/WEB-INF/jsp/"></property>
      <property name="suffix" value=".jsp"></property>
   </bean>
   
   <mvc:annotation-driven/>
   
   <mvc:interceptors>
      <mvc:interceptor>
         <mvc:mapping path="/**"/>
         <bean class="com.ssm.interceptor.LoginInterceptor"></bean>
      </mvc:interceptor>
   </mvc:interceptors>
   
   <bean class="com.ssm.exception.ExceptionResolver"/>
</beans>

 

 

 

db.properties,数据库配置可根据自己本机的环境添加

dbcp.driverClassName = 
dbcp.url = 
dbcp.username = 
dbcp.password = 
dbcp.maxActive = 20
dbcp.maxIdle = 20
dbcp.minIdle = 20
dbcp.initialSize = 0

 

redis.properties

 

redis.hostName = 127.0.0.1
redis.port = 6379
redis.timeout = 10000 
redis.maxIdle = 400
redis.maxTotal = 400
redis.maxWaitMillis = 1000
redis.testOnBorrow = true

 

 

 

 

到这里,框架的搭建以及XML文件的配置基本已经完成,下一步开始实现业务代码

该业务主要实现用户的登录以及新增用户的功能,接下来看下是如何与Redis交互的。

 

UserLoginController.java

package com.ssm.controller;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.ssm.entity.Users;
import com.ssm.service.UserLoginService;

@Controller
public class UserLoginController {

    @Autowired
    private UserLoginService userLoginService;

    @RequestMapping("tologin")
    public String toLoginPage() {
        return "login/login";
    }

    @RequestMapping("login")
    public String userLogin(Model model, Users user, HttpServletRequest req) {
        boolean bool = userLoginService.checkUser(user);
        if (bool == true) {        
            req.getSession().setAttribute("user", user);
            return "login/loginSuccess";
        } else {
            model.addAttribute("error", "用户名或密码错误!");
            return "login/login";
        }
    }
    
    @RequestMapping("addUser")
    public String addUser(Model model,Users user) throws Exception{
        userLoginService.addUser(user);
        model.addAttribute("success", "添加成功");
        return "login/loginSuccess";
    }
}

 

 

与redis交互,我们写在Service层,登录时,先去缓存中查找是否有数据,如果有就直接返回,没有再去数据库查找,如果数据库存在该用户,则将数据添加到缓存中,代码如下:

UserLoginServiceImpl.java

package com.ssm.service.impl;



import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ssm.dao.UserLoginDao;
import com.ssm.entity.Users;
import com.ssm.exception.UserException;
import com.ssm.redis.RedisCacheUtil;
import com.ssm.service.UserLoginService;

@Service
public class UserLoginServiceImpl implements UserLoginService{
    
    @Autowired
    private UserLoginDao userLoginDao;
    @Autowired
    private RedisCacheUtil redisCacheUtil;

    public boolean checkUser(Users user) {
        //先去缓存中查找是否存在,没有再去数据库中查找        
        Users userRedis = (Users)redisCacheUtil.get(user.getUsername());
        if(userRedis!=null) {
           if(userRedis.getPassword().equals(user.getPassword())) {
               System.out.println("用户名:"+userRedis.getUsername()+" 密码:"+userRedis.getPassword());
               return true;
           }            
        }
        int i = userLoginDao.checkUserDao(user);
        if(i>0) {
            //将数据放入缓存并设置过期时间600秒
            boolean bool = redisCacheUtil.set(user.getUsername(), user,600);
            System.out.println(bool==false?"添加缓存失败":"添加缓存成功!");
            return true;
        }
        return false;
    }

    
    /**
     * 用@Transactional实现spring事务管理和redis事务管理,为了验证事务的回滚,定义添加超过两笔记录即抛出自定义异常
     * @param user    
     */
    @Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
    public void addUser(Users user) throws Exception{    
        for(int i=0;i<5;i++) {
            userLoginDao.addUser(user);    
            redisCacheUtil.set(user.getUsername(), user);
            user.setUsername(user.getUsername()+i);            
            if(i>=2) {
                //throw new RuntimeException("最多只能插入两笔记录");
                throw new UserException("最多只能插入两笔记录");
                            
            }
        }        
    } 

}

 

 

Redis工具类采用的是spring集成的redisTemplate操作缓存

RedisCacheUtil.java

package com.ssm.redis;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

@Component
public class RedisCacheUtil {

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;
        
    
    /**指定缓存失效时间
     * @param key
     * @param time
     * @return
     */
    public boolean expire(String key,long time) {    
        try {
            if (time > 0) {
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }    
    }
    
    /**根据key获取过期时间
     * @param key
     * @return
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }
        
    /**判断key是否存在
     * @param key
     * @return
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {            
            e.printStackTrace();
            return false;
        }
    }
        
    /**删除缓存
     * @param key 可以传一个值或多个
     */
    public void del(String ... key) {
        if(key!=null&&key.length>0) {
            if(key.length==1) {
                redisTemplate.delete(key[0]);
            }else {
                redisTemplate.delete(Arrays.asList(key));
            }
        }
    }

//  ==========================String============================    
    /**普通缓存获取
     * @param key
     * @return
     */
    public Object get(String key) {
        try {
            Object object = redisTemplate.opsForValue().get(key);        
            return object;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }        
    }
        
    /**普通缓存放入
     * @param key
     * @param value
     * @return
     */
    public boolean set(String key,Object value) {
        try {
            redisTemplate.opsForValue().set(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
        
    /**普通缓存放入并设置时间
     * @param key
     * @param value
     * @param time time如果小于等于0,将设置无限期
     * @return
     */
    public boolean set(String key,Object value,long time) {
        try {
            if(time>0) {
                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
            }else {
                set(key,value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
        
    /**递增或递减
     * @param key
     * @param delta
     * @return
     */
    public long incre(String key,long delta) {        
        return redisTemplate.opsForValue().increment(key, delta);
    }
    
 //==============================Map==================================
    /**HashMap或HashSet缓存获取具体的value
     * @param key
     * @param item
     * @return
     */
    public Object hget(String key,String item) {
        return redisTemplate.opsForHash().get(key, item);
    }
    
    /**获取所有键值对
     * @param key
     * @return
     */
    public Map<Object,Object> hmget(String key) {
        return redisTemplate.opsForHash().entries(key);
    }
    
    /**hashmap放入缓存
     * @param key
     * @param map
     * @return
     */
    public boolean hmset(String key,Map<Object,Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**hashmap放入缓存并设置时间
     * @param key
     * @param map
     * @param time
     * @return
     */
    public boolean hmset(String key,Map<Object,Object> map,long time) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            if(time>0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**向一张hash表中放入数据,如果不存在则创建
     * @param key
     * @param item
     * @param value
     * @return
     */
    public boolean hset(String key,String item,Object value) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    /**向一张hash表中放入数据并设置时间,如果不存在则创建
     * @param key
     * @param item
     * @param value
     * @param time
     * @return
     */
    public boolean hset(String key,String item,Object value,long time) {
        try {
            redisTemplate.opsForHash().put(key, item, value);
            if(time>0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    
    
    /**删除hash表中的值
     * @param key
     * @param item
     */
    public void hdel(String key,Object...item ) {
        redisTemplate.opsForHash().delete(key, item);
    }
    
    /**判断hash表中是否有该项的值
     * @param key
     * @param item
     * @return
     */
    public boolean hHasKey(String key,String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }
    
//==========================List=================================
    /**
     * 获取list缓存的内容
     * @param key 键
     * @param start 开始
     * @param end 结束  0 到 -1代表所有值
     * @return
     */
    public List<Object> lGet(String key,long start, long end){
        try {
            return redisTemplate.opsForList().range(key, start, end);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
     
    /**
     * 获取list缓存的长度
     * @param key 键
     * @return
     */
    public long lGetListSize(String key){
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
     
    /**
     * 通过索引 获取list中的值
     * @param key 键
     * @param index 索引  index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
     * @return
     */
    public Object lGetIndex(String key,long index){
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
     
    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
     
    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
     
    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
     
    /**
     * 将list放入缓存
     * @param key 键
     * @param value 值
     * @param time 时间(秒)
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) expire(key, time);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
     
    /**
     * 根据索引修改list中的某条数据
     * @param key 键
     * @param index 索引
     * @param value 值
     * @return
     */
    public boolean lUpdateIndex(String key, long index,Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
     
    /**
     * 移除N个值为value
     * @param key 键
     * @param count 移除多少个
     * @param value 值
     * @return 移除的个数
     */
    public long lRemove(String key,long count,Object value) {
        try {
            Long remove = redisTemplate.opsForList().remove(key, count, value);
            return remove;
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }
    
}

 

 

dao接口,没有实现类,dao层动态代理,注意接口方法要和mapper文件id名称一致:

UserLoginDao.java

package com.ssm.dao;

import com.ssm.entity.Users;

public interface UserLoginDao {
    
    public int checkUserDao(Users user);
    
    public void addUser(Users user);

}

 

 

mapper文件:

UserLoginMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper  
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssm.dao.UserLoginDao">
 <select id="checkUserDao" parameterType="Users" resultType="int">
       select count(*) from tblogin  where loginname = #{username} and loginpassword= #{password}
 </select>
 
 <insert id="addUser" parameterType="Users">
      insert into tblogin(loginid,loginname,loginpassword) values(seq_tbu_userrole.nextval,#{username},#{password})
 </insert>
</mapper>

 

到这一步,业务类已经基本编写完成,下一步到页面上测试:

这个时候缓存中是没有的,会去数据库查询,数据库如果存在该用户,会添加到缓存中,我们看到已经添加到缓存中了。

 

 

 

 我们再登录一次,会发现,没有去数据库查询,通过AOP管理日志打印可看到执行效率提升很多

Opening RedisConnection
用户名:CarryStone 密码:123456
[INFO ] 2018-12-28 15:23:44,807 method:com.ssm.aspect.LogAspect.around(LogAspect.java:40)
Around:execution(boolean com.ssm.service.impl.UserLoginServiceImpl.checkUser(Users))耗时:1ms
[INFO ] 2018-12-28 15:23:44,807 method:com.ssm.aspect.LogAspect.around(LogAspect.java:41)

 

 

接下来看一下spring事务管理和redis事务管理,我们采用注解的方式

 

提交后发现数据库和redis都没有新增,提交的数据都已经回滚了。

 

 

 

控制台信息如下,抛出了异常信息并且事务已经回滚,说明事务已经生效:

 

 

 

如果不想回滚,可将@Transactional注解注释掉,再看下是否起作用,要注意的是抛出一般的异常spring不会回滚该事务,只有抛出Error及RuntimeException及其子类才会捕捉并回滚

可在注解中添加自定义的异常即可

@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM