【 CMS接口开发 】

1 页面查询接口定义

1.1 定义模型

1.1.1 需求分析

在梳理完用户需求后就要去定义前后端的接口,接口定义后前端和后端就可以依据接口去开发功能了。

本次定义页面查询接口,本接口供前端请求查询页面列表,支持分页及自定义条件查询方式。

具体需求如下:
1、分页查询CmsPage 集合下的数据
2、根据站点Id、模板Id、页面别名查询页面信息
3、接口基于Http Get请求,响应Json数据

1.1.2 模型类介绍

接口的定义离不开数据模型,根据前边对需求的分析,整个页面管理模块的数据模型如下:
【 CMS接口开发 】_第1张图片

  • CmsSite:站点模型
  • CmsTemplate:页面模板
  • CmsPage:页面信息

页面信息如下:

package com.xuecheng.framework.domain.cms;

import lombok.Data;
import lombok.ToString;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Date;
import java.util.List;

/**
 * @Author: mrt.
 * @Description:
 * @Date:Created in 2018/1/24 10:04.
 * @Modified By:
 */
@Data
@ToString
@Document(collection = "cms_page")
public class CmsPage {
    /**
     * 页面名称、别名、访问地址、类型(静态/动态)、页面模版、状态
     */
    //站点ID
    private String siteId;
    //页面ID
    @Id
    private String pageId;
    //页面名称
    private String pageName;
    //别名
    private String pageAliase;
    //访问地址
    private String pageWebPath;
    //参数
    private String pageParameter;
    //物理路径
    private String pagePhysicalPath;
    //类型(静态/动态)
    private String pageType;
    //页面模版
    private String pageTemplate;
    //页面静态化内容
    private String pageHtml;
    //状态
    private String pageStatus;
    //创建时间
    private Date pageCreateTime;
    //模版id
    private String templateId;
    //参数列表
    private List<CmsPageParam> pageParams;
    //模版文件Id
//    private String templateFileId;
    //静态文件Id
    private String htmlFileId;
    //数据Url
    private String dataUrl;

}

属性说明:
1、定义一个页面需要指定页面所属站点

一个站点包括多个页面,比如:学成在线的门户站点(网站)包括了多个页面。

2、定义一个页面需要指定页面使用的模板

多个页面可以使用相同的模板,比如:商品信息模板,每个商品就是一个页面,所有商品使用同一个商品信息模板

注解说明:
@Data、@ToString、@Document注解表示什么意思?

  • @Data、@ToString:是Lombok提供的注解
  • @Document:是Spring Data mongodb提供的注解,里面 collection 的值就是集合
  • @Id:指定集合的主键

1.2.3 Lombok

上边的Data注解表示什么意思呢?Data注解,ToString注解都是Lombok提供的注解。

Lombok是一个实用的java工具,使用它可以消除java代码的臃肿,Lombok提供一系列的注解,使用这些注解可以不用定义getter/setter、equals、构造方法等,它会在编译时在字节码文件自动生成这些通用的方法,简化开发
人员的工作。

项目官方地址:https://www.projectlombok.org/

比如上节创建的UserTest模型,@Data注解可以自动生成getter/setter方法,@ToString生成tostring方法。

使用方法:
1、在项目中添加Lombok的依赖
作用:项目在编译时根据Lombok注解生成通用方法。

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
dependency>

2、在IDEA开发工具中添加Lombok插件
作用:使用IDEA开发时根据Lombok注解生成通用方法,不报错。
【 CMS接口开发 】_第2张图片
【 CMS接口开发 】_第3张图片

1.2 定义接口

1.2.1 定义请求及响应类型

1、定义请求模型QueryPageRequest,此模型作为查询条件类型
为后期扩展需求,请求类型统一继承RequestData类型。

package com.xuecheng.framework.domain.cms.request;

import lombok.Data;

/**
 *  定义请求类型
 */
@Data
public class QueryPageRequest {
    //站点id
    private String siteId;
    //页面ID
    private String pageId;
    //页面名称
    private String pageName;
    //别名
    private String pageAliase;
    //模版id
    private String templateId;
}

2、响应结果类型,分页查询统一使用QueryResponseResult

package com.xuecheng.framework.model.response;

import lombok.Data;
import lombok.ToString;

@Data
@ToString
public class QueryResponseResult extends ResponseResult {

    QueryResult queryResult;

    public QueryResponseResult(ResultCode resultCode,QueryResult queryResult){
        super(resultCode);
       this.queryResult = queryResult;
    }

}
package com.xuecheng.framework.model.response;

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * @Author: mrt.
 * @Description:
 * @Date:Created in 2018/1/24 18:33.
 * @Modified By:
 */
@Data
@ToString
@NoArgsConstructor
public class ResponseResult implements Response {

    //操作是否成功
    boolean success = SUCCESS;

    //操作代码
    int code = SUCCESS_CODE;

    //提示信息
    String message;

    public ResponseResult(ResultCode resultCode){
        this.success = resultCode.success();
        this.code = resultCode.code();
        this.message = resultCode.message();
    }

    public static ResponseResult SUCCESS(){
        return new ResponseResult(CommonCode.SUCCESS);
    }
    public static ResponseResult FAIL(){
        return new ResponseResult(CommonCode.FAIL);
    }

}
package com.xuecheng.framework.model.response;

/**
 * Created by admin on 2018/3/5.
 */
public interface Response {
    public static final boolean SUCCESS = true;
    public static final int SUCCESS_CODE = 10000;
}

1.2.2 定义接口

Api接口工程专门定义接口,在Api工程单独定义接口的原因如下:
1、接口集中管理
2、Api工程的接口将作为各微服务远程调用使用。

页面查询接口定义如下:

package com.xuecheng.api.cms;

import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.QueryResponseResult;

/**
 * 页面查询接口
 */
public interface CmsPageControllerApi {

    public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest);
}

此接口编写后会在CMS服务工程编写Controller类实现此接口。

2 页面查询服务端开发

2.1 创建CMS服务工程

2.1.1 创建CMS工程结构

创建maven工程, CMS工程的名称为 xc-service-manage-cms,父工程为xc-framework-parent。

pom.xml如下:


<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>xc-framework-parentartifactId>
        <groupId>com.xuechenggroupId>
        <version>1.0-SNAPSHOTversion>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>xc-service-manage-cmsartifactId>

    <dependencies>
    <dependency>
        <groupId>com.xuechenggroupId>
        <artifactId>xc-service-apiartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
    <dependency>
    <groupId>com.xuechenggroupId>
        <artifactId>xc-framework-modelartifactId>
        <version>1.0-SNAPSHOTversion>
    dependency>
        <dependency>
            <groupId>com.xuechenggroupId>
            <artifactId>xc-framework-utilsartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>
        <dependency>
            <groupId>com.xuechenggroupId>
            <artifactId>xc-framework-commonartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-freemarkerartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-mongodbartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-amqpartifactId>
        dependency>
        <dependency>
            <groupId>com.squareup.okhttp3groupId>
            <artifactId>okhttpartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
        dependency>
    dependencies>
    
project>

由于cms工程要连接mongodb所以需要在在cms服务端工程添加如下依赖:

项目使用spring data mongodb操作mongodb数据库

<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-data-mongodbartifactId>
dependency>

2、创建基本的包结构:

  • com.xuecheng.manage_cms.config:配置类目录,数据库配置、MQ配置等
  • com.xuecheng.manage_cms.dao:dao接口目录
  • com.xuecheng.manage_cms.service:service类目录
  • com.xuecheng.manage_cms.web.controller:controller类目录

工程结构如下:
【 CMS接口开发 】_第4张图片

3、配置文件
在classpath下配置application.yml

server:
  port: 31001
spring:
  application:
    name: xc-service-manage-cms
  data:
    mongodb:
      uri: mongodb://root:[email protected]:27017
      database: xc_cms

创建工程的日志配置文件logback-spring.xml



<configuration>
    
    <property name="LOG_HOME" value="d:/logs"/>

    
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
            <charset>utf8charset>
        encoder>
    appender>

    
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            
            <fileNamePattern>${LOG_HOME}/xc.%d{yyyy-MM-dd}.logfileNamePattern>
        rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%npattern>
        encoder>
    appender>

    
    <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        
        <discardingThreshold>0discardingThreshold>
        
        <queueSize>512queueSize>
        
        <appender-ref ref="FILE"/>
    appender>


    <logger name="org.apache.ibatis.cache.decorators.LoggingCache" level="DEBUG" additivity="false">
        <appender-ref ref="CONSOLE"/>
    logger>
    <logger name="org.springframework.boot" level="DEBUG"/>
    <root level="info">
        
        <appender-ref ref="FILE"/>
        <appender-ref ref="CONSOLE"/>
    root>
configuration>

4、SpringBoot 启动类
Spring Boot应用需要创建一个应用启动类,启动过程中会扫描Bean并注入spring 容器

注意:此类创建在本工程com.xuecheng.manage_cms包下,因为只会扫描本包或子包下面的类

package com.xuecheng.manage_cms;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@EntityScan("com.xuecheng.framework.domain.cms")// 扫描xc-framework-model模块下面的实体类
@ComponentScan(basePackages={"com.xuecheng.api"})// 扫描xc-service-api模块下面的接口
@ComponentScan(basePackages={"com.xuecheng.manage_cms"})// 扫描本模块下的所有类
public class ManageCmsApplication {
    public static void main(String[] args) {
        SpringApplication.run(ManageCmsApplication.class, args);
    }
}

2.1.2 测试Controller

使用springMVC完成接口实现开发,这里暂时使用测试数据,稍后会让controller调用service来查询数据。

package com.xuecheng.manage_cms.controller;

import com.xuecheng.api.cms.CmsPageControllerApi;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/cms/page")
public class CmsPageController implements CmsPageControllerApi {

    @Override
    @GetMapping("/list/{page}/{size}")
    public QueryResponseResult findList(@PathVariable("page") int page,
                                        @PathVariable("size") int size,
                                        QueryPageRequest queryPageRequest) {
        //暂时采用测试数据,测试接口是否可以正常运行
        QueryResult<CmsPage> queryResult = new QueryResult();
        queryResult.setTotal(2);
        //静态数据列表
        List<CmsPage> list = new ArrayList();
        CmsPage cmsPage = new CmsPage();
        cmsPage.setPageName("测试页面");
        list.add(cmsPage);

        queryResult.setList(list);
        
        QueryResponseResult queryResponseResult = new
                QueryResponseResult(CommonCode.SUCCESS, queryResult);
        return queryResponseResult;
    }
}

使用浏览器测试,输入:http://localhost:31001/cms/page/list/1/10 查询第1页,每页显示10条记录。

【 CMS接口开发 】_第5张图片

{
  "success": true,
  "code": 10000,
  "message": "操作成功!",
  "queryResult": {
    "list": [
      {
        "siteId": null,
        "pageId": null,
        "pageName": "测试页面",
        "pageAliase": null,
        "pageWebPath": null,
        "pageParameter": null,
        "pagePhysicalPath": null,
        "pageType": null,
        "pageTemplate": null,
        "pageHtml": null,
        "pageStatus": null,
        "pageCreateTime": null,
        "templateId": null,
        "pageParams": null,
        "htmlFileId": null,
        "dataUrl": null
      }
    ],
    "total": 2
  }
}

为什么在 api 模块中定义接口,而不直接在 cms 模块中定义接口?

原因一:在 api 模块中统一的管理接口;
原因二:微服务与微服务之间的远程调用都是基于接口调用的,如果将接口定义在不同的微服务中,若微服务A要调用微服务B,那么微服务A依赖微服务B才能拿到该接口,而现在我们将接口统一的定义在了 api 模块中,那么只需要依赖 api 模块,就能拿到所有的接口了;
原因三:如果我们以后接口的实现类不使用 SpringMVC 了,那么只需要修改实现类即可。

2.2 Dao

2.2.1 分页查询测试

2.2.1.1 定义Dao接口

本项目使用Spring Data Mongodb完成Mongodb数据库的查询,Spring Data Mongodb提供一套快捷操作mongodb的方法。

创建Dao,继承MongoRepository,并指定实体类型和主键类型。

CmsPageRepository

package com.xuecheng.manage_cms.dao;

import com.xuecheng.framework.domain.cms.CmsPage;
import org.springframework.data.mongodb.repository.MongoRepository;

public interface CmsPageRepository extends MongoRepository<CmsPage, String> {
}

2.2.1.2 编写测试类

【 CMS接口开发 】_第6张图片
test下的包路径与main下的包路径保持一致。

测试程序使用@SpringBootTest和@RunWith(SpringRunner.class)注解,启动测试类会从main下找springBoot启动类,加载spring容器。

分页查询测试

package com.xuecheng.manage_cms;

import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.manage_cms.dao.CmsPageRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class CmsPageRepositoryTest {

    @Autowired
    CmsPageRepository cmsPageRepository;

    // 分页测试
    @Test
    public void testFindPage() {
        int page = 0; // 从0开始
        int size = 10; // 每页记录数
        Pageable pageable = PageRequest.of(page, size);
        Page<CmsPage> all = cmsPageRepository.findAll(pageable);
        System.out.println(all); // Page 1 of 3 containing com.xuecheng.framework.domain.cms.CmsPage instances
    }
}

2.2.2 基础方法测试

这里Dao接口继承了MongoRepository,在MongoRepository中定义了很多现成的方法,如save、delete等,通
过下边的代码来测试这里父类方法。
此小节内容请同学们自行测试。

2.2.3.1 添加

// 添加
@Test
public void testInsert(){
    // 定义实体类
    CmsPage cmsPage = new CmsPage();
    cmsPage.setSiteId("s01");
    cmsPage.setTemplateId("t01");
    cmsPage.setPageName("测试页面");
    cmsPage.setPageCreateTime(new Date());
    List<CmsPageParam> cmsPageParams = new ArrayList<
    CmsPageParam cmsPageParam = new CmsPageParam();
    cmsPageParam.setPageParamName("param1");
    cmsPageParam.setPageParamValue("value1");
    cmsPageParams.add(cmsPageParam);
    cmsPage.setPageParams(cmsPageParams);
    cmsPageRepository.save(cmsPage);
    System.out.println(cmsPage);
}

2.2.3.2 删除

// 删除
@Test
public void testDelete() {
    cmsPageRepository.deleteById("5b17a2c511fe5e0c409e5eb3");
}

2.2.3.3 修改

//修改
@Test
public void testUpdate() {
    Optional<CmsPage> optional = cmsPageRepository.findOne("5b17a34211fe5e2ee8c116c9");
    if(optional.isPresent()){
        CmsPage cmsPage = optional.get();
        cmsPage.setPageName("测试页面01");
        cmsPageRepository.save(cmsPage);
    }
}

关于Optional:
Optional是jdk1.8引入的类型,Optional是一个容器对象,它包括了我们需要的对象,使用isPresent方法判断所包含对象是否为空,isPresent方法返回false则表示Optional包含对象为空,否则可以使用get()取出对象进行操作。

Optional的优点是:
1、提醒你非空判断。
2、将对象非空检测标准化。

2.2.3.4 自定义Dao方法

同Spring Data JPA一样Spring Data mongodb也提供自定义方法的规则,如下:

按照findByXXX,findByXXXAndYYY、countByXXXAndYYY等规则定义方法,实现查询操作。

public interface CmsPageRepository extends MongoRepository<CmsPage,String> {

    //根据页面名称查询
    CmsPage findByPageName(String pageName);
    //根据页面名称和类型查询
    CmsPage findByPageNameAndPageType(String pageName,String pageType);
    //根据站点和页面类型查询记录数
    int countBySiteIdAndPageType(String siteId,String pageType);
    //根据站点和页面类型分页查询
    Page<CmsPage> findBySiteIdAndPageType(String siteId,String pageType, Pageable pageable);
}

2.3 Service

定义页面查询方法,根据条件查询暂时不实现:

package com.xuecheng.manage_cms.service;

import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.CommonCode;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.framework.model.response.QueryResult;
import com.xuecheng.manage_cms.dao.CmsPageRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

/**
 * @author Administrator
 * @version 1.0
 * @create 2018-09-12 18:32
 **/
@Service
public class PageService {

    @Autowired
    CmsPageRepository cmsPageRepository;

    /**
     * 页面查询方法
     * @param page 页码,从1开始记数;但是调用dao时是从0开始
     * @param size 每页记录数
     * @param queryPageRequest 查询条件
     * @return
     */
    public QueryResponseResult findList(int page, int size, QueryPageRequest queryPageRequest){

        // 分页参数
        if(page <= 0){
            page = 1; // 暴露给 controller
        }
        page = page - 1;
        if(size <= 0){
            size = 10;
        }
        Pageable pageable = PageRequest.of(page, size);
        Page<CmsPage> all = cmsPageRepository.findAll(pageable);
        QueryResult queryResult = new QueryResult();
        queryResult.setList(all.getContent()); // 数据列表
        queryResult.setTotal(all.getTotalElements()); // 数据总记录数
        QueryResponseResult queryResponseResult = new QueryResponseResult(CommonCode.SUCCESS, queryResult);
        return queryResponseResult;
    }
}

2.4 Controller

使用springMVC完成接口实现开发。

package com.xuecheng.manage_cms.controller;

import com.xuecheng.api.cms.CmsPageControllerApi;
import com.xuecheng.framework.domain.cms.request.QueryPageRequest;
import com.xuecheng.framework.model.response.QueryResponseResult;
import com.xuecheng.manage_cms.service.PageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/cms/page")
public class CmsPageController implements CmsPageControllerApi {

    @Autowired
    private PageService pageService;

    @Override
    @GetMapping("/list/{page}/{size}")
    public QueryResponseResult findList(@PathVariable("page") int page,
                                        @PathVariable("size") int size,
                                        QueryPageRequest queryPageRequest) {
        
        return pageService.findList(page, size, queryPageRequest);
    }
}

使用浏览器测试

输入:http://localhost:31001/cms/page/list/1/10 查询第1页,每页显示10条记录。

【 CMS接口开发 】_第7张图片

{
  "success": true,
  "code": 10000,
  "message": "操作成功!",
  "queryResult": {
    "list": [
      {
        "siteId": "5a751fab6abb5044e0d19ea1",
        "pageId": "5a754adf6abb500ad05688d9",
        "pageName": "index.html",
        "pageAliase": "首页",
        "pageWebPath": "/index.html",
        "pageParameter": null,
        "pagePhysicalPath": "F:\\develop\\xc_portal_static\\",
        "pageType": "0",
        "pageTemplate": null,
        "pageHtml": null,
        "pageStatus": null,
        "pageCreateTime": "2018-02-03T05:37:53.256+0000",
        "templateId": "5a962b52b00ffc514038faf7",
        "pageParams": null,
        "htmlFileId": "5a7c1c54d019f14d90a1fb23",
        "dataUrl": null
      },
      {
        "siteId": "5a751fab6abb5044e0d19ea1",
        "pageId": "5a795ac7dd573c04508f3a56",
        "pageName": "index_banner.html",
        "pageAliase": "轮播图",
        "pageWebPath": "/include/index_banner.html",
        "pageParameter": null,
        "pagePhysicalPath": "F:\\develop\\xc_portal_static\\include\\",
        "pageType": "0",
        "pageTemplate": null,
        "pageHtml": null,
        "pageStatus": null,
        "pageCreateTime": "2018-02-06T07:34:21.255+0000",
        "templateId": "5a962bf8b00ffc514038fafa",
        "pageParams": null,
        "htmlFileId": "5a795bbcdd573c04508f3a59",
        "dataUrl": null
      }
    ],
    "total": 22
  }
}

2.6 接口开发规范

2.6.1 Api 请求及响应规范

为了严格按照接口进行开发,提高效率,对请求及响应格式进行规范化。
1、get 请求时,采用key/value格式请求,SpringMVC可采用基本类型的变量接收,也可以采用对象接收。

2、Post请求时,可以提交form表单数据(application/x-www-form-urlencoded)和Json数据(ContentType=application/json),文件等多部件类型(multipart/form-data)三种数据格式,SpringMVC接收Json数据,使用@RequestBody注解解析请求的json数据。

3、响应结果统一信息为:是否成功、操作代码、提示信息及自定义数据。

4、响应结果统一格式为json。

2.6.2 Api定义约束

Api定义使用SpringMVC来完成,由于此接口后期将作为微服务远程调用使用,在定义接口时有如下限制:
1、@PathVariable 统一指定参数名称,如:@PathVariable(“id”)

2、@RequestParam统一指定参数名称,如:@RequestParam(“id”)

你可能感兴趣的:(文章)