发表于: 2017-09-05 16:00:57

3 1004


今天做的事:

今天改别人的项目。。。

很绝望,每次从网上copy例子的时候,想让它跑起来就得不停debug,感觉有这时间差不多能自己写出来一个了,不过也算是锻炼了接手别人项目的能力,锤炼一下我的耐性,省的以后要杀人。


反正都是老生常谈,把配置文件改了,然后就开始跑项目,跑不起来,就按照错误排除,修复bug,最后感觉配置文件不能再有问题了,就需要考虑是否是pom文件的问题了


今天就是,把配置文件改来改去改的差不多了,发现项目跑起来不会进入index.jsp页面,然后就找啊,改啊的,把这个copy下来的项目改了个遍,最后感觉应该是依赖有问题,绝对少jar包,果然加了几个Spring的jar包就没问题了,跑的很是开心。所以,以后应该记得,先从pom文件改起,之后在处理配置文件的问题。这样会降低出现莫名其妙的问题的几率。


还有一点,就是大家都不喜欢自己的代码被人copy跑完就算了,这样感觉自己不受尊重,所以为了防止有人纯粹的copy跑项目,就会在自己的代码里设陷阱,唉~

还是自己太懒,所以被阴了一手,copy的代码被人下绊子,排查错误找了好半天,我把dao层及以下的代码什么的全重写了一遍,结果发现这小的在Service层插入了个空对象,关键还标出来这是个错误了,好气啊~以后还是得尊重别人,认真看吧,不然排bug的时间只多不少。


吐槽结束,既然已经实现@Cache**的注解实现缓存,那么就剖析一下吧。


首先我们使用了springMVC的事务管理注解

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

先看一下事务

spring支持编程式事务管理和声明式事务管理两种方式。声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明(或通过基于@Transactional注解的方式),便可以将事务规则应用到业务逻辑中。

这正是spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不受污染,一个普通的POJO对象,只要加上注解就可以获得完全的事务支持。

我们使用的就是声明式,即注解


接下来看这两个参数:

1.TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。

2.rollbackFor = Exception.class,当你的方法中抛出异常时,它会将事务回滚,数据库中的数据将不会改变,也就是回到进入此方法前的状态。


使用事务记得要在配置文件中进行相关配置

<!-- transaction config related... start -->
<tx:annotation-driven transaction-manager="transactionManager" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <property name="dataSource" ref="dataSource" />
</bean>
<!-- transaction config related... end -->

只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源与DataSourceTransactionManager引用的数据源一致即可,否则事务管理会不起作用。



我们把重头戏放到Redis的工具类和使用@Cache**注解中

package com.redis.cache;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

/**
* Created by yubotao on 2017/09/04.
*/

@Configuration
@EnableCaching
public class RedisCacheConfig extends CachingConfigurerSupport {

@Bean
   public JedisConnectionFactory redisConnectionFactory(){
JedisConnectionFactory redisConnectionFactory = new JedisConnectionFactory();
       
       //Defaults
       redisConnectionFactory.setHostName("127.0.0.1");
       redisConnectionFactory.setPort(6379);
       return redisConnectionFactory;
   }

@Bean
   public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
       redisTemplate.setConnectionFactory(cf);
       return redisTemplate;
   }

@Bean
   public CacheManager cacheManager(RedisTemplate redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
       
       // Number of seconds before expiration. Defaults to unlimited (0)
       cacheManager.setDefaultExpiration(3000); // Sets the default expire time (in seconds)
       return cacheManager;
   }

}

先逐一分析这个工具类,其实这个工具类的实现非常简单,一一剖析

1.用@Configuration注解该类,等价 与XML中配置beans;用@Bean标注方法等价于XML中配置bean。

2.EnableCaching,开启spring注解驱动的cache管理能力,类似于spring xml命名空间<cache:*>的支持。将会和org.springframework.context.annotation.Configuration一起使用

如下

  1. @Configuration

  2. @EnableCaching

  3.   public class AppConfig {

  4.     @Bean

  5.       public MyService myService() {

  6.           // configure and return a class having @Cacheable methods

  7.           return new MyService();

  8.       }

  9.  

  10.       @Bean

  11.       public CacheManager cacheManager() {

  12.           // configure and return an implementation of Spring's CacheManager SPI

  13.           SimpleCacheManager cacheManager = new SimpleCacheManager();

  14.           cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("default")));

  15.           return cacheManager;

  16.       }

  17.   }

对应的是xml配置

<beans>

      <cache:annotation-driven/>

      <bean id="myService" class="com.foo.MyService"/>


      <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">

         

          <property name="caches">

             <set>

                  <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">

                      <property name="name" value="default"/>

                  </bean>

              </set>

          </property>


      </bean>


  </beans>


3.剩下的那些个类,集中起来讲:

RedisCacheConfig
CachingConfigurerSupport

由于没有相关讲解,我就不看官方文档,从字面理解了,就是Redis缓存的配置(-_-||)

JedisConnectionFactory

和Redis建立连接的工厂类

RedisTemplate

我们昨天介绍过了,一个帮助类

RedisCacheManager

Redis缓存管理器。


这几个就是Redis的相关配置


接下来看Service层使用的Cache注解

@CacheEvict(value = {"selectByPrimaryKey"},allEntries = true)
public void insertCity() {
City city = new City();
       city.setCityCode("1100");
       city.setCityJb("1");
       city.setProvinceCode("1100");
       city.setCityName("天津市");
       city.setCity("天津市");
       city.setProvince("天津市");
       logger.debug("before insert the first city");
//        System.out.println(city);
       cityMapper.insert(city);
       logger.debug("after insert the first city, and before insert the second city");
//        cityMapper.insert(new City()); // this will throw an exception
       logger.debug("after insert the second city");
   }

@Cacheable("selectByPrimaryKey")
public City selectByPrimaryKey(Long id){
logger.debug("ID" + id);
       return this.cityMapper.selectByPrimaryKey(id);
   }


先看现象,再写分析

@RequestMapping("/create")
@ResponseBody
public Integer create() {
try {
this.cityService.insertCity();
       return 1;
   } catch (Exception e) {
logger.error(e);
   }
return 0;
   
}


@RequestMapping("/selCity")
@ResponseBody
public Integer select() {
try {
this.cityService.selectByPrimaryKey(8L);
       return 1;
   } catch (Exception e) {
logger.error(e);
   }
return 0;
   
}


然后我们看看什么现象

使用RDM看看本地Redis的变化

没变化,好

我们再看


而再次运行


不见了


所以我们看一下到底是什么起的作用


@CacheEvict(value = {"selectByPrimaryKey"},allEntries = true)
@Cacheable("selectByPrimaryKey")

这两个注解起了作用,而它们的作用是什么,接下来分析

@Cacheable 主要针对方法配置,能够根据方法的请求参数对其结果进行缓存

@CachEvict 主要针对方法配置,能够根据一定的条件对缓存进行清空

这里专门讲解这个Redis注解的:http://www.cnblogs.com/davidwang456/p/5703037.html

大概了解了一下。

通过上面的解释可以和我们看到的现象吻合了。


不过这里有个问题,就是我们存到Redis里了,但是存的值是否使我们想要的



显然存入的并不是我们想要的值,因为存入的都是hash值,所以,明天需要花点时间,探索如何存取正确的值。


明天计划:整合Redis到任务代码,压测,提交任务6,开始任务7.


问题:暂无,只不过很多地方源码什么的读不懂,选择性跳过


收获:Redis和Spring整合的注解形式。




返回列表 返回列表
评论

    分享到