Spring 后台管理系统项目练习03 -----商品列表,Nginx,项目本地发布

1 商品列表

1.1 准备

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

2 商品列表展现

2.1 前端请求

在这里插入图片描述

2.2 ItemController

/*业务需求:商品列表的展现
    请求路径: /item/getItemList?query=&pageNum=1&pageSize=10
    请求类型: get
    请求参数: 使用pageResult对象接收
    返回值:SysResult(pageResult)
    * */
    //@PathVariable restful动态获取参数
    @GetMapping("/getItemList")
    public SysResult getItemList(PageResult pageResult){//3个参数
        pageResult=itemService.getItemList(pageResult);//3+2

        return SysResult.success(pageResult);
    }

2.3 ItemServiceImpl

	/*
    * sql:select * from item limit 起始位置,显示条数
    *
    * */
    @Override
    public PageResult getItemList(PageResult pageResult) {
        //1.构建模糊查询
        boolean flag= StringUtils.hasLength(pageResult.getQuery());//动态sql,为true才拼接条件
        QueryWrapper<Item> queryWrapper = new QueryWrapper<>();
        queryWrapper.like(flag,"title", pageResult.getQuery());
        //2.定义分页对象
                                        //页数                条数
        IPage page=new Page(pageResult.getPageNum(), pageResult.getPageSize());

        //page的参数由原来的页数/条数 ,经过业务调用添加了 总记录数和分页的结果
        page=itemMapper.selectPage(page,queryWrapper);
        long total=page.getTotal();//获取总数
        List<Item> rows=page.getRecords();//获取分页的结果
        return pageResult.setTotal(total).setRows(rows);
    }

在这里插入图片描述

2.4 编辑分页配置类

在这里插入图片描述

@Configuration //标识配置类
public class MybatisPlusConfig {
    //将自定义对象交给容器管理  告诉MP 当前使用的数据库是mysql/maridb
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
    
}

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

3 商品新增业务接口

3.1 关于商品信息说明

说明: item的基本信息与ItemDesc的详情信息 可以采用对象的方式进行包裹.
例如: {item: item的数据信息, itemDesc: itemDesc的数据信息}
在这里插入图片描述

3.1 修改表字段类型

在这里插入图片描述

3.2 业务接口分析

请求路径: http://localhost:8091/item/saveItem
请求类型: post
前端传递参数分析
	{
		item: {
			images: "/2021/05/20/da0c1d4781c1499399f090da8b60f359.jpg,/2021/05/20/2ac1c34776a7465887eb019655354c3c.jpg"
			itemCatId: 560
			num: "100"
			price: 718800
			sellPoint: "【华为官方直供,至高12期免息0首付,原装正品】送华为原装无线充+运动蓝牙耳机+蓝牙音箱+三合一多功能数据线+钢化膜等!"
			title: "华为P40 Pro 5G手机【12期免息可选送豪礼】全网通智能手机"
		},
		itemDesc: {
				itemDesc: "<ul><li>品牌:&nbsp;<a href=https://list.jd.com/list.html".......      "
		},
		itemParam: {
			dynamicArray: [
							{paramId: 1, paramVals: "亮黑色,釉白色"}, 
							{paramId: 2, paramVals: "8GB+128GB,8GB+256GB"}
						   ],
			staticArray: [
				 	{"paramId": 3,"paramVals": "华为Mate 40 Pro"},
				    {"paramId": 4,"paramVals": "0.575kg"}.....
			 		]
		}
	}

请求参数: 使用ItemVO对象接收

参数名称参数类型参数说明备注
itemItem商品基本信息对象封装不能为null
itemDescItemDesc商品详情信息不能为null

3.3 前端请求

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

3.4 封装ItemVO对象

把Item和ItemDesc封装到一个ItemVO对象中

@Data
@Accessors(chain = true)
public class ItemVO implements Serializable {
    private Item item;
    private ItemDesc itemDesc;
}

3.5 ItemController

/*商品新增
    请求路径: /item/saveItem
    请求类型: post
    参数信息: itemVO对象
    * */
    @PostMapping("/saveItem")
    public SysResult saveItem(@RequestBody ItemVO itemVO){//Item+ItemDesc

        itemService.saveItem(itemVO);
        return SysResult.success();
    }

3.6 ItemServiceImpl

 /**
     * 需求: 完成2部分入库操作
     * 步骤1: 完成Item入库操作
     * 步骤2: 完成ItemDesc入库操作 item.id=itemDesc.id
     * mybatis 知识讲解
     *  <insert id="xxxx" useGeneratedKeys="true"
     *             keyColumn="id"
     *             keyProperty="id">
     *         新增sql
     *  </insert>
     *  MP知识讲解:
     *      MP基于对象的方式操作数据,如果实现数据的入库操作,
     *      则数据都会与对象绑定,动态回显.
     *  难点知识: 如何实现数据回显!!!!!!
     * @param itemVO
     */
    @Override
    @Transactional
    public void saveItem(ItemVO itemVO) {
        //1.步骤1 实现Item对象入库
        Item item = itemVO.getItem().setStatus(true);
        //刚开始id为null,入库操作时候,id在数据库中会自动赋值
        //赋值之后,对象中的ID依然为null
        itemMapper.insert(item);
        //2.步骤2 实现ItemDesc对象入库
        ItemDesc itemDesc = itemVO.getItemDesc();
        itemDesc.setId(item.getId());
        itemDescMapper.insert(itemDesc);
    }

4 商品删除 和状态更新 操作

4.1 商品删除

4.1.1 ItemController

/*
    请求路径: /item/deleteItemById
    请求类型: delete
    请求参数: id
    */
    @DeleteMapping("/deleteItemById")
    public SysResult deleteItemById(Integer id){
        itemService.deleteItemById(id);
        return SysResult.success();
    }

4.1.2 ItemService

item和item_desc都要一起删除

		@Override
    @Transactional
    public void deleteItemById(Integer id) {
        itemMapper.deleteById(id);
        itemDescMapper.deleteById(id);
    }

4.2 商品状态更新

4.2.1 ItemController

		/*
    /item/updateItemStatus
     */
    @PutMapping("/updateItemStatus")
    public SysResult updateItemStatus(@RequestBody Item item){
        itemService.updateItemStatus(item);
        return SysResult.success();
    }

4.2.2 ItemService

		@Override
    @Transactional
    public void updateItemStatus(Item item) {
        itemMapper.updateById(item);
    }

4.3 商品修改

4.3.1

/*
    回显
    * 根据ID查询商品信息:
    请求路径: /item/{id}
    * 参数:  id
    请求类型: GET
     */
    @GetMapping("/{id}")
    public SysResult findItemReturnById(@PathVariable Integer id){
        Item item=itemService.findItemReturnById(id);
        return SysResult.success(item);
    }

    /*
    请求路径: /user/updateItem
    请求类型: PUT
    请求参数: 对象结构
    返回值: SysResult对象*/
    @PutMapping("/updateItem")
    public SysResult updateItem(@RequestBody Item item){

        itemService.updateItem(item);

        return SysResult.success();
    }

4.3.2

@Override
    public Item findItemReturnById(Integer id) {
        return itemMapper.selectItemById(id);
    }

    @Override
    public void updateItem(Item item) {

        itemMapper.updateItemById(item);
    }

4.3.3

@Update("update item set title=#{title},sell_point=#{sellPoint},price=#{price},num=#{num} where id=#{id}")
    void updateItemById(Item item);
    @Select("select * from item where id=#{id}")
    Item selectItemById(Integer id);

5 文件上传操作

5.1 文件上传业务说明

说明:当用户选择多张图片时,则是一张一张的传输.

在这里插入图片描述

5.2 接口信息

请求路径: http://localhost:8091/file/upload
请求类型: post
请求参数:

参数名称参数说明备注
file文件上传的参数名称file中携带的是二进制信息

ImageVO对象说明

参数名称参数类型参数说明备注
virtualPathStringvirtualPath例如: 2021/11/11/a.jpg 不需要写磁盘地址
urlPathStringurlPathhttp://image.jt.com/2021/11/11/a.jpg 需要指定域名地址
fileNameString文件上传后的文件名称UUID.type

5.3 ImageVO对象封装

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class ImageVO implements Serializable {
    private String virtualPath; //虚拟路径 动态变化的路径
    private String urlPath;     //图片网络地址
    private String fileName;    //图片名称
}

5.4 文件上传入门案例

		@RestController
		@CrossOrigin
		@RequestMapping("/file")
		public class FileController {
    /**
     * URL: /file/upload
     * 类型: post
     * 参数: file=字节信息
     * 返回值: SysResult(ImageVO)
     * 知识点:
     *   SpringMVC针对与IO操作开发了MultipartFile
     *   底层实现就是常规IO流,简化了用户的操作过程.无需手动关流
     *   SpringMVC中默认支持最大1M
     * 步骤:
     *      1.获取文件名称
     *      2.准备文件路径
     *      3.准备文件上传的全路径
     *      4.实现文件上传操作
     */
    @PostMapping("/upload")
    public SysResult upload(MultipartFile file) throws IOException {
        //1.获取文件名称  a.jpg
        String fileName = file.getOriginalFilename();
        //2.准备文件目录
        String dir = "D:/project3/images";
        File dirFile = new File(dir);
        if(!dirFile.exists()){//判断目录是否存在
            dirFile.mkdirs(); //创建多级目录
        }
        String path = dir + "/" + fileName;
        //实现文件上传
        file.transferTo(new File(path));
        return SysResult.success();
    }
}

5.5 文件上传完整代码

5.5.1 编辑FileController

@PostMapping("/upload")
    public SysResult fileUpload(MultipartFile file){

        ImageVO imageVO=fileService.upload(file);
        if (imageVO==null){
            return SysResult.fail();
        }
        return SysResult.success(imageVO);
    }

5.5.2 编辑FileService

思路:
1.校验文件是否为图片
2.防止文件为恶意程序
3.分目录存储 按照时间维护划分
4.防止文件重名 UUID
5.5.2.1 校验(1,2步)
@Override
    public ImageVO upload(MultipartFile file) {
        //1.
        //获取图片名称全部转小写
        String filename = file.getOriginalFilename().toLowerCase();
        if (!filename.matches("^.+\\.(jpg|png|gif)$")) {//java中 \\ 代表 \ ;不识别单个\
            return null;
        }
        //2.通过校验宽度和高度判断是否为图片
        try {
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            if (width == 0 || height == 0) {
                return null;
            }
        } catch (IOException e) {
            //一般条件下,为了不影响代码结构,将检查异常,转化为运行时异常
            e.printStackTrace();
            throw new RuntimeException(e);//
        }

        return null;
    }

在这里插入图片描述

在这里插入图片描述

5.5.2.2
@Override
    public ImageVO upload(MultipartFile file) {
        //1.
        //获取图片名称全部转小写
        String fileName = file.getOriginalFilename().toLowerCase();
        if (!fileName.matches("^.+\\.(jpg|png|gif)$")) {//java中 \\ 代表 \ ;不识别单个\
            return null;
        }
        //2.通过校验宽度和高度判断是否为图片
        try {

            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int width = bufferedImage.getWidth();
            int height = bufferedImage.getHeight();
            if (width == 0 || height == 0) {
                return null;
            }
            //3 分目录存储
            String datePath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
            String fileDir = rootDir + datePath;
            File dirFile = new File(fileDir);//
            if (!dirFile.exists()) {
                dirFile.mkdirs();
            }

            //4.动态生成UUID
            String UUID = java.util.UUID.randomUUID().toString();
            int index = fileName.lastIndexOf(".");
            String fileType = fileName.substring(index);
            fileName = UUID + fileType;

            //5.实现文件上传
            String path = fileDir + "/" + fileName;
            file.transferTo(new File(path));

            //6.准备imageVO的数据返回
            String virtualPath = datePath + fileName;
            //String urlPath="https://img14.360buyimg.com/n0/jfs/t1/162878/20/21270/387542/61b8da25Ed63246d6/baffb7e01f3edefb.jpg";
            String urlPath = rootURL + virtualPath;
            //String urlPath = rootDir + virtualPath;
            System.out.println(urlPath);

            ImageVO imageVO = new ImageVO(virtualPath, urlPath, fileName);
            return imageVO;

        } catch (IOException e) {
            //一般条件下,为了不影响代码结构,将检查异常,转化为运行时异常
            e.printStackTrace();
            throw new RuntimeException(e);//
        }

    }

6 文件删除业务接口

在这里插入图片描述

6.2 FileController

/*
    请求路径: /file/deleteFile
    请求类型: delete
    请求参数: virtualPath
    返回值: SysResult
     */
    @DeleteMapping("/deleteFile")
    public SysResult deleteFile(String virtualPath){
        fileService.deleteFile(virtualPath);
        return SysResult.success();
    }

6.3 FileService

/*
    删除文件 需要文件全路径
     */

    @Override
    public void deleteFile(String virtualPath) {
        String localPath=rootDir+virtualPath;
        File file = new File(localPath);
        if (file.exists()) {//如果文件存在则删除
            file.delete();
        }
    }

7 拓展(商品列表修改)

7.1 前端

7.1.1 修改按钮

在这里插入图片描述

7.1.2 弹窗回显

<!-- 修改商品数据 -->
      <el-dialog title="修改商品" :visible.sync="updateItemDialogVisible" width="50%" @close="closeUpdateDialog">
        <!-- 定义用户提交表单数据-->
        <el-form :model="updateItemModel" :rules="rules" ref="updateItemRef" label-width="100px">
          <!-- <el-form-item label="ID" prop="id">
            <el-input v-model="updateItemModel.id"  disabled ></el-input>
          </el-form-item> -->
          <el-form-item label="标题" prop="title">
            <el-input v-model="updateItemModel.title"   ></el-input>
          </el-form-item>
          <el-form-item label="买点" prop="sellPoint">
            <el-input v-model="updateItemModel.sellPoint"   ></el-input>
          </el-form-item>
          <el-form-item label="价格" prop="price">
            <el-input v-model="updateItemModel.price"></el-input>
          </el-form-item>
          <el-form-item label="数量" prop="num">
            <el-input v-model="updateItemModel.num"></el-input>
          </el-form-item>
        </el-form>

        <span slot="footer" class="dialog-footer">
          <el-button @click="updateItemDialogVisible = false" >取 消</el-button>
          <el-button type="primary" @click="updateItem">确 定</el-button>
        </span>
        </el-dialog>

7.1.3 data

		updateItemDialogVisible: false,
        //定义修改用户数据封装
        updateItemModel: {
        }

7.1.4 methods

 	//商品列表修改
      // 数据回显 根据ID获取数据
      async updateItemBtn(item){
        this.updateItemDialogVisible = true
        const {data: result} = await this.$http.get("/item/"+item.id)
        if(result.status !== 200) return this.$message.error("商品查询失败")
        this.updateItemModel = result.data
      },
      closeUpdateDialog(){
        //重置表格数据
        this.$refs.updateItemRef.resetFields()
      },
      updateItem(){
        //1.预校验数据
        this.$refs.updateItemRef.validate(async valid => {
           if(!valid)  return this.$message.error("表单验证没有通过")
           //根据接口文档要求封装数据
           let item = {}
           item.id = this.updateItemModel.id
           item.title = this.updateItemModel.title
           item.sellPoint = this.updateItemModel.sellPoint
           item.price = this.updateItemModel.price
           item.num = this.updateItemModel.num
           const {data: result} = await this.$http.put(`/item/updateItem`,item)
           if(result.status !== 200) return this.$message.error("用户修改失败")
           this.$message.success("用户更新成功")
           this.updateItemDialogVisible = false
           this.getItemList()
        })
      }

7.2 后端实现

7.2.1 ItemController

	/*
    回显
    * 根据ID查询商品信息:
    请求路径: /item/{id}
    * 参数:  id
    请求类型: GET
     */
    @GetMapping("/{id}")
    public SysResult findItemReturnById(@PathVariable Integer id){
        Item item=itemService.findItemReturnById(id);
        return SysResult.success(item);
    }

    /*
    请求路径: /user/updateItem
    请求类型: PUT
    请求参数: 对象结构
    返回值: SysResult对象*/
    @PutMapping("/updateItem")
    public SysResult updateItem(@RequestBody Item item){

        itemService.updateItem(item);

        return SysResult.success();
    }

7.2.2 ItemService

	@Override
    public Item findItemReturnById(Integer id) {
        return itemMapper.selectById(id);
    }

    @Override
    public void updateItem(Item item) {

        itemMapper.updateItemById(item);
    }

7.2.3 ItemController

public interface ItemMapper extends BaseMapper<Item> {

    @Update("update item set title=#{title},sell_point=#{sellPoint},price=#{price},num=#{num} where id=#{id}")
    void updateItemById(Item item);
//    @Select("select * from item where id=#{id}")
//    Item selectItemById(Integer id);
}

7.3 效果

在这里插入图片描述

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

8 反向代理

8.1 业务需求

需求说明: 当用户完成图片上传之后 会根据网络地址访问图片,但是查找的图片一定存在于磁盘中.
URL地址: http://image.jt.com/2021/12/16/f9981c76-e6a7-49fa-88d9-3be0851dbf50.jpg
磁盘地址: D:/project3/images/2021/12/16/f9981c76-e6a7-49fa-88d9-3be0851dbf50.jpg

技术难点:
1.当用户访问URL网络地址时,应该按照磁盘地址进行查找!
如何将网络地址转化为磁盘地址?

8.2 反向代理介绍

反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源。同时,用户不需要知道目标服务器的地址,也无须在用户端作任何设定。反向代理服务器通常可用来作为Web加速,即使用反向代理作为Web服务器的前置机来降低网络和服务器的负载,提高访问效率。

8.2.1 知识铺垫

如果网站将真实地址直接告知用户.导致整个服务器不安全. 所以需要采用代理的技术规避该问题.

8.2.2 反向代理特点

反向代理服务器介于用户和目标服务器之间
用户从反向代理服务器获取资源, 用户以为反向代理服务器就是目标服务器.
用户不清楚真实的服务器到底是谁, 保护了真实服务器的信息. 也称之为 "服务器端代理"

8.3 正向代理介绍

8.3.1 正向代理介绍

正向代理,意思是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端才能使用正向代理。

8.3.2 正向代理特点

正向代理服务器介于客户端和原始服务器之间.
用户访问正向代理服务器,并且指定目标服务器地址.
服务器端不清楚到底是谁访问的,以为是正向代理服务器访问的. 保护了用户信息. 也称之为客户端代理

在这里插入图片描述
.

8.4 nginx

8.4.1 Nginx介绍

Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、简单的配置文件和低系统资源的消耗而闻名。2011年6月1日,nginx 1.0.4发布。
Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,在BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。

8.4.2 Nginx特点

nginx是一块开源免费的 轻量级的反向代理服务器/web服务器.
nginx并发能力强 理论值: 5万次/秒 实际值: 3万次/秒
tomcat: 150-220 —>1000个/秒 内存占用200M
nginx占用内存少 不超过2M

8.4.3 Nginx下载

URL地址: http://nginx.org/en/download.html

8.4.4 Nginx 安装和使用

说明:
1.nginx启动会占用80端口!!
2.nginx启动路径不要有中文/空格/特殊字符 底层开发语言:C语言

访问测试:
在这里插入图片描述

8.4.5 关于nginx 80端占用问题说明

检查端口号占用
在这里插入图片描述

8.4.6 关于nginx 启动项说明

说明: nginx的启动每次都会启动2个进程项.
主进程: 主要提供反向代理服务. 占用内存大的
守护进程: 防止主进程意外关闭. 占用内存小的

任务管理器 进程
在这里插入图片描述

8.4.7 nginx 命令(熟练掌握)

说明: nginx的命令需要在根目录中运行 nginx.exe 所在的路径就是根目录
命令:

  1. 启动nginx start nginx
  2. 重启nginx nginx -s reload
  3. 关闭nginx nginx -s stop

8.5 Nginx反向代理机制

	http {
		 #每个反向代理服务,就是一个server
		 server {
		 	#nginx默认监听端口号 默认都是80
			listen       80;
			#nginx要拦截的域名
			server_name  localhost;
			
			#拦截所有的请求
			location / {
				# root 代表代理的是一个目录 
            	root   html;
            	# 配置默认访问的首页
            	index  index.html index.htm;
        	}
		 }	
	}

8.6 Nginx实现图片代理

URL地址: http://image.jt.com/2021/12/16/f9981c76-e6a7-49fa-88d9-3be0851dbf50.jpg
磁盘地址: D:/project3/images/2021/12/16/f9981c76-e6a7-49fa-88d9-3be0851dbf50.jpg
代理机制:
域名: http://image.jt.com:80
代理为:
D:/project3/images

配置图片代理:

#配置图片代理
	server {
		listen 80;
		server_name  image.jt.com;

		location / {
			root D:/project3/images;
		}
	}

编辑完成之后,重启nginx

在这里插入图片描述

8.7 修改hosts文件

文件位置: C:\Windows\System32\drivers\etc
在这里插入图片描述

8.7.1 检查是否只读

如果该文件为只读 应该去除只读选项
在这里插入图片描述

8.7.2 检查权限

在这里插入图片描述

8.7.3 修改hosts文件

127.0.0.1       localhost
127.0.0.1		image.jt.com			#图片
127.0.0.1		manage.jt.com			#后端
127.0.0.1		web.jt.com				#前端

9 项目发布准备

9.1 项目发布

1.检查所有的sql中的表名是否存在大小写问题. 检查注解 检查Sql
2.根据码云 检查POM.xml文件内容
3.将项目打包 install 命令
4.前端项目打包

在这里插入图片描述检查是否生成dist目录
在这里插入图片描述

9.2 前端发布准备

1.修改main.js的路径

在这里插入图片描述
2.编辑AddItem.vue文件
在这里插入图片描述
3.将前端项目进行编译
如果将上述的操作修改完成,之后需要将程序编译。如图所示
在这里插入图片描述

9.3 前端项目发布

9.3.1 业务说明

将编译之后的dist目录 复制到nginx的根目录中。

在这里插入图片描述

9.3.2 前端项目发布

需求: 用户通过http://web.jt.com 访问 dist/index.html
在这里插入图片描述

#配置前端代理
	server {
		listen 80;
		server_name  web.jt.com;

		location / {
			root dist;
			index index.html;
		}
	}

重启nginx

9.3.3 前端代码测试

在这里插入图片描述

9.4 后端项目发布

9.4.1 动态获取端口号

package com.jt.controller;
@RestController
@CrossOrigin
public class PortController {
    //动态获取端口号
    @Value("${server.port}")
    private Integer port;

    @GetMapping("/getPort")
    public String getPort(){

        return "当前端口号:"+port;
    }
}


9.4.2 项目发布

命令: java -jar 8091.jar
在这里插入图片描述
在这里插入图片描述

9.4.3 nginx完成后端发布

#配置后端代理
	server {
		listen 80;
		server_name  manage.jt.com;

		location / {
			#proxy_pass 映射的是请求的地址
			proxy_pass http://localhost:8091;
		}
	}

9.4.4 后端项目测试

通过:http://manage.jt.com/itemCat/findItemCatList/3 测试后端域名是否可用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值