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