docker常用镜像的拉取和容器的安装
docker一、docker的安装在centos7.5的虚拟机中安装命令yum install dockerdocker的启动和关闭,重启,及状态查询systemctl status/start/stop/restart docker查看版本docker -v查看信息docker -info二、 镜像展示所有的镜像docker ima...
docker
一、docker的安装
在centos7.5的虚拟机中安装命令
yum install docker
docker的启动和关闭,重启,及状态查询
systemctl status/start/stop/restart docker
查看版本
docker -v
查看信息
docker -info
设置开机自启动docker
systemctl enable docker
查看docker的开机自启动的状态
systemctl list-unit-files | grep docker
二、 镜像
展示所有的镜像
docker images
**从网上拉镜像**
docker pull hello-world
**删除镜像**
docker rmi (端口号imageid)
镜像加速
$ docker pull registry.docker-cn.com/library/centos:7(版本这个自选)
为了永久性保留更改,您可以修改 /etc/docker/daemon.json 文件并添加上 registry-mirrors 键值。
{
"registry-mirrors": ["https://registry.docker-cn.com"]
}
这个不好用可以访问这个地址
https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
比这个快多啦
修改保存后重启 Docker 以使配置生效。
查找镜像
docker search 镜像名称
当出现一台机器能上网,一台机器不能上网,导入导出镜像
cd /home
在那个目录就会导入那个目录,导出到啦home文件夹下
docker save -o tomcat.tar docker.io/tomcat:7-jre7
拷贝到另一台机器上,取另一台机器的ip
scp ./tomcat.tar root@192.168.64.131:/home
在没有镜像的机器上可以使用tomcat.tar 镜像的压缩包执行如下命令安装镜像
docker load -i tomcat.tar
三、容器
查看docker所运行的容器
docker ps -a
通过镜像安装交互容器
docker run -i -t --name mycentos centos:7 /bin/bash
退出 exit
通过镜像安装守护式容器
docker run -i -d --name mycentos1 centos:7
进入容器
docker exec -i -t mycentos1 /bin/bash
使用退出exit 但是容器并没有退出,真正的关闭要写
docker stop mycentos1
开启容器
docker start 容器名称/container id
docker exec -i -t mycentos1 /bin/bash
删除容器
docker rm mycentos
删除所有的容器(注意不是rmi,加i就是删除镜像)
docker rm `docker ps -a`
这个也行
docker rm `docker ps -a -q`
拷贝
将宿主机中的文件传到容器为mycentos1的home文件夹下
docker cp 1.txt mycentos1:/home
将mycentos容器中的Hi.txt拷贝到宿主机的home文件夹下
docker cp mycentos:/home/Hi.txt /home
共享
docker run -di -v /home/a:/home/ --name =mycentos2 --privileged=true centos:7
一台机器能上网,一台机器不能上网如何在不能联网的机器怎么使用镜像?
在有镜像的机器上做如下操作
cd /home
把镜像导出到home文件夹下
docker save -o tomcat.tar docker.io/tomcat:7-jre7
操作之后在,home文件夹下就会出现 tomcat.tar文件做如下操作
不能联网机器的ip
scp ./tomcat.tar root@192.168.15.39:/home
在新机器上做如下操作
cd /home
导入镜像
docker load -i tomcat.tar
创建tomcat容器
docker run -i -d --name mytomcat1 -p 8081:8080 镜像的imageid
四、MySQL
安装mysql镜像
docker pull mysql
安装mysql的容器
docker run -di --name mysql_easybuy -p 3307:3306 -e MYSQL_ROOT_PASSWORD=root mysql
注意这样写window下的mysql访问的端口号是3307
进入到mysql的容器中
docker exec -i -t mysql_easybuy /bin/bash
如果进入到mysql中发现出现中文?则使用下列命令进入
docker exec -it mysql_test env LANG=C.UTF-8 bash
进入到mysql里
mysql -u root -p
默认没有放开root的远程登录权限权限 要放开,执行下列代码,否则链接报错
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root';
链接window下的数据库
察看ip(要退出mysql再察看)
内容较多
docker inspect mysql_easybuy;
只察看ip地址
docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql_easybuy;
五、Tomcat
一、安装tomcat
第一种
docker install tomcat
第二种:详情看容器版本末尾
二、创建tomcat容器
window下访问8080
docker run -i -d --name mytomcat1 -p 8081:8080 镜像的imageid
三、问题解决如果出现404
使用docker exec -it b6a955c3cbea /bin/bash命令进入tomcat目录,查看目录信息:
发现webapps为空,tomcat的默认项目资源都在webapps.dist文件夹下
将webapps删除,将webapps.dist重命名为webapps
docker exec -it b6a955c3cbea /bin/bash
rm -rf webaps
mv webapps.dist/ webapps
四、一个镜像产生多个容器问题
1)首先产生三个tomcat容器
docker run -i -d --name mytomcat1 -p 8081:8080 f43f44c16fb0
docker run -i -d --name mytomcat2 -p 8082:8080 f43f44c16fb0
docker run -i -d --name mytomcat3 -p 8083:8080 f43f44c16fb0
(2)察看tomcat的容器的ip地址
docker inspect mytomcat1 |grep IPAddress
发现ip地址按启动顺序自动递增分配
如果想自定义分配需要创建定义网络
****(1)这个老师视频有问题得问
六、如何利用docker在linux上部署项目
修改database.配置文件的ip地址
1.首先进入到mysql的容器当中查看mysql的对应的id地址
docker exec -i -t mysql_easybuy /bin/bash
docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql_easybuy;
2.在war包中修改WEB-INF下的classes文件下的database.properties文件夹下的url 地址使用的是mysql的ip地址,端口号使用的是创建mysql的容器时指定的端口号
3.将war包导入到linux中的home文件夹下面,再移动到tomcat容器中的webapps文件夹下面
rz
docker cp /home/EasyBuy.war mytomcat1:/usr/local/tomcat/webapps
4.将对应项目的sql文件,上传到home文件夹下面,再将文件通过命令转入到mysql的容器中的home文件夹下面
rz
docker cp /home/easybuy.sql mysql_easybuy:/home
5.在mysql的容器中首先,创建一个同名数据库,再通过命令将容器中的home文件夹使用
create database easybuy
注意在mysql的文件夹下使用
mysql> source /home/easybuy.sql;
6.在浏览器中访问改linux的ip地址tomcat的端口号+项目名称即可
七、 docker 下面的redis的使用
拉取redis的镜像
docker pull redis
创建redis的容器
docker run -i -d --name redis -p 6379:6379 redis
进入到redis容器中
docker exec -i -t redis /bin/bash
在redis容器中查看redis的默认IP地址和端口号以及进入到redis的客户端上
redis-cli
在redis的客户端上测试redis是否启动
127.0.0.1:6379> ping
在客户端中使用set,get等基础语法
set name jss
get name
在idea中使用redis Nosql技术创建项目步骤
1.创建Spring Initializr 选择Web下面的SpirngWeb 和NoSQL下面的 Spring Data Redis(Access+Driver)
2.在application.propertites的配置文件中进行如下的配置
spring.redis.host= 192.168.64.132
spring.redis.port = 6379
**3.在测试类中进行操作使java代码链接redis缓存 **
package com.hdax.redis02;
import com.hdax.redis02.entity.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.*;
@SpringBootTest
class Redis02ApplicationTests {
//redisTemplate可以操作所有的数据类型 list/set/ String
@Autowired
private RedisTemplate redisTemplate;
@Test
public void setFunction(){
redisTemplate.opsForValue().set("sex","女");
}
@Test
public void getFunction(){
String sex = (String)redisTemplate.opsForValue().get("sex");
System.out.println(sex);
}
@Test
public void setObject(){
User user =new User();
user.setId(12);
user.setName("jss");
//想redis服务器存放对象的时,默认使用的jdk的序列化器
redisTemplate.opsForValue().set("u",user);
}
@Test
public void getObject(){
User u = (User)redisTemplate.opsForValue().get("u");
System.out.println(u.getId()+"--"+u.getName());
/* Object user = redisTemplate.opsForValue().get("u");
User t = (User) JSON.toJavaObject((JSON) user, User.class);
System.out.println(t.getId() + " -- " + t.getName());*/
}
@Test
public void testHasKey(){
Boolean flag = redisTemplate.hasKey("u");
System.err.println(flag);
}
@Test
public void testOBjectList(){
User user =new User();
user.setName("zs");
user.setId(1);
User user1 =new User();
user1.setName("zs");
user1.setId(1);
List<User> list =new ArrayList<>();
list.add(user);
list.add(user1);
redisTemplate.opsForValue().set("ulist",list);
}
@Test
public void testGetObjectList(){
List<User> list = (List<User>)redisTemplate.opsForValue().get("ulist");
for(User u:list){
System.out.println(u.getId()+"---"+u.getName());
}
}
@Test
//如果出现不能转换为user对象的时候要使用这中形式
public void testGetObject1(){
LinkedHashMap t = (LinkedHashMap) redisTemplate.opsForValue().get("user") ;
Set<Map.Entry<String,Object>> set = t.entrySet() ;
for(Map.Entry entry :set){
System.out.println(entry.getKey() + " -- " + entry.getValue());
}
}
@Test
void contextLoads() {
}
}
(4)也有专用的处理字符串的对象stringRedisTemplated
/**
* Copyright (C), 2020, Y2 T205
* FileName: StringRedisTemplateTest
* Author: Lenovo
* Date: 2020-04-22 17:50
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.hdax.redis02;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author Lenovo
* @create 2020-04-22
* @since 1.0.0
*/
@SpringBootTest
public class StringRedisTemplateTest {
//这个对象可防止在存入string类型的值时,在redis desktop manager 中乱码的情况,但不能对对象进行操作
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testSetString(){
stringRedisTemplate.opsForValue().set("lastname","姬少帅");
}
@Test
public void testGetString(){
String lastname = stringRedisTemplate.opsForValue().get("lastname");
System.err.println("我的名字时"+lastname);
}
}
(5)重写redistemplate对象,好处是<Object,Object>转化为<Stirng,Object>减少类型转换的操作,Object ->json,两种手段使用fastjson和自带的springboot自带的jackson,这回使用jackson在项目中引入RedisConfig类
package com.hdax.redis02.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.*;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
/**
* redis配置类
*/
@Configuration
@EnableCaching //开启注解
public class RedisConfig extends CachingConfigurerSupport {
/**
* retemplate相关配置
* @param factory
* @return
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer jacksonSeial = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jacksonSeial.setObjectMapper(om);
// 值采用json序列化
template.setValueSerializer(jacksonSeial);
//使用StringRedisSerializer来序列化和反序列化redis的key值
template.setKeySerializer(new StringRedisSerializer());
// 设置hash key 和value序列化模式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(jacksonSeial);
template.afterPropertiesSet();
return template;
}
/**
* 对hash类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public HashOperations<String, String, Object> hashOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForHash();
}
/**
* 对redis字符串类型数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ValueOperations<String, Object> valueOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForValue();
}
/**
* 对链表类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ListOperations<String, Object> listOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForList();
}
/**
* 对无序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public SetOperations<String, Object> setOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForSet();
}
/**
* 对有序集合类型的数据操作
*
* @param redisTemplate
* @return
*/
@Bean
public ZSetOperations<String, Object> zSetOperations(RedisTemplate<String, Object> redisTemplate) {
return redisTemplate.opsForZSet();
}
}
(6)封装redistemplate的操作
创建一个util包下面的
package com.hdax.redis02.util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* redisTemplate封装
*
* @author david
*/
@Component
public class RedisUtil {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
public RedisUtil(RedisTemplate<String, Object> redisTemplate) {
this.redisTemplate = redisTemplate;
}
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
* @return
*/
public boolean expire(String key,long time){
try {
if(time>0){
redisTemplate.expire(key, time, TimeUnit.SECONDS);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据key 获取过期时间
* @param key 键 不能为null
* @return 时间(秒) 返回0代表为永久有效
*/
public long getExpire(String key){
return redisTemplate.getExpire(key,TimeUnit.SECONDS);
}
/**
* 判断key是否存在
* @param key 键
* @return true 存在 false不存在
*/
public boolean hasKey(String key){
try {
return redisTemplate.hasKey(key);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除缓存
* @param key 可以传一个值 或多个
*/
@SuppressWarnings("unchecked")
public void del(String ... key){
if(key!=null&&key.length>0){
if(key.length==1){
redisTemplate.delete(key[0]);
}else{
redisTemplate.delete(CollectionUtils.arrayToList(key));
}
}
}
//============================String=============================
/**
* 普通缓存获取
* @param key 键
* @return 值
*/
public Object get(String key){
return key==null?null:redisTemplate.opsForValue().get(key);
}
/**
* 普通缓存放入
* @param key 键
* @param value 值
* @return true成功 false失败
*/
public boolean set(String key,Object value) {
try {
redisTemplate.opsForValue().set(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 普通缓存放入并设置时间
* @param key 键
* @param value 值
* @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期
* @return true成功 false 失败
*/
public boolean set(String key,Object value,long time){
try {
if(time>0){
redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);
}else{
set(key, value);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 递增
* @param key 键
* @param delta 要增加几(大于0)
* @return
*/
public long incr(String key, long delta){
if(delta<0){
throw new RuntimeException("递增因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, delta);
}
/**
* 递减
* @param key 键
* @param delta 要减少几(小于0)
* @return
*/
public long decr(String key, long delta){
if(delta<0){
throw new RuntimeException("递减因子必须大于0");
}
return redisTemplate.opsForValue().increment(key, -delta);
}
//================================Map=================================
/**
* HashGet
* @param key 键 不能为null
* @param item 项 不能为null
* @return 值
*/
public Object hget(String key,String item){
return redisTemplate.opsForHash().get(key, item);
}
/**
* 获取hashKey对应的所有键值
* @param key 键
* @return 对应的多个键值
*/
public Map<Object,Object> hmget(String key){
return redisTemplate.opsForHash().entries(key);
}
/**
* HashSet
* @param key 键
* @param map 对应多个键值
* @return true 成功 false 失败
*/
public boolean hmset(String key, Map<String,Object> map){
try {
redisTemplate.opsForHash().putAll(key, map);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* HashSet 并设置时间
* @param key 键
* @param map 对应多个键值
* @param time 时间(秒)
* @return true成功 false失败
*/
public boolean hmset(String key, Map<String,Object> map, long time){
try {
redisTemplate.opsForHash().putAll(key, map);
if(time>0){
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
* @param key 键
* @param item 项
* @param value 值
* @return true 成功 false失败
*/
public boolean hset(String key,String item,Object value) {
try {
redisTemplate.opsForHash().put(key, item, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 向一张hash表中放入数据,如果不存在将创建
* @param key 键
* @param item 项
* @param value 值
* @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间
* @return true 成功 false失败
*/
public boolean hset(String key,String item,Object value,long time) {
try {
redisTemplate.opsForHash().put(key, item, value);
if(time>0){
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除hash表中的值
* @param key 键 不能为null
* @param item 项 可以使多个 不能为null
*/
public void hdel(String key, Object... item){
redisTemplate.opsForHash().delete(key,item);
}
/**
* 判断hash表中是否有该项的值
* @param key 键 不能为null
* @param item 项 不能为null
* @return true 存在 false不存在
*/
public boolean hHasKey(String key, String item){
return redisTemplate.opsForHash().hasKey(key, item);
}
/**
* hash递增 如果不存在,就会创建一个 并把新增后的值返回
* @param key 键
* @param item 项
* @param by 要增加几(大于0)
* @return
*/
public double hincr(String key, String item,double by){
return redisTemplate.opsForHash().increment(key, item, by);
}
/**
* hash递减
* @param key 键
* @param item 项
* @param by 要减少记(小于0)
* @return
*/
public double hdecr(String key, String item,double by){
return redisTemplate.opsForHash().increment(key, item,-by);
}
//============================set=============================
/**
* 根据key获取Set中的所有值
* @param key 键
* @return
*/
public Set<Object> sGet(String key){
try {
return redisTemplate.opsForSet().members(key);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 根据value从一个set中查询,是否存在
* @param key 键
* @param value 值
* @return true 存在 false不存在
*/
public boolean sHasKey(String key,Object value){
try {
return redisTemplate.opsForSet().isMember(key, value);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将数据放入set缓存
* @param key 键
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSet(String key, Object...values) {
try {
return redisTemplate.opsForSet().add(key, values);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 将set数据放入缓存
* @param key 键
* @param time 时间(秒)
* @param values 值 可以是多个
* @return 成功个数
*/
public long sSetAndTime(String key,long time,Object...values) {
try {
Long count = redisTemplate.opsForSet().add(key, values);
if(time>0) {
expire(key, time);
}
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 获取set缓存的长度
* @param key 键
* @return
*/
public long sGetSetSize(String key){
try {
return redisTemplate.opsForSet().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 移除值为value的
* @param key 键
* @param values 值 可以是多个
* @return 移除的个数
*/
public long setRemove(String key, Object ...values) {
try {
Long count = redisTemplate.opsForSet().remove(key, values);
return count;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
//===============================list=================================
/**
* 获取list缓存的内容
* @param key 键
* @param start 开始
* @param end 结束 0 到 -1代表所有值
* @return
*/
public List<Object> lGet(String key, long start, long end){
try {
return redisTemplate.opsForList().range(key, start, end);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 获取list缓存的长度
* @param key 键
* @return
*/
public long lGetListSize(String key){
try {
return redisTemplate.opsForList().size(key);
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
/**
* 通过索引 获取list中的值
* @param key 键
* @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推
* @return
*/
public Object lGetIndex(String key,long index){
try {
return redisTemplate.opsForList().index(key, index);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, Object value) {
try {
redisTemplate.opsForList().rightPush(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, Object value, long time) {
try {
redisTemplate.opsForList().rightPush(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @return
*/
public boolean lSet(String key, List<Object> value) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 将list放入缓存
* @param key 键
* @param value 值
* @param time 时间(秒)
* @return
*/
public boolean lSet(String key, List<Object> value, long time) {
try {
redisTemplate.opsForList().rightPushAll(key, value);
if (time > 0) {
expire(key, time);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据索引修改list中的某条数据
* @param key 键
* @param index 索引
* @param value 值
* @return
*/
public boolean lUpdateIndex(String key, long index,Object value) {
try {
redisTemplate.opsForList().set(key, index, value);
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 移除N个值为value
* @param key 键
* @param count 移除多少个
* @param value 值
* @return 移除的个数
*/
public long lRemove(String key,long count,Object value) {
try {
Long remove = redisTemplate.opsForList().remove(key, count, value);
return remove;
} catch (Exception e) {
e.printStackTrace();
return 0;
}
}
}
测试类
/**
* Copyright (C), 2020, Y2 T205
* FileName: RedisUtilTest
* Author: Lenovo
* Date: 2020-04-22 20:16
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.hdax.redis02;
import com.hdax.redis02.util.RedisUtil;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author Lenovo
* @create 2020-04-22
* @since 1.0.0
*/
@SpringBootTest
public class RedisUtilTest {
@Autowired
private RedisUtil redisUtil;
@Test
public void testhaskey(){
boolean flag = redisUtil.hasKey("sex");
System.out.println(flag);
}
}
八、 redis gui 可视化界面 partainer
(1)安装docker中的protainer镜像
docker pull docker.io/portainer/portainer
(2)配置加速器
vi /etc/docker/daemon.json
“hosts”: [“tcp://127.0.0.1:2375”, “unix:///var/run/docker.sock”]
(3)重启docker服务
systemctl restart docker
(4)创建容器
docker volume create partiner_db
(5)进入容器
docker run -d -p 9000:9000 --restart=always -v /var/run/docker.sock:/var/run/docker.sock --name portainer --privileged=true docker.io/portainer/portainer
(6)浏览器访问
192.168.64.132:9000/
账号:admin
密码:12345678
九、 elasticsearch的安装与使用
1.搜索镜像
docker search elasticsearch
2.拉取镜像
这个版本要依据创建springboot项目中的依赖所决定的版本要一致
docker pull elasticsearch:6.8.7
3.因为需要的内存和资源多,所以要重新设置虚拟机的cpu核心和内存
分配内存太小,需要将vm.max_map_count的值调大,网上查资料,得知用命令的方式来设置vm.max_map_count,命令如下:
sysctl -w vm.max_map_count=262144
查看vm.max_map_count命令:
sysctl -a|grep vm.max_map_count
但是以上方法在重启虚拟机之后就不生效,如果想要一直生效的话,到 /etc目录下编辑sysctl.conf文件,添加vm.max_map_count=262144就可以了
vi /etc/sysctl.conf
保存文件之后用sysctl -a|grep vm.max_map_count命令查看,显示的还是修改之前的值,此时需要重启虚拟机才能生效
4 安装elasticsearch容器
docker run -d --name=elasticsearch -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -p 9200:9200 -p 9300:9300 9cdc9986c313
5 访问地址
http://192.168.64.132:9200/
6 文档
/{index}/{type}/{id}
每个属性相当于
index: mysql
type:mysql中的表
id: 相当于表的主键
7.放入一个文档
使用postman软件 (红色字体的text可以换成json)
(1)使用id号,使用put请求
(2)不使用id号添加,用post请求
8.取出一个文档
(1)加上一个pretty参数使出来的数据更方便可读
(2)source参数使的打印出源码
(3)检查文档是否存在
如果只想检查一个文档是否存在–根本不想关心内容—那么用 HEAD 方法来代替 GET 方法。 HEAD 请求没有返回体,只返回一个 HTTP 请求报头:
curl -i -XHEAD http://localhost:9200/website/blog/123
(4)更新文档
(5)创建新文档
第二种方法是在 URL 末端使用 /_create :
PUT /website/blog/123/_create
{ … }
如果创建新文档的请求成功执行,Elasticsearch 会返回元数据和一个 201 Created 的 HTTP 响应码。
(6)删除文档
(7)java代码与elasticsearch项目的整合
1.创建一个springboot的web项目,首先在pom.xml中加入elasticsearch的依赖
<!--加入elasticsearch的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2.application.yml的配置
server.port=8082
#spring.elasticsearch.jest.uris=http://192.168.15.15:9200
#spring.data.elasticsearch.cluster-name=elasticsearch
#spring.data.elasticsearch.cluster-nodes=192.168.15.15:9300
#spring.elasticsearch.rest.uris=http://192.168.15.15:9200
spring.data.elasticsearch.cluster-name=docker-cluster
spring.data.elasticsearch.cluster-nodes=192.168.64.132:9300
3.创建一个bean下面的Book实体类 **注意使用注解@Document
**
/**
* Copyright (C), 2020, Y2 T205
* FileName: Book
* Author: Lenovo
* Date: 2020-04-27 16:53
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.hdax.springbootandelasticsearch.bean;
import org.springframework.data.elasticsearch.annotations.Document;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author Lenovo
* @create 2020-04-27
* @since 1.0.0
*/
@Document(indexName ="hdax",type ="book")
public class Book {
private Integer id;
private String bookName;
private String author;
public Book() {
}
public Book(Integer id, String bookName, String author) {
this.id = id;
this.bookName = bookName;
this.author = author;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
- 创建repository包,在下面创建BookRepository的接口
/**
* Copyright (C), 2020, Y2 T205
* FileName: BookRespository
* Author: Lenovo
* Date: 2020-04-27 16:57
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.hdax.springbootandelasticsearch.Repository;
import com.hdax.springbootandelasticsearch.bean.Book;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author Lenovo
* @create 2020-04-27
* @since 1.0.0
*/
public interface BookRespository extends ElasticsearchRepository<Book,Integer> {
//public List<Book> findByBookNameLike(String bookName);
}
5、测试类
package com.hdax.springbootandelasticsearch;
import com.hdax.springbootandelasticsearch.Repository.BookRespository;
import com.hdax.springbootandelasticsearch.bean.Book;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
@SpringBootTest
class SpringbootandelasticsearchApplicationTests {
@Test
void contextLoads() {
}
@Resource
private BookRespository bookRespository;
@Test
public void test1(){
Book b=new Book();
b.setId(1);
b.setAuthor("jss");
b.setBookName("dsafd");
bookRespository.save(b);
}
}
6.在postman中访问,得到数据 如果访问第二个加入的数据,把1改为2
十 、 kibana的安装与使用
- 安装(注意版本要和elasticsearch的版本保持一致)
docker pull kibana:6.8.7
2 创建容器
docker run --link elasticsearch:elasticsearch -d --name kibana -p 5601:5601 kibana:6.8.7
3 浏览器访问 http://192.168.64.132:5601/
4.在Dev Tools 模块中写
GET /hdax/book/1/_source
GET /hdax/book/2/_source
就可以得到相应的数据
获取所有数据:
GET /_search
创建数据
PUT /ecommerce/product/1
{
"name" : "gaolujie yagao",
"desc" : "gaoxiao meibai",
"price" : 30,
"producer" : "gaolujie producer",
"tags": [ "meibai", "fangzhu" ]
}
PUT /ecommerce/product/2
{
"name" : "jiajieshi yagao",
"desc" : "youxiao fangzhu",
"price" : 25,
"producer" : "jiajieshi producer",
"tags": [ "fangzhu" ]
}
PUT /ecommerce/product/3
{
"name" : "zhonghua yagao",
"desc" : "caoben zhiwu",
"price" : 40,
"producer" : "zhonghua producer",
"tags": [ "qingxin" ]
}
进行crud
#2.查询
GET /ecommerce/product/2
#3.覆盖,替换文档(全量替换)
PUT /ecommerce/product/1
{
"name" : "jiaqiangban gaolujie yagao",
"desc" : "gaoxiao meibai",
"price" : 30,
"producer" : "gaolujie producer",
"tags" : [ "meibai" , "fangzhu" ]
}
注意:1.document是不可变的,如果要修改document的内容,可以通过全量替换,直接对document
重新建立索引,替换里面所有的内容。
2.es会将老的document标记为deleted(逻辑删除),然后新增我们给定的一个document,当我们
创建越来越多的document的时候,es会在适当的时机在后台自动删除(物理删除)标记为deleted
的document。
3.替换必须带上所有的field,否则其他数据会丢失。
#4.修改(更新文档)
POST /ecommerce/product/1/_update
{
"doc" : {
"name" : "jiaqianban gaolujie yagao1"
}
}
#5.删除文档
DELETE /ecommerce/product/2
注意:在删除一个document之后,我们可以从侧面证明,它不是立即物理删除的,因为它的一些版本号信息还是保留的
#6.使用query DSL 请求查询
GET /ecommerce/product/_search
{
"query" : {
"match_all" : {}
}
}
#6.1查询名称包含yaogao的商品,同时按照价格降序排列
这里刚开始可能报错说需要把fileddata设置为true,解决方案如下 注意这个price是要进行分组的字段
PUT /ecommerce/_mapping/product
{
"properties": {
"price":{
"type": "text",
"fielddata": true
}
}
}
GET /ecommerce/product/_search
{
"query" : {
"match" : {
"name" : "yagao"
}
},
"sort" : [
{ "price" : "desc"}
]
}
#6.2分页查询
#总共3条商品,假设每页就显示1条商品,现在显示第2页,所以就查出来第2个商品
GET /ecommerce/product/_search
{
"query" : { "match_all" : {}},
"from" : 1,
"size" : 1
}
#6.3指定查询项
GET /ecommerce/product/_search
{
"query" : {"match_all" : {}},
"_source" : ["name", "price"]
}
#6.4过滤查询
#搜索商品名称包含yaogao,而且售价大于25元的商品
GET /ecommerce/product/_search
{
"query" : {
"bool" : {
"must" : {
"match" : {
"name" : "yagao"
}
},
"filter" : {
"range" : {
"price": {"gt" : 25}
}
}
}
}
}
#7.ull-text search(全文检索)
GET /ecommerce/product/_search
{
"query" : {
"match" : {
"producer": "yagao producer"
}
}
}
#8.phrase search(短语搜索)
GET /ecommerce/product/_search
{
"query" : {
"match_phrase" : {
"producer" : "yagao producer"
}
}
}
#9.多条件查询
#名字中有"yagao",描述上可以有fangzhu也可以没有,价格不能是25元
GET /ecommerce/_search
{
"query" : {
"bool" : {
"must" : [
{
"match" : {
"name" : "yagao"
}
}
],
"should" : [
{
"match" : {
"desc" : "fangzhu"
}
},
{
"match" : {
"desc" : "caoben"
}
}
],
"must_not" : [
{
"match" : {
"price" :25
}
}
],
"minimum_should_match" : 1
}
}
}
在以上的实例中:
从第六条开始需要做出的补充:
两种请求分类:query string search / query DSL
第一种:类似搜索全部商品: GET /ecommerce/product/_search (参数直接拼接在请求上,不带json参数的)
query string search的由来,因为search参数都是以http请求的query string来附带的。
搜索商品名称中包含yagao的商品,而且按照售价降序排列:
GET /ecommerce/product/_search?q=name:yagao&sort=price:desc
适用于临时的在命令行使用一些工具,比如curl,快速的发出请求,来检索想要的信息;但是
如果查询请求很复杂,是很难去构建的,所以在生产环境中,几乎很少使用query string search。
第二种:DSL:Domain Specified Language,特定领域的语言
http request body:请求体,可以用json的格式来构建查询语法,比较方便,可以构建各种复杂的语法,
比query string search肯定强大太多了。
full-text search 全文检索)和 phrase search(短语搜索)的区别:
全文检索:会将输入的搜索串拆解开来,去索引里面去一一匹配,只要能匹配任意一个拆解后的单词,就可以作为结果返回。
phrase search: 要求输入的搜索串,必须在指定的字段文本中,完全包含一模一样的,才可以算匹配成功,才能作为结果返回。
多条件查询中的字段描述:
must: 表示一定要满足;
should: 表示可以满足也可以不满足;
must_not: 表示不能满足该条件;
minimum_should_match:1 :表示最小匹配度,可以设置为百分之百,设置了这个值的时候就必须满足should里面的设置了,
另外注意这边should里面同一字段设置的多个值,意思是当这个值等于X或者等于Y都成立,务必注意格式。
十一、Rabbitmq的安装与使用
1.安装镜像
docker pull rabbitmq:3.6-management
2.创建容器
docker run -i -d -p 5672:5672 -p 15672:15672 --name myr1 9df8e9792ce6
服务器是5672 管理页面时15672
3.在浏览器中访问
http://192.168.64.132:15672/
账号 guest 密码 guest
4.新建队列
5.创建交换机
创建交换机的四种方式以及区别
第一种,以direct的方式创建,规则是“先匹配,在投送”,即在绑定的时候设置一个routing key,消息的routing_key 匹配是,才会被交换器投送到绑定的队列中,在绑定队列的时候需要在routingkey中写值 就是点对点,发送到对应的一个队列一次,相应的队列接受一次
绑定队列
通过转换器发送消息
第二种,Fanout 转发消息到所有绑定的队列中去,这个就是在绑定队列的时候不用填写routingkey的值,发送一次,绑定的所有的队列都会接受,不用重复发送
第三种,topic创建 按照规则转发消息也就是routingkey中可以写*或者.来表示相应的字段
绑定队列
- *代表任意一个词
- #代表任意多个词
发送消息
第四种,Headers的创建,设置header attribute 参数类型的交换机
6.使用java代码控制mq
第一种,使用的交换器的类型是direct
(1)创建springboot的空项目 (rabbitmq)这个是发消息的项目
(2)引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
(3)创建配置文件application.properties
spring.rabbitmq.host = 192.168.64.132
spring.rabbitmq.username = guest
spring.rabbitmq.password= guest
(4)测试类中写
package com.hdaccp.rabbitmq;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.HashMap;
import java.util.Map;
@SpringBootTest
class RabbitmqApplicationTests {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
}
@Test
public void send(){
Map<String,Object> map =new HashMap<>();
map.put("msg","第一个消息");
rabbitTemplate.convertAndSend("c1","q3",map);
}
}
(5)重复123步骤再创建一个springboot项目(rabbitmq2) 接受消息 ,注意接受消息后队列中的消息信息会被消耗
(6)测试类中的写法
package com.hdaccp.rabbitmq2;
import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Map;
@SpringBootTest
class Rabbitmq2ApplicationTests {
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
void contextLoads() {
}
@Test
public void receive(){
Object q3 = rabbitTemplate.receiveAndConvert("q3");
Map<String,Object> map =(Map<String,Object>) q3;
System.out.println(map.get("msg"));
}
}
7.如果需要让发送的信息在,rabbitmq客户端上显示的是中文,需要进行以下配置
(1)在项目的依赖中添加web依赖,因为其中包含jackson的依赖
<!--如果想要在rabbitmq的控制器中队列显示的消息不是java序列化的乱码,而是json的形式,需要使用jkson的,而json在web的依赖里面-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
(2) 创建一个配置文件类,将转换模式转化为jackson的转化模式
/**
* Copyright (C), 2020, Y2 T205
* FileName: JsonConfig
* Author: Lenovo
* Date: 2020-04-30 9:46
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.hdaccp.rabbitmq.config;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author Lenovo
* @create 2020-04-30
* @since 1.0.0
*/
@Configuration
public class JsonConfig {
@Bean
public MessageConverter messageConverter(){
return new Jackson2JsonMessageConverter();
}
}
(3)执行相应的发送代码,会在客户端中显示成json的格式
8 信息监听器 让信息发过来就能被监听或者接受到
(1)在发送的项目(rabbitmq)中把,config的那个文件注释掉 @configuration @bean,不注释,就会因为转换问题报错
(2) 在接受的项目中(rabbitmq2)依赖中添加web依赖,引入jackson
<!--如果想要在rabbitmq的控制器中队列显示的消息不是java序列化的乱码,而是json的形式,需要使用jkson的,而json在web的依赖里面-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
(3)在项目中启动类中添加注解
package com.hdaccp.rabbitmq2;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableRabbit
@SpringBootApplication
public class Rabbitmq2Application {
public static void main(String[] args) {
SpringApplication.run(Rabbitmq2Application.class, args);
}
}
(4)建立一个service包下的myservice类
/**
* Copyright (C), 2020, Y2 T205
* FileName: MyService
* Author: Lenovo
* Date: 2020-04-30 10:04
* Description:
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.hdaccp.rabbitmq2.service;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;
import java.util.HashMap;
/**
* 〈一句话功能简述〉<br>
* 〈〉
*
* @author Lenovo
* @create 2020-04-30
* @since 1.0.0
*/
@Service
public class MyService {
@RabbitListener(queues = "q3")
public void receive(HashMap<String,Object> map){
System.out.println(map.get("msg")+"---");
}
}
(5)运行接受项目可以监听传递过来的数据信息
第二种,使用的交换器的类型是Fanout
(1)在发送的测试类中写
@Test
public void sendFanout(){
Map<String,Object> map =new HashMap<>();
map.put("msg","第一个消息");
rabbitTemplate.convertAndSend("c2",null,map);
}
(2) 在接受的myservice这个类中添加监听
@RabbitListener(queues = "q2")
public void receiveQ2(HashMap<String,Object> map){
System.out.println(map.get("msg")+"---");
}
@RabbitListener(queues = "q1")
public void receiveQ1(HashMap<String,Object> map){
System.out.println(map.get("msg")+"---");
}
(3)启动接受的信息的项目启动监听
第三种,使用的交换器的类型是topic的
(1)在发送的测试类中写
@Test
public void sendTopic(){
Map<String,Object> map =new HashMap<>();
map.put("msg","发送topic的消息");
rabbitTemplate.convertAndSend("c3","q1.adsfa.adsfa",map);
rabbitTemplate.convertAndSend("c3","x.q2",map);
}
9. 发送对象
更多推荐
所有评论(0)