Spring Boot第八章-非关系型数据库(MongoDB,Redis)

Spring Boot第八章-非关系型数据库(MongoDB,Redis)

                                                                 Spring Boot第八章-非关系型数据

目录

1.MongoDB

1.1 介绍

1.2 Spring的支持

1.2.1 Object/Document 映射注解支持

1.2.2 MongoTemplate

1.2.3 Repository的支持

1.3 Spring Boot的支持

1.4 Spring Boot Mongo实战

1.4.1 MongoDB安装

1.4.2 搭建Spring Boot项目

1.4.3 主要代码

1.4.4 测试结果

2 redis

2.1 Spring的支持

2.1.1 配置

 2.1.2 使用

2.1.3 定义Serializer

2.2 Spring Boot的支持

2.3 Spring Boot Redis实战

2.3.1 安装Redis

2.3.2 增加依赖

2.3.3 主要代码

2.3.4 测试结果

项目地址

3.redis的发布订阅

3.1 redis发布订阅原理

3.2 测试例子

3.3 测试结果


1.MongoDB

1.1 介绍

  MongoDB是一个是一个基于文档(Document)的存储型数据库,使用面向对象的思想,每一条数据文档的对象。来自菜鸟教程的解释是:

MongoDB 是一个基于分布式文件存储的数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。

MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

1.2 Spring的支持

1.2.1 Object/Document 映射注解支持

  JPA提供了一套Object/Relation映射的注解(如@Entity,@Id),而Spring Data MongoDB也提供了一套注解:

@Document:映射领域对象与MongoDB的一个文档,类似于hibernate的@Entity注解

@Id:主键,不可重复,自带索引

@Field:为文档的属性定义名称

@Indexed: 为该字段加索引

@CompoundIndex:符合索引

@DBRef:关联另一个document对象,但不会级联表

1.2.2 MongoTemplate

 类似于jdbcTemplate

1.2.3 Repository的支持

和Spring Data JPA的使用方式一样,需要在配置类上加上@EnableMongoRepositories注解

1.3 Spring Boot的支持

 Spring Boot对MongoDB的支持,位于:org.springframework.boot.autoconfigure.mongo

在配置文件中,以”spring.data.mongodb”为前缀的属性配置MongoDB的信息

Spring Boot提供了一些默认属性以及自动配置,默认端口27017,host为localhost,数据库为test

1.4 Spring Boot Mongo实战

1.4.1 MongoDB安装

虚拟机内docker安装MongoDB,直接安装官方的

  • docker search mongo      查看官方mongo
  • docker pull mongo           拉取mongo镜像
  • docker images mongo     查看mongo镜像
  • docker run -p 27017:27017 -v $PWD/db:/data/db -d mongo:3.2

可视化工具Robo 3T,增加用户,查看,管理Mongo数据内容非常方便,已上传到百度网盘,

链接: https://pan.baidu.com/s/1oRRftXKtgdAJewFF3v0sAg 密码: yy84

1.4.2 搭建Spring Boot项目

新建Spring Boot项目,依赖spring-boot-starter-data-mongodb和spring-boot-starter-web

我的配置信息,虚拟机上安装的Mongo,ip是虚拟机的ip:

#mongodb的配置,springboot已经给我们做了很多默认配置,配置自己需要修改的地方就行了
#默认localhost
spring.data.mongodb.host=192.168.4.219  
spring.data.mongodb.port=27017

#connection url 默认数据库为test
#spring.data.mongodb.uri=mongodb://192.168.4.219/test
#spring.data.mongodb.database=test
#spring.data.mongodb.authentication-database=test
#spring.data.mongodb.username=admin
#spring.data.mongodb.password=123456
##默认开启
#spring.data.mongodb.repositories.enabled=true

1.4.3 主要代码

领域模型:

package com.just.springbootnosql.domain;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;

import java.util.Collection;

@Document  //映射领域模型和mongoDB的文档
public class Person {
    @Id
    private String id;
    private String name;
    private Integer age;
    @Field("locs") //此属性在文档中的名字是locs,locations属性将以数组形式存在当前数据记录中
    private Collection<Location> locations;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Collection<Location> getLocations() {
        return locations;
    }

    public void setLocations(Collection<Location> locations) {
        this.locations = locations;
    }
}

Location

package com.just.springbootnosql.domain;

public class Location {
    private String place;
    private String year;

    public Location(String place, String year) {
        this.place = place;
        this.year = year;
    }

    public String getPlace() {
        return place;
    }

    public void setPlace(String place) {
        this.place = place;
    }

    public String getYear() {
        return year;
    }

    public void setYear(String year) {
        this.year = year;
    }
}

数据访问:

package com.just.springbootnosql.dao;

import com.just.springbootnosql.domain.Person;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;

import java.util.List;

public interface PersonRepository extends MongoRepository<Person,String> {
    //支持方法名查询
    Person findByName(String name);

    //支持@Query查询,查询参数构造JSON字符串即可
    @Query("{'age':?0}")
    List<Person> withQueryByAge(Integer age);
}

控制器:

package com.just.springbootnosql.controller;

import com.just.springbootnosql.dao.PersonRepository;
import com.just.springbootnosql.domain.Location;
import com.just.springbootnosql.domain.Person;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;

@RestController
@RequestMapping("/person")
public class PersonController {
    @Autowired
    private PersonRepository personRepository;
    @PostMapping("/save")
    public Person save(@RequestBody Person person){
        Collection<Location> locations=new LinkedHashSet<>();
        Location location1=new Location("南京","2016");
        Location location2=new Location("常州","2016");
        Location location3=new Location("上海","2017");
        Location location4=new Location("上海","2018");
        locations.add(location1);
        locations.add(location2);
        locations.add(location3);
        locations.add(location4);
        person.setLocations(locations);
        return personRepository.save(person);
    }
    @GetMapping("/findByName")
    public Person findByName(String name){
        return personRepository.findByName(name);
    }
    @GetMapping("/findByAge")
    public List<Person> findByAge(Integer age){
        return personRepository.withQueryByAge(age);
    }
}

1.4.4 测试结果

controller测试结果:

Spring Boot第八章-非关系型数据库(MongoDB,Redis)

Spring Boot第八章-非关系型数据库(MongoDB,Redis) Spring Boot第八章-非关系型数据库(MongoDB,Redis)

mongodb数据:

Spring Boot第八章-非关系型数据库(MongoDB,Redis)

2 redis

Redis是一个基于键值对的开源内存数据存储

2.1 Spring的支持

2.1.1 配置

Spring对Redis的支持也是通过Spring Data Redis来实现的。

根据Redis的不同的Java客户端,Spring Data Redis提供了以下的ConnectionFactory,可以在

org.springframework.data.redis.connection 这个目录下找到各种ConnectionFactory:

JedisConnectionFactory,JredisConnectionFactory,LettuceConnectionFactory等等

Spring Boot第八章-非关系型数据库(MongoDB,Redis)

 2.1.2 使用

Spring Data Redis提供了RedisTemplate和StringRedisTemplate两个模板进行数据操作,其中StringRedisTemplate只针对键值都是字符串的数据类型进行操作

常用的数据访问方法:

opsForValue(): 简单属性

opsForList(): 操作含有list的数据

opsForSet(): 操作含有set的数据

opsForZSet(): 操作含有ZSet(有序的set)的数据

opsForHash(): 操作含有hash的数据

具体的操作将在持续更新的代码中体现

2.1.3 定义Serializer

定义键值序列化方式,Spring Data JPA提供了好几种序列化方式,RedisTemplate默认使用的是JdkSerializationSerializer。其他常用的具体详见代码

2.2 Spring Boot的支持

Spring Boot对Redis做了自动配置,org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration。

Spring Boot配置文件”spring.redis”为前缀的可以配置redis相关参数

2.3 Spring Boot Redis实战

2.3.1 安装Redis

docker安装redis,类似于mongoDB的安装,直接关键步骤就行了

  • docker pull redis
  • docker run redis –name redis -p 6379:6379 -d redis-server

windows上redis的安装教程很多,自行查找吧

redis的可视化工具:redis desktop manager,已放到百度网盘:

链接: https://pan.baidu.com/s/1SkIXmn1IkGrz-lUokzhyhA 密码: brui

2.3.2 增加依赖

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

配置信息:

# Redis服务器地址
spring.redis.host=192.168.4.219
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=

2.3.3 主要代码

新建一个user类:

package com.just.springbootnosql.domain;

import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID=1L;
    private String id;
    private String name;
    private Integer age;

    public User(){
        super();
    }
    public User(String id, String name, Integer age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }
    /**省略setter和getter**/
}

service层,用redisTemplate操作

redis有五种数据类型,redisTemplate对其的操作做了封装,可以在实际中看看他们的用法,这里只是测试常用的方法,每一种都有好多方法,可以自己去测试。

/**
 * 结构类型    结构存储的值    结构的读写能力
 * String    可以是字符串、整数或者浮点数    对整个字符串或者字符串的其中一部分执行操作;对象和浮点数执行自增(increment)或者自减(decrement)
 * List    一个链表,链表上的每个节点都包含了一个字符串    从链表的两端推入或者弹出元素;根据偏移量对链表进行修剪(trim);读取单个或者多个元素;根据值来查找或者移除元素
 * Set    包含字符串的无序收集器(unorderedcollection),并且被包含的每个字符串都是独一无二的、各不相同    添加、获取、移除单个元素;检查一个元素是否存在于某个集合中;计算交集、并集、差集;从集合里卖弄随机获取元素
 * Hash    包含键值对的无序散列表    添加、获取、移除单个键值对;获取所有键值对
 * Zset    字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定    添加、获取、删除单个元素;根据分值范围(range)或者成员来获取元素
 */

package com.just.springbootnosql.service;

import com.just.springbootnosql.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 结构类型	结构存储的值	结构的读写能力
 * String	可以是字符串、整数或者浮点数	对整个字符串或者字符串的其中一部分执行操作;对象和浮点数执行自增(increment)或者自减(decrement)
 * List	一个链表,链表上的每个节点都包含了一个字符串	从链表的两端推入或者弹出元素;根据偏移量对链表进行修剪(trim);读取单个或者多个元素;根据值来查找或者移除元素
 * Set	包含字符串的无序收集器(unorderedcollection),并且被包含的每个字符串都是独一无二的、各不相同	添加、获取、移除单个元素;检查一个元素是否存在于某个集合中;计算交集、并集、差集;从集合里卖弄随机获取元素
 * Hash	包含键值对的无序散列表	添加、获取、移除单个键值对;获取所有键值对
 * Zset	字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定	添加、获取、删除单个元素;根据分值范围(range)或者成员来获取元素
 */
@Service
@SuppressWarnings("unchecked")
public class UserServiceImpl implements UserService{
//    @Autowired
//    private JedisCluster jedisCluster;
    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public String findRedis() {
        redisTemplate.opsForValue().set("userName","呵呵哒");
        return redisTemplate.opsForValue().get("userName").toString();
    }

    @Override
    public List<User> cacheUsers() {
        List<User> users=new ArrayList<>();
        User user1=new User("1","阿西吧",12);
        User user2=new User("2","阿西九",20);
        User user3=new User("3","阿西十",18);
        users.add(user1);
        users.add(user2);
        users.add(user3);
        redisTemplate.opsForList().leftPush("user.list",user1);
        redisTemplate.opsForList().leftPush("user.list",user2);
        redisTemplate.opsForList().leftPush("user.list",user3);
        //第二种方式
        //redisTemplate.delete("users.list");
        //redisTemplate.opsForList().leftPushAll("user.list",users);
        redisTemplate.expire("user.list",30,TimeUnit.SECONDS);
        return redisTemplate.opsForList().range("user.list",0L,-1L);
    }

    @Override
    public Map<String, User> cacheUserMap() {
        User user=new User("4","测试hash",66);
        User user1=new User("6","测试hash",67);
        User user2=new User("7","测试hash",68);
        User user3=new User("8","测试hash",69);
        Map<String,User> map=new HashMap<>();
        map.put(user1.getId(),user1);
        map.put(user2.getId(),user2);
        map.put(user3.getId(),user3);
        //第一种方式,单个加入
        redisTemplate.opsForHash().put("user.map","4",user);
        //第二种方式,整个map加入
        redisTemplate.opsForHash().putAll("user.map",map);
        return redisTemplate.opsForHash().entries("user.map");
    }

    @Override
    public User findUser(String id) {
        return (User) redisTemplate.opsForHash().get("user.map",id);
    }

    @Override
    public Set<User> cacheUserSet() {
        Set<User> userSet=new HashSet<>();
        User user1=new User("10","测试set",20);
        User user2=new User("11","测试set",21);
        User user3=new User("12","测试set",22);
        userSet.add(user1);
        userSet.add(user2);
        userSet.add(user3);
        //只能一个一个放进去。。。
        redisTemplate.opsForSet().add("user.set",user1,user2,user3);
        return redisTemplate.opsForSet().members("user.set");
    }

    /**
     * zSet:字符串成员(member)与浮点数分值(score)之间的有序映射,元素的排列顺序由分值的大小决定
     */
    @Override
    public Set<User> cacheUserZSet() {
        User user=new User("20","测试zset",13);
        User user1=new User("21","测试zset",14);
        User user2=new User("22","测试zset",15);
        User user3=new User("23","测试zset",16);

        redisTemplate.opsForZSet().add("user.zset",user,1.0);
        ZSetOperations.TypedTuple<Object> typedTuple1=new DefaultTypedTuple<>(user1,Double.valueOf(user1.getId()));
        ZSetOperations.TypedTuple<Object> typedTuple2=new DefaultTypedTuple<>(user2,Double.valueOf(user2.getId()));
        ZSetOperations.TypedTuple<Object> typedTuple3=new DefaultTypedTuple<>(user3,Double.valueOf(user3.getId()));
        Set<ZSetOperations.TypedTuple<Object>> tuples=new HashSet<>();
        tuples.add(typedTuple1);
        tuples.add(typedTuple2);
        tuples.add(typedTuple3);
        redisTemplate.opsForZSet().add("user.zset",tuples);
        return redisTemplate.opsForZSet().range("user.zset",0,-1);
    }
}

controller层,来测试redis各种数据结构效果

package com.just.springbootnosql.controller;

import com.just.springbootnosql.dao.UserDao;
import com.just.springbootnosql.domain.User;
import com.just.springbootnosql.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
import java.util.Map;
import java.util.Set;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    UserDao userDao;
    @Autowired
    UserService userService;
    @RequestMapping("/save")
    public User saveUser(){
        User user=new User("1","哈哈哈",11);
        userDao.save(user);
        userDao.stringRedisTemplateDemo();
        return user;
    }
    @GetMapping("/getString")
    public String getString(){
       return userDao.getString();
    }

    @GetMapping("/getUser")
    public User getUser(){
        return userDao.getUser("1");
    }
    @GetMapping("/findRedis")
    public String findRedis(){
        return userService.findRedis();
    }
    @GetMapping("/testList")
    public List<User> findList(){
        return userService.cacheUsers();
    }
    @GetMapping("/map")
    public Map<String,User> findMap(){
        return userService.cacheUserMap();
    }
    @GetMapping("/getFromMap")
    public User findOneFromMap(String id){
        return userService.findUser(id);
    }
    @GetMapping("/set")
    public Set<User> findFromSet(){
        return userService.cacheUserSet();
    }
    @GetMapping("/zset")
    public Set<User> findFromZSet(){
        return userService.cacheUserZSet();
    }
}

2.3.4 测试结果

展示不同数据类型接口的测试结果

Spring Boot第八章-非关系型数据库(MongoDB,Redis)

Spring Boot第八章-非关系型数据库(MongoDB,Redis) Spring Boot第八章-非关系型数据库(MongoDB,Redis)

Spring Boot第八章-非关系型数据库(MongoDB,Redis) Spring Boot第八章-非关系型数据库(MongoDB,Redis)

Spring Boot第八章-非关系型数据库(MongoDB,Redis) Spring Boot第八章-非关系型数据库(MongoDB,Redis)

项目地址

https://gitee.com/yuanhan93/springbootnosql

补充内容:

3.redis的发布订阅

3.1 redis发布订阅原理

参考:https://blog.csdn.net/clh604/article/details/19754939

3.2 测试例子

新建一个接收类:

package com.just.springbootnosql;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.just.springbootnosql.domain.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
public class Receiver {
    private static final Logger logger=LoggerFactory.getLogger(Receiver.class);
    private CountDownLatch latch;
    //我们给Receiver的构造函数通过@AutoWired标注注入了一个CountDownLatch实例,当接收到消息时,调用cutDown()方法。
    @Autowired
    public Receiver(CountDownLatch latch){
        this.latch=latch;
    }

    public void receiveMessage(String message){
        logger.info("receive message:"+message);
        latch.countDown();
    }

    public void receiveJsonMessage(String message){
        logger.info("receive json message:"+message);
        ObjectMapper mapper=new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL,JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //GenericJackson2JsonRedisSerializer 里会有class的类路径,可以直接反序列化
        //GenericJackson2JsonRedisSerializer g=new GenericJackson2JsonRedisSerializer();
        try {
            User user=mapper.readValue(message,User.class);
            //User user=(User) g.deserialize(message.getBytes());
            logger.info("反序列化为user成功,userId:"+user.getId());
        } catch (Exception e) {
            logger.info("这不是user");
        }
        latch.countDown();
    }

}

在这个接受类中加入了CountDownLatch,为了在下面的测试代码中运行,能看到接收的效果,因为发送消息是异步的,在test代码中如果不用这个就看不到打印的效果。CountDownLatch能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。使用一个计数器进行实现。

CountDownLatch不是必要加的,只是为了测试方便!

在这个类里面有两个接收方法,一个是普通的string类型,另一个是json字符串,可以反序列化为对象

redis监听器配置:

package com.just.springbootnosql;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

import java.util.concurrent.CountDownLatch;

@Configuration
public class RedisListenerConfig {
    /**
     * redis监听容器
     */
    @Bean
    RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
                                            MessageListenerAdapter listenerAdapter,
                                            MessageListenerAdapter listenerJsonAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic("p_topic"));
        container.addMessageListener(listenerJsonAdapter, new PatternTopic("p_topic_json"));
        return container;
    }

    @Bean
    MessageListenerAdapter listenerAdapter(Receiver receiver) {
        return new MessageListenerAdapter(receiver, "receiveMessage");
    }

    /**
     * 在redisTemplate的配置中已经是json的序列化方式,这里不需要再进行序列化了
     */
    @Bean
    MessageListenerAdapter listenerJsonAdapter(Receiver receiver) {
        MessageListenerAdapter messageListenerAdapter=new MessageListenerAdapter(receiver, "receiveJsonMessage");
        return messageListenerAdapter;
    }

    @Bean
    Receiver receiver(CountDownLatch latch) {
        return new Receiver(latch);
    }

    @Bean
    CountDownLatch latch() {
        return new CountDownLatch(1);
    }


}

配置两个频道,并且配置两个频道的监听方法。由于redis的配置中已经对消息进行了序列化方式的处理,这里就不用再次序列化了。

测试:

package com.just.springbootnosql;

import com.just.springbootnosql.domain.User;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootnosqlApplicationTests {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void testRedisPub() throws JSONException {
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("name","小李子");
        jsonObject.put("age",18);
        User user=new User();
        user.setId("1");
        user.setName("超级用户");
        user.setAge(0);
        redisTemplate.convertAndSend("p_topic","我来啦,呵呵哒");
        redisTemplate.convertAndSend("p_topic_json",jsonObject);
        redisTemplate.convertAndSend("p_topic_json",user);
    }

}

3.3 测试结果

不启动项目,直接test,testRedisPub()方法测试结果:

2018-09-05 10:55:03.557  INFO 15196 --- [    container-2] com.just.springbootnosql.Receiver        : receive message:"我来啦,呵呵哒"
2018-09-05 10:55:03.634  INFO 15196 --- [    container-3] com.just.springbootnosql.Receiver        : receive json message:["org.json.JSONObject",{"nameValuePairs":["java.util.HashMap",{"name":"小李子","age":18}]}]
2018-09-05 10:55:03.664  INFO 15196 --- [    container-4] com.just.springbootnosql.Receiver        : receive json message:["com.just.springbootnosql.domain.User",{"id":"1","name":"超级用户","age":0}]
2018-09-05 10:55:03.700  INFO 15196 --- [    container-3] com.just.springbootnosql.Receiver        : 这不是user
2018-09-05 10:55:03.703  INFO 15196 --- [    container-4] com.just.springbootnosql.Receiver        : 反序列化为user成功,userId:1
2018-09-05 10:55:03.714  INFO 15196 --- [       Thread-2] o.s.w.c.s.GenericWebApplicationContext   : Closing org.springframework.web.context.support.GenericWebApplicationContext@4758820d: startup date [Wed Sep 05 10:54:58 CST 2018]; root of context hierarchy
2018-09-05 10:55:03.716  INFO 15196 --- [       Thread-2] o.s.c.support.DefaultLifecycleProcessor  : Stopping beans in phase 2147483647
Disconnected from the target VM, address: '127.0.0.1:50580', transport: 'socket'

Process finished with exit code 0

启动项目,用redis客户端写语句发布消息测试:

Spring Boot第八章-非关系型数据库(MongoDB,Redis)

2018-09-05 14:40:40.854  INFO 12656 --- [    container-2] com.just.springbootnosql.Receiver        : receive message:我来自客户端

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100280.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • Android图片裁剪之自由裁剪

    Android图片裁剪之自由裁剪

  • Python 中return用法及意义「建议收藏」

    Python 中return用法及意义「建议收藏」return意义其实说白了,函数就是个你招来的工人。你给他一些材料,告诉他怎么用这些材料拼装,然后他负责把拼装好的成品交给你。材料就是函数的参数,成品是函数的输出,而怎么拼装就是你写的函数体代码了。比如这段代码defworker(a,b,c):x=a+by=x*c这个工人worker在你的指导下,用abc三个材料,装配出了x和y两个成品。但是程…

    2022年10月28日
  • forkjoin用法_fork join_none

    forkjoin用法_fork join_noneFork/Join是一个分而治之的任务框架,如一个任务需要多线程执行,分割成很多块计算的时候,可以采用这种方法。动态规范:和分而治之不同的是,每个小任务之间互相联系。工作密取:分而治之分割了每个任务之后,某个线程提前完成了任务,就会去其他线程偷取任务来完成,加快执行效率。同时,第一个分配的线程是从队列中的头部拿任务,当完成任务的线程去其他队列拿任务的时候是从尾部拿任务,所以这样就避免了竞争。在Java的Fork/Join框架中,使用两个类完成上述操作:  1.ForkJoinTask:我们要使用F

    2022年10月22日
  • 基于麦克风阵列的现有声源定位技术有_阵列原理

    基于麦克风阵列的现有声源定位技术有_阵列原理《基于麦克风阵列声源定位系统.doc》由会员分享,可免费在线阅读全文,更多与《基于麦克风阵列声源定位系统》相关文档资源请在帮帮文库(www.woc88.com)数亿文档库存里搜索。1、()cosiiiiettH,则有:cos()ex()()cosjiijijjiijretjkrretr()由于()()cos()cosex()jjijjijjjjiettHtHjkrr…

  • golang 面试题(从基础到高级)

    golang 面试题(从基础到高级)Golang面试问题汇总通常我们去面试肯定会有些不错的Golang的面试题目的,所以总结下,让其他Golang开发者也可以查看到,同时也用来检测自己的能力和提醒自己的不足之处,欢迎大家补充和提交新的面试题目.Golang面试问题汇总:1.Golang中除了加Mutex锁以外还有哪些方式安全读写共享变量?Golang中Goroutine可以通过Channel进行安全读写…

  • c语言中fprintf_c语言输出函数printf

    c语言中fprintf_c语言输出函数printf目录一.fprintf函数简介二.fprintf函数使用三.猜你喜欢零基础C/C++学习路线推荐:C/C++学习目录>>C语言基础入门一.fprintf函数简介fprintf是C/C++中的一个格式化库函数,位于头文件中,其作用是格式化输出到一个流文件中;函数原型为/**描述:fputs函数是向指定的文件写入一个字符串**参数:*[in]stream:文件指针句柄;*[in]format:格式化字符串,

    2022年10月10日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号