Pont神坑 ,添加swagger @ApiParam后无法导出参数

文章讲述了在使用Pont工具自动生成API时遇到的问题,即@PostMapping中的@ApiParam注解导致某些参数无法导出。作者发现@ApiParam仅处理query类型参数,对于Post请求,需调整为@RequestParam或指定paramType。更新后解决了multipart/form-data上传文件时的数据传递问题。
摘要由CSDN通过智能技术生成

Pont是一个很好的前后端一体化工具,能够帮助自动生成API代码。

今天正在整Pont的时候,发现个别API参数在pont里无法导出,经过反复的对比发现有一个神坑,很容易踩中。例如下面这个PostMapping,很习惯的,给它添加了@ApiParam参数。

    @PostMapping("testPost")
    @ApiOperation(value = "后台管理员登录aaaa")
    public String testPost(
        @ApiParam("登录ID--》") String loginId,
        String userPsw, String validateCode, String sid,@ApiIgnore RequestSite adminSite, HttpServletResponse response){
        return loginId + " " + userPsw;
    }

然后在knife4j里也工作的很好。

但是实际生成的Pont接口api.d.ts如下:

declare namespace API {
  /**
   * Common Admin Controller
   */
  export namespace commonAdmin {
    /**
     * 后台管理员登录
     * /admin/common/doLogin
     */
    export namespace doLogin {
      export class Params {}

      export type Response = string

      export const init: Response

      export function request(params: Params, body: string, options?: any): Promise<Response>
    }

啥,写过@ApiParam注解后,参数就导不出来啦?难道是鼓励我们不要写注释😅
 

看了下swagger的docs接口,生成的API json如下:

		"/admin/common/testPost": {
			"post": {
				"tags": ["common-admin-controller"],
				"summary": "后台管理员登录aaaa",
				"operationId": "testPostUsingPOST",
				"parameters": [{
					"name": "adminToken",
					"in": "header",
					"description": "adminToken 后台Token",
					"required": false,
					"type": "string"
				}, {
					"in": "body",
					"name": "loginId",
					"description": "登录ID--》",
					"required": false,
					"schema": {
						"type": "string"
					}
				}, {
					"name": "sid",
					"in": "query",
					"description": "sid",
					"required": false,
					"type": "string"
				}, {
					"name": "userPsw",
					"in": "query",
					"description": "userPsw",
					"required": false,
					"type": "string"
				}, {
					"name": "validateCode",
					"in": "query",
					"description": "validateCode",
					"required": false,
					"type": "string"
				}],
				"responses": {
					"200": {
						"description": "OK",
						"schema": {
							"type": "string"
						}
					},
					"401": {
						"description": "Unauthorized"
					},
					"403": {
						"description": "Forbidden"
					},
					"404": {
						"description": "Page Not Found"
					},
					"500": {
						"description": "Server Internal Error"
					}
				},
				"deprecated": false
			}
		},

再写多几个反复编译测试后。发现一个规律:

pont的param这里只处理query类型的参数

所以,对于Get请求,@ApiParam注解后,类型还是query,这里是没有问题;但是对于Post请求,@ApiParam注解后,类型会从query变成form,于是乎就无法导出到Param了。

而body部分,实际也还是会处理,仔细看有body导出的,接口的request里会多一个body参数,用来执行此部分的请求,例如上面的:

export function request(params: Params, body: string, options?: any): Promise<Response>
就是说,还是会执行,但是放到body请求了。但是mvc代码里没有@RequestBody来接收,实际执行还是有问题的

解决办法:
1)在@ApiParam上再加多一个@RequestParam注解
2)如果嫌注解太多难看,也可以抽离到ApiImplicitParam统一书写,ApiImplicitParam自带paramType可以指定为query
3)仔细核对swagger的类型,以前没有太留意这个,在生成API代码这里踩坑了

--------------- [ 2024/03/25 更新] ------------------

前面修改后,还是会有问题。当使用multipart/form-data上传文件时,发现数据始终传不上去。经过检查,发现axios最终上传的data为空。而FormData参数放到了param里面,因此,需要调整一下。当API里consumes有multipart/form-data时,把form参数放到data,否则才是放params。

调整后的 pontTemplates.ts如下:

import { Interface, BaseClass, Property, CodeGenerator, Surrounding } from 'pont-engine'

export default class MyGenerator extends CodeGenerator {
  getInterfaceContentInDeclaration(inter: Interface) {
    const requestParams = inter.getRequestParams()
    const paramsCode = inter.getParamsCode('Params')

    return `
      export ${paramsCode}

      export type Response = ${inter.responseType}

      export const init: Response;

      export function request(${requestParams}): Promise<Response>;
    `
  }

  getBaseClassInDeclaration(base: BaseClass) {
    const originProps = base.properties

    base.properties = base.properties.map((prop) => {
      return new Property({
        ...prop,
        required: false
      })
    })

    const result = super.getBaseClassInDeclaration(base)
    base.properties = originProps

    return result
  }

  getInterfaceContent(inter: Interface) {
    //const method = inter.method.toUpperCase()
    const axiosParamKey = 'GET' == inter.method.toUpperCase() ? 'params' : 'data' // 如果是GET,放param,如果是POST/PUT,放data
    const requestParams = inter.getRequestParams(this.surrounding)
    const paramsCode = inter.getParamsCode('Params', this.surrounding).replace(/([A-Za-z0-9_]+):/g, '$1?:') //适配严格模式
    const formAsData = inter.consumes?.includes('multipart/form-data') ? 'form' : 'params' // 如果是FormData,则data是form

    return `
    /**
     * @desc ${inter.description}
     */

    import * as defs from '../../baseClass';
    import { request as service } from '../../../utils/service';

    export ${paramsCode}

    export const init = ${inter.response.getInitialValue()};

    export function request(${requestParams}, jsonPost: boolean = false) {
      return service({url:"${inter.path}", ...${inter.getRequestContent()}, ${axiosParamKey}: ${formAsData}, jsonPost})
    }
   `
  }
}

这样就可以正常上传了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ZTEK USB-to-Serial Comm Port是一种驱动程序,可用于连接计算机与串口设备之间的通信。该驱动程序由ZTEK公司提供,用于使USB端口能够识别和使用串口设备。 USB-to-Serial驱动程序是一种在计算机与串口设备之间进行数据传输的桥梁。由于现代计算机不再配备串口,因此使用USB接口可以方便地将计算机连接到串口设备,如调制解调器、串口打印机、工业控制设备等。 安装ZTEK USB-to-Serial Comm Port驱动程序的步骤如下: 1. 首先,从ZTEK官方网站或其他可靠来源下载该驱动程序的安装文件。 2. 双击安装文件,并根据提示完成驱动程序的安装过程。 3. 安装完成后,插入USB-to-Serial转换器到计算机的USB接口上。 4. 计算机会自动识别并安装ZTEK USB-to-Serial Comm Port驱动程序。 5. 在设备管理器中,可以找到串口设备,在属性中可以查看到ZTEK USB-to-Serial Comm Port驱动程序的相关信息。 安装完成后,用户可以通过串口设备与计算机进行通信。例如,可以使用串口设备与其他设备进行数据传输、进行设备控制或进行固件升级等操作。 ZTEK USB-to-Serial Comm Port驱动程序能够提供稳定的数据传输,并兼容多种操作系统,如Windows、Mac和Linux等。用户可以根据自己的需要选择适合的驱动程序版本进行安装。同时,ZTEK还提供了技术支持,以解决用户在使用过程中遇到的问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值