Spring Boot + Vue项目开发学习笔记2

server/2024/10/25 7:07:20/

这个笔记是在看B站视频的时候做的,所以肯定是很多直接把课程的ppt的文字直接写下来了或者把老师口述的内容写下来,目的是为了让自己遗忘某些知识点的时候能直接看笔记,应该不至于构成侵权吧,如有不妥望告知,我会删除并道歉的。

而且视频发布时间是2022年8月,可能不会很新,但是我觉得讲的很好用来初学是很不错的。非常感谢刘老师分享的视频。

学习视频链接如下:
1.课程介绍及环境准备_哔哩哔哩_bilibili1.课程介绍及环境准备是1天搞定SpringBoot+Vue全栈开发的第1集视频,该合集共计20集,视频收藏或关注UP主,及时了解更多相关视频内容。icon-default.png?t=O83Ahttps://www.bilibili.com/video/BV1nV4y1s7ZN?p=1&vd_source=d6fc444a0835fb167ab777abdb6df08f

目录

1 RESTful服务+Swagger

1.1 RESTful介绍

1.1.1 RESTful的特点

1.1.2 RESTful API

1.1.3 HTTP Method

1.1.4 HTTP 状态码

2 Spring Boot实现RESTful API

3 Swagger

3.1 Swagger是什么

3.2 使用Swagger生成Web API文档

3.3 Swagger常用注释

3.4 在Swagger生成的网站中代替Apipost等测试软件进行测试

4 MybatisPlus快速上手

4.1 ORM的介绍

4.2 MyBatis-Plus介绍

4.3 MyBatis-Plus在idea的配置

4.4 MyBatis-Plus CRUD操作

4.4.1 使用MyBatis-Plus查询数据的示例

4.4.2 插入更新删除 

4.4.3 真MyBatis-Plus 

5 多表查询和分页查询

5.1 多表查询 

5.2 条件查询

5.3 分页查询 

6 总结 

1 RESTful服务+Swagger

 感觉下面很多都是了解就好了

1.1 RESTful介绍

RESTful是目前最流行的互联网软件服务架构设计风格,REST并不是一个标准,更像是一组客户端和服务端交互时的架构理念和设计原则,基于这种架构理念和设计原则的Web API更加简洁,更有层次

如果一个架构符合REST原则,则称之为RESTful架构

1.1.1 RESTful的特点

  • 每一个URI代表一种资源
  • 客户端使用GET、POST、PUT、DELETE四种表示操作方式的动词对服务端资源进行操作:GET用于获取资源,POST用于新建资源(也可以用于更新资源),PUT用于更新资源,DELETE用于删除资源。
  • 通过操作资源的表现形式来实现服务端请求操作。
  • 资源的表现形式是JSON或者HTML。
  • 客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都包含必需的信息

1.1.2 RESTful API

符合RESTfuI规范的Web API需要具备如下两个关键特性:
1、安全性:安全的方法被期望不会产生任何副作用,当我们使用GET操作获取资源时,不会引起资源本身的改变,也不会引起服务器状态的改变。
2、幂等性:幂等的方法保证了重复进行一个请求和一次请求的效果相同(并不是指响应总是相同的,而是指服务器上资源的状态从第一次请求后就不再改变了),在数学上幂等性是指N次变换和一次变换相同

1.1.3 HTTP Method

HTTP提供了POST、GET、PUT、DELETE等操作类型对某个Web资源进行Create、Read、Update和Delete操作
一个HTTP请求除了利用URI标志目标资源之外,还需要通过HTTPMethod指定针对该资源的操作类型,一些常见的HTTP方法及其在RESTfuI风格下的使用:

1.1.4 HTTP 状态码

HTTP状态码就是服务向用户返回的状态码和提示信息,客户端的每一次请求,服务都必须给出回应,回应包括HTTP状态码和数据两部分

HTTP定义了40个标准状态码,可用于传达客户端请求的结果。状态码类别如下:

  • 1xx:信息,通信传输协议级信息
  • 2xx:成功,表示客户端请求已经被接受
  • 3xx:重定向,表示客户端必须执行一些其他操作才能完成请求
  • 4xx:客户端错误,此类错误状态码指向客户端
  • 5xx:服务器错误,服务器负责写这一块的代码有错误

2 Spring Boot实现RESTful API

Spring Boot提供的spring-boot-starter-web组件完全支持开发RESTfuI API提供了与REST操作方式(GET、POST、PUT、DELETE)对应的注解。

  • @GetMapping:处理GET请求,获取资源
  • @PostMapping:处理POST请求,新增资源
  • @PutMapping:处理PUT请求,更新资源。
  • @DeleteMapping:处理DELETE请求,删除资源。
  • @PatchMapping:处理PATCH请求,用于部分更新资源

在RESTful架构中,每个网址代表一种资源,所以URI中建议不要包含动词,只包含名词即可,而且所用名词往往与数据库的表格名对应

下面是用户管理api示例 

 这样的话id是通过路径传递的,而且id是变化的,所以代码跟之前学习的用 http:/localhost:8080/user?id=10001 路径传递参数会有所不同,示例如下:

    @GetMapping("/user1/{id}")public String getUserById(@PathVariable int id){return "根据ID获取用户";}

输入网址 http:/localhost:8080/user1/2000 (后面传递的数字可以随便写

 

注意:需要传参的话,URL上要有花括号,参数需加上注解@PathVariable

3 Swagger

3.1 Swagger是什么

Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,是非常流行的API表达工具

Swagger能够自动完成RESTful API文档,同时并根据后台代码的修改同步更新,同时提供更完整的测试页面来调试API。

这样一来,我们就不需要继续使用Apipost来进行调试了。

3.2 使用Swagger生成Web API文档

在Spring boot项目中集成Swagger非常简单,只需在项目中引入springfox-swagger2和springfox-swagger-ui依赖即可

配置Swagger步骤:

给pom.xml文件的<dependencies>  </dependencies>标签之间引入pringfox-swagger2和springfox-swagger-ui依赖,引入依赖后要刷新一下maven

 代码:

        <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency>

新建一个包,命名为config,然后新建一个类,命名为Swagger2Config,如图

在Swagger2Config类中添加以下代码:


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration
@EnableSwagger2
public class Swagger2Config {@Beanpublic Docket createRestApi(){return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.basePackage("com"))   //com包下所有API都归swagger2管理.paths(PathSelectors.any()).build();}//api文档页面显示信息private ApiInfo apiInfo(){return new ApiInfoBuilder().title("演示项目testAPI").description("学习swagger2的演示项目").build();}
}

 然后此时开始运行项目会报错,错误如下:

应该是SpringBoot2.6.x后与Swagger有版本冲突问题 

为了解决这个错误,我们需要在application.propertites中添加下面代码:

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

 然后再跑就不会有错误了,在网页上搜索 http://localhost:8080/swagger-ui.html 就会出现类似这样的页面:

3.3 Swagger常用注释

Swagger提供了一系列注解来描述接口信息,包括接口说明、请求方法、请求参数、返回信息等

 例如:@ApiOperation的使用

3.4 在Swagger生成的网站中代替Apipost等测试软件进行测试

上图中,点击Try it out,然后得到下图,根据需要填写数据或者不需要填写,完成之后点击Execute按钮就会出现测试结果

 

4 MybatisPlus快速上手

4.1 ORM的介绍

ORM(Object Relational Mapping,对象关系映射)是为了解决面向对象与关系数据库存在的互不匹配现象的一种技术

ORM通过使用描述对象和数据库之间映射的元数据将程序中的对象自动持久化到关系数据库中

ORM框架的本质是简化编程中操作数据库的编码

4.2 MyBatis-Plus介绍

MyBatis是一款优秀的数据持久层ORM框架,被广泛应用在应用系统中

MyBatis能够灵活实现动态SQL,可以使用XML或注解来配置和映射原生信息,能够轻松将Java的POJO与数据库中的表和字段进行映射关联

MyBatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上做了增强,简化开发 

4.3 MyBatis-Plus在idea的配置

① 在 pom.xml 添加依赖

        <!--MybatisPlus依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.2</version></dependency><!--mysql驱动依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!--数据连接池druid--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.20</version></dependency>

我们在做数据库的操作依赖的同时最好使用连接池的技术,让它一次性申请多个链接,提高我们数据库连接的效率

② 全局配置

(1)在 application.properties 中配置数据库相关信息

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false
spring.datasource.username=root
spring.datasource.password=154922
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

 解释:

  1. spring.datasource.type=com.alibaba.druid.pool.DruidDataSource :意思是使用阿里巴巴提供的数据连接池技术,与上面的数据池连接池依赖相对应
  2. spring.datasource.driver-class-name=com.mysql.jdbc.Driver:意思是用什么驱动去连接数据库
  3. spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false:连接的数据库的路径,其中的mydb是自己建立的数据库的名字,注意要修改成与自己建立的数据库名称一致
  4. spring.datasource.username=root
    spring.datasource.password=154922 分别是数据库的账号和密码,一般只需要修改为自己安装数据库时设置密码即可
  5. mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl:日志输出格式

(2)添加@MapperScan注解 

在SpringBoot启动类中添加@MapperScan注解,扫描Mapper文件夹(mapper包是自己创建的,具体路径根据情况进行修改和调整)

@SpringBootApplication
@MapperScan("com.example.test.mapper")
public class TestApplication {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);}}

4.4 MyBatis-Plus CRUD操作

提供了很多注解来让我们完成数据库的工作,简化了代码

4.4.1 使用MyBatis-Plus查询数据的示例

先介绍我创建的数据库,需要我们自己准备一个数据库,具体操作和软件可以自行解决

(1)

新建一个名为mapper的包,用来装有关数据库操作的接口

又新建一个名为entity的包,用来装示例对象

(2)

在写查询方法之前,我们需要在entity包中添加User类,作为一个实体类存放数据库表格中的数据信息,方便我们管理和符合java面向对象的特点

User类的写法很简单,首先在类里面写上和建好的表格中一样的名称,类型也要一样,方便自动管理

public class User {private String username;private int age;
}

然后按住键盘ALT + Insert,出现下面的选择

选择Getter and Setter,全选所有属性,idea会自动为我们生成get和set方法,toString方法也是同理,完整代码如下:

public class User {private String username;private int age;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "User{" +"username='" + username + '\'' +", age=" + age +'}';}
}

然后,在mapper包中添加一个接口,命名规则一般是连接的数据库的名字+Mapper

注意:要在接口前面添加@Mapper注解

在接口里面写查询方法的声明,方法声明前面添加注解@Select(),括号里面写mysql查询的语句即可

@Mapper
public interface UserMapper {// 查询用户@Select("select * from user")public List<User> find();
}

这里就有使用到上面建立的实体类User,具体的查询方法的实现不需要我们去手敲代码实现,mybatisplus和springboot会自动处理的 

(3)在Controller中调用查询方法

先在controller类中定义在前面新建接口UserMapper的属性,注意要在前面添加@Autowired的注解,表明这个会自动将UserMapper类实例化出来的对象注入到userMapper中,这样userMapper就不为空会有值

然后在查询方法里面直接通过userMapper调用即可

@RestController
public class UserController {//数据库查询示例@Autowiredprivate UserMapper userMapper;@GetMapping("/mysqlUser")public String query(){List<User> listUser = userMapper.find();return "查询用户:" + listUser.toString();}
}

会发现,实际写的代码非常少,就能实现数据库查询功能

运行项目之后的结果如下:

还有查询日志,如果结果不对可以查看日志来排查问题(在idea的run里面)

 一般后端传给前端的数据格式都是json格式,我们只需要将上面query方法返回值改为List即可,返回的对象会自动转为json

@RestController
public class UserController {//数据库查询示例@Autowiredprivate UserMapper userMapper;@GetMapping("/mysqlUser")public List<User> query(){List<User> listUser = userMapper.find();return listUser;}
}

4.4.2 插入更新删除 

要注意#{}里面的名称与User类中的属性名称一致 

4.4.3 真MyBatis-Plus 

哈哈哈,刘老师上面讲的东西都是MyBatis,不是MyBatis-Plus ,在MyBatis-Plus中我们不需要详细写数据库对应表中的增删改查,MyBatis-Plus会自动完成

直接上代码吧

·User Mapper2接口的代码:需要继承BaseMapper,并用尖括号注明哪个实体类

@Mapper
public interface UserMapper2 extends BaseMapper<User> {}

·UserController的代码:使用UserMapper2继承了BaseMapper中已有的方法

import java.util.List;@RestController
public class UserController {@Autowiredprivate UserMapper2 userMapper2;@GetMapping("/mysqlUser2")public String query(){List<User> listUser = userMapper2.selectList(null);return "查询用户:" + listUser.toString();}
}

更多的用法可以自行上网搜索,我真的是有点懒的写了(,最终结果如下:

简介 | MyBatis-Plus (baomidou.com)icon-default.png?t=O83Ahttps://baomidou.com/introduce/学到这里,我当时有点疑惑,当数据库有多个表格的时候,我要怎么区分这些不同的表并对应做增删改查的操作呢。听老师讲到后面一点,我才知道当entity包中的实体类名如果跟数据库中表格名字一样的话(不区分大小写),编译器会自动将表格与这个实体类相对应匹配,名字不同可以用@TableName注解来注明。这样的话,在mapper包中的接口中的增删改查操作由于是对实体类的操作,那么也会对应上表格(个人拙见,可能表述不当或者理解有误,发现了我会修改

5 多表查询和分页查询

我的天,数据库没学好,多表查询差点没学明白,难受(好像也不能怪数据库没学好,反正难受就是了

感觉自己总结的也很狗屎,直接看视频免受文字的折磨吧还是

5.1 多表查询 

实现复杂关系映射,可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置

现在讲的多表查询依然是mybatis的内容,mybatisplus并没有增强这一方面(2024年了有没有增强改变我不知道啊

提前写好的数据库如图:

我们现在要查询用户的时候,还想知道用户有什么订单

首先是对类的设计:

还是非常常规的对用户和订单两个表写出来两个实体类 User1,Order,这两个类放在entity包中(忽略下面图片中的User类,之前写的代码,懒的删或者新建项目了)

User1 类代码如下:

package com.example.test.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;import java.util.List;@TableName("t_user")
public class User1 {@TableId(type = IdType.AUTO)private int id;private String username;private String password;@TableField(exist = false)private List<Order> orders;     //描述用户的所有订单,在表中不存在//alt + insertpublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public List<Order> getOrders() {return orders;}public void setOrders(List<Order> orders) {this.orders = orders;}
}

Order 类代码如下:

package com.example.test.entity;import com.baomidou.mybatisplus.annotation.TableName;@TableName("t_order")
public class Order {private int id;private String order_time;private int uid;//alt + insertpublic int getId() {return id;}public void setId(int id) {this.id = id;}public String getOrder_time() {return order_time;}public void setOrder_time(String order_time) {this.order_time = order_time;}public int getUid() {return uid;}public void setUid(int uid) {this.uid = uid;}
}

如果是普通查询的话,因为数据库表格中没有orders的字段,所以查询代码和出来的结果如下

UserMapper2 接口的代码如下:

package com.example.test.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.test.entity.User;
import com.example.test.entity.User1;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface UserMapper2 {@Select("select * from t_user")List<User1> selectAllUserAndOrders();
}

 UserController 类的代码如下:

@RestController
public class UserController {@Autowiredprivate UserMapper2 userMapper2;@GetMapping("/getAll")public List<User1> find(){return userMapper2.selectAllUserAndOrders();}
}

运行项目,在网页中的结果如下:

 orders显示为空,说明没有完成我们需要的映射效果

那么,我们就需要用到一开始给出表格中的注解了

首先我们需要在 OrderMapper 接口中写出来根据给出的uid查询订单的方法

package com.example.test.mapper;import com.example.test.entity.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;import java.util.List;@Mapper
public interface OrderMapper {// 下面这个方法会被UserMapper2中被调用,而不是在控制器中被调用@Select("select * from t_order where uid = #{uid}")List<Order> selectByUid(int uid);
}

然后在 UserMapper2 接口中写下面的代码:

package com.example.test.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.test.entity.User;
import com.example.test.entity.User1;
import org.apache.ibatis.annotations.*;import java.util.List;@Mapper
public interface UserMapper2 extends BaseMapper<User1> {// 查询用户及其所有订单 一对多 所以用@Many@Select("select * from t_user")@Results({@Result(column = "id",property = "id"),@Result(column = "username",property = "username"),@Result(column = "password",property = "password"),@Result(column = "id",property = "orders",javaType = List.class,many = @Many(select = "com.example.test.mapper.OrderMapper.selectByUid"))})List<User1> selectAllUserAndOrders();
}

然后运行项目出来的结果:

orders不为空了。

主要就是注解的应用,好像也没有什么特别的。但是数据库的查询操作要清楚一点要怎么做比较好,会更有逻辑

5.2 条件查询

MyBatis-Plus 框架中QueryWrapper基本用法_querywrapper having-CSDN博客

这玩意是MyBatis-Plus的用法

UserMapper2接口要继承BaseMapper

然后在UserController类中写下下面的方法:

    // 条件查询@GetMapping("/user/find")public List<User1> findByCond(){QueryWrapper<User1> queryWrapper=new QueryWrapper<>();queryWrapper.eq("username","kucy");return userMapper2.selectList(queryWrapper);}

然后运行项目,输入网址可得:

5.3 分页查询 

这也是mybatis-plus的知识

编写配置文件

新建一个配置文件

package com.example.test.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor paginationInterceptor(){MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();PaginationInnerInterceptor paginationInnerInterceptor=new PaginationInnerInterceptor(DbType.MYSQL);interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}
}

然后写分页查询,例如 

    // 分页查询@GetMapping("/user/findByPage")public IPage findByPage(){// 设置起始值及每页条数Page<User1> page=new Page<>(0,2);IPage<User1> iPage=userMapper2.selectPage(page,null);return iPage;}

运行项目的结果: 

如果没有写配置文件的话,项目也能运行,这个运行结果如图:

写了配置文件之后运行项目,运行结果如图:

不太懂,为什么不写配置文件也能出结果,但是有些细节不一样

6 总结 

写了很多,但是有点懵懵懂懂的,希望后面写项目的时候能更理解一点吧。


http://www.ppmy.cn/server/134637.html

相关文章

动态规划之打家劫舍

大纲 题目思路第一步&#xff1a;确定下标含义第二步&#xff1a;确定递推公式第二步&#xff1a;dp数组如何初始化第三步&#xff1a;确定遍历顺序第四步&#xff1a;举例推导dp数组 总结 最近有人询问我 LeetCode 「打家劫舍」系列问题&#xff08;英文版叫 House Robber&…

CentOS 8在Linux虚拟机修改IP地址,出现:错误:“ens160“ 不是活动的连接。错误:未提供活动连接。

问题&#xff1a;错误&#xff1a;"ens160" 不是活动的连接。错误&#xff1a;未提供活动连接。 1.查看网络服务运行状态&#xff1a; 1)CentOS 7执行命令&#xff1a;systemctl status network 2)CentOS 8执行命令&#xff1a;systemctl status NetworkManager&a…

医院信息化与智能化系统(7)

医院信息化与智能化系统(7) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应的…

又是一年 1024

今天是 1024 程序员节&#xff0c;现在是一名大数据讲师&#xff0c;我和往常一样&#xff0c;依旧在讲课中度过。对于很多程序员来说&#xff0c;这一天也许是属于代码、调试和无数行 SQL 查询的&#xff0c;而对于我来说&#xff0c;虽然工作内容不同&#xff0c;却也和数据、…

AMD XILINX 20nm器件价格上调25%

随着市场回暖&#xff0c;台积电也在调整价格策略&#xff0c;近期台积电上调了20nm的出厂价格。 据相关消息显示&#xff0c;AMD为了保障持续的供货和服务&#xff0c;也计划将20nm器件的价格统一上调25%&#xff0c;预计将于11月发布正式的涨价通知&#xff0c;并于2025年Q1开…

【软件工程】软件项目管理/工程项目管理复习资料

第一章 软件项目管理概述习题 一. 填空题 实现项目目标的制约因素有&#xff08; 项目范围 &#xff09;、&#xff08; 成本 &#xff09;、&#xff08; 进度计划 &#xff09;、&#xff08; 客户满意度 &#xff09;等。 项目管理&#xff08; 启动过程组 &#xff09;、…

从算盘到云计算:计算机发展的壮丽历程

早期的计算器 在计算机发展史上&#xff0c;早期的计算器起到了重要的作用。而其中最早的计算器便是算盘。算盘是古代中国人使用的一种计算工具&#xff0c;它由一根木棍和一些珠子组成。通过将珠子在木棍上移动&#xff0c;人们可以进行简单的加减乘除运算。虽然算盘的计算速…

[蓝桥杯 2018 省 B] 乘积最大-题解

[蓝桥杯 2018 省 B] 乘积最大 题目描述 给定 N N N 个整数 A 1 , A 2 , ⋯ , A N A_1, A_2,\cdots, A_N A1​,A2​,⋯,AN​。请你从中选出 K K K 个数&#xff0c;使其乘积最大。 请你求出最大的乘积&#xff0c;由于乘积可能超出整型范围&#xff0c;你只需输出乘积除以…