coding之前还是简单介绍一下springboot和redis。
说springboot之前也介绍一些微服务的特点。
相对于单体式运用,微服务具有以下几个优点:
1.分解应用,解决复杂性问题
2.每个服务开发独立,可以使用各自适合的架构和语言
3.独立部署,不影响整个应用,而且可以快速部署,便于测试
4.每个服务独立扩展,可选择合适的硬件资源
但
微服务也有它的不足:
1.作为分布式服务,消息传递复杂,事务控制复杂
2.测试复杂
3.部署复杂
springboot是一种最简单的微服务框架,基于spring框架设计,除了spring所有优秀特性,还有以下特点:
1.为spring开发提供更简单的使用,快速开发
2.具有开箱即用的默认配置,根据依赖自动配置
3.不用配置各种xml,更加轻巧灵活
4.提供嵌入式、安全、性能指标、健康检查等服务体系
redis是一种高性能的缓存产品,它可以做数据库、缓存以及消息中间件,效率高、数据类型丰富、通用性好。这个教程里面有详细介绍它的安装配置以及特性:http://www.runoob.com/redis/redis-install.html,这里就不细说了。
____________________________________________________________________________________________________________________
长话短说,现在开始写demo了:
1.首先做一些准备工作,从http://start.spring.io/构建一个springboot的maven项目,再导入到eclipse,这时候基本的配置也有了,如果这里不熟悉的可以参考http://www.ityouknow.com/springboot/2016/01/06/springboot(%E4%B8%80)-%E5%85%A5%E9%97%A8%E7%AF%87.html,此时目录结构如下:
2.在本地mysql建数据库test,建表sys_user:
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` varchar(20) NOT NULL COMMENT '主键',
`name` varchar(20) DEFAULT NULL COMMENT '姓名',
`age` int(3) DEFAULT NULL COMMENT '年龄',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
3.添加依赖,主要添加这几个依赖就可以了:
<!-- springboot 核心启动器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- springboot web支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 提供默认值设置、自动重启等特性 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- mybatis支持 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!-- redis支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.3.8.RELEASE</version>
</dependency>
<!-- springboot 数据缓存支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
4.添加配置信息,主要对mybatis,mysql和redis做一些配置
#mybatis
mybatis.config-locations=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/*.xml
mybatis.type-aliases-package=com.yantu.sbmm
#mysql
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = root
#redis
# 连接设置
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
# 连接池设置
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=-1
spring.redis.pool.max-idle=8
spring.redis.pool.min-idle=0
spring.redis.timeout=0
5.编写实体,dao接口和mapper
User实体:
public class User implements Serializable{
private static final long serialVersionUID = -1115715873116050652L;
private String id;
private String name;
private int age;
//...(getter and setter)
}
dao接口:
@Repository
public interface UserDAO {
User findById(User user);
int updateUser(User user);
int insertUser(User user);
int deleteUserById(String id);
}
6.编写redis缓存配置类
SpringBoot提供了对Redis的自动配置功能,在RedisAutoConfiguration中默认为我们配置了JedisConnectionFactory(客户端连接)、RedisTemplate以及StringRedisTemplate(数据操作模板),其中StringRedisTemplate模板只针对键值对都是字符型的数据进行操作,本示例采用RedisTemplate作为数据操作模板
@Configuration//SpringBoot注解,启动时会注入
@EnableCaching //启用缓存
public class RedisCacheConfig extends CachingConfigurerSupport{
/**
* 缓存管理器
* @param redisTemplate
* @return
*/
@Bean
public CacheManager cacheManager(RedisTemplate<?,?> redisTemplate) {
RedisCacheManager rcm = new RedisCacheManager(redisTemplate);
return rcm;
}
/**
* redis模板操作类
* @param factory 由springboot注入
* @return
*/
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, String> redisTemplate = new RedisTemplate<String, String>();
redisTemplate.setConnectionFactory(factory);
//key序列化方式,在定义了key生成策略之后再加以下代码
// RedisSerializer<String> redisSerializer = new StringRedisSerializer();
// redisTemplate.setKeySerializer(redisSerializer);
// redisTemplate.setHashKeySerializer(redisSerializer);
return redisTemplate;
}
}
如果要定义缓存key的生成策略,还需要实现KeyGenerator缓存生成器,具体可参照源码。
7. 编写service和实现
userService:
public interface UserService {
User findById(String id);
boolean deleteFromCache(String id);
User updateUser(User user);
User addUser(User user);
}
UserServiceRedisImpl:
@Service("userRedisImpl")
public class UserServiceRedisImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Resource
private RedisTemplate<String, String> redisTemplate;
@Cacheable(value = "user", key = "#root.targetClass + #id", unless = "#result eq null")
@Override
public User findById(String id) {
System.out.println("=====================缓存中查找失败,从数据库中获取,id="+id);
User user = new User();
user.setId(id);
return userDAO.findById(user);
}
@CacheEvict(value="user1",key = "#root.targetClass + #user.id")
@Override
public User updateUser(User user) {
System.out.println("===================从数据库中更新,从缓存中删除,id="+user.getId());
if(userDAO.updateUser(user) > 0){
return user;
}
return null;
}
@CachePut(value="user1",key = "#root.targetClass + #user.id")
@Override
public User addUser(User user) {
System.out.println("===================新增用户到数据库,id="+user.getId());
User oldUser = userDAO.findById(user);
if(null != oldUser) return null;
if(userDAO.insertUser(user) > 0){
return user;
}
return null;
}
@CacheEvict(value="user1",key = "#root.targetClass + #id")
@Override
public boolean deleteFromCache(String id) {
System.out.println("===================从数据库中删除,从缓存中删除,id="+id);
return userDAO.deleteUserById(id)>0;
}
}
这里面缓存注解基于spring cache实现,其中每一个注解的作用和参数作以下简单说明:
@Cacheable:用于读取方法,如果读的是数据库,就把返回值放入缓存
value:缓存名
key:缓存key
condition:缓存条件,为true才执行缓存操作
@CachePut :用于新增/修改方法,效果同@Cacheable
参数同上
@CacheEvict:用于删除方法,删除对应数据同时,删除缓存
除以上参数外,还包括
allEntries:是否清空所有缓存
beforeInvocation:是否在方法执行前就清空
要注意,缓存的key值必须唯一且一致,不然不同的操作,想要操作同一个缓存的时候会报错。比如新增的缓存1,更新的时候却更新到了缓存2,那就没有让缓存发挥应有的作用。
8.编写Controller,提供Restful接口:
UserController:
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
@Qualifier("userRedisImpl")
private UserService userService;
@RequestMapping("/findUserById")
public User findUser(@RequestParam Map<String,String> json){
String id = StringUtils.isNullOrEmpty(json.get("id"))?null:json.get("id");
return userService.findById(id);
}
@RequestMapping(value="/deleteUserById",method=RequestMethod.POST)
public boolean delete(@RequestParam Map<String,String> json){
String id = StringUtils.isNullOrEmpty(json.get("id"))?null:json.get("id");
return userService.deleteFromCache(id);
}
@RequestMapping(value="/addUser",method=RequestMethod.POST)
public User addUser(User user,HttpServletRequest request){
return userService.addUser(user);
}
@RequestMapping(value="/updateUser",method=RequestMethod.POST)
public User updateUser(User user){
return userService.updateUser(user);
}
}
9.启动SpringBootApplication服务,通过Postman测试接口:
新增 [POST]:http://127.0.0.1:8080/user/addUser?id=1001&name=令狐冲&age=18
通过id查找[GET]:
http://127.0.0.1:8080/user/findUserById?id=1001
更新[POST]:http://127.0.0.1:8080/user/updateUser?id=1001&name=任我行&age=56
通过id删除[POST]:
http://127.0.0.1:8080/user/deleteUserById?id=1001
这里的参数仅供参考,大家随意,自己操作一下,就明白缓存的原理了,关于redis的使用,建议下一个Redis Desktop Manager来用,会方便得多。
源码见:https://github.com/yan-tu/springboot_mybatis_mysql
(终于写完了,催我改bug了...)