亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java調(diào)用第三方接口封裝實現(xiàn)

 更新時間:2023年02月16日 16:23:38   作者:wangfenglei123456  
本文主要介紹了Java調(diào)用第三方接口封裝實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

介紹

在Java項目中,會遇到很多調(diào)用第三方接口的地方,比如接入微信,其他公司的系統(tǒng),需要傳token或者簽名。由于接入調(diào)用接口很多,每個接口內(nèi)部都需要手動設置token或者其他數(shù)據(jù),這就顯得很麻煩。而且發(fā)送http請求還需要自己創(chuàng)建request對象。下面介紹2中封裝方式,

一、利用feign功能封裝請求,所有接口和服務之間調(diào)用是一樣的,只需要執(zhí)行后面的url,參數(shù)類,請求方式等。內(nèi)部需要傳輸?shù)膖oken信息,在自定的攔截器中設置,自定義的攔截器需要實現(xiàn)RequestInterceptor接口。在這里面設置公共的請求參數(shù)。比較推薦的。

二、自己封裝一個通用的請求類,里面自己創(chuàng)建Request對象,發(fā)送完http請求之后拿到返回的json對象在封裝返回類,借助于ObjectMapper類。

一、借助feign實現(xiàn)調(diào)用

寫一個feign的接口調(diào)用類,因為調(diào)用服務和接收服務不在一個注冊中心,所以需要指定url,并實現(xiàn)攔截器

自定義的feign接口

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
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.RequestMapping;
 
@FeignClient(
    url = "${e-sign.apiHost}",        // 這個值在配置文件中配置好
    value = "authFeign"               // 這個是自定義的服務名稱,沒有用
)
@RequestMapping(
    headers = {"X-Tsign-Open-Auth-Mode=Signature"}    // 設置請求的header
)
public interface EAuthFeign {
    
// 寫封裝的參數(shù)和請求路徑
    @PostMapping({"/v3/oauth2/index"})
    EResponse<String> applyAuth(@RequestBody EApplyAuthDTO params);
}

配置文件內(nèi)容

e-sign:
  projectId: 111111
  projectSecret: fasdfads
  apiHost: https://ss.sign.cn
  callbackHost: https://call.baidu.com
  redirectHost: https://web.baidu.com

自定義攔截器,這個是feign的攔截器,只需要標記被掃描到就行,會自動加載。寫了這個類后,這個類所在的項目所有的feign都會被這個攔截器控制

import common.exception.E;
import esign.config.ESignConfig;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.Map;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Encoder;
 
@Component
public class EAuthFeignRequestInterceptor implements RequestInterceptor {
    private static final Logger log = LoggerFactory.getLogger(EAuthFeignRequestInterceptor.class);
    @Autowired
    private ESignConfig eSignConfig;
    private static final BASE64Encoder encodeBase64 = new BASE64Encoder();
 
    public EAuthFeignRequestInterceptor() {
    }
 
    public void apply(RequestTemplate template) {
        String host = this.eSignConfig.getApiHost();
        String url = template.url();
        String target = template.feignTarget().url();
        boolean b = target.equals(host);
// 這個判斷就是為了防止所有的feign都走這個攔截器,限制只有第三方接口才能進入下面的邏輯
        if (b) {
            template.header("X-Tsign-Open-App-Id", new String[]{this.eSignConfig.getProjectId()});
            Map<String, Collection<String>> headers = template.headers();
            Collection<String> authMode = (Collection)headers.get("X-Tsign-Open-Auth-Mode");
            boolean isSign = authMode != null && authMode.contains("Signature");
            if (isSign) {
                template.header("X-Tsign-Open-Ca-Timestamp", new String[]{String.valueOf(System.currentTimeMillis())});
                template.header("Accept", new String[]{"*/*"});
                template.header("Content-Type", new String[]{"application/json;charset=UTF-8"});
 
                try {
                    this.setMd5AndSignature(template);
                } catch (Exception var10) {
                    log.error("發(fā)送請求失敗, url:{}, params:{}", url, new String(template.body()));
                    throw new E("發(fā)送請求失敗");
                }
            } else {
                template.header("X-Tsign-Open-Authorization-Version", new String[]{"v2"});
            }
 
            log.info("發(fā)送請求, url:{}, params:{}", url, template.body() == null ? "" : new String(template.body()));
        }
    }
 
    public void setMd5AndSignature(RequestTemplate template) {
        byte[] body = template.body();
        String url = template.url();
        String method = template.method();
        String contentMD5 = doContentMD5(body);
        if ("GET".equals(method) || "DELETE".equals(method)) {
            contentMD5 = "";
            url = URLDecoder.decode(url);
        }
 
        String message = appendSignDataString(method, "*/*", contentMD5, "application/json;charset=UTF-8", "", "", url);
        log.info("接口,url:{}, 簽名字符串:{}", url, message);
        String reqSignature = doSignatureBase64(message, this.eSignConfig.getProjectSecret());
        template.header("Content-MD5", new String[]{contentMD5});
        template.header("X-Tsign-Open-Ca-Signature", new String[]{reqSignature});
    }
 
    private static String doContentMD5(byte[] body) {
        if (body == null) {
            return "";
        } else {
            byte[] md5Bytes = null;
            MessageDigest md5 = null;
            String contentMD5 = null;
 
            try {
                md5 = MessageDigest.getInstance("MD5");
                md5.update(body);
                byte[] md5Bytes = md5.digest();
                contentMD5 = encodeBase64.encode(md5Bytes);
                return contentMD5;
            } catch (NoSuchAlgorithmException var5) {
                log.error("不支持此算法", var5);
                throw new E("不支持此算法");
            }
        }
    }
 
    private static String doSignatureBase64(String message, String secret) {
        String algorithm = "HmacSHA256";
        String digestBase64 = null;
 
        try {
            Mac hmacSha256 = Mac.getInstance(algorithm);
            byte[] keyBytes = secret.getBytes(StandardCharsets.UTF_8);
            byte[] messageBytes = message.getBytes(StandardCharsets.UTF_8);
            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, algorithm));
            byte[] digestBytes = hmacSha256.doFinal(messageBytes);
            digestBase64 = encodeBase64.encode(digestBytes);
            return digestBase64;
        } catch (NoSuchAlgorithmException var8) {
            log.error("不支持此算法", var8);
            throw new E("不支持此算法");
        } catch (InvalidKeyException var9) {
            log.error("無效的密鑰規(guī)范", var9);
            throw new E("無效的密鑰規(guī)范");
        }
    }
 
    private static String appendSignDataString(String method, String accept, String contentMD5, String contentType, String date, String headers, String url) {
        StringBuilder sb = new StringBuilder();
        sb.append(method).append("\n").append(accept).append("\n").append(contentMD5).append("\n").append(contentType).append("\n").append(date).append("\n");
        if ("".equals(headers)) {
            sb.append(headers).append(url);
        } else {
            sb.append(headers).append("\n").append(url);
        }
 
        return new String(sb);
    }
}

配置類

@Configuration
@ConfigurationProperties(
    prefix = "e-sign"
)
public class ESignConfig {
    private static final Logger log = LoggerFactory.getLogger(ESignConfig.class);
    private String projectId;
    private String projectSecret;
    private String apiHost;
    private String callbackHost;
    private String redirectHost;
}

上邊幾個類就可以封裝對外請求了。自己服務根據(jù)要求可以另外處理

二、自己封裝請求類

通用請求返回結(jié)果類

package com.service;
 
import com.alibaba.fastjson.JSONObject;
import com.common.dto.coop.HttpDTO;
import com.common.vo.coop.ThirdResultVO;
import com.cooperation.generator.ThirdTokenGenerator;
import com.cooperation.template.TokenTemplate;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
 
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
 
/**
 * 基于okhttp的請求客戶端的service
 *
 * @author aaa 2022-04-28
 */
@Slf4j
@Service
public class HttpService2 {
 
    @Autowired
    private TokenTemplate tokenTemplate;
 
    /**
     * 獲取接口調(diào)用返回值
     *
     * @param param 請求參數(shù)
     * @author aaa 2022-04-28
     */
    public ThirdResultVO getInterfaceResult(HttpDTO param) {
 
        // 參數(shù)轉(zhuǎn)換成json
        JSONObject json = Objects.isNull(param.getObj()) ? new JSONObject()
                : JSONObject.parseObject(JSONObject.toJSONString(param.getObj()));
 
        // 如果需要token,將token放在參數(shù)中
        if (param.getNeedToken()) {
 
            String token = tokenTemplate.getToken(new ThirdTokenGenerator());
 
            json.put("token", token);
        }
 
        // 發(fā)起請求,獲得響應
        Response response = doRequest(param.getUrl(), json);
 
        // 處理返回值
        ThirdResultVO ThirdResult = handleReturn(response);
 
        // 如果為null,響應有問題,不能轉(zhuǎn)成返回值類型
        Assert.notNull(ThirdResult, "接口調(diào)用異常");
 
        return ThirdResult;
    }
 
    /**
     * 處理返回值
     *
     * @param response 請求響應
     * @author aaa 2022-04-28
     */
    private ThirdResultVO handleReturn(Response response) {
        // 如果響應為空,返回null
        if (Objects.isNull(response)) {
            return null;
        }
 
        try {
            // 如果響應體為空,返回null
            if (Objects.isNull(response.body())) {
                return null;
            }
 
            // 響應體的字節(jié)數(shù)組
            byte[] bytes = response.body().bytes();
            log.info("調(diào)用接口返回數(shù)據(jù)--:{}", new String(bytes));
            // 轉(zhuǎn)換成返回值類型
            return JSONObject.parseObject(bytes, ThirdResultVO.class);
 
        } catch (Exception e) {
            log.info("處理返回值失敗:{}", e.getMessage(), e);
        }
 
        return null;
    }
 
    /**
     * 發(fā)送請求
     *
     * @param url        請求地址
     * @param jsonObject 參數(shù)DTO
     * @author aaa 2022-04-28
     */
    private Response doRequest(String url, JSONObject jsonObject) {
 
        // 獲得表單請求對象
        Request formRequest = getFormRequest(url, jsonObject);
 
        // 調(diào)用接口 請求入?yún)?
        log.info("調(diào)用接口請求入?yún)?-:url:{} , jsonObject :{}",url, JSONObject.toJSONString(jsonObject));
 
        // 獲得okhttp請求工具
        OkHttpClient requestClient = getRequestClient();
 
        // 獲得請求調(diào)用對象
        Call call = requestClient.newCall(formRequest);
 
        // 發(fā)起請求,獲得響應
        Response execute = null;
        try {
            execute = call.execute();
        } catch (IOException e) {
            log.info("調(diào)用接口失敗:{}", e.getMessage(), e);
        }
 
        return execute;
    }
 
    /**
     * 獲得表單請求
     *
     * @param url        請求地址
     * @param jsonObject 參數(shù)DTO
     * @author aaa 2022-04-28
     */
    private Request getFormRequest(String url, JSONObject jsonObject) {
 
        // 獲得請求構(gòu)造器
        Request.Builder requestBuilder = new Request.Builder();
 
        // 設置表單請求的請求頭
        try {
            requestBuilder.addHeader("content-type", "application/x-www-form-urlencoded").post(getFormBody(jsonObject)).url(new URL(url));
        } catch (MalformedURLException e) {
            log.info("url轉(zhuǎn)換失?。簕}", e.getMessage(), e);
        }
 
        // 返回請求對象
        return requestBuilder.build();
    }
 
    /**
     * 獲取請求客戶端
     *
     * @author aaa 2022-04-28
     */
    private OkHttpClient getRequestClient() {
        return new OkHttpClient.Builder()
                .readTimeout(2L, TimeUnit.MINUTES)
                .build();
    }
 
    /**
     * 獲取form表單請求的body
     *
     * @param jsonObject 請求參數(shù)DTO
     * @author aaa 2022-04-28
     */
    private FormBody getFormBody(JSONObject jsonObject) {
 
        // 獲取表單請求構(gòu)造器
        FormBody.Builder fb = new FormBody.Builder();
 
        // 設置請求參數(shù)
        jsonObject.keySet().forEach(item -> fb.addEncoded(item, jsonObject.getString(item)));
 
        // 返回body
        return fb.build();
    }
}

通用請求參數(shù)類

@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class HttpDTO implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @NotNull(message = "請求路徑不能為空")
    @NotBlank(message = "請求路徑不能為空")
    @ApiModelProperty(value = "請求路徑url")
    private String url;
 
    @ApiModelProperty(value = "參數(shù)")
    private Object obj;
 
    @NotNull(message = "是否需要token 不能為空")
    @ApiModelProperty(value = "是否需要token:true是,false否")
    private Boolean needToken;
}

請求調(diào)用示例

public List<String> getSkuCode(String classifyCode) {
 
        ResultVO interfaceResult = httpService.getInterfaceResult(new HttpDTO()
                .setUrl(Constant.HOST.concat(Constant.GOODS_GET_SKUS_BY_CLASSID_URI))
                .setNeedToken(true)
                .setObj(new DeLiGetSkusByClassId3DTO().setCode(classifyCode3).setIsAll(1)));
 
        log.info(interfaceResult.getResultMessage());
 
        return JSONArray.parseArray(interfaceResult.getResult(), String.class);
    }

上邊的請求返回,從結(jié)果里取出result字符串,再轉(zhuǎn)一下list,這可以放在后面的請求方法中,傳一個返回的類class。使用objectMapper轉(zhuǎn)一下。

private ObjectMapper mapper = new ObjectMapper();
 
public <T, RR> Response<RR> api(ApiDTO<T> jsonParams, Class<RR> responseResult) {
        String json = JSONObject.toJSONString(jsonParams);
        log.info("三方api.do, requestParams:{}", json);
        String responseStr = this.thirdFileAgentFeign.api(json);
        // 構(gòu)建返回類型
        JavaType javaType1 = this.mapper.getTypeFactory().constructParametricType(YZResponse.class, new Class[]{responseResult});
 
        try {
            // 這個代碼塊就看這里返回帶泛型的類
            return (Response)this.mapper.readValue(responseStr, javaType1);
        } catch (JsonProcessingException e) {
            log.error("反序列化返回值異常, responseStr:{}, errInfo:{}", new Object[]{responseStr, var7.getMessage(), e});
            throw new E("反序列化返回值異常");
        }
    }

第二種返回類型

import com.fasterxml.jackson.core.type.TypeReference;
 
public static <T> T toObj(String json, Class<T> type) {
        try {
            return MAPPER.readValue(json, type);
        } catch (IOException e) {
            log.error("toObj error", e);
            throw E.of(BaseExceptionEnum.FORMAT_ERROR);
        }
    }
 
public static <T> T toObj(String json, TypeReference<T> typeReference) {
        try {
            return mapper.readValue(json, typeReference);
        } catch (IOException e) {
            log.error("toObj error", e);
            throw E.of(BaseExceptionEnum.FORMAT_ERROR);
        }
    }

泛型返回處理可以參考RestTemplate里面的postForObject()

Class<?> deserializationView = ((MappingJacksonInputMessage)inputMessage).getDeserializationView();
                if (deserializationView != null) {
                    // 部分代碼,構(gòu)建一個reader
                    ObjectReader objectReader = this.objectMapper.readerWithView(deserializationView).forType(javaType);
                    if (isUnicode) {
                    // 返回class類型的對象
                        return objectReader.readValue(inputMessage.getBody());
                    }
 
                    Reader reader = new InputStreamReader(inputMessage.getBody(), charset);
                    return objectReader.readValue(reader);
                }

具體可以學習一下ObjectMapper的用法

請求接口返回結(jié)果類

@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class ResultVO implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @ApiModelProperty(value = "接口返回成功與否")
    private Boolean success;
 
    @ApiModelProperty(value = "返回數(shù)據(jù)描述")
    private String resultMessage;
 
    @ApiModelProperty(value = "平臺業(yè)務代碼標記")
    private String resultCode;
 
// 返回的json結(jié)果,再處理成返回對象
    @ApiModelProperty(value = "業(yè)務數(shù)據(jù)")
    private String result;
}

三、調(diào)用第三方生成token,可以使用策略類實現(xiàn)

策略接口類

public interface TokenGeneratorStrategy {
    /**
     * 獲取token
     *
     * @author aaa 2022-04-26
     */
    String getToken();
 
    /**
     * 獲取token緩存key
     *
     * @author aaa 2022-04-26
     */
    String getTokenCacheKey();
 
    /**
     * 獲取token過期時間,采用redis單位
     *
     * @author aaa 2022-04-26
     */
    Duration getTokenExpireTime();
 
}

獲取token的實現(xiàn)類

package com.generator;
 
import com.alibaba.fastjson.JSONObject;
import com.common.constant.ThirdConstant;
import com.common.constant.MallCacheKeyConstant;
import com.common.constant.MallCommonConstant;
import com.common.dto.coop.HttpDTO;
import com.common.vo.coop.ThirdResultVO;
import com.common.vo.coop.ThirdTokenVO;
import com.cooperation.dto.ThirdTokenDTO;
import com.cooperation.service.HttpService;
import com.cooperation.strategy.TokenGeneratorStrategy;
import com.common.exception.E;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
 
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;
 
/**
 * 三方生成token
 *
 */
@Slf4j
@Service
public class ThirdTokenGenerator implements TokenGeneratorStrategy {
 
    @Autowired
    private HttpService httpService;
 
    @Override
    public String getToken() {
 
        // 獲取當前時間,轉(zhuǎn)換成yyyy/MM/dd格式
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = LocalDateTime.now().format(dateTimeFormatter);
 
        // 簽名規(guī)則:client_secret+timestamp+client_id+username+password+scope+client_secret將上面字符串MD5 加密后轉(zhuǎn)為小寫。
        String sign = ThirdConstant.CLIENT_SECRET
                .concat(format)
                .concat(ThirdConstant.CLIENT_ID)
                .concat(ThirdConstant.USERNAME)
                .concat(ThirdConstant.PASSWORD)
                .concat(ThirdConstant.CLIENT_SECRET);
 
        // md5 加密
        String signMd5 = DigestUtils.md5DigestAsHex(sign.getBytes(StandardCharsets.UTF_8)).toLowerCase();
 
        ThirdTokenDTO ThirdTokenDto = new ThirdTokenDTO().setClient_id(ThirdConstant.CLIENT_ID).setClient_secret(ThirdConstant.CLIENT_SECRET)
                .setUsername(ThirdConstant.USERNAME).setPassword(ThirdConstant.PASSWORD)
                .setTimestamp(format).setSign(signMd5);
 
        // 接口調(diào)用
        ThirdResultVO interfaceResult = httpService.getInterfaceResult(
                new HttpDTO()
                        .setUrl(ThirdConstant.HOST.concat(ThirdConstant.TOKEN_URI))
                        .setObj(ThirdTokenDto)
                        .setNeedToken(false));
 
 
        ThirdTokenVO ThirdToken = new ThirdTokenVO();
        try {
            ThirdToken = JSONObject.parseObject(interfaceResult.getResult(), ThirdTokenVO.class);
        } catch (Exception e) {
            log.info("token 返回值處理異常:{}", e.getMessage(), e);
        }
        if (Objects.isNull(ThirdToken)) {
            log.error("獲取三方token為空----{}", interfaceResult);
            throw new E("獲取三方token異常信息--" + interfaceResult.getResultMessage());
        }
 
        return ThirdToken.getAccess_token();
    }
 
    @Override
    public String getTokenCacheKey() {
        return MallCacheKeyConstant.COOP_Third_TOKEN + MallCommonConstant.DEFAULT_KEY;
    }
 
    /**
     * 三方有效時間一小時,這里的過期時間采用50分鐘
     */
    @Override
    public Duration getTokenExpireTime() {
 
        // 當前時間到12點的時間
        Duration nowTo12 = Duration.between(LocalDateTime.now(), LocalDateTime.of(LocalDate.now(), LocalTime.MAX));
 
        // 50分鐘
        Duration fiftyMin = Duration.ofSeconds(50 * 60L);
 
        // 如果當前時間到12點的時間超過50分鐘,返回50分鐘
        if (nowTo12.compareTo(fiftyMin) > 0) {
            return fiftyMin;
        }
 
        // 否則返回當前時間到12點的時間
        return nowTo12;
    }
}

總結(jié)

到此這篇關于Java調(diào)用第三方接口封裝實現(xiàn)的文章就介紹到這了,更多相關Java調(diào)用第三方接口封裝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 詳解java線程的開始、暫停、繼續(xù)

    詳解java線程的開始、暫停、繼續(xù)

    本文將介紹通過線程讀取文件內(nèi)容,并且可以控制線程的開始、暫停、繼續(xù),來控制讀文件。具有一定的參考作用,下面跟著小編一起來看下吧
    2017-01-01
  • 淺談自定義校驗注解ConstraintValidator

    淺談自定義校驗注解ConstraintValidator

    鑒于通用性和普遍性,Spring框架提供了validator組件,通過一些校驗器,可以對一些數(shù)據(jù)進行統(tǒng)一的完整性和有效性等校驗,即簡單又好用
    2021-06-06
  • SpringBoot整合Caffeine實現(xiàn)本地緩存的實踐分享

    SpringBoot整合Caffeine實現(xiàn)本地緩存的實踐分享

    緩存是提升系統(tǒng)性能的一個不可或缺的工具,通過緩存可以避免大部分重復的請求到數(shù)據(jù)庫層,減少IO鏈接次數(shù),提升整體的響應速率,本地緩存中比較常見的比如 Caffeine 緩存,這篇文章將結(jié)合具體的 Springboot 項目搭配 Caffeine 實現(xiàn)本地緩存的各種使用方式
    2024-07-07
  • Java之SpringBoot自定義配置與整合Druid

    Java之SpringBoot自定義配置與整合Druid

    這篇文章主要介紹的是java之SpringBoot自定義配置與整合Druid的相關資料,關于SpringBoot配置文件可以是properties或者是yaml格式的文件,但是在SpringBoot加載application配置文件時是存在一個優(yōu)先級,下面小編就和大家一起進入文章學習這項知識
    2021-09-09
  • eclipse實現(xiàn)DSA數(shù)字簽名

    eclipse實現(xiàn)DSA數(shù)字簽名

    這篇文章主要為大家詳細介紹了eclipse實現(xiàn)DSA數(shù)字簽名算法,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Java計算時間差和日期差五種常用示例

    Java計算時間差和日期差五種常用示例

    這篇文章主要給大家介紹了關于Java計算時間差和日期差五種常用示例的相關資料,最近工作中遇到需要計算時間差和日期差,搜索了幾種計算時間差和日期差的方法,這里總結(jié)一下,需要的朋友可以參考下
    2023-08-08
  • Java中for循環(huán)的執(zhí)行過程分析

    Java中for循環(huán)的執(zhí)行過程分析

    這篇文章主要介紹了Java中for循環(huán)的執(zhí)行過程,實例分析了for循環(huán)的執(zhí)行原理與順序,對于深入理解Java具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • Java?Cookie與Session實現(xiàn)會話跟蹤詳解

    Java?Cookie與Session實現(xiàn)會話跟蹤詳解

    session的工作原理和cookie非常類似,在cookie中存放一個sessionID,真實的數(shù)據(jù)存放在服務器端,客戶端每次發(fā)送請求的時候帶上sessionID,服務端根據(jù)sessionID進行數(shù)據(jù)的響應
    2022-11-11
  • SpringMVC表單標簽知識點詳解

    SpringMVC表單標簽知識點詳解

    這篇文章主要為大家詳細介紹了SpringMVC表單標簽知識點,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Java超詳細講解三大特性之一的封裝

    Java超詳細講解三大特性之一的封裝

    封裝是一個非常廣泛的概念,小到一個屬性的封裝,大到一個框架或者一個項目的封裝,下面這篇文章主要給大家介紹了關于java中封裝的那點事,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-05-05

最新評論