FeignClient和RestFul使用笔记

简介

这篇文章主要讲解FeignClient解析和RestFul的开发使用和一些简单注意事项。

  1. FeignClient分两种介绍,一个指定请求、一个注册中心寻找;也就是如何动态url和指定url、注册中心寻找
  2. RestFul的几种解读和差异:GetMapping、PostMapping、PutMapping、DeleteMapping、PatchMapping

实践讲解

FeignClient例子

在feiignClient之前,我们来编写如下代码
UserCenterClient 客户端调用类

package com.lgh.client;
import lombok.Data;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import java.net.URI;
@FeignClient(name = "test", url = "EMPTY")
public interface UserCenterClient {
    
    
    @PostMapping("/feign/{id}/client")
    public String client(URI uri, @RequestHeader(value = "token", required = true) String token,
                         @PathVariable("id") int id,
                         @RequestBody User user);
    @Data
    class User {
    
    
        private String userId;
        private String passwd;
    }
}

调用方式 TestController

package com.lgh.controller;
import com.lgh.client.UserCenterClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.net.URI;
import java.net.URISyntaxException;
@Api(tags = "测试feignClient")
@RestController
@RequestMapping("/feign")
@Slf4j
public class TestController {
    
    
    @Autowired
    private UserCenterClient userCenterClient;

    @ApiOperation("测试springmvc和feignClient")
    @PostMapping("/{id}/client")
    public String client(@RequestHeader(value = "token", required = true) String token,
                         @PathVariable("id") int id,
                         @RequestBody UserCenterClient.User user) throws URISyntaxException {
    
    
        return userCenterClient
                .client(new URI("http://localhost:8080")
                        , token, id, user);
    }
}

上面地址是动态指定url来调用http://localhost:8080
服务类TestController

package com.lgh.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@Api(tags = "测试feignClient")
@RestController
@RequestMapping("/feign")
@Slf4j
public class TestController {
    
    

    @ApiOperation("测试springmvc和feignClient")
    @PostMapping("/{id}/client")
    public String client(@RequestHeader(value = "token", required = true) String token,
                         @PathVariable("id") int id, @RequestBody User user) {
    
    
        log.info("token={},id={},user={}", token, id, user.toString());
        return "OK";
    }

    @Data
    class User {
    
    
        private String userId;
        private String passwd;

        @Override
        public String toString() {
    
    
            return "User{" +
                    "userId='" + userId + '\'' +
                    ", passwd='" + passwd + '\'' +
                    '}';
        }
    }
}

通过如上例子可以动态指定url调用服务器的地址,只要参数中存在URI即可。具体实现都在代理类中解析,分四步

  1. feign.ReflectiveFeign#newInstance解析FeignClient
  2. feign.Contract.BaseContract#parseAndValidateMetadata解析元数据
  3. feign.Contract.BaseContract#parseAndValidateMetadata(java.lang.Class<?>, java.lang.reflect.Method) 解析对参数判断,设置urlIndex的值寻找target目标,如下代码
 protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
    
    
 // ……
  if (parameterTypes[i] == URI.class) {
    
    
          data.urlIndex(i);
        }
 }else if (!isHttpAnnotation && parameterTypes[i] != Request.Options.class) {
    
    
  //……
 }
 //……
  1. feign.ReflectiveFeign.BuildTemplateByResolvingArgs#create构造中判断是否有指定url
 public RequestTemplate create(Object[] argv) {
    
    
 //……
if (metadata.urlIndex() != null) {
    
    
        int urlIndex = metadata.urlIndex();
        checkArgument(argv[urlIndex] != null, "URI parameter %s was null", urlIndex);
        mutable.target(String.valueOf(argv[urlIndex]));
      }
 //……
}

FeignClient解析

FeignClient注解我们比较关注的是几个属性;

  1. value或者name
    这里是设置请求的应用,当url和参数的URI未设置时,这里生效即服务注册名称,FeignClient调用时从注册中心寻找轮询。
  2. url
    指定url。当参数为存在uri时,此参数生效,即FeignClient请求的目标服务地址
  3. path 这里是请求路径,当方法参数未存在URI时,此路径生效

RestFul用法

其实RestFul每种都有自己特点,主要做的就是规约。也是spring官网对DispatcherServlet的完善补充。具体其实有get和post方法请求即可,但是为了更好归约和编程规范,便出现RestFul概念。

/**
* @author Juergen Hoeller
 * @author Arjen Poutsma
 * @author Sam Brannen
 * @since 2.5
 * @see GetMapping
 * @see PostMapping
 * @see PutMapping
 * @see DeleteMapping
 * @see PatchMapping
 */
 @Target({
    
    ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
    
    
//…………
}
  1. GetMapping
    从服务器获取参数时,使用get请求类型,这里获取参数不能通过RequestBody设置,因为参数在request的Param中。也就是会限制路径长度,使用时要预估参数是否超限。
  2. PostMapping
    上送提交参数,是一次性上送全部参数时使用,和PatchMapping相对应,因为PatchMapping也就是部分提交不具备幂等性,PostMapping全量表单提交,具备幂等性,这里是以post请求方式提交,是流时传输,一般来说不限制大小。
  3. PutMapping
    更新数据,也就是需要更新记录时使用此方法
  4. DeleteMapping
    删除数据,删除服务器数据时使用此方式
  5. PatchMapping
    部分更新数据,不具备幂等性是PostMapping的扩展

总结

1)FeignClient中如果要动态请求URL,则可以在方法入参中传入URI
2)FeignClient如果要设置指定的URL可以设置FeignClient属性URL
3)RestFul使用特性每种方法均有意义。get请求无法通过@RequestBody获取参数值,可通过@RequestParam指定参数值
4)PATCH和PUT方法的区别,两种均是更新操作。PUT全量,PATCH部分。PUT具备幂等意义,PATCH不具备。

参考文献

[1] PATCH和PUT方法的区别

猜你喜欢

转载自blog.csdn.net/soft_z1302/article/details/114750038
今日推荐