Integração da estrutura Redis e SpringBoot e resumo detalhado do aprendizado

Índice

springBoot integra Redis

Vantagens do Redis

Instalação do Redis

Tipos de dados do Redis

Springboot opera Redis

configuração do springboot redis

RedisTemplate e seus métodos relacionados

springBoot implementa upload e download

RedisTemplate e seus métodos relacionados

springBoot implementa upload e download

springBoot CORS (Compartilhamento de recursos entre domínios)

projeto de agregação springBoot


springBoot integra Redis

Redis é totalmente open source, está em conformidade com o protocolo BSD e é um banco de dados chave-valor de alto desempenho.

O Redis e outros produtos de cache de valor-chave têm as três características a seguir:

  • O Redis oferece suporte à persistência de dados, que pode salvar os dados na memória no disco e pode ser carregado novamente para uso ao reiniciar.

  • O Redis não apenas oferece suporte a dados simples do tipo chave-valor, mas também fornece armazenamento de estruturas de dados, como lista, conjunto, zset e hash.

  • O Redis suporta backup de dados, ou seja, backup de dados no modo mestre-escravo.

Vantagens do Redis

  • Desempenho extremamente alto – o Redis pode ler a 110.000 vezes/s e gravar a 81.000 vezes/s

  • Tipos de dados ricos – o Redis oferece suporte aos tipos de dados String, List, Hash, Set e zset para casos binários.

  • Atômica – todas as operações do Redis são atômicas, o que significa que elas são bem-sucedidas ou falham. As operações individuais são atômicas. Operações múltiplas também suportam transações, ou seja, atomicidade, agrupadas por instruções MULTI e EXEC.

  • Recursos avançados – o Redis também suporta publicação/assinatura, notificação, expiração de chave e outros recursos

  • O Redis é de thread único e a versão 6.0 oferece suporte a multithreading.

Instalação do Redis

Endereço de download: Releases·tporadowski/redis·GitHub .

Descompacte o arquivo compactado baixado, a lista de arquivos após a descompactação é a seguinte:

 

 

Abra o Redis usando a janela cmd

Instale o cliente de banco de dados Redis

 

Instruções relacionadas à biblioteca:

flushdb limpa a biblioteca atual 
flushall
limpa todas as bibliotecas 
selecione
1 switch library

Instruções relacionadas à chave

instrução efeito gramática
do excluir uma ou mais chaves do nome-chave
existe Determine se uma ou mais chaves existem e retorne 1 se uma das chaves existir existe nome-chave
expirar Defina a unidade de tempo de sobrevivência da chave: segundos expirar keyname segundos
chave s Consultar todas as chaves correspondentes ao padrão? Combine um personagem * Combine 0-n caracteres [] para encontrar um deles chave * chave h?llo
mover Mova a chave para a biblioteca especificada mover nome-chave db
expirar Defina a unidade de tempo de sobrevivência da chave: retorne 1 se a configuração de milissegundos for bem-sucedida, caso contrário, retorne 0 pexpire keyname milissegundos
ttl Retorna o tempo de vida restante da chave em segundos, retorna -1 para armazenamento permanente, -2 para chave inexistente nome-chave ttl
chave aleatória Retorna aleatoriamente uma chave do banco de dados atual chave aleatória
renomear Renomeie a chave, retorne ok se for bem-sucedida, caso contrário, retorne uma mensagem de erro. renomear chave newkey
tipo Retorna o tipo do valor armazenado pela chave digite o nome-chave

Tipos de dados do Redis

1. Corda (corda)

  • string é o tipo mais básico de redis, você pode entendê-lo exatamente como o mesmo tipo do Memcached, uma chave corresponde a um valor.

  • O tipo string é binário seguro. Isso significa que a string de redis pode conter qualquer dado. Como imagens jpg ou objetos serializados.

  • O tipo string é o tipo de dados mais básico do Redis, e o valor do tipo string pode armazenar até 512 MB.

Instrução de Operação:

Ordem descrever
DEFINIR Defina o valor da chave especificada
PEGAR Obtenha o valor da chave especificada.
AFETADO Retorna os subcaracteres do valor da string na chave
PREPARE-SE Define o valor da chave fornecida como valor e retorna o valor antigo da chave.
SETE Associe o valor value à chave e defina o tempo de expiração da chave para segundos (em segundos).
SETNX Apenas defina o valor da chave se a chave não existir
STRLEN Retorna o comprimento do valor da string armazenado pela chave.
MSET Defina um ou mais pares chave-valor ao mesmo tempo.
MSETNX Defina simultaneamente um ou mais pares chave-valor se e somente se nenhuma das chaves fornecidas existir
INCR Incrementar o valor numérico armazenado na chave em um
INCRBY Adicione o valor armazenado pela chave ao valor de incremento fornecido (incremento)
INCRBYFLOAT Adicione o valor armazenado pela chave ao valor de incremento de ponto flutuante fornecido (incremento)
dezembro Decrementa o valor numérico armazenado na chave em um.
DECRETO O valor armazenado pela chave menos o valor de decremento dado (decremento)
ACRESCENTAR Se a chave já existir e for uma string, o comando APPEND anexará o valor especificado ao final do valor original da chave (valor)

2. Hash (hash)

  • Redis hash é uma coleção de pares chave-valor (chave=>valor).

  • Redis hash é uma tabela de mapeamento de campo e valor do tipo string, e o hash é especialmente adequado para armazenar objetos.

Instrução de Operação:

Ordem descrever
hset Definir um par de chave/valor
hget Obter o valor correspondente à chave
hgetall Obter todos os pares chave/valor
hdel Excluir um par chave/valor
hexista Determinar se existe uma chave
hkeys Obter todas as chaves
baleia Obter todos os valores
hmset Definir várias chaves/valores
hmget Obter o valor de várias chaves
hsetnx Defina o valor de uma chave que não existe
perto Execute a operação de adição para o valor de value
hincrbyfloat Adicionar operação de valor de tipo de ponto flutuante ao valor de value

3. Lista (lista)

  • As listas Redis são simplesmente listas de strings, classificadas por ordem de inserção. Você pode adicionar um elemento à cabeça (à esquerda) ou à cauda (à direita) da lista.

Instrução de Operação

Ordem descrever
LINDEX 通过索引获取列表中的元素 lindex lists 0
LINSERT key BEFORE|AFTER 在列表的元素前或者后插入元素
LLEN 获取列表长度
LPOP 移出并获取列表的第一个元素
LPUSH 将一个或多个值插入到列表头部
LPUSHX 将一个值插入到已存在的列表头部
LRANGE 获取列表指定范围内的元素 (0 -1)
LREM 移除列表重复元素
LSET 通过索引设置列表元素的值 ,但是索引必须存在,实质是根据索引修改值
LTRIM 对一个列表进行修剪(trim),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
RPOP 移除列表的最后一个元素,返回值为移除的元素
RPOPLPUSH 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
RPUSH 在列表中添加一个或多个值
RPUSHX 为已存在的列表添加值

4.Set(集合)

  • Redis 的 Set 是 string 类型的无序集合。

  • 集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。

操作指令:

命令 描述
sadd 为集合添加元素
smembers 显示集合中所有元素 (无序)
scard 返回集合中元素的个数
spop 随机返回一个元素,并将这个元素删除
smove 从一个集合向令一个集合中转移元素
srem 从集合中删除一个元素
sismember 判断集合中是否包含这个元素
srandmember 随机返回一个元素
sinter 求交集
sunion 求和集

5.zset(sorted set:有序集合)

  • Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。

  • 不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

  • zset的成员是唯一的,但分数(score)却可以重复。

操作指令:

命令 描述
zadd 添加一个有序集合元素
zcard 返回集合中元素的个数
zrange升序 zrevrange降序 返回一个范围内的元素
zrangebyscore 按照分数查找一个范围内的元素
zrank 返回排名
zrevrank 倒叙排名
zscore 显示某个元素的分数
zrem 移除某个元素
zincrby 给某个特定元素加分

springboot操作Redis

spring boot data redis中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是Redistemplate的子类,两个方法基本一致,不同之处主要体现在操作的数据类型不同,RedisTemplate中的两个泛型都是Object,意味着存储的key和value都可以是一个对象,而StringRedisTemplate的两个泛型都是String,意味着StringRedisTemplate的key和value都只能是字符串。

引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

springboot 配置redis

 

RedisTemplate及其相关方法

1.RedisTemplate

Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。

2.Redis5种数据结构操作

  • redisTemplate.opsForValue(); //操作字符串

  • redisTemplate.opsForHash(); //操作hash

  • redisTemplate.opsForList(); //操作list

  • redisTemplate.opsForSet(); //操作set

  • redisTemplate.opsForZSet(); //操作有序set

或者:

  • redistempalate.boundValueOps

  • redistempalate.boundSetOps

  • redistempalate.boundListOps

  • redistempalate.boundHashOps

  • redistempalate.boundZSetOps

opsForXXX和boundXXXOps的区别:XXX为value的类型,前者获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value;后者获取了一个指定操作对象(key)的operator,在一个连接(事务)内只能操作这个key对应的value。

SpringBootTest 实现Redis数据库增删改查

/**
 * 使用RedisTemplate 操作Redis数据的不同数据类型
 */
@SpringBootTest
public class Springbootday03ApplicationTests {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * String 类型数据操作
     */
    @Test
    public void operateString() {

        //添加值
        redisTemplate.opsForValue().set("str", "strValue1");

        //添加值  判定是否存在 存在则不添加
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str", "strAbsent");
        System.out.println("str设置成功:" + aBoolean);

        //获取值
        String str = redisTemplate.opsForValue().get("str");
        System.out.println("str = " + str);

        //更新值
        redisTemplate.opsForValue().set("str", "strValue2");
        str = redisTemplate.opsForValue().get("str");
        System.out.println("newStr = " + str);

        //删除值
        Boolean b = redisTemplate.delete("str");
        System.out.println("str删除成功:" + b);

    }

    /**
     * 操作string类型数据  设置过期时间
     */
    @Test
    public void operateString2() {
        redisTemplate.opsForValue().set("str", "strTimeout", 10, TimeUnit.SECONDS);
        //判定值是否存在 不存在则设置值 同时设置过期时间
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str2", "strTimeoutAbsent", 20, TimeUnit.SECONDS);
        System.out.println("setIfAbsent:" + aBoolean);
    }

    /**
     * 操作hash类型数据
     */
    @Test
    public void operateHash() {
        //添加hash类型数据  key - value
        redisTemplate.opsForHash().put("hash", "username", "admin");
        //修改hash类型数据
        redisTemplate.opsForHash().put("hash", "username", "tom");
        redisTemplate.opsForHash().put("hash", "password", "123456");

        //添加hash类型数据  key - map
        HashMap<String, String> map = new HashMap<>();
        map.put("driverName", "com.mysql.jdbc.Driver");
        map.put("url", "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC");
        redisTemplate.opsForHash().putAll("hash", map);

        //获取hash类型数据  entries
        Map<Object, Object> hash = redisTemplate.opsForHash().entries("hash");
        hash.forEach((key, value) -> {
            System.out.println(key + "::" + value);
        });

        //获取所有的key
        Set<Object> keys = redisTemplate.opsForHash().keys("hash");
        for (Object key : keys) {
            System.out.println("key:" + key);
        }
        //获取所有value
        List<Object> values = redisTemplate.opsForHash().values("hash");
        values.forEach(value -> System.out.println("value:" + value));

        //删除hash类型数据  删除一个  返回删除的个数
        Long delete = redisTemplate.opsForHash().delete("hash", "username");
        System.out.println("delete = " + delete);

        //删除hash类型数据  删除多个  返回删除的个数
        delete = redisTemplate.opsForHash().delete("hash", "username", "password", "driverName");
        System.out.println("delete = " + delete);

        //删除hash类型数据  删除所有
        Boolean delHash = redisTemplate.delete("hash");
        System.out.println("delHah:" + delHash);

    }

    /**
     * 操作List类型  有序 可重复
     */
    @Test
    public void operateList() {

        //左压栈
        // redisTemplate.opsForList().leftPush("list", "listValue1");
        // redisTemplate.opsForList().leftPush("list", "listValue1");
        // redisTemplate.opsForList().leftPush("list", "listValue2");
        // redisTemplate.opsForList().leftPush("list", "listValue3");

        //右压栈
        redisTemplate.opsForList().rightPush("list", "listValue0");
        redisTemplate.opsForList().rightPush("list", "listValue2");
        redisTemplate.opsForList().rightPush("list", "listValue0");

        //左出栈
        String list1 = redisTemplate.opsForList().leftPop("list");
        System.out.println("leftPop list1 = " + list1);
        //右出栈
        String list2 = redisTemplate.opsForList().rightPop("list");
        System.out.println("rightPop list2 = " + list2);

        //获取所有数据
        List<String> lists = redisTemplate.opsForList().range("list", 0, 		        redisTemplate.opsForList().size("list") - 1);
        lists.forEach(list -> System.out.println(list));


        //设置指定位置的数据
        redisTemplate.opsForList().set("list", 0, "listValue0");
        /**
         * 从存储在键中的列表中删除等于值的元素的第一个计数事件。
         * count> 0:删除等于从左到右移动的值的第一个元素;
         * count< 0:删除等于从右到左移动的值的第一个元素;
         * count = 0:删除等于value的所有元素。
         */
        Long remove = redisTemplate.opsForList().remove("list", -1, "listValue0");
        System.out.println("remove:" + remove);

        //删除指定key的list数据
        Boolean list = redisTemplate.delete("list");
        System.out.println("list集合删除成功:" + list);
    }

    /**
     * 操作Set类型  无序 不可重复
     */
    @Test
    public void operateSet() {

        //设置set值
        redisTemplate.opsForSet().add("set", "setValue0");
        redisTemplate.opsForSet().add("set", "setValue0");
        redisTemplate.opsForSet().add("set", "setValue1");

        //判定是否包含
        Boolean member = redisTemplate.opsForSet().isMember("set", "setValue0");
        System.out.println("isMember:" + member);

        //删除set中的值
        Long remove = redisTemplate.opsForSet().remove("set", "setValue0");
        System.out.println("remove = " + remove);

        //获取set类型值
        Set<String> set = redisTemplate.opsForSet().members("set");
        set.forEach(str -> {
            System.out.println("str = " + str);
        });
    }

    /**
     * 操作 ZSet  有序 不可重复
     */
    @Test
    public void operateZSet() {
        //存储值
        Boolean add = redisTemplate.opsForZSet().add("zset", "zsetValue0", 10);
        System.out.println("add = " + add);
        System.out.println("add = " + add);
        add = redisTemplate.opsForZSet().add("zset", "zsetValue2", 2);
        System.out.println("add = " + add);
        //获取值
        // Boolean zset = redisTemplate.delete("zset");
        // System.out.println("delete zset = " + zset);
    }
}

 

Redis工具类的封装

 
 
/**
 * Redis 工具类
 * @author mosin
 * date 2021/11/30
 * @version 1.0
 */
@Component
public final class RedisUtil {

    private RedisUtil(){};
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    //设置值
    public void  setValue(String key,String value){
        redisTemplate.opsForValue().set(key, value);
    }
    // 设置值 同时设置有效时间
    public void setValue(String key, String value, Long timeOut, TimeUnit timeUnit){
        redisTemplate.opsForValue().setIfAbsent(key, value, timeOut, timeUnit);
    }

    //设置值 没有则设置 有则不设置
    public void  setNx(String key,String value){
        redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    //设置值 没有则设置 同时设置有效时间 有则不设置
    public void  setNx(String key,String value,long timeOut,TimeUnit timeUnit){
        redisTemplate.opsForValue().setIfAbsent(key, value,timeOut,timeUnit);
    }

    //删除值
    public boolean del(String key){
        return redisTemplate.delete(key);
    }
    
     //获取值
    public String getValue(String key){
        return  redisTemplate.opsForValue().get(key);
    }
}

业务实践(redis存储token,实现非法请求拦截)

1.编写拦截器

2.配置拦截器  

3.编写统一返回数据格式类  

4.编写控制器

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private RedisUtil redisUtil;
    @ResponseBody
    @RequestMapping("/login")
    public Object login(User user) throws JsonProcessingException {
        User usr = User.builder().id(1).name("admin").password("123456").build();
        //获取token  放入redis
        String token = UUID.randomUUID().toString().replace("-", "");
        //将user 转为json格式放入 redis
        ObjectMapper objectMapper = new ObjectMapper();
        String s1 = objectMapper.writeValueAsString(usr);
        //将 token 和用户信息存入 redis
        redisUtil.setValue(token, s1, 2L, TimeUnit.MINUTES);
        //将token 存入map集合返回
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);
        return map;
    }

    @ResponseBody
    @RequestMapping("/register")
    public Object register(User user){
        HashMap<String, String> map = new HashMap<>();
        map.put("msg", "ok");
        return map;
    }

    @ResponseBody
    @RequestMapping("/add")
    public Object add(User user){
        HashMap<String, String> map = new HashMap<>();
        map.put("msg", "ok");
        return map;
    }
}

 

5.编写业务类和Mapper接口

6.使用postman接口测试工具测试接口

springBoot实现上传下载

1.编写控制器

/**
 * 文件上传下载控制类
 * @author mosin
 * date 2021/12/1
 * @version 1.0
 */
@Controller
@RequestMapping("/file")
public class FileController {

    @RequestMapping("/toupload")
    public String toUpload(){ //跳转上传页
        return "upload";
    }

    @RequestMapping("/upload")
    public Object fileUpload(MultipartFile file, Model model){
        if( !file.isEmpty()){
            String originalFilename = file.getOriginalFilename();
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = uuid+suffix;
            File f = new File("D:\\upload",fileName);
            try {
                file.transferTo(f);
                model.addAttribute("downloadName", fileName);
                model.addAttribute("originalFilename", originalFilename);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "download";
    }

    @RequestMapping("/download")
    @ResponseBody
    public Object fileDownLoad(String fileName, HttpServletResponse response){
        HashMap<String, String> map = new HashMap<>();
        try {
            FileInputStream fis= new FileInputStream(new File("D:\\upload", fileName));
            //设置以附件形式输出
           response.setHeader("Content-disposition", "attachment; filename="+fileName);
            //获取输出流
            ServletOutputStream outputStream = response.getOutputStream();
            //org.springframework.util.FileCopyUtils  工具类
            FileCopyUtils.copy(fis, outputStream);
            map.put("msg", "上传成功!");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "上传失败!");
        }
        return map ;
    }
}

2.编写上传页面

3.编写下载页面  

设置上传文件大小限制 ​​​​​​​ 

RedisTemplate及其相关方法

1.RedisTemplate

Spring封装了RedisTemplate对象来进行对Redis的各种操作,它支持所有的Redis原生的api。RedisTemplate位于spring-data-redis包下。RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅。

2.Redis5种数据结构操作

  • redisTemplate.opsForValue(); //操作字符串

  • redisTemplate.opsForHash(); //操作hash

  • redisTemplate.opsForList(); //操作list

  • redisTemplate.opsForSet(); //操作set

  • redisTemplate.opsForZSet(); //操作有序set

或者:

  • redistempalate.boundValueOps

  • redistempalate.boundSetOps

  • redistempalate.boundListOps

  • redistempalate.boundHashOps

  • redistempalate.boundZSetOps

opsForXXX和boundXXXOps的区别:XXX为value的类型,前者获取一个operator,但是没有指定操作的对象(key),可以在一个连接(事务)内操作多个key以及对应的value;后者获取了一个指定操作对象(key)的operator,在一个连接(事务)内只能操作这个key对应的value。

SpringBootTest 实现Redis数据库增删改查

/**
 * 使用RedisTemplate 操作Redis数据的不同数据类型
 */
@SpringBootTest
public class Springbootday03ApplicationTests {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * String 类型数据操作
     */
    @Test
    public void operateString() {

        //添加值
        redisTemplate.opsForValue().set("str", "strValue1");

        //添加值  判定是否存在 存在则不添加
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str", "strAbsent");
        System.out.println("str设置成功:" + aBoolean);

        //获取值
        String str = redisTemplate.opsForValue().get("str");
        System.out.println("str = " + str);

        //更新值
        redisTemplate.opsForValue().set("str", "strValue2");
        str = redisTemplate.opsForValue().get("str");
        System.out.println("newStr = " + str);

        //删除值
        Boolean b = redisTemplate.delete("str");
        System.out.println("str删除成功:" + b);

    }

    /**
     * 操作string类型数据  设置过期时间
     */
    @Test
    public void operateString2() {
        redisTemplate.opsForValue().set("str", "strTimeout", 10, TimeUnit.SECONDS);
        //判定值是否存在 不存在则设置值 同时设置过期时间
        Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("str2", "strTimeoutAbsent", 20, TimeUnit.SECONDS);
        System.out.println("setIfAbsent:" + aBoolean);
    }

    /**
     * 操作hash类型数据
     */
    @Test
    public void operateHash() {
        //添加hash类型数据  key - value
        redisTemplate.opsForHash().put("hash", "username", "admin");
        //修改hash类型数据
        redisTemplate.opsForHash().put("hash", "username", "tom");
        redisTemplate.opsForHash().put("hash", "password", "123456");

        //添加hash类型数据  key - map
        HashMap<String, String> map = new HashMap<>();
        map.put("driverName", "com.mysql.jdbc.Driver");
        map.put("url", "jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC");
        redisTemplate.opsForHash().putAll("hash", map);

        //获取hash类型数据  entries
        Map<Object, Object> hash = redisTemplate.opsForHash().entries("hash");
        hash.forEach((key, value) -> {
            System.out.println(key + "::" + value);
        });

        //获取所有的key
        Set<Object> keys = redisTemplate.opsForHash().keys("hash");
        for (Object key : keys) {
            System.out.println("key:" + key);
        }
        //获取所有value
        List<Object> values = redisTemplate.opsForHash().values("hash");
        values.forEach(value -> System.out.println("value:" + value));

        //删除hash类型数据  删除一个  返回删除的个数
        Long delete = redisTemplate.opsForHash().delete("hash", "username");
        System.out.println("delete = " + delete);

        //删除hash类型数据  删除多个  返回删除的个数
        delete = redisTemplate.opsForHash().delete("hash", "username", "password", "driverName");
        System.out.println("delete = " + delete);

        //删除hash类型数据  删除所有
        Boolean delHash = redisTemplate.delete("hash");
        System.out.println("delHah:" + delHash);

    }

    /**
     * 操作List类型  有序 可重复
     */
    @Test
    public void operateList() {

        //左压栈
        // redisTemplate.opsForList().leftPush("list", "listValue1");
        // redisTemplate.opsForList().leftPush("list", "listValue1");
        // redisTemplate.opsForList().leftPush("list", "listValue2");
        // redisTemplate.opsForList().leftPush("list", "listValue3");

        //右压栈
        redisTemplate.opsForList().rightPush("list", "listValue0");
        redisTemplate.opsForList().rightPush("list", "listValue2");
        redisTemplate.opsForList().rightPush("list", "listValue0");

        //左出栈
        String list1 = redisTemplate.opsForList().leftPop("list");
        System.out.println("leftPop list1 = " + list1);
        //右出栈
        String list2 = redisTemplate.opsForList().rightPop("list");
        System.out.println("rightPop list2 = " + list2);

        //获取所有数据
        List<String> lists = redisTemplate.opsForList().range("list", 0, 		        redisTemplate.opsForList().size("list") - 1);
        lists.forEach(list -> System.out.println(list));


        //设置指定位置的数据
        redisTemplate.opsForList().set("list", 0, "listValue0");
        /**
         * 从存储在键中的列表中删除等于值的元素的第一个计数事件。
         * count> 0:删除等于从左到右移动的值的第一个元素;
         * count< 0:删除等于从右到左移动的值的第一个元素;
         * count = 0:删除等于value的所有元素。
         */
        Long remove = redisTemplate.opsForList().remove("list", -1, "listValue0");
        System.out.println("remove:" + remove);

        //删除指定key的list数据
        Boolean list = redisTemplate.delete("list");
        System.out.println("list集合删除成功:" + list);
    }

    /**
     * 操作Set类型  无序 不可重复
     */
    @Test
    public void operateSet() {

        //设置set值
        redisTemplate.opsForSet().add("set", "setValue0");
        redisTemplate.opsForSet().add("set", "setValue0");
        redisTemplate.opsForSet().add("set", "setValue1");

        //判定是否包含
        Boolean member = redisTemplate.opsForSet().isMember("set", "setValue0");
        System.out.println("isMember:" + member);

        //删除set中的值
        Long remove = redisTemplate.opsForSet().remove("set", "setValue0");
        System.out.println("remove = " + remove);

        //获取set类型值
        Set<String> set = redisTemplate.opsForSet().members("set");
        set.forEach(str -> {
            System.out.println("str = " + str);
        });
    }

    /**
     * 操作 ZSet  有序 不可重复
     */
    @Test
    public void operateZSet() {
        //存储值
        Boolean add = redisTemplate.opsForZSet().add("zset", "zsetValue0", 10);
        System.out.println("add = " + add);
        System.out.println("add = " + add);
        add = redisTemplate.opsForZSet().add("zset", "zsetValue2", 2);
        System.out.println("add = " + add);
        //获取值
        // Boolean zset = redisTemplate.delete("zset");
        // System.out.println("delete zset = " + zset);
    }
}

 Redis工具类的封装

/**
 * Redis 工具类
 * @author mosin
 * date 2021/11/30
 * @version 1.0
 */
@Component
public final class RedisUtil {

    private RedisUtil(){};
    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    //设置值
    public void  setValue(String key,String value){
        redisTemplate.opsForValue().set(key, value);
    }
    // 设置值 同时设置有效时间
    public void setValue(String key, String value, Long timeOut, TimeUnit timeUnit){
        redisTemplate.opsForValue().setIfAbsent(key, value, timeOut, timeUnit);
    }

    //设置值 没有则设置 有则不设置
    public void  setNx(String key,String value){
        redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    //设置值 没有则设置 同时设置有效时间 有则不设置
    public void  setNx(String key,String value,long timeOut,TimeUnit timeUnit){
        redisTemplate.opsForValue().setIfAbsent(key, value,timeOut,timeUnit);
    }

    //删除值
    public boolean del(String key){
        return redisTemplate.delete(key);
    }
    
     //获取值
    public String getValue(String key){
        return  redisTemplate.opsForValue().get(key);
    }
}

业务实践(redis存储token,实现非法请求拦截)

1.编写拦截器

@Component
public class AdminInterceptor implements HandlerInterceptor {
    @Autowired
    private RedisUtil redisUtil;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("拦截器以拦截请求");
        //从请求头中获取token  验证用户是否登录
        String token = request.getHeader("token");
        System.out.println(token);
        String tokenValue = redisUtil.getValue(token);
        System.out.println("tokenValue = " + tokenValue);
        if(tokenValue!=null){ //用户已登录 放行请求
            return  true;
        }else{//重定向到登录页面
            response.sendRedirect(request.getContextPath()+"/login.jsp");
            return false;
        }
    }
}

2.配置拦截器

3.编写统一返回数据格式类  

4.编写控制器

@Controller
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;
    @Autowired
    private RedisUtil redisUtil;
    @ResponseBody
    @RequestMapping("/login")
    public Object login(User user) throws JsonProcessingException {
        User usr = User.builder().id(1).name("admin").password("123456").build();
        //获取token  放入redis
        String token = UUID.randomUUID().toString().replace("-", "");
        //将user 转为json格式放入 redis
        ObjectMapper objectMapper = new ObjectMapper();
        String s1 = objectMapper.writeValueAsString(usr);
        //将 token 和用户信息存入 redis
        redisUtil.setValue(token, s1, 2L, TimeUnit.MINUTES);
        //将token 存入map集合返回
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);
        return map;
    }

    @ResponseBody
    @RequestMapping("/register")
    public Object register(User user){
        HashMap<String, String> map = new HashMap<>();
        map.put("msg", "ok");
        return map;
    }

    @ResponseBody
    @RequestMapping("/add")
    public Object add(User user){
        HashMap<String, String> map = new HashMap<>();
        map.put("msg", "ok");
        return map;
    }
}

 

5.编写业务类和Mapper接口

6.使用postman接口测试工具测试接口

springBoot实现上传下载

1.编写控制器

/**
 * 文件上传下载控制类
 * @author mosin
 * date 2021/12/1
 * @version 1.0
 */
@Controller
@RequestMapping("/file")
public class FileController {

    @RequestMapping("/toupload")
    public String toUpload(){ //跳转上传页
        return "upload";
    }

    @RequestMapping("/upload")
    public Object fileUpload(MultipartFile file, Model model){
        if( !file.isEmpty()){
            String originalFilename = file.getOriginalFilename();
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
            String fileName = uuid+suffix;
            File f = new File("D:\\upload",fileName);
            try {
                file.transferTo(f);
                model.addAttribute("downloadName", fileName);
                model.addAttribute("originalFilename", originalFilename);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "download";
    }

    @RequestMapping("/download")
    @ResponseBody
    public Object fileDownLoad(String fileName, HttpServletResponse response){
        HashMap<String, String> map = new HashMap<>();
        try {
            FileInputStream fis= new FileInputStream(new File("D:\\upload", fileName));
            //设置以附件形式输出
           response.setHeader("Content-disposition", "attachment; filename="+fileName);
            //获取输出流
            ServletOutputStream outputStream = response.getOutputStream();
            //org.springframework.util.FileCopyUtils  工具类
            FileCopyUtils.copy(fis, outputStream);
            map.put("msg", "上传成功!");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "上传失败!");
        }
        return map ;
    }
}

2.编写上传页面

3.编写下载页面  

设置上传文件大小限制

 
 

 

springBoot CORS(跨域资源共享)

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

什么是同源策略? 同源策略是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。所以a.com下的js脚本采用ajax读取b.com里面的文件数据是会报错的。

先来说说什么是源 • 源(origin)就是协议、域名和端口号。 若地址里面的协议、域名和端口号均相同则属于同源。 以下是相对于 http:// www.a.com/test/index.html 的同源检测 http://www.a.com/dir/page.html ----成功 http://www.child.a.com/test/index.html ----失败,域名不同 https://www.a.com/test/index.html ----失败,协议不同 http://www.a.com:8080/test/index.html ----失败,端口号不同

哪些操作不受同源限制

1.script

2.link

3.img

4.form

5.a

哪些操作受同源的限制

1.ajax

解决方案:

1.局部解决跨域

  • 使用注解@CrossOrigin(局部跨域)

2.全局解决跨域

  • 配置类解决跨域(全局跨域)

 
 
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import java.util.ArrayList;
import java.util.List;

@Configuration
public class CorsConfig {
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true); //sessionid 多次访问一致
        // 允许访问的客户端域名
        List<String> allowedOriginPatterns = new ArrayList<>();
        allowedOriginPatterns.add("*");
        corsConfiguration.setAllowedOriginPatterns(allowedOriginPatterns);
        corsConfiguration.addAllowedHeader("*"); // 允许任何头
        corsConfiguration.addAllowedMethod("*"); // 允许任何方法(post、get等)
        return corsConfiguration;
    }
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig()); // 对接口配置跨域设置
        return new CorsFilter(source);
    }
}


方式2:
    
@Configuration
public class MyWebMvcConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*");
    }
}

 

springBoot聚合工程

多模块聚合工程:按照MVC的思想,将应用分成三层web、service、mapper/dao这三个主要模块,在实际的开发过程中可能会根据实际的业务将聚合工程分成如下的形式:

  1. common:通用工具类模块,专门用于项目中使用的一些工具类。

  2. entity:实体类模块,专门存放实体类对象,例如:DTO、BO、AO、VO等等对象。

  3. mapper:dao接口模块,专门存放操作数据库的dao接口。

  4. service:业务逻辑模块,专门进行业务逻辑的处理。

  5. web:控制器模块,用于页面请求控制模块。

搭建聚合工程步骤如下:

(1)IDEA创建maven工程

通过IDEA创建一个maven的quickstart类型项目,然后删除里面的src目录,保留pom.xml文件即可,如下图所示

(2)修改pom依赖,修改父工程项目中的pom.xml文件,添加【springboot】依赖。

 

(3)创建common子模块 ​​​​​​​ 

Na interface pop-up, selecione o tipo de projeto [início rápido] e preencha as informações do subprojeto na próxima etapa 

No subprojeto, exclua o diretório redundante [test] e a classe de inicialização [App], modifique o arquivo pom, exclua o conteúdo redundante e adicione dependências do projeto pai 

Siga as etapas acima para concluir a criação dos submódulos subsequentes. O módulo da web pode criar um projeto de aplicativo da web para formar a seguinte estrutura de diretório 

Gerenciamento unificado de dependências

Nas etapas anteriores, construímos o projeto pai e o projeto filho e introduzimos a dependência do projeto pai [springboot]. Aqui, para facilitar o gerenciamento das dependências de cada subprojeto e outras dependências de terceiros, podemos optar por definir uniformemente a versão da dependência no arquivo [pom] do projeto pai.

 

No arquivo pom do subprojeto [-web], adicione a dependência [web] e crie a classe de inicialização [Application]. 

Crie a classe de inicialização [Application]. 

Crie o diretório [src/main/resources] e adicione o arquivo de configuração [application.yml] 

Criar classe de teste [HelloController] 

Inicie o projeto, abra o navegador e acesse o caminho de teste 

Neste ponto, o projeto de agregação SpringBoot foi criado e o acesso pode ser iniciado. Embora os subprojetos acima tenham sido criados, não há relação de dependência entre cada subprojeto, agora vamos associar esses subprojetos com dependências.

web----->serviço (----> indica dependência)

service----->mapper,app-common

mapeador----->entidade

Adicione as dependências acima a cada subprojeto por vez

Este é o fim do compartilhamento de hoje

A criação não é fácil, curtidas, comentários e relações mútuas

 

 

 

Acho que você gosta

Origin blog.csdn.net/swy2560666141/article/details/130317328
Recomendado
Clasificación