首页 文章 精选 留言 我的

精选列表

搜索[AI生态],共10000篇文章
优秀的个人博客,低调大师

【SpringCloud技术专题】「原生态Fegin」打开Fegin之RPC技术的开端,你会使用原生态的Fegin吗?(上)

前提介绍 Feign是SpringCloud中服务消费端的调用框架,通常与ribbon,hystrix等组合使用。 由于遗留原因,某些项目中,整个系统并不是SpringCloud项目,甚至不是Spring项目,而使用者关注的重点仅仅是简化http调用代码的编写。 如果采用httpclient或者okhttp这样相对较重的框架,对初学者来说编码量与学习曲线都会是一个挑战,而使用spring中RestTemplate,又没有配置化的解决方案,由此想到是否可以脱离Spring cloud,独立使用Feign。 内容简介 Feign使得 Java HTTP 客户端编写更方便。Feign 灵感来源于Retrofit、JAXRS-2.0和WebSocket。Feign最初是为了降低统一绑定Denominator到HTTP API的复杂度,不区分是否支持Restful。Feign旨在通过最少的资源和代码来实现和HTTP API的连接。通过可定制的解码器和错误处理,可以编写任意的HTTP API。 maven依赖 <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-core</artifactId> <version>8.18.0</version> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-jackson</artifactId> <version>8.18.0</version> </dependency> <dependency> <groupId>io.github.lukehutch</groupId> <artifactId>fast-classpath-scanner</artifactId> <version>2.18.1</version> </dependency> <dependency> <groupId>com.netflix.feign</groupId> <artifactId>feign-jackson</artifactId> <version>8.18.0</version> </dependency> 定义配置类 RemoteService service = Feign.builder() .options(new Options(1000, 3500)) .retryer(new Retryer.Default(5000, 5000, 3)) .encoder(new JacksonEncoder()) .decoder(new JacksonDecoder()) .target(RemoteService.class, "http://127.0.0.1:8085"); options方法指定连接超时时长及响应超时时长 retryer方法指定重试策略 target方法绑定接口与服务端地址。 返回类型为绑定的接口类型。 自定义接口 随机定义一个远程调用的服务接口,并且声明相关的接口参数和请求地址。 通过@RequestLine指定HTTP协议及URL地址 public class User{ String userName; } public interface RemoteService { @Headers({"Content-Type: application/json","Accept: application/json"}) @RequestLine("POST /users/list") User getOwner(User user); @RequestLine("POST /users/list2") @Headers({ "Content-Type: application/json", "Accept: application/json", "request-token: {requestToken}", "UserId: {userId}", "UserName: {userName}" }) public User getOwner(@RequestBody User user, @Param("requestToken") String requestToken, @Param("userId") Long userId, @Param("userName") String userName); } 服务提供者 import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Controller @RequestMapping(value="users") public class UserController { @RequestMapping(value="/list",method={RequestMethod.GET,RequestMethod.POST,RequestMethod.PUT}) @ResponseBody public User list(@RequestBody User user) throws InterruptedException{ System.out.println(user.getUsername()); user.setId(100L); user.setUsername(user.getUsername().toUpperCase()); return user; } } 调用 与调用本地方法相同的方式调用feign包装的接口,直接获取远程服务提供的返回值。 String result = service.getOwner(new User("scott")); 原生Feign的两个问题 原生Feign只能一次解析一个接口,生成对应的请求代理对象,如果一个包里有多个调用接口就要多次解析非常麻烦。 Feign生成的调用代理只是一个普通对象,该如何注册到Spring中,以便于我们可以使用@Autowired随时注入。 解决方案: 针对多次解析的问题,可以通过指定扫描包路径,然后对包中的类依次解析。 实现BeanFactoryPostProcessor接口,扩展Spring容器功能。 定义一个注解类 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface FeignApi { /** * 调用的服务地址 * @return */ String serviceUrl(); } 生成Feign代理并注册到Spring实现类: import feign.Feign; import feign.Request; import feign.Retryer; import feign.jackson.JacksonDecoder; import feign.jackson.JacksonEncoder; import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner; import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.stereotype.Component; import java.util.List; @Component public class FeignClientRegister implements BeanFactoryPostProcessor{ //扫描的接口路径 private String scanPath="com.xxx.api"; @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { List<String> classes = scan(scanPath); if(classes==null){ return ; } System.out.println(classes); Feign.Builder builder = getFeignBuilder(); if(classes.size()>0){ for (String claz : classes) { Class<?> targetClass = null; try { targetClass = Class.forName(claz); String url=targetClass.getAnnotation(FeignApi.class).serviceUrl(); if(url.indexOf("http://")!=0){ url="http://"+url; } Object target = builder.target(targetClass, url); beanFactory.registerSingleton(targetClass.getName(), target); } catch (Exception e) { throw new RuntimeException(e.getMessage()); } } } } public Feign.Builder getFeignBuilder(){ Feign.Builder builder = Feign.builder() .encoder(new JacksonEncoder()) .decoder(new JacksonDecoder()) .options(new Request.Options(1000, 3500)) .retryer(new Retryer.Default(5000, 5000, 3)); return builder; } public List<String> scan(String path){ ScanResult result = new FastClasspathScanner(path).matchClassesWithAnnotation(FeignApi.class, (Class<?> aClass) -> { }).scan(); if(result!=null){ return result.getNamesOfAllInterfaceClasses(); } return null; } } 调用接口编写示例: import com.xiaokong.core.base.Result; import com.xiaokong.domain.DO.DeptRoom; import feign.Headers; import feign.Param; import feign.RequestLine; import com.xiaokong.register.FeignApi; import java.util.List; @FeignApi(serviceUrl = "http://localhost:8085") public interface RoomApi { @Headers({"Content-Type: application/json","Accept: application/json"}) @RequestLine("GET /room/selectById?id={id}") Result<DeptRoom> selectById(@Param(value="id") String id); @Headers({"Content-Type: application/json","Accept: application/json"}) @RequestLine("GET /room/test") Result<List<DeptRoom>> selectList(); } 接口使用示例: @Service public class ServiceImpl{ //将接口注入要使用的bean中直接调用即可 @Autowired private RoomApi roomApi; @Test public void demo(){ Result<DeptRoom> result = roomApi.selectById("1"); System.out.println(result); } } 注意事项: 如果接口返回的是一个复杂的嵌套对象,那么一定要明确的指定泛型,因为Feign在解析复杂对象的时候,需要通过反射获取接口返回对象内部的泛型类型才能正确使用Jackson解析。如果不明确的指明类型,Jackson会将json对象转换成一个LinkedHashMap类型。 如果你使用的是的Spring,又需要通过http调用别人的接口,都可以使用这个工具来简化调用与解析的操作。

优秀的个人博客,低调大师

从“守护进程”到“无根”:Podman如何重塑容器化生态

长期以来,Docker几乎是容器技术的代名词。然而,随着容器应用深入生产环境,Docker的“单点架构”开始暴露出安全隐患与运维复杂性——其核心守护进程(dockerd)以root权限运行,一旦被攻破,整个宿主机即告沦陷;同时,守护进程的故障会导致所有容器失控。在这样的背景下,Podman作为新一代容器引擎强势崛起,以其无守护进程(Daemonless)、无根(Rootless)、兼容Kubernetes原生的设计理念,正在重新定义容器化的未来。

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册