发表于: 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一起使用
如下
@Configuration
@EnableCaching
public class AppConfig {
@Bean
public MyService myService() {
// configure and return a class having @Cacheable methods
return new MyService();
}
@Bean
public CacheManager cacheManager() {
// configure and return an implementation of Spring's CacheManager SPI
SimpleCacheManager cacheManager = new SimpleCacheManager();
cacheManager.addCaches(Arrays.asList(new ConcurrentMapCache("default")));
return cacheManager;
}
}
对应的是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整合的注解形式。
-
评论