外卖小程序06

目录

  • 使用Redis缓存数据
    • 需求
    • 代码开发
      • 用户Controller层
      • 服务端Controller层
  • SpringCache框架
    • 介绍
    • 起步依赖
    • 常用注解
    • 案例
      • 准备工作
        • springCacheDemo.sql
        • pom.xml
        • application.yml
        • 启动类CacheDemoApplication
        • Controller层
        • 实体类User
        • Mapper层

使用Redis缓存数据

需求

使用Redis缓存功能解决用户量很大时,大量请求导致的数据库访问压力过大,性能低下问题

场景:使用Redis缓存菜品数据

代码开发

用户Controller层

@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {
    @Autowired
    private DishService dishService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据分类id查询菜品
     *
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    public Result<List<DishVO>> list(Long categoryId) {
        //查询redis中是否存在菜品数据
        String key = "dish_" + categoryId;//key的形式:dish_13
        List<DishVO> list = (List<DishVO>) redisTemplate.opsForValue().get(key);
        //若存在,无需查询数据库,直接返回
        if (list != null && list.size() > 0) {
            return Result.success(list);
        }
        //若不存在,查询数据库,并将数据存入redis
        Dish dish = new Dish();
        dish.setCategoryId(categoryId);
        dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品

        list = dishService.listWithFlavor(dish);
        redisTemplate.opsForValue().set(key, list);

        return Result.success(list);
    }
}

为保证数据库中的数据与Redis缓存数据保持一致,服务端操作菜品数据后需要清理被影响的缓存数据

服务端Controller层

@Slf4j
@RestController
@Api(tags = "菜品相关接口")
@RequestMapping("admin/dish")
public class DishController {
    @Autowired
    private DishService dishService;
    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping
    @ApiOperation("新增菜品")
    public Result save(@RequestBody DishDTO dishDTO) {
        log.info("新增菜品");
        dishService.saveWithFlavor(dishDTO);

        //清理被影响数据的缓存
        cleanCache("dish_" + dishDTO.getCategoryId());

        return Result.success();
    }

    @ApiOperation("分页查询菜品")
    @GetMapping("page")
    public Result<PageResult> page(DishPageQueryDTO dishPageQueryDTO) {
        log.info("菜品分页查询:{}", dishPageQueryDTO);
        PageResult pageResult = dishService.pageQuery(dishPageQueryDTO);

        return Result.success(pageResult);
    }

    @ApiOperation("根据id查询菜品")
    @GetMapping("{id}")
    public Result<DishVO> selectById(@PathVariable Long id) {
        log.info("根据id查询菜品:{}", id);
        DishVO dishVO = dishService.selectById(id);
        return Result.success(dishVO);
    }

    @PutMapping
    @ApiOperation("更新菜品")
    public Result update(@RequestBody DishDTO dishDTO) {
        log.info("更新菜品:{}", dishDTO);
        dishService.update(dishDTO);

        //清理所有数据的缓存
        cleanCache("dish_*");

        return Result.success();
    }

    @DeleteMapping
    @ApiOperation("批量删除菜品")
    public Result deleteByIds(@RequestParam List<Long> ids) {
        log.info("批量删除菜品:{}", ids);
        dishService.deleteByIds(ids);

        //清理所有数据的缓存
        cleanCache("dish_*");

        return Result.success();
    }

    @PostMapping("status/{status}")
    @ApiOperation("启售停售菜品")
    public Result startOrStop(@PathVariable Integer status, Long id) {
        log.info("启售停售菜品:{}", status, id);
        dishService.startOrStop(status, id);

        //清理所有数据的缓存
        cleanCache("dish_*");

        return Result.success();
    }

    @GetMapping("list")
    @ApiOperation("动态条件名查询菜品")
    public Result<List<Dish>> list(Dish dish) {
        log.info("动态条件名查询菜品:{}", dish);
        dish.setStatus(StatusConstant.ENABLE);
        List<Dish> dishList = dishService.list(dish);
        return Result.success(dishList);
    }

    /**
     * 清理缓存数据
     *
     * @param pattern
     */
    private void cleanCache(String pattern) {
        Set keys = redisTemplate.keys(pattern);
        redisTemplate.delete(keys);
    }
}

SpringCache框架

介绍

SpringCache框架实现了基于注解的缓存功能

其底层提供了一层抽象,可以切换不同的缓存实现,eg:EHCache,Caffeine,Redis等

起步依赖

<dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-cacheartifactId>  		            		       	 <version>2.7.3version> 
dependency>

常用注解

@EnableCaching 开启缓存注解功能,常用于启动类上

@Cacheable 执行方法前先查询缓存中是否有需要的数据,若则直接返回缓存中的数据,若没有则查询数据库,并将返回值加入缓存中

@Cacheput 将方法的返回值放入缓存中

@CacheEvict 将一条或多条数据从缓存中删除

案例

准备工作

  • 创建数据库spring_cache_demo,并执行sql脚本生成表

springCacheDemo.sql

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(45) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
);
  • 引入redis依赖,springCache依赖,配置相关信息

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.7.3version>
        <relativePath/>
    parent>
    <groupId>com.sihfangroupId>
    <artifactId>springcache-demoartifactId>
    <version>1.0-SNAPSHOTversion>

    <properties>
        <maven.compiler.source>11maven.compiler.source>
        <maven.compiler.target>11maven.compiler.target>
    properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
            <scope>compilescope>
        dependency>
        <dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.20version>
        dependency>

        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>fastjsonartifactId>
            <version>1.2.76version>
        dependency>

        <dependency>
            <groupId>commons-langgroupId>
            <artifactId>commons-langartifactId>
            <version>2.6version>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-cacheartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>

        <dependency>
            <groupId>mysqlgroupId>
            <artifactId>mysql-connector-javaartifactId>
            <scope>runtimescope>
        dependency>

        <dependency>
            <groupId>org.mybatis.spring.bootgroupId>
            <artifactId>mybatis-spring-boot-starterartifactId>
            <version>2.2.0version>
        dependency>

        <dependency>
            <groupId>com.alibabagroupId>
            <artifactId>druid-spring-boot-starterartifactId>
            <version>1.2.1version>
        dependency>

        <dependency>
            <groupId>com.github.xiaoymingroupId>
            <artifactId>knife4j-spring-boot-starterartifactId>
            <version>3.0.2version>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
        dependency>
    dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
                <version>2.7.3version>
            plugin>
        plugins>
    build>
project>

application.yml

server:
  port: 8888
spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/spring_cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
      username: root
      password: 1234
  redis:
    host: localhost
    port: 6379
    password: root
    database: 1
logging:
  level:
    com:
      itheima:
        mapper: debug
        service: info
        controller: info
  • 在启动类上加上@EnableCaching注解,开启缓存注解功能

启动类CacheDemoApplication

@Slf4j
@SpringBootApplication
@EnableCaching//开启缓存注解功能功能
public class CacheDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(CacheDemoApplication.class,args);
        log.info("项目启动成功...");
    }
}

Controller层

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {

    @Autowired
    private UserMapper userMapper;

    /*
    @CachePut:将方法的返回值放入缓存中去
    使用Spring Cache缓存数据,Redis中key的生成方式:cacheNames::key,eg:userCache::user.id
    key的写法支持SpEL语法,以#开头,后面跟方法参数名即可访问对应方法参数
    .为对象导航,用于访问对象的属性
    也可使用#result.id访问方法返回值对象的id属性
    或者使用方法参数索引访问,如#p0,#a0,#root.args[0],均表示方法的第一个参数
     */
    @PostMapping
    //@CachePut(cacheNames = "userCache", key = "#result.id")
    //@CachePut(cacheNames = "userCache", key = "#p0.id")
    //@CachePut(cacheNames = "userCache", key = "#a0.id")
    //@CachePut(cacheNames = "userCache", key = "#root.args[0].id")
    @CachePut(cacheNames = "userCache",key = "#user.id")//对象插入完毕后会返回主键,user中id属性就有了值
    public User save(@RequestBody User user){
        userMapper.insert(user);
        return user;
    }

    /**
     * @CacheEvict :将一条或多条数据从缓存中删除
     * @param id
     */
    @DeleteMapping
    @CacheEvict(cacheNames = "userCache",key = "#id")
    public void deleteById(Long id){
        userMapper.deleteById(id);
    }

    /**
     * 删除所有数据
     */
    @CacheEvict(cacheNames = "userCache",allEntries = true)
	@DeleteMapping("/delAll")
    public void deleteAll(){
        userMapper.deleteAll();
    }

    /**
    @Cacheable :方法执行前先查询缓存中是否有数据,有则直接返回,
    没有则调用方法并将方法的返回值存入缓存中
     */
    @GetMapping
    @Cacheable(cacheNames = "userCache",key = "#id")
    public User getById(Long id){
        User user = userMapper.getById(id);
        return user;
    }
}

实体类User

@Data
public class User implements Serializable {

    private static final long serialVersionUID = 1L;

    private Long id;

    private String name;

    private int age;

}

Mapper层

package com.itheima.mapper;

import com.itheima.entity.User;
import org.apache.ibatis.annotations.*;

@Mapper
public interface UserMapper{

    @Insert("insert into user(name,age) values (#{name},#{age})")
    @Options(useGeneratedKeys = true,keyProperty = "id")
    void insert(User user);

    @Delete("delete from user where id = #{id}")
    void deleteById(Long id);

    @Delete("delete from user")
    void deleteAll();

    @Select("select * from user where id = #{id}")
    User getById(Long id);
}

你可能感兴趣的:(Java从入门到精通,redis,数据库,缓存)