# OpenFeign **Repository Path**: tangcco/open-feign ## Basic Information - **Project Name**: OpenFeign - **Description**: SpringClould组件OpenFeign - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2021-01-30 - **Last Updated**: 2022-06-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ``` http 的背景原理 a. 两台服务器建立 http 连接的过程是很复杂的一个过程,涉及到多个数据包的交换,并且也很耗时间。 b. Http 连接需要的 3 次握手 4 次分手开销很大,这一开销对于大量的比较小的 http 消息来说更大。 2优化解决方案 a. 如果我们直接采用 http 连接池,节约了大量的 3 次握手 4 次分手;这样能大大提升吞吐率。 b. feign 的 http 客户端支持 3 种框架;HttpURLConnection、httpclient、okhttp;默认是HttpURLConnection。 c. 传统的 HttpURLConnection 是 JDK 自带的,并不支持连接池,如果要实现连接池的机制,还需要自己来管理连接对象。 对于网络请求这种底层相对复杂的操作,如果有可用的其他方案,也没有必要自己去管理连接对象。 d. HttpClient 相比传统 JDK 自带的 HttpURLConnection,它封装了访问 http 的请求头,参数,内容体,响应等等; 它不仅使客户端发送 HTTP 请求变得容易,而且也方便了开发人员测试接口(基于 Http 协议的),即提高了开发的效率,也方便提高代码的健壮性; 另外高并发大量的请求网络的时候,还是用“连接池”提升吞吐量。 ``` ```shell maven打包时可以通过两种方式传入参数: a)、通过 -D命令传入属性值profileActive,如:clean install -Dmaven.test.skip=true -DprofileActive=dev b)、通过-P命令指定profile环境,如:clean package -P prod ``` ### 启动注册中心 ```shell ./consul agent -dev -client=0.0.0.0 -ui ``` ### service-provider #### 1. pom.xml ```xml 4.0.0 org.springframework.boot spring-boot-starter-parent 2.4.2 cn.kgc.tangcco idiom-provider 0.0.1-SNAPSHOT war idiom-provider consul project for Spring Boot 15 2020.0.0 org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-data-jpa org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-commons org.springframework.cloud spring-cloud-starter-consul-discovery org.springframework.boot spring-boot-devtools runtime true mysql mysql-connector-java runtime com.alibaba druid-spring-boot-starter 1.2.4 org.springframework.boot spring-boot-configuration-processor true org.projectlombok lombok true org.springframework.boot spring-boot-starter-tomcat provided org.springframework.boot spring-boot-starter-test test org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin ${project.artifactId} ../package org.projectlombok lombok spring-milestones Spring Milestones https://repo.spring.io/milestone ``` #### 2. 配置文件 ```yaml server: port: 8080 compression: enabled: true # 是否开启压缩 servlet: encoding: force: true charset: UTF-8 spring: application: name: idiom-provider #应用名称 集群环境下相同 servlet: multipart: max-file-size: 50MB # 文件上传大小限制为500kb max-request-size: 200MB # 请求大小限制为500kb datasource: url: jdbc:mysql://47.94.130.233:3306/knowledge?useUnicode=true&characterEncoding=UTF8&useSSL=true&serverTimeZone=Aisa/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: # 下面为连接池的补充设置,应用到上面所有数据源中 # 初始化大小,最小,最大 initial-size: 5 min-idle: 5 max-active: 200 # 配置获取连接等待超时的时间 max-wait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 time-between-eviction-runs-millis: 60000 # 配置一个连接在池中最小生存的时间,单位是毫秒 min-evictable-idle-time-millis: 300000 validation-query: SELECT 1 FROM DUAL test-while-idle: true test-on-borrow: false test-on-return: false # 打开PSCache,并且指定每个连接上PSCache的大小 pool-prepared-statements: true # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 max-pool-prepared-statement-per-connection-size: 20 filters: stat,wall,slf4j use-global-data-source-stat: true # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 connect-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 stat-view-servlet: login-username: admin login-password: 123456 reset-enable: false url-pattern: /druid/* allow: 0.0.0.0 #deny: enabled: true web-stat-filter: url-pattern: /* exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*" jpa: database: MySQL database-platform: org.hibernate.dialect.MySQL8Dialect show-sql: true hibernate: ddl-auto: none cloud: consul: host: 192.168.1.110 # 注册中心地址 port: 8500 # 注册中心端口 discovery: register: true # 是否注册 instance-id: ${spring.application.name}-00 # 注册实例 id 必须唯一 service-name: ${spring.application.name} # 服务名称 port: ${server.port} # 服务端口 prefer-ip-address: true # 是否使用 ip 注册 ip-address: ${spring.cloud.client.ip-address} # 服务请求 ip heartbeat: enabled: true # 是否打开心跳监测 # 度量指标监控与健康检查 management: endpoints: web: exposure: include: shutdown # 开启 shutdown 端点访问 endpoint: shutdown: enabled: true # 开启 shutdown 请求方式必须是post health: show-details: ALWAYS logging: level: com.netflix: warn ``` #### 3. pojo类 ```java package cn.kgc.tangcco.pojo; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; import org.hibernate.annotations.DynamicInsert; import org.hibernate.annotations.DynamicUpdate; import javax.persistence.*; import java.io.Serializable; /** * @author 李昊哲 * @Description * @create 2020/12/29 14:22 */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) @DynamicInsert @DynamicUpdate @Table(name = "idiom") @Entity public class Idiom implements Serializable { private static final long serialVersionUID = 7553935244407585482L; /** * 主键ID */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id; /** * 成语 */ @Column(name = "name") private String name; /** * 拼音 */ @Column(name = "spell") private String spell; /** * 解释 */ @Column(name = "content") private String content; /** * 典故 */ @Column(name = "derivation") private String derivation; /** * 举例句子 */ @Column(name = "samples") private String samples; } ``` ```java package cn.kgc.tangcco.pojo; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; /** * @author 李昊哲 * @Description * @create 2021/1/30 10:54 */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class Paginator { private Integer page; private Integer size; } ``` #### 4. 持久层接口 ```java package cn.kgc.tangcco.repository; import cn.kgc.tangcco.pojo.Idiom; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; /** * @author 李昊哲 * @Description * @create 2020/12/29 14:48 */ @Repository public interface IdiomRepository extends JpaRepository, JpaSpecificationExecutor {} ``` #### 5. service接口 ```java package cn.kgc.tangcco.service; import cn.kgc.tangcco.pojo.Idiom; import org.springframework.data.domain.Page; import java.util.List; /** * @author 李昊哲 * @Description * @create 2020/12/29 14:51 */ public interface IdiomService { /** * 分页查询 * * @param page 查询页码 * @param size 每页记录数 * @return */ public Page findAll(Integer page, Integer size); /** * 根据主键查找 * * @param id * @return */ public Idiom findById(Integer id); public Idiom save(Idiom idiom); public Long deleteById(Integer id); public long count(); } ``` #### 6. service实现类 ```java package cn.kgc.tangcco.service.impl; import cn.kgc.tangcco.pojo.Idiom; import cn.kgc.tangcco.repository.IdiomRepository; import cn.kgc.tangcco.service.IdiomService; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.Optional; /** * @author 李昊哲 * @Description * @create 2021/1/27 11:51 */ @Service public class IdiomServiceImpl implements IdiomService { private final IdiomRepository idiomRepository; public IdiomServiceImpl(IdiomRepository idiomRepository) { this.idiomRepository = idiomRepository; } @Override public Page findAll(Integer page, Integer size) { return idiomRepository.findAll(PageRequest.of(page - 1, size)); } @Override public Idiom findById(Integer id) { Optional optional = idiomRepository.findById(id); if (optional.isEmpty()) { return null; } return optional.get(); } @Transactional @Override public Idiom save(Idiom idiom) { return idiomRepository.saveAndFlush(idiom); } @Transactional @Override public Long deleteById(Integer id) { long count = idiomRepository.count(); idiomRepository.deleteById(id); return count - idiomRepository.count(); } @Override public long count() { return idiomRepository.count(); } } ``` #### 7. controller ```java package cn.kgc.tangcco.controller; import cn.kgc.tangcco.pojo.Idiom; import cn.kgc.tangcco.pojo.Paginator; import cn.kgc.tangcco.service.IdiomService; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @author 李昊哲 * @Description * @create 2021/1/27 11:59 */ @RestController @RequestMapping(value = "/idiom") public class IdiomController { private final IdiomService idiomService; public IdiomController(IdiomService idiomService) { this.idiomService = idiomService; } @GetMapping(value = "/count") public long count() { return idiomService.count(); } @GetMapping(value = "/findById/{id}") public Idiom findById(@PathVariable("id") Integer id) { return idiomService.findById(id); } @GetMapping(value = "/findAllWithGetForm") public Page findAllWithGetForm(Integer page, Integer size) { return idiomService.findAll(page, size); } @PostMapping(value = "/findAllWithPostForm") public Page findAllWithPostForm(Integer page, Integer size) { return idiomService.findAll(page, size); } @PostMapping(value = "/findAllWithPostJson") public Page findAllWithPostJson(@RequestBody Paginator paginator) { return idiomService.findAll(paginator.getPage(), paginator.getSize()); } @PutMapping(value = "/save") public Idiom save(@RequestBody Idiom idiom) { return idiomService.save(idiom); } @DeleteMapping(value = "/deleteById/{id}") public Long deleteById(@PathVariable("id") Integer id) { return idiomService.deleteById(id); } } ``` ### idiom-consumer #### 1. pom.xml ```xml 4.0.0 org.springframework.boot spring-boot-starter-parent 2.4.2 cn.kgc.tangcco idiom-consumer 0.0.1-SNAPSHOT war idiom-consumer consul project for Spring Boot 15 2020.0.0 org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-consul-discovery org.springframework.cloud spring-cloud-starter-openfeign io.github.openfeign feign-httpclient 11.0 io.github.openfeign feign-okhttp 11.0 org.springframework.boot spring-boot-devtools runtime true org.springframework.boot spring-boot-configuration-processor true org.projectlombok lombok true org.springframework.boot spring-boot-starter-tomcat provided org.springframework.boot spring-boot-starter-test test org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import org.springframework.boot spring-boot-maven-plugin ${project.artifactId} ../package org.projectlombok lombok spring-milestones Spring Milestones https://repo.spring.io/milestone ``` #### 2. 配置文件 ```yaml spring: profiles: active: httpclient ``` ```yaml server: port: 80 compression: enabled: true # 是否开启压缩 servlet: encoding: force: true charset: UTF-8 spring: application: name: idiom-consumer #应用名称 集群环境下相同 servlet: multipart: max-file-size: 50MB # 文件上传大小限制为500kb max-request-size: 200MB # 请求大小限制为500kb cloud: consul: host: 192.168.1.110 # 注册中心地址 port: 8500 # 注册中心端口 discovery: register: false # 是否注册 instance-id: ${spring.application.name}-01 # 注册实例 id 必须唯一 service-name: ${spring.application.name} # 服务名称 port: ${server.port} # 服务端口 prefer-ip-address: true # 是否使用 ip 注册 ip-address: ${spring.cloud.client.ip-address} # 服务请求 ip heartbeat: enabled: true # 是否打开心跳监测 feign: httpclient: enabled: true logging: level: com.netflix: warn ``` ```yaml server: port: 80 compression: enabled: true # 是否开启压缩 servlet: encoding: force: true charset: UTF-8 spring: application: name: idiom-consumer #应用名称 集群环境下相同 servlet: multipart: max-file-size: 50MB # 文件上传大小限制为500kb max-request-size: 200MB # 请求大小限制为500kb cloud: consul: host: 192.168.1.110 # 注册中心地址 port: 8500 # 注册中心端口 discovery: register: false # 是否注册 instance-id: ${spring.application.name}-01 # 注册实例 id 必须唯一 service-name: ${spring.application.name} # 服务名称 port: ${server.port} # 服务端口 prefer-ip-address: true # 是否使用 ip 注册 ip-address: ${spring.cloud.client.ip-address} # 服务请求 ip heartbeat: enabled: true # 是否打开心跳监测 feign: okhttp: enabled: true logging: level: com.netflix: warn ``` #### 3. pojo类 ```java package cn.kgc.tangcco.pojo; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; import java.io.Serializable; /** * @author 李昊哲 * @Description * @create 2020/12/29 14:22 */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class Idiom implements Serializable { private static final long serialVersionUID = 7553935244407585482L; /** * 主键ID */ private Integer id; /** * 成语 */ private String name; /** * 拼音 */ private String spell; /** * 解释 */ private String content; /** * 典故 */ private String derivation; /** * 举例句子 */ private String samples; } ``` ```java package cn.kgc.tangcco.pojo; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; import lombok.experimental.Accessors; /** * @author 李昊哲 * @Description * @create 2021/1/30 10:54 */ @Setter @Getter @NoArgsConstructor @AllArgsConstructor @Accessors(chain = true) public class Paginator { private Integer page; private Integer size; } ``` #### 4. service接口 ```java package cn.kgc.tangcco.service; import cn.kgc.tangcco.pojo.Idiom; import cn.kgc.tangcco.pojo.Paginator; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @author 李昊哲 * @Description * @create 2020/12/29 14:51 */ @FeignClient("idiom-provider") public interface IdiomService { @GetMapping(value = "/idiom/count") public long count(); @GetMapping(value = "/idiom/findById/{id}") public Idiom findById(@PathVariable("id") Integer id); /** * 分页查询 * * @param page 查询页码 * @param size 每页记录数 * @return */ @GetMapping(value = "/idiom/findAllWithGetForm") public String findAllWithGetForm(@RequestParam Integer page, @RequestParam Integer size); /** * 分页查询 * * @param page 查询页码 * @param size 每页记录数 * @return */ @PostMapping(value = "/idiom/findAllWithPostForm") public String findAllWithPostForm(@RequestParam Integer page, @RequestParam Integer size); /** * 分页查询 * * @return */ @PostMapping(value = "/idiom/findAllWithPostJson") public String findAllWithPostJson(@RequestBody Paginator paginator); @PutMapping(value = "/idiom/save") public Idiom save(@RequestBody Idiom idiom); @DeleteMapping(value = "/idiom/deleteById/{id}") public Long deleteById(@PathVariable("id") Integer id); } ``` #### 5. controller ```java package cn.kgc.tangcco.controller; import cn.kgc.tangcco.pojo.Idiom; import cn.kgc.tangcco.pojo.Paginator; import cn.kgc.tangcco.service.IdiomService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @author 李昊哲 * @Description * @create 2021/1/27 11:59 */ @RestController @RequestMapping(value = "/idiom") public class IdiomController { @Autowired private IdiomService idiomService; @GetMapping(value = "/count") public long count() { return idiomService.count(); } @GetMapping(value = "/findById/{id}") public Idiom findById(@PathVariable("id") Integer id) { return idiomService.findById(id); } @GetMapping(value = "/findAllWithGetForm") public String findAllWithGetForm( @RequestParam(name = "page", defaultValue = "1", required = true) Integer page, @RequestParam(name = "size", defaultValue = "2", required = true) Integer size) { return idiomService.findAllWithGetForm(page, size); } @PostMapping(value = "/findAllWithPostForm") public String findAllWithPostForm( @RequestParam(name = "page", defaultValue = "1", required = true) Integer page, @RequestParam(name = "size", defaultValue = "2", required = true) Integer size) { return idiomService.findAllWithPostForm(page, size); } @PostMapping(value = "/findAllWithPostJson") public String findAllWithPostJson(@RequestBody Paginator paginator) { return idiomService.findAllWithPostJson(paginator); } @PutMapping(value = "/save") public Idiom save(Idiom idiom) { return idiomService.save(idiom); } @DeleteMapping(value = "/deleteById/{id}") public Long deleteById(@PathVariable("id") Integer id) { return idiomService.deleteById(id); } } ``` #### 6. 启动类 ```java package cn.kgc.tangcco; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestOperations; @EnableFeignClients @SpringBootApplication public class IdiomConsumerApplication { public static void main(String[] args) { SpringApplication.run(IdiomConsumerApplication.class, args); } } ``` #### 7. 测试 ##### 7.1 GET方式无参数的请求 测试地址:http://localhost/idiom/count 请求方式:GET 请求参数:无 返回结果:31851 ##### 7.2 GET方式地址栏传参 测试地址:http://localhost/idiom/findById/ 请求方式:GET 请求参数:3 返回结果: ```json { "id": 3, "name": "备而不用", "spell": "bèi ér bù yòng", "content": "准备好了,以备急用,眼下暂存不用。", "derivation": "清·吴趼人《糊涂世界》:“虽说备而不用,到得那时候,听凭兵丁造一句谣言,开上几排枪,那人可就死了不少。”", "samples": "凡是零星物件,本地买不出,一定要用,或是~的,也都齐全。(清·颐琐《黄绣球》第十七回)" } ``` ##### 7.3 GET方式传参 测试地址:http://localhost/idiom/findAllWithGetForm 请求方式:GET 请求参数: | key | value | | ---- | ----- | | page | 2 | | size | 2 | 返回结果: ```json { "content": [ { "id": 3, "name": "备而不用", "spell": "bèi ér bù yòng", "content": "准备好了,以备急用,眼下暂存不用。", "derivation": "清·吴趼人《糊涂世界》:“虽说备而不用,到得那时候,听凭兵丁造一句谣言,开上几排枪,那人可就死了不少。”", "samples": "凡是零星物件,本地买不出,一定要用,或是~的,也都齐全。(清·颐琐《黄绣球》第十七回)" }, { "id": 4, "name": "贝阙珠宫", "spell": "bèi què zhū gōng", "content": "用珍珠宝贝做的宫殿。形容房屋华丽。", "derivation": "战国·楚·屈原《九歌·河伯》:“鱼鳞屋兮龙堂,紫贝阙兮朱宫。”", "samples": "你看那香焚宝鼎,紫雾漾漾,玉楼金殿,~,便如天宫之景也。(明·无名氏《庆长生》第四折)" } ], "pageable": { "sort": { "sorted": false, "unsorted": true, "empty": true }, "offset": 2, "pageSize": 2, "pageNumber": 1, "paged": true, "unpaged": false }, "last": false, "totalPages": 15926, "totalElements": 31851, "size": 2, "number": 1, "sort": { "sorted": false, "unsorted": true, "empty": true }, "first": false, "numberOfElements": 2, "empty": false } ``` ##### 7.4 POST方式表单传参 测试地址:http://localhost/idiom/findAllWithPostForm 请求方式:POST 请求参数: | key | value | | ---- | ----- | | page | 2 | | size | 2 | 返回结果: ```json { "content": [ { "id": 3, "name": "备而不用", "spell": "bèi ér bù yòng", "content": "准备好了,以备急用,眼下暂存不用。", "derivation": "清·吴趼人《糊涂世界》:“虽说备而不用,到得那时候,听凭兵丁造一句谣言,开上几排枪,那人可就死了不少。”", "samples": "凡是零星物件,本地买不出,一定要用,或是~的,也都齐全。(清·颐琐《黄绣球》第十七回)" }, { "id": 4, "name": "贝阙珠宫", "spell": "bèi què zhū gōng", "content": "用珍珠宝贝做的宫殿。形容房屋华丽。", "derivation": "战国·楚·屈原《九歌·河伯》:“鱼鳞屋兮龙堂,紫贝阙兮朱宫。”", "samples": "你看那香焚宝鼎,紫雾漾漾,玉楼金殿,~,便如天宫之景也。(明·无名氏《庆长生》第四折)" } ], "pageable": { "sort": { "sorted": false, "unsorted": true, "empty": true }, "offset": 2, "pageSize": 2, "pageNumber": 1, "paged": true, "unpaged": false }, "last": false, "totalPages": 15926, "totalElements": 31851, "size": 2, "number": 1, "sort": { "sorted": false, "unsorted": true, "empty": true }, "first": false, "numberOfElements": 2, "empty": false } ``` ##### 7.5 POST方式传递json 测试地址:http://localhost/idiom/findAllWithPostJson 请求方式:POST 请求参数: ```json { "page":"4", "size":"2" } ``` 返回结果: ```json { "content": [ { "id": 7, "name": "毕恭毕敬", "spell": "bì gōng bì jìng", "content": "形容态度十分恭敬。", "derivation": "《诗经·小雅·小弁》:“维桑与梓,必恭敬止,靡瞻匪父,靡依匪母。”", "samples": "他~地将书递给了老师,请求解答两个疑难问题。" }, { "id": 8, "name": "婢作夫人", "spell": "bì zuò fū rén", "content": "婢:侍女;夫人:主妇。旧时指在文艺方面虽刻意模仿别人,但才力和作品的规模总赶不上。", "derivation": "唐·张彦远《法书要录》引南朝梁袁昂《古今书评》:“羊欣书如大家婢为夫人。虽处其位,而举止羞涩,终不似真。”", "samples": "不过偶尔学着写,正是~,那里及得到大哥什一。(清·吴趼人《二十年目睹之怪现状》第四十一回)" } ], "pageable": { "sort": { "sorted": false, "unsorted": true, "empty": true }, "offset": 6, "pageNumber": 3, "pageSize": 2, "paged": true, "unpaged": false }, "last": false, "totalPages": 15926, "totalElements": 31851, "size": 2, "number": 3, "sort": { "sorted": false, "unsorted": true, "empty": true }, "first": false, "numberOfElements": 2, "empty": false } ``` ##### 7.6 PUT新增数据 测试地址:http://localhost/idiom/save 请求方式:PUT 请求参数: | key | value | | ---------- | ------------------------------------------------------------ | | name | 桃李不言下自成蹊 | | spell | táo lǐ bù yán xià zì chéng xī | | content | 原意是桃树和李树不主动招引人,但人们都来看它们开出的鲜花,采摘它们结出的果实,在树下走成了一条小路。 | | derivation | 西汉·司马迁《史记·李将军列传论》:“太史公曰:传曰:‘其身正,不令而行;其身不正,虽令不从。’其李将军之谓也。余睹李将军,悛悛如鄙人,口不能道辞。及死之日,天下知与不知,皆为尽哀。彼其忠实心诚信于士大夫也。谚曰:‘桃李不言,下自成蹊。’此言虽小,可以谕大也。” | | samples | 俗话说:“桃李不言,下自成蹊”,你不必过于急躁 。 | 返回结果: ```json { "id": 31852, "name": "桃李不言下自成蹊", "spell": "táo lǐ bù yán xià zì chéng xī", "content": "原意是桃树和李树不主动招引人,但人们都来看它们开出的鲜花,采摘它们结出的果实,在树下走成了一条小路。", "derivation": " 西汉·司马迁《史记·李将军列传论》:“太史公曰:传曰:‘其身正,不令而行;其身不正,虽令不从。’其李将军之谓也。余睹李将军,悛悛如鄙人,口不能道辞。及死之日,天下知与不知,皆为尽哀。彼其忠实心诚信于士大夫也。谚曰:‘桃李不言,下自成蹊。’此言虽小,可以谕大也。”", "samples": "俗话说:“桃李不言,下自成蹊”,你不必过于急躁 。" } ``` ##### 7.7 PUT修改数据 测试地址:http://localhost/idiom/save 请求方式:PUT 请求参数: | key | value | | ---------- | ------------------------------------------------------------ | | id | 31852 | | name | 桃李不言下自成蹊 | | spell | táo lǐ bù yán xià zì chéng xī | | content | 比喻为人品德高尚、诚实、正直,用不着自我宣传,就自然受到人们的[尊重](https://baike.baidu.com/item/尊重/788873)和敬仰。 | | derivation | 西汉·司马迁《史记·李将军列传论》:“太史公曰:传曰:‘其身正,不令而行;其身不正,虽令不从。’其李将军之谓也。余睹李将军,悛悛如鄙人,口不能道辞。及死之日,天下知与不知,皆为尽哀。彼其忠实心诚信于士大夫也。谚曰:‘桃李不言,下自成蹊。’此言虽小,可以谕大也。” | | samples | 俗话说:“桃李不言,下自成蹊”,你不必过于急躁 。 | 返回结果: ```json { "id": 31852, "name": "桃李不言下自成蹊", "spell": "táo lǐ bù yán xià zì chéng xī", "content": "比喻为人品德高尚、诚实、正直,用不着自我宣传,就自然受到人们的尊重和敬仰。", "derivation": " 西汉·司马迁《史记·李将军列传论》:“太史公曰:传曰:‘其身正,不令而行;其身不正,虽令不从。’其李将军之谓也。余睹李将军,悛悛如鄙人,口不能道辞。及死之日,天下知与不知,皆为尽哀。彼其忠实心诚信于士大夫也。谚曰:‘桃李不言,下自成蹊。’此言虽小,可以谕大也。”", "samples": "俗话说:“桃李不言,下自成蹊”,你不必过于急躁 。" } ``` ##### 7.8 DELETE地址栏传参 测试地址:http://localhost/idiom/deleteById/ 请求方式:DELETE 请求参数:31852 返回结果:1