欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中HTTP接口請求重試的實(shí)現(xiàn)方式

 更新時(shí)間:2024年01月04日 09:07:17   作者:有一只柴犬  
HTTP接口請求重試是指在請求失敗時(shí),再次發(fā)起請求的機(jī)制,在實(shí)際應(yīng)用中,由于網(wǎng)絡(luò)波動(dòng)、服務(wù)器故障等原因,HTTP接口請求可能會(huì)失敗,為了保證系統(tǒng)的可用性和穩(wěn)定性,需要對HTTP接口請求進(jìn)行重試,所以本文給大家介紹了HTTP接口請求重試的實(shí)現(xiàn)方式,需要的朋友可以參考下

1、前言

HTTP接口請求重試是指在請求失敗時(shí),再次發(fā)起請求的機(jī)制。在實(shí)際應(yīng)用中,由于網(wǎng)絡(luò)波動(dòng)、服務(wù)器故障等原因,HTTP接口請求可能會(huì)失敗。為了保證系統(tǒng)的可用性和穩(wěn)定性,需要對HTTP接口請求進(jìn)行重試。

2、實(shí)現(xiàn)方式

今天給大家分享一些常見的接口請求重試的方式。本地模擬了一個(gè)請求接口,后面的代碼示例均模擬請求該接口:

@GetMapping("http_test")
public String getHttpTest(){
    return "接口請求成功,返回:OK";
}

2.1、循環(huán)重試

循環(huán)重試是最簡單最粗暴的方式,就是在請求接口代碼中加入循環(huán)機(jī)制,如果接口請求失敗,則循環(huán)繼續(xù)發(fā)起接口請求,直到請求成功或接口重試次數(shù)達(dá)到上限。如果請求成功,則不進(jìn)行重試。

簡單代碼示例如下:

@GetMapping("retry_demo_loop")
public String retry_demo_loop(){
    // 重試上限次數(shù)為3次
    int maxRetryTime = 3;
    String result = null;
    // 接口循環(huán)請求
    for (int i = 1; i <= maxRetryTime; i++) {
        try {
            // 模擬請求接口
            result = HttpUtil.get("http://localhost:8080/http_test");
            // 模擬一次請求失敗
            if(i == 1){
                int co = i / 0;
            }
            // 請求成功,跳出循環(huán)
            break;
        } catch (Exception e) {
            log.error("接口請求異常,進(jìn)行第{}次重試", i);
            result = "接口請求失敗,請聯(lián)系管理員";
        }
    }
    return result;
}

請求結(jié)果:

重試日志打?。?/p>

2.2、遞歸重試

除了循環(huán),還可以使用遞歸來實(shí)現(xiàn)接口的請求重試。遞歸是我們都比較熟悉的編程技巧,在請求接口的方法中調(diào)用自身,如果請求失敗則繼續(xù)調(diào)用,直到請求成功或達(dá)到最大重試次數(shù)。

@GetMapping("retry_demo_rec")
public String retry_demo_rec(){
    // 重試上限次數(shù)為3次
    int maxRetryTime = 3;
    return retryRequest(maxRetryTime);
}
 
/**
 * 遞歸方法
 * @param maxRetryTime
 * @return
 */
private String retryRequest(int maxRetryTime){
    if (maxRetryTime <= 0) {
        return "接口請求失敗,請聯(lián)系管理員";
    }
 
    int retryTime = 0;
    try {
        // 模擬請求接口
        String result = HttpUtil.get("http://localhost:8080/http_test");
        // 模擬一次請求失敗
        if(maxRetryTime == 3){
            int co = 1 / 0;
        }
        return result;
    } catch (Exception e) {
        // 處理異常
        log.error("接口請求異常,進(jìn)行第{}次重試", ++retryTime);
        return retryRequest(maxRetryTime - 1);
    }
}

請求結(jié)果:

重試日志打?。?/p>

2.3、Spring Retry

第三種便是使用Spring Retry依賴實(shí)現(xiàn)。首先我們需要集成相關(guān)依賴:

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
<!-- 由于retry使用到了aop,所以還需要加入aop依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

加入@EnableRetry啟動(dòng):

@EnableRetry
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

添加retry方法注解:

public interface MyRetryService {
 
    /**
     * retryable注解表示該方法需要重試
     * value:出現(xiàn)該指定異常后,進(jìn)行重試
     * maxAttempts:重試次數(shù)上限,這里指定為3次
     * backoff:重試策略,這里指定200ms間隔一次
     * @param code
     * @return
     * @throws Exception
     */
    @Retryable(value = {Exception.class}, maxAttempts = 3, backoff = @Backoff(200))
    String retry(int code) throws Exception;
 
 
    /**
     * 當(dāng)重試達(dá)到上限后還是失敗,則作為異?;卣{(diào)方法
     * @param th
     * @param code
     * @return
     */
    @Recover
    String recover(Throwable th, int code);
 
}

MyReretService實(shí)現(xiàn)類:

@Slf4j
@Service
public class MyRetryServiceImpl implements MyRetryService {
 
    @Override
    public String retry(int code) throws Exception {
        log.info("請求retry接口");
        String result = HttpUtil.get("http://localhost:8080/http_test");
        if(code != 200){
            throw new Exception("接口請求異常");
        }
 
        return result;
    }
 
    @Override
    public String recover(Throwable th, int code) {
        log.error("回調(diào)方法執(zhí)行!?。?!");
        return "異常碼為:" + code + ",異常信息:" + th.getMessage();
    }
}

Controller:

@Autowired
private MyRetryService myRetryService;
 
 
/**
 * 當(dāng)請求code參數(shù)為200時(shí),直接成功
 * 當(dāng)code參數(shù)!=200時(shí),會(huì)出發(fā)重試
 * @param code
 * @return
 * @throws Exception
 */
@GetMapping("retry_demo_spring_retry")
public String retry_demo_spring_retry(Integer code) throws Exception {
    return myRetryService.retry(code);
}

訪問地址:http://localhost:8080/retry_demo_spring_retry?code=123

查看結(jié)果:可以看到接口重試了3次,最后執(zhí)行了@Recover方法最后的回調(diào)。

2.4、Resilience4j

Resilience4j是一個(gè)輕量級(jí)、易于使用的輕量級(jí)“容錯(cuò)”包。它受Neflix Hystrix啟發(fā)但只有一個(gè)依賴(Vavr),而不像Hystrix很多很多的依賴。同時(shí)它是一個(gè) Java 庫,可以幫助我們構(gòu)建彈性和容錯(cuò)的應(yīng)用程序。Resilience4j在“容錯(cuò)”方面提供了各種模式:斷路器(Circuit Breaker)、重試(Retry)、限時(shí)器(Time Limiter)、限流器(Rate Limiter)、隔板(BulkHead)。我們今天討論的話題是重試,那么今天就來演示下Retry。

Github地址:GitHub - resilience4j/resilience4j: Resilience4j is a fault tolerance library designed for Java8 and functional programming

首先,添加相應(yīng)依賴:

<dependency>
    <groupId>io.github.resilience4j</groupId>
    <artifactId>resilience4j-spring-boot2</artifactId>
    <version>2.1.0</version>
</dependency>

application.yml配置相關(guān)策略,配置官方文檔:https://resilience4j.readme.io/docs/retry

resilience4j:
  retry:
    instances:
      retry_demo:
        max-attempts: 3     # 重試的上限次數(shù)
        wait-duration: 1s   # 重試的間隔時(shí)間,配置為1s

我們改造一下上面spring-retry的demo。

controller:

@GetMapping("retry_demo_spring_retry")
@Retry(name = "retry_demo", fallbackMethod = "recover")
public String retry_demo_spring_retry(Integer code) throws Exception {
    return myRetryService.retry(code);
}
 
public String recover(Throwable th) {
    log.error("回調(diào)方法執(zhí)行?。。。?);
    return "異常信息:" + th.getMessage();
}

myRetryService:

@Override
public String retry(int code) throws Exception {
    log.info("請求retry接口");
    String result = HttpUtil.get("http://localhost:8080/http_test");
    if(code != 200){
        throw new Exception("接口請求異常");
    }
    return result;
}

程序執(zhí)行,打印結(jié)果:

同樣接口請求了3次,均失敗后執(zhí)行了fallback回調(diào)方法。

2.5、http請求網(wǎng)絡(luò)工具內(nèi)置重試方式

通常一些外部的http網(wǎng)絡(luò)工具,都會(huì)內(nèi)置一些重試的策略。如Apache HttpClient。這里以httpclient5為例。

首先添加依賴:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.1.4</version>
</dependency>

定義HttpClient相關(guān)類,指定重試策略??梢允褂媚J(rèn)的DefaultHttpRequestRetryStrategy,也可以自定義重試策略CustomRetryStrategy。

private static volatile CloseableHttpClient HTTP_CLIENT = null;
    static {
        if(HTTP_CLIENT == null){
            synchronized (HelloWorldController.class) {
                if(HTTP_CLIENT == null){
                    HTTP_CLIENT = HttpClients.custom()
                            // 設(shè)置重試策略
//                            .setRetryStrategy(new DefaultHttpRequestRetryStrategy(3, TimeValue.NEG_ONE_SECOND))
                            // 自定義重試策略
                            .setRetryStrategy(new CustomRetryStrategy())
                            .build();
                }
            }
        }
    }

CustomRetryStrategy:

public static class CustomRetryStrategy implements HttpRequestRetryStrategy {
 
    @Override
    public boolean retryRequest(HttpRequest httpRequest, IOException e, int executeCount, HttpContext httpContext) {
        return false;
    }
 
    @Override
    public boolean retryRequest(HttpResponse httpResponse, int executeCount, HttpContext httpContext) {
        System.out.println("進(jìn)入重試策略");
        if(executeCount > 3){
            System.out.println("重試超過3次,終止重試");
            return false;
        }
 
        if(httpResponse.getCode() != 200){
            System.out.println("http狀態(tài)碼不等于200,進(jìn)行重試");
            return true;
        }
 
        // 其他情況,不重試
        return false;
    }
 
    @Override
    public TimeValue getRetryInterval(HttpResponse httpResponse, int executeCount, HttpContext httpContext) {
        return null;
    }
}

Controller代碼:

@GetMapping("retry_demo_httpclient")
public String retry_demo_httpclient(Integer code) throws Exception {
    return httpclientRetry(code);
}
 
private String httpclientRetry(int code) throws Exception {
    log.info("請求retry接口");
    // 這里模擬了一個(gè)不存在的地址
    HttpGet request = new HttpGet("http://localhost:8080/http_test1");
    CloseableHttpResponse httpResponse = HTTP_CLIENT.execute(request);
    String result = IoUtil.read(httpResponse.getEntity().getContent()).toString();
    if(code != 200){
        throw new Exception("接口請求異常");
    }
 
    return result;
}

訪問接口地址:http://localhost:8080/retry_demo_httpclient?code=200。查看控制臺(tái)日志打?。?/p>

2.6、自定義重試工具

裝X的話,我們還可以自定義我們的重試工具。其實(shí)無非以下幾個(gè)步驟:

  • 自定義重試的工具類
  • 接收一個(gè)方法調(diào)用,并對該方法進(jìn)行異常捕獲
  • 如果捕獲了該異常,則進(jìn)行一定間隔,然后重新請求
  • 記錄請求次數(shù),如果超過上限,則提示異常信息

直接定義一個(gè)重試的工具類RetryUtil.java:

import cn.hutool.core.thread.ThreadUtil;
import lombok.extern.slf4j.Slf4j;
 
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.function.Supplier;
 
@Slf4j
public class RetryUtil {
 
 
    /**
     * 重試方法
     * @param invokeFunc   原方法調(diào)用
     * @param maxAttempts  重試次數(shù)上限
     * @param deplay   重試的間隔時(shí)間
     * @param timeUnit   重試的間隔時(shí)間單位
     * @param faultFunc   如果超過重試上限次數(shù),那么會(huì)執(zhí)行該錯(cuò)誤回調(diào)方法
     * @return
     * @param <T>
     */
    public static <T> T retry(Supplier<T> invokeFunc, int maxAttempts, long deplay, TimeUnit timeUnit, Function<Throwable, T> faultFunc) {
        AtomicInteger retryTimes = new AtomicInteger(0);
        for(;;) {
            try{
                return invokeFunc.get();
            } catch (Throwable th) {
                if(retryTimes.get() > maxAttempts){
                    log.error("重試次數(shù)超過{}次,進(jìn)入失敗回調(diào)", retryTimes.get());
                    return faultFunc.apply(th);
                }
                ThreadUtil.sleep(deplay, timeUnit);
                retryTimes.getAndAdd(1);
            }
        }
    }
 
}

工具類使用:

@GetMapping("retry_demo_custom")
public String retry_demo_custom(Integer code)  {
    return RetryUtil.retry(() -> {
        String result = null;
        try {
            result = customRetry(code);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return result;
    }, 3, 1000, TimeUnit.MILLISECONDS, Throwable::getMessage);
}
 
private String customRetry(int code) throws Exception {
    log.info("請求customRetry接口");
    String result = HttpUtil.get("http://localhost:8080/http_test");
    if(code != 200){
        throw new Exception("接口請求異常");
    }
 
    return result;
}

執(zhí)行完后,訪問地址:http://localhost:8080/retry_demo_custom?code=2001

這里只是簡單的進(jìn)行了定義,如果項(xiàng)目中使用肯定需要考慮更復(fù)雜的因素。如進(jìn)入重試時(shí)不一定只有異常的時(shí)候需要重試,可以指定重試策略,然后制定進(jìn)入重試策略的規(guī)則。

2.7、并發(fā)框架異步重試

在 Java 并發(fā)框架中,異步重試通常涉及到使用線程池和定時(shí)器,以便在異步任務(wù)失敗后進(jìn)行重試。以下是一個(gè)簡單的示例,演示了如何使用 CompletableFuture、ScheduledExecutorService 和 CompletableFuture.supplyAsync 來實(shí)現(xiàn)異步任務(wù)的重試。

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
 
public class AsyncRetryExample {
 
    private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
 
    public static void main(String[] args) {
        // 示例異步任務(wù),這里使用 supplyAsync,你可以根據(jù)實(shí)際情況選擇其他異步任務(wù)
        CompletableFuture<String> asyncTask = CompletableFuture.supplyAsync(() -> performAsyncTask("Task"));
 
        // 異步任務(wù)失敗后的重試邏輯
        retryAsyncTask(asyncTask, 3, 1, TimeUnit.SECONDS);
    }
 
    private static CompletableFuture<String> performAsyncTask(String taskName) {
        // 模擬異步任務(wù),這里可以是任何異步操作
        System.out.println("Performing async task: " + taskName);
        // 這里模擬任務(wù)失敗的情況
        throw new RuntimeException("Task failed");
    }
 
    private static <T> void retryAsyncTask(CompletableFuture<T> asyncTask, int maxRetries, long delay, TimeUnit timeUnit) {
        asyncTask.exceptionally(throwable -> {
            // 異步任務(wù)失敗后的處理邏輯
            System.out.println("Task failed: " + throwable.getMessage());
 
            // 重試邏輯
            if (maxRetries > 0) {
                System.out.println("Retrying...");
 
                CompletableFuture<T> retryTask = CompletableFuture.supplyAsync(() -> performAsyncTask("Retry Task"));
                // 遞歸調(diào)用,進(jìn)行重試
                retryAsyncTask(retryTask, maxRetries - 1, delay, timeUnit);
            } else {
                System.out.println("Max retries reached. Task failed.");
            }
 
            return null; // 必須返回 null,否則會(huì)影響鏈?zhǔn)秸{(diào)用
        });
    }
}

示例中,performAsyncTask 模擬了一個(gè)異步任務(wù),如果任務(wù)失敗,它會(huì)拋出一個(gè)運(yùn)行時(shí)異常。retryAsyncTask 方法用于處理異步任務(wù)的失敗情況,并進(jìn)行重試。在重試時(shí),它使用 CompletableFuture.supplyAsync 創(chuàng)建一個(gè)新的異步任務(wù),模擬了重試的過程。請注意,這只是一個(gè)簡單的示例,實(shí)際應(yīng)用中可能需要更復(fù)雜的重試策略和錯(cuò)誤處理邏輯。

2.8、消息隊(duì)列

網(wǎng)上還有一種消息隊(duì)列的方式來實(shí)現(xiàn),這里沒過多的去研究過,目前以上幾種方式應(yīng)該也是夠用的了。這里直接貼出網(wǎng)上的部分代碼,使用 RabbitMQ 作為消息隊(duì)列,演示了請求重試的實(shí)現(xiàn):

首先添加依賴:

<dependencies>
    <dependency>
        <groupId>com.rabbitmq</groupId>
        <artifactId>amqp-client</artifactId>
        <version>5.13.1</version>
    </dependency>
</dependencies>

然后,創(chuàng)建一個(gè)發(fā)送者和接收者類:

消息發(fā)送者(Producer)

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
 
import java.io.IOException;
import java.util.concurrent.TimeoutException;
 
public class MessageProducer {
 
    private static final String QUEUE_NAME = "retry_queue";
 
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
 
        try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
 
            // 模擬發(fā)送請求
            String request = "Your request data";
 
            // 將請求發(fā)送到隊(duì)列
            channel.basicPublish("", QUEUE_NAME, null, request.getBytes());
            System.out.println(" [x] Sent '" + request + "'");
        }
    }
}

消息接收者(Consumer)

import com.rabbitmq.client.*;
 
import java.io.IOException;
import java.util.concurrent.TimeoutException;
 
public class MessageConsumer {
 
    private static final String QUEUE_NAME = "retry_queue";
 
    public static void main(String[] args) throws IOException, TimeoutException {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
 
        try (Connection connection = factory.newConnection(); Channel channel = connection.createChannel()) {
            channel.queueDeclare(QUEUE_NAME, false, false, false, null);
 
            // 設(shè)置消息監(jiān)聽器
            DeliverCallback deliverCallback = (consumerTag, delivery) -> {
                String request = new String(delivery.getBody(), "UTF-8");
 
                // 模擬處理請求,這里可能會(huì)出現(xiàn)處理失敗的情況
                boolean processingSucceeded = processRequest(request);
 
                if (processingSucceeded) {
                    System.out.println(" [x] Received and processed: '" + request + "'");
                } else {
                    // 處理失敗,將請求重新放入隊(duì)列,進(jìn)行重試
                    channel.basicPublish("", QUEUE_NAME, null, delivery.getBody());
                    System.out.println(" [x] Processing failed. Retrying: '" + request + "'");
                }
            };
 
            // 消費(fèi)消息
            channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> {
            });
        }
    }
 
    private static boolean processRequest(String request) {
        // 模擬處理請求的方法
        // 在實(shí)際應(yīng)用中,這里應(yīng)該是對請求的處理邏輯
        // 返回 true 表示處理成功,返回 false 表示處理失敗,需要進(jìn)行重試
        // 這里簡單地模擬了一個(gè)失敗的情況
        return !request.equals("Your request data");
    }
}

示例中,消息發(fā)送者(MessageProducer)將請求發(fā)送到名為 "retry_queue" 的隊(duì)列中。消息接收者(MessageConsumer)監(jiān)聽隊(duì)列,當(dāng)接收到消息時(shí),模擬處理請求的邏輯。如果處理失敗,將請求重新放入隊(duì)列進(jìn)行重試。

3、小結(jié)

接口請求重試機(jī)制對保證系統(tǒng)高可用非常關(guān)鍵,需要根據(jù)業(yè)務(wù)需求選擇合適的重試策略。常用的組合策略包括帶最大次數(shù)的定時(shí)/指數(shù)退避重試、故障轉(zhuǎn)移重試等。重試機(jī)制需要綜合設(shè)置以達(dá)到容錯(cuò)效果 又避免產(chǎn)生過大的系統(tǒng)負(fù)載。

以上就是Java中HTTP接口請求重試的實(shí)現(xiàn)方式的詳細(xì)內(nèi)容,更多關(guān)于Java HTTP接口請求重試的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot基于MyBatis-Plus實(shí)現(xiàn)Lambda Query查詢的示例代碼

    SpringBoot基于MyBatis-Plus實(shí)現(xiàn)Lambda Query查詢的示例代碼

    MyBatis-Plus 是 MyBatis 的增強(qiáng)工具,簡化了數(shù)據(jù)庫操作,并提高了開發(fā)效率,它提供了多種查詢方式,包括常規(guī)的 SQL 查詢、Lambda Query 查詢、分頁查詢、條件查詢等,在本篇博客中,我們將詳細(xì)講解如何使用 MyBatis-Plus 的各種查詢方式,需要的朋友可以參考下
    2025-01-01
  • Security中的@PostAuthorize、@PreFilter和@PostFilter詳解

    Security中的@PostAuthorize、@PreFilter和@PostFilter詳解

    這篇文章主要介紹了Security中的@PostAuthorize、@PreFilter和@PostFilter詳解,@PostAuthorize是在方法調(diào)用完成后進(jìn)行權(quán)限檢查,它不能控制方法是否能被調(diào)用,只能在方法調(diào)用完成后檢查權(quán)限決定是否要拋出AccessDeniedException,需要的朋友可以參考下
    2023-11-11
  • Java Hibernate中的持久化類和實(shí)體類關(guān)系

    Java Hibernate中的持久化類和實(shí)體類關(guān)系

    Hibernate是一種Java對象關(guān)系映射框架,通過持久化類將Java對象映射到數(shù)據(jù)庫表中。持久化類需要實(shí)現(xiàn)無參構(gòu)造器、具有標(biāo)識(shí)屬性和使用注解或XML進(jìn)行映射。Hibernate通過Session來管理對象的狀態(tài),包括臨時(shí)狀態(tài)、持久化狀態(tài)和游離狀態(tài)
    2023-04-04
  • 淺談junit4單元測試高級(jí)用法

    淺談junit4單元測試高級(jí)用法

    這篇文章主要介紹了淺談junit4單元測試高級(jí)用法,小編覺得挺不錯(cuò)的,在這里分享給大家,需要的朋友可以參考下。
    2017-10-10
  • Java線程池源碼的深度解析

    Java線程池源碼的深度解析

    線程池的好處和使用本篇文章就不贅敘了,這篇文章主要通過線程池的源碼帶大家深入了解一下jdk8中線程池的實(shí)現(xiàn),感興趣的小伙伴可以了解一下
    2022-10-10
  • springboot實(shí)現(xiàn)極驗(yàn)校驗(yàn)的項(xiàng)目實(shí)踐

    springboot實(shí)現(xiàn)極驗(yàn)校驗(yàn)的項(xiàng)目實(shí)踐

    在系統(tǒng)業(yè)務(wù)中,需要想客戶發(fā)送手機(jī)驗(yàn)證碼,進(jìn)行驗(yàn)證后,才能提交,本文主要介紹了springboot實(shí)現(xiàn)極驗(yàn)校驗(yàn)的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • java實(shí)現(xiàn)在線預(yù)覽--poi實(shí)現(xiàn)word、excel、ppt轉(zhuǎn)html的方法

    java實(shí)現(xiàn)在線預(yù)覽--poi實(shí)現(xiàn)word、excel、ppt轉(zhuǎn)html的方法

    這篇文章主要介紹了java實(shí)現(xiàn)在線預(yù)覽--poi實(shí)現(xiàn)word、excel、ppt轉(zhuǎn)html的方法,本文需要引入poi的jar包給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2019-09-09
  • SpringBoot中的錯(cuò)誤處理機(jī)制源碼解析

    SpringBoot中的錯(cuò)誤處理機(jī)制源碼解析

    這篇文章主要介紹了SpringBoot中的錯(cuò)誤處理機(jī)制源碼解析,springboot根據(jù)訪問者的request中的Accept屬性來判斷要返回什么樣的數(shù)據(jù),SpringBoot存在一個(gè)錯(cuò)誤處理機(jī)制,會(huì)根據(jù)不同請求返回不同的結(jié)果,需要的朋友可以參考下
    2023-12-12
  • java日期時(shí)間格式化@JsonFormat與@DateTimeFormat的使用

    java日期時(shí)間格式化@JsonFormat與@DateTimeFormat的使用

    本文主要介紹了java日期時(shí)間格式化@JsonFormat與@DateTimeFormat的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • Java虛擬機(jī)內(nèi)存結(jié)構(gòu)及編碼實(shí)戰(zhàn)分享

    Java虛擬機(jī)內(nèi)存結(jié)構(gòu)及編碼實(shí)戰(zhàn)分享

    這篇文章主要介紹了Java虛擬機(jī)內(nèi)存結(jié)構(gòu)及編碼實(shí)戰(zhàn)分享,文章圍繞詳細(xì)主題展開相關(guān)資料具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-04-04

最新評(píng)論