大数跨境
0
0

9大核心技巧:让你的Spring Boot API性能提升300%

9大核心技巧:让你的Spring Boot API性能提升300% Spring全家桶实战案例
2025-11-18
0
导读:9大核心技巧:让你的Spring Boot API性能提升300%
Spring Boot 3实战案例锦集PDF电子书已更新至130篇!

🎉🎉《Spring Boot实战案例合集》目前已更新190个案例,我们将持续不断的更新。文末有电子书目录。

💪💪永久更新承诺

我们郑重承诺,所有订阅合集的粉丝都将享受永久免费的后续更新服务

💌💌如何获取
订阅我们的合集点我订阅,并通过私信联系我们,我们将第一时间将电子书发送给您。

→ 现在就订阅合集

环境:SpringBoot3.4.2



1. 简介

在使用Spring Boot项目开发中,你可能大部分时间都花在API集成上——调用第三方API、暴露自己的REST端点、处理身份验证、错误处理以及性能优化等等。

本篇文章将详细介绍关于API接口开发及调用中的9大核心开发技巧。

2.实战案例
2.1 远程接口调用超时&重试

默认情况下,若API无响应,RestTemplate或WebClient可能出现卡死现象。为此我们需要配置超时和重试机制。如下示例:

官方已经推荐使用WebClient,所以这里我们就以WebClient为例:
// 配置读写超时HttpClient httpClient = HttpClient.create()    .doOnConnected(conn -> conn        .addHandlerLast(new ReadTimeoutHandler(10))        .addHandlerLast(new WriteTimeoutHandler(10)));// 全局连接设置WebClient webClient = WebClient.builder()    .clientConnector(new ReactorClientHttpConnector(httpClient))    .build();
重试机制配置:
Mono<String> ret = webClient.get().uri("/data")    .retrieve()    .bodyToMono(String.class)    .retryWhen(Retry.fixedDelay(3Duration.ofSeconds(2)));
关于WebClient更多高级用法,请查看下面链接:
强悍的重试机制:Spring Boot 中 WebClient 弹性设计实战
2.2 熔断保护API

我们使用Resilience4j或Spring Cloud Circuit Breaker(引入对应的Resilientce4j实现)。接下来我们通过2种方式实现接口保护,基于注解和编程方式:

基于注解方式:

@CircuitBreaker(name = "a-info", fallbackMethod = "infoFallback")public Map<StringObjectinfo(Integer id) {  if (id == -1) {    throw new RuntimeException("非法数字") ;  }  return this.restTemplate.getForObject("http://localhost:8088/demos/info/{id}"Map.class, id) ;}public Map<StringObjectinfoFallback(Integer id, Throwable e) {  return Map.of("code", -1"message", e.getMessage(), "args", id) ;}
对应的配置文件
resilience4j:  circuitbreaker:    instances:      a-info:        minimum-number-of-calls: 10
基于编程方式:
private final WebClient webClient ; private final ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory ;public CircuitBreakerService(WebClient webClient,    ReactiveCircuitBreakerFactory reactiveCircuitBreakerFactory) {  this.webClient = webClient ;  this.reactiveCircuitBreakerFactory = reactiveCircuitBreakerFactory ;}// 接口调用public Mono<Map> reactiveInvoke(Integer id) {  return webClient.get()      .uri("/demos/info/{id}", id)      .retrieve().bodyToMono(Map.class)      .transform(it -> this.reactiveCircuitBreakerFactory.create("akk").run(it,          ex -> Mono.just(Map.ofEntries(entry("code", -1), entry("message", ex.getMessage()))))) ;}
这里我们需要引入对应的依赖:
<dependency>  <groupId>org.springframework.cloud</groupId>  <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId></dependency>
2.3 请求拦截增强
当我们需要对请求或者响应逻辑进行增强时,针对不同的Rest Client有不同的实现方式,接下我们就介绍基于RestClient和WebClient两种实现方式。
RestClient:
// 1.定义拦截器public class LoggerRequestInterceptor implements ClientHttpRequestInterceptor {  private static final Logger logger = LoggerFactory.getLogger("ClientHttpRequestInterceptor") ;  @Override  public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)      throws IOException {    logger.info("Rest Client request before...") ;    ClientHttpResponse response = execution.execute(request, body) ;    logger.info("Rest Client response after...") ;    return response ;  }}// 2.全局配置RestClient@BeanRestClient restClient(RestClient.Builder builder) {  RestClient restClient = builder      .requestInterceptor(new LoggerRequestInterceptor())      .build() ;  return restClient ;  }
WebClient:
WebClient webClient = WebClient.builder()    .clientConnector(new ReactorClientHttpConnector(httpClient))    .filter((request, next) -> {      ClientRequest filtered = ClientRequest.from(request)          .header("x-token""xxxooo-packxg")          .build() ;      return next.exchange(filtered);    })    .build();
在发送请求前添加header信息。
2.4 第三方接口调用限流
我们可以使用Bucket4j等库实现令牌桶算法;或使用Resilience4j的RateLimiter。如下使用RateLimiter实现限流:
@TimeLimiter(name = "api.timeout", fallbackMethod = "reactorTimeoutFallback")@GetMapping("/t")public Mono<Stringquery() {  return webClient.get().uri("http://localhost:8081/api/query").retrieve().bodyToMono(String.class) ;}public Mono<StringreactorTimeoutFallback(Throwable e) {  return Mono.just("请求超时") ;}
配置文件:
resilience4j:  timelimiter:    instances:      #该名称为上面注解中的name      queryUser:        timeout-duration: 1s
注意基于响应式的需要引入如下依赖:
<dependency>  <groupId>io.github.resilience4j</groupId>  <artifactId>resilience4j-reactor</artifactId>  <version>2.2.0</version></dependency>
2.5 正确处理4xx和5xx错误
在WebClient中已经为我们提供了对应的不同状态法的处理方式,如下示例:
webClient.get().uri("http://localhost:8081/api/query")  .retrieve()  .onStatus(HttpStatusCode::is4xxClientError, response ->       Mono.error(new RuntimeException("Client error")))  .onStatus(HttpStatusCode::is5xxServerError, response ->       Mono.error(new RuntimeException("Server error")))  .bodyToMono(String.class) ;
2.6 保护API接口安全
通过Spring Security能非常方便快速的构建安全的API保护机制,如下示例:
@Configurationpublic class SecurityConfig {  @Bean  SecurityFilterChain apiSecurity(HttpSecurity http) throws Throwable {    http.csrf(csrf -> csrf.disable()) ;    http.securityMatcher("/api/**""/login") ;    http.formLogin(Customizer.withDefaults()) ;    http.authorizeHttpRequests(registry -> {      registry.anyRequest().authenticated() ;    }) ;    return http.build() ;  }  // 配置内存用户(你也可以直接在配置文件中配置)  @Bean  UserDetailsService userDetailsService() {    UserDetails user = User.withUsername("pack")      .password("{noop}123123")      .roles("ADMIN")      .build() ;    return new InMemoryUserDetailsManager(user) ;  }}
在上面的SecurityFilterChain配置中,我们将只会对/api/*,/login接口进行拦截。如果没有权限将会自动定向到登录页面。
2.7 API接口测试

使用 MockWebServer(来自 OkHttp)或 WireMock 模拟 API 响应。在单元测试中使用 @MockBean RestTemplate/WebClient。如下示例:

@WebMvcTest(UserController.class)public class UserControllerTest1 {  // 用于模拟 HTTP 请求。  @Resource  private MockMvc mockMvc;  // 被模拟的服务(真实的服务被忽略)。  @MockitoBean  private UserService userService;  @Test  public void testUsers() throws Exception {    // 1.设置模拟行为    when(userService.queryUsers()).thenReturn(List.of(new User(1L"pack"33))) ;    // 2.模拟 HTTP GET 请求到 /users 并验证响应    mockMvc.perform(get("/users"))      .andExpect(status().isOk())      .andExpect(jsonPath("$[0].name").value("pack"));  }  @Test  public void testUser() throws Exception {    when(userService.queryUser(1L))      .thenThrow(new UserNotFoundException());    mockMvc.perform(get("/users/1"))      .andExpect(status().isNotFound());  }}
关于测试的更多内容,请查看下面链接:
8种测试方法,让 Spring Boot 接口稳定性提升 200%
2.8 并发API接口调用
为了提升接口性能,我们使用 WebClient 进行并行调用(zip、merge、flatMap)。如下示例:
Mono<String> request1 = webClient.get()  .uri("http://localhost:8081/api/query")  .retrieve()  .bodyToMono(String.class);Mono<String> request2 = webClient.get()  .uri("http://localhost:8081/api/query")  .retrieve()  .bodyToMono(String.class);String ret = Mono.zip(request1, request2)    .map(tuple -> tuple.getT1() + ", " + tuple.getT2())    .block();System.err.println(ret) ;
如此,API调用就能并行运行,而不是顺序执行。
2.9 多API版本控制

要定义多版本的API接口,我们可以采用URL版本控制 → /api/v1/users, /api/v2/users;基于头部的版本控制 → X-API-VERSION: 1;内容协商 → Accept: application/vnd.app.v1+json。如下示例:

@GetMapping(value = "/query", headers = "X-API-VERSION=1")public String queryV1() { return "User v1"; }
@GetMapping(value = "/query", headers = "X-API-VERSION=2")public String queryV2() { return "User v2"; }
关于多版本API更高级应用,请查看下面链接:
优雅!自定义注解轻松管理多版本Controller接口

以上是本篇文章的全部内容,如对你有帮助帮忙点赞+转发+收藏
Spring Boot 多版本API控制 5 种实现方案

确保Spring Boot定时任务只执行一次方案

弃用HTTP!Spring Boot 集成 GRPC 优化接口调用性能

Spring Boot自定义注解玩转Controller接口参数任意转换

强大!基于Spring Boot动态注册 / 删除Controller接口(支持动态上传)

绝了!8个 Spring Boot 开发必备技能

简单!详解@RefreshScope动态刷新核心原理

查漏补缺!OpenFeign整合Resilience4j,你真的会用吗?

Spring Boot 通过 6 种方式实现开关功能,最后一种直接封神

TargetSource炸场!Spring AOP动态换“靶”超神!

高手必备!Spring Boot 非常实用的10个核心扩展点

图片
图片
图片
图片
图片
图片
图片
图片
图片

【声明】内容源于网络
0
0
Spring全家桶实战案例
Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
内容 832
粉丝 0
Spring全家桶实战案例 Java全栈开发,前端Vue2/3全家桶;Spring, SpringBoot 2/3, Spring Cloud各种实战案例及源码解读
总阅读38
粉丝0
内容832