• docker方式启动一个java项目-Nginx本地有代码,并配置反向代理


    案例导入说明

    导入一个现成的IDEA项目工程,但是利用Docker从0开始配置环境,最终达到项目成功运行的目的

    此外,我们导入的是一个商品管理的案例,其中包含商品的CRUD功能。我们将来会给查询商品添加多级缓存。
    也即本项目可以用于演示多级缓存。

    1.安装MySQL

    后期做数据同步需要用到MySQL的主从功能,所以需要在虚拟机中,利用Docker来运行一个MySQL容器。

    1.1.准备目录

    为了方便后期配置MySQL,我们先准备两个目录,用于挂载容器的数据和配置文件目录:

    # 进入/tmp目录
    cd /tmp
    # 创建文件夹
    mkdir mysql
    # 进入mysql目录
    cd mysql
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    1.2.运行命令

    进入mysql目录后,执行下面的Docker命令

    注意之前别忘了先启动docker

    systemctl start docker
    
    • 1
    docker run \
     -p 3306:3306 \
     --name mysql \
     -v $PWD/conf:/etc/mysql/conf.d \
     -v $PWD/logs:/logs \
     -v $PWD/data:/var/lib/mysql \
     -e MYSQL_ROOT_PASSWORD=1234 \
     --privileged \
     -d \
     mysql:5.7.25
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    docker run 创建一个新容器,并运行他
    --name 给容器取个名字 (此处给容器取名就叫mysql)
    -d 后面接一个镜像名称 表示根据哪个镜像创建新容器
    -p 宿主机端口:容器端口 隔离容器配置绑定端口,否则访问不了
    -v 本地目录:容器内的目录 本地数据卷挂载到容器内的数据卷上

    1.3.修改配置

    在/tmp/mysql/conf目录添加一个my.cnf文件,作为mysql的配置文件:

    # 创建文件
    touch /tmp/mysql/conf/my.cnf
    
    • 1
    • 2

    文件的内容如下:

    [mysqld]
    skip-name-resolve
    character_set_server=utf8
    datadir=/var/lib/mysql
    server-id=1000
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.4.重启

    配置修改后,必须重启容器:

    docker restart mysql
    
    
    • 1
    • 2

    上面给容器取了名字的好处,这里可以直接使用name启动容器,而非容器id(需要docker ps 或者docker ps -a查一下,比较麻烦)
    注意是docker start 不是docker run(创建并运行容器)

    查看:

    docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Image}}\t{{.Status}}"
    
    • 1

    在这里插入图片描述
    进入容器登陆看看:

    docker exec -it mysql bash
    mysql -uroot -p1234
    show databases;
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    在这里插入图片描述

    宿主机无法直接登陆mysql,做了隔离了,找不到该进程:
    在这里插入图片描述

    2.导入SQL

    接下来,利用Navicat客户端连接MySQL,然后导入资料提供的sql文件:

    链接:https://pan.baidu.com/s/1dv6ydcwaum3tXRnqmCNxmA
    提取码:hzan

    在这里插入图片描述

    其中包含两张表:

    • tb_item:商品表,包含商品的基本信息
    • tb_item_stock:商品库存表,包含商品的库存信息

    之所以将库存分离出来,是因为库存是更新比较频繁的信息,写操作较多。而其他信息修改的频率非常低。

    1. 先创建数据库
      在这里插入图片描述
    2. 导入数据
      在这里插入图片描述

    在这里插入图片描述

    3.导入Demo工程

    下面导入资料提供的工程:

    在这里插入图片描述

    项目结构如图所示:

    在这里插入图片描述

    其中的业务包括:

    • 分页查询商品
    • 新增商品
    • 修改商品
    • 修改库存
    • 删除商品
    • 根据id查询商品
    • 根据id查询库存

    业务全部使用mybatis-plus来实现,如有需要请自行修改业务逻辑。

    3.1.分页查询商品(仔细看代码,很多新的MP编程技巧)

    cn.whu.item.web包的ItemController中可以看到接口定义:

    @GetMapping("list")
    public PageDTO queryItemPage(
            @RequestParam(value = "page", defaultValue = "1") Integer page,
            @RequestParam(value = "size", defaultValue = "5") Integer size){
            // 一般名称不一致或者需要设置默认值时,才需要用到@RequestParam注解
            // 此注解是接受url参数的  value是前端的name值,映射到后面变量里面 (一般name和形参名不一致时才需要指定)
            // 当然,还可以设置默认值 如此处的defaultValue
        // 分页查询商品
        Page<Item> result = itemService.query() //用query方法,链式编程,好处:不用写lambda条件了
                .ne("status", 3)
                .page(new Page<>(page, size));
    
        // 查询库存
        List<Item> list = result.getRecords().stream().peek(item -> {
            ItemStock stock = stockService.getById(item.getId());
            item.setStock(stock.getStock());
            item.setSold(stock.getSold());//库存和余量在另一张表 需要一个个查出来然后设置
        }).collect(Collectors.toList());
    
        // 封装返回
        return new PageDTO(result.getTotal(), list);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3.2.新增商品

    cn.whu.item.web包的ItemController中可以看到接口定义:

    在这里插入图片描述

    3.3.修改商品

    cn.whu.item.web包的ItemController中可以看到接口定义:

    在这里插入图片描述

    3.4.修改库存

    cn.whu.item.web包的ItemController中可以看到接口定义:

    在这里插入图片描述

    3.5.删除商品

    cn.whu.item.web包的ItemController中可以看到接口定义:

    逻辑删除,修改状态为3 (MP内部有这个机制呀,这里竟然没用)

    在这里插入图片描述

    这里是采用了逻辑删除,将商品状态修改为3

    3.6.根据id查询商品

    cn.whu.item.web包的ItemController中可以看到接口定义:

    在这里插入图片描述

    这里只返回了商品信息,不包含库存

    3.7.根据id查询库存

    cn.whu.item.web包的ItemController中可以看到接口定义:

    在这里插入图片描述

    3.8.启动

    注意修改application.yml文件中配置的mysql地址信息:

    在这里插入图片描述

    需要修改为自己的虚拟机地址信息、还有账号和密码。

    修改后,启动服务,访问:http://localhost:8081/item/10001即可查询数据

    • 完整Controller代码
    package cn.whu.item.web;
    
    import cn.whu.item.service.IItemService;
    import cn.whu.item.service.IItemStockService;
    import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
    import cn.whu.item.pojo.Item;
    import cn.whu.item.pojo.ItemStock;
    import cn.whu.item.pojo.PageDTO;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    import java.util.stream.Collectors;
    
    @RestController
    @RequestMapping("item")
    public class ItemController {
    
        @Autowired
        private IItemService itemService;
        @Autowired
        private IItemStockService stockService;
    
        @GetMapping("list")
        public PageDTO queryItemPage(
                @RequestParam(value = "page", defaultValue = "1") Integer page,
                @RequestParam(value = "size", defaultValue = "5") Integer size){
                // 一般名称不一致或者需要设置默认值时,才需要用到@RequestParam注解
                // 此注解是接受url参数的  value是前端的name值,映射到后面变量里面 (一般name和形参名不一致时才需要指定)
                // 当然,还可以设置默认值 如此处的defaultValue
            // 分页查询商品
            Page<Item> result = itemService.query() //用query方法,链式编程,好处:不用写lambda条件了
                    .ne("status", 3)
                    .page(new Page<>(page, size));
    
            // 查询库存
            List<Item> list = result.getRecords().stream().peek(item -> {
                ItemStock stock = stockService.getById(item.getId());
                item.setStock(stock.getStock());
                item.setSold(stock.getSold());//库存和余量在另一张表 需要一个个查出来然后设置
            }).collect(Collectors.toList());
    
            // 封装返回
            return new PageDTO(result.getTotal(), list);
        }
    
        @PostMapping
        public void saveItem(@RequestBody Item item){
            itemService.saveItem(item);
        }
    
        @PutMapping
        public void updateItem(@RequestBody Item item) {
            itemService.updateById(item);
        }
    
        @PutMapping("stock")
        public void updateStock(@RequestBody ItemStock itemStock){
            stockService.updateById(itemStock);
        }
    
        @DeleteMapping("/{id}")
        public void deleteById(@PathVariable("id") Long id){
            itemService.update().set("status", 3).eq("id", id).update();
        }
    
        @GetMapping("/{id}")
        public Item findById(@PathVariable("id") Long id){
            return itemService.query()
                    .ne("status", 3).eq("id", id)
                    .one();
        }
    
        @GetMapping("/stock/{id}")
        public ItemStock findStockById(@PathVariable("id") Long id){
            return stockService.getById(id);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79

    4.导入商品查询页面

    商品查询是购物页面,与商品管理的页面是分离的。

    部署方式如图:

    在这里插入图片描述

    我们需要准备一个反向代理的nginx服务器,如上图红框所示,将静态的商品页面放到nginx目录中。

    页面需要的数据通过ajax向服务端(nginx业务集群)查询。

    4.1.运行nginx服务

    这里直接使用资料中准备好了的nginx反向代理服务器和静态资源。

    链接:https://pan.baidu.com/s/1dv6ydcwaum3tXRnqmCNxmA
    提取码:hzan

    找到资料的nginx目录:

    在这里插入图片描述

    将其拷贝到一个非中文无空格的目录下,运行这个nginx服务。

    在这里插入图片描述

    运行命令:

    start nginx.exe
    
    • 1

    然后访问 http://localhost/item.html?id=10001即可:

    在这里插入图片描述

    4.2.反向代理

    现在,页面是假数据展示的。我们需要向服务器发送ajax请求,查询商品数据。

    打开控制台,可以看到页面有发起ajax查询数据:

    在这里插入图片描述

    而这个请求地址同样是80端口,所以被当前的nginx反向代理了。

    http://localhost/api/item/10002 其中的api一看就知道是nginx.conf里配置的反向代理规则

    查看nginx的conf目录下的nginx.conf文件:

    在这里插入图片描述

    其中的关键配置如下:

    在这里插入图片描述

    监听80端口,以/api开头的请求

    其中的192.168.150.101是我的虚拟机IP,也就是我的Nginx业务集群要部署的地方:

    若你的不一样,如:192.168.141.100 , 手动修改一下

    在这里插入图片描述

    完整内容如下:

    #user  nobody;
    worker_processes  1;
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       mime.types;
        default_type  application/octet-stream;
    
        sendfile        on;
        #tcp_nopush     on;
        keepalive_timeout  65;
    
    	#nginx的业务集群,集群里可以做:nginx本地缓存、redis缓存、tomcat查询
        upstream nginx-cluster{
            server 192.168.141.100:8081;
    	   server 192.168.141.100:8082;
        }
        server {
            listen       80;
            server_name  localhost;
    
    	location /api {
                proxy_pass http://nginx-cluster;
            }
    
            location / {
                root   html;
                index  index.html index.htm;
            }
    
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    环境都准备好啦,接下来实现nginx集群(部署到linux端)(然后windows端一个nginx做反向代理即可)

  • 相关阅读:
    软件测试是个青春饭,怎么才能避免35岁危机?我想吃一辈子
    逸飞激光在科创板IPO过会:前三季度营收约3亿元,同比增长59%
    工商管理专业的毕业论文怎么选题?
    Attingo:西部数据部分SSD存在硬件设计制造缺陷
    认识主被动无人机遥感数据、预处理无人机遥感数据、定量估算农林植被关键性状、期刊论文插图精细制作与Appdesigner应用开发
    MySQL基础与库的基本操作
    现代 CSS 解决方案:文字颜色自动适配背景色!
    列式存储的分布式数据库——HBase Shell与SQL实战操作(HBase Master高可用实现)
    ESP32 IDF开发 应用篇⑳ WebSocket
    基于JAVA小说阅读网站计算机毕业设计源码+数据库+lw文档+系统+部署
  • 原文地址:https://blog.csdn.net/hza419763578/article/details/133322780