springboot篇】二十一. 基于springboot电商项目 七 Redis做为缓存服务的使用

中国加油,武汉加油!

篇幅较长,配合目录观看

案例准备

  1. 本案例基于springboot篇】二十一. 基于springboot电商项目 七 springboot整合Redis

1. 项目准备

1.1 shop-temp新建springboot-redis-user(module-maven)

  1. Spring Boot DevTools
  2. Lombok
  3. Spring Web
  4. Thymeleaf
  5. MyBatis Framework
  6. Spring Data Redis(Access+Driver)

1.2 导相关依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>2.3</version>
</dependency>
<dependency>
	<groupId>com.wpj</groupId>
	<artifactId>base</artifactId>
	<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.48</version>
</dependency>

1.3 编写User

package com.wpj.entity;

import com.baomidou.mybatisplus.annotations.TableId;
import com.baomidou.mybatisplus.annotations.TableName;
import com.baomidou.mybatisplus.enums.IdType;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("t_user")
public class User implements Serializable {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String username;
    private String password;
}

1.4 编写Mapper接口

package com.wpj.mapper;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.wpj.entity.User;

public interface IUserMapper extends BaseMapper<User> {
}

1.5 编写Service及其impl

package com.wpj.service;

import com.wpj.entity.User;

public interface IUserService extends IBaseService<User> {
}
package com.wpj.service.impl;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.wpj.entity.User;
import com.wpj.mapper.IUserMapper;
import com.wpj.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private IUserMapper userMapper;

    @Override
    public BaseMapper<User> getMapper() {
        return userMapper;
    }
}

1.6 编写Controller

package com.wpj.controller;

import com.wpj.entity.User;
import com.wpj.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
public class UserController {
    @Autowired
    private IUserService userService;

    @RequestMapping(value = "/getUserList")
    public String getUserList(ModelMap map){
        List<User> list = userService.getList();
        map.put("list", list);
        return "userList";
    }

    @RequestMapping(value = "/addUser")
    public String addUser(){
        User user = new User();
        user.setUsername("admin");
        user.setPassword("123");
        userService.insert(user);
        return "redirect:getUserList";
    }


    @RequestMapping(value = "/deleteUser/{id}")
    public String deleteUser(@PathVariable Integer id){
        userService.deleteById(id);
        return "redirect:../getUserList";
    }

    @RequestMapping(value = "/updateUser")
    public String updateUser(User user){
        userService.update(user);
        return "redirect:getUserList";
    }

    @RequestMapping(value = "/getUserById/{id}")
    public String getUserById(@PathVariable Integer id,ModelMap map){
        User user = userService.selectById(id);
        map.put("user",user);
        return "updateUser";
    }

}

1.7 编写程序入口

package com.wpj;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication(scanBasePackages = "com.wpj")
@MapperScan(basePackages = "com.wpj.mapper")
public class SpringbootRedisUserApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootRedisUserApplication.class, args);
    }
}

1.8 编写yml

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/nz1904-springboot-shop
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
mybatis-plus:
  type-aliases-package: com.wpj.entity

1.9 编写页面

1.10 启动程序入口

2. Redis做为缓存服务的使用

2.1 配置yml


spring:
  datasource:
    url: jdbc:mysql://localhost:3306/nz1904-springboot-shop
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  redis:
    host: 192.168.59.100
    password: admin

mybatis-plus:
  type-aliases-package: com.wpj.entity

2.2 Impl重写getList

@Autowired
private RedisTemplate redisTemplate;

@Override
public List<User> getList() {
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    System.out.println("UserServiceImpl.getList");
    // 准备一个集合
    List<User> userList = null;
    // 先去缓存中查询,如果有直接返回,没有再到数据库中查询
    userList = (List<User>) redisTemplate.opsForValue().get("userList");
    if (userList == null) {
        // 双重锁机制来解决重复查询的问题,在单体架构中有效
        synchronized (this){
            if (userList == null) {
                System.out.println("进入数据库中查询");
                // 缓存没有,到数据库中
                userList = userMapper.selectList(null);
                // 把结果放入缓存中
                redisTemplate.opsForValue().set("userList", userList, 30, TimeUnit.SECONDS);
            }
        }
    }
    return userList;
}
@Override
public int deleteById(Integer id) {
    int i = super.deleteById(id);
    redisTemplate.delete("userList");
    return i;
}

2.3 改进

@Override
public List<User> getList() {
    redisTemplate.setKeySerializer(new StringRedisSerializer());
    List<User> userList = null;
    userList = (List<User>) redisTemplate.opsForValue().get("userList");

    if(userList == null) {
        // 先获取锁
        try {
            boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", "true", 30,TimeUnit.SECONDS);
            if(lock) {
                // 获取了锁
                userList = userMapper.selectList(null);
                System.out.println("查询数据库。。");
                // 缓存的重建
                redisTemplate.opsForValue().set("userList", userList, 30, TimeUnit.SECONDS);
                // 释放锁
                redisTemplate.delete("lock");
            } else {
                // 休眠一会
                Thread.sleep(50);
                return getList();
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    return userList;
}

2.4 注解改进

2.4.1 导入相关依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-cache</artifactId>
   <version>2.1.5.RELEASE</version>
</dependency>

2.4.2 修改程序入口

package com.wpj;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication(scanBasePackages = "com.wpj")
@MapperScan(basePackages = "com.wpj.mapper")
@EnableCaching // 开启注解缓存
public class SpringbootRedisUserApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootRedisUserApplication.class, args);
    }
}

2.4.3 配置yml


spring:
  datasource:
    url: jdbc:mysql://localhost:3306/nz1904-springboot-shop
    username: root
    password: 123456
    driver-class-name: com.mysql.jdbc.Driver
  redis:
    host: 192.168.59.100
    password: admin
  cache:
    type: redis
mybatis-plus:
  type-aliases-package: com.wpj.entity

2.4.4 Impl

package com.wpj.service.impl;

import com.baomidou.mybatisplus.mapper.BaseMapper;
import com.wpj.entity.User;
import com.wpj.mapper.IUserMapper;
import com.wpj.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Primary
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private IUserMapper userMapper;

    @Override
    public BaseMapper<User> getMapper() {
        return userMapper;
    }

    @Override
    // value: key名称的前缀
    // key: key名称的后缀(单引号引起)
    // user::list
    @Cacheable(value = "user", key = "'list'") // 先去缓存中查询,如果没有就调用方法查询,把返回值放到缓存
    public List<User> getList() {
        System.out.println("UserServiceImpl.getList");
        return userMapper.selectList(null);
    }

    @Override
    @Cacheable(value = "user", key = "'id_'+#id")
    public User selectById(Integer id) {
        return super.selectById(id);
    }

    @Override
    @CacheEvict(value = "user", key = "'list'")
    public int deleteById(Integer id) {
        return super.deleteById(id);
    }

    @Override
    public int insert(User user) {
        return super.insert(user);
    }

    @Override
    @Caching(evict = {
        @CacheEvict(value = "user", key = "'list'"),
        @CacheEvict(value = "user", key = "'id_'+#user.id")
    })
    public int update(User user) {
        return super.update(user);
    }

    @CachePut(value = "user", key = "'id_'+#result.id") // 把方法的返回值添加到注解中
    @CacheEvict(value = "user", key = "'list'")
    @Override
    public User addUser(User user) {
        return userMapper.addUser(user);
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章