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);
    }

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