最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

在SpringBoot項(xiàng)目中優(yōu)雅的連接多臺(tái)Redis的操作方法

 更新時(shí)間:2025年09月05日 15:23:44   作者:CavenWang  
本文將基于一個(gè)實(shí)際案例,詳細(xì)介紹如何在Spring Boot中優(yōu)雅地配置和使用多個(gè)Redis實(shí)例,解決常見(jiàn)的注入歧義問(wèn)題,并提供一個(gè)通用的Redis工具類來(lái)簡(jiǎn)化操作,本文給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧

如何在SpringBoot項(xiàng)目中優(yōu)雅的連接多臺(tái)Redis

在Spring Boot項(xiàng)目中,連接單個(gè)Redis實(shí)例是常見(jiàn)需求,但有時(shí)需要同時(shí)連接多個(gè)Redis實(shí)例(例如,主Redis用于業(yè)務(wù)數(shù)據(jù)存儲(chǔ),另一個(gè)Redis用于爬蟲(chóng)數(shù)據(jù)緩存)。本文將基于一個(gè)實(shí)際案例,詳細(xì)介紹如何在Spring Boot中優(yōu)雅地配置和使用多個(gè)Redis實(shí)例,解決常見(jiàn)的注入歧義問(wèn)題,并提供一個(gè)通用的Redis工具類來(lái)簡(jiǎn)化操作。

背景

在一個(gè)Spring Boot項(xiàng)目中,我們需要連接兩臺(tái)Redis實(shí)例:

  • 主Redis:用于常規(guī)業(yè)務(wù)數(shù)據(jù),配置在spring.redis(數(shù)據(jù)庫(kù)索引4)。
  • 爬蟲(chóng)Redis:用于爬蟲(chóng)相關(guān)數(shù)據(jù),配置在spring.redis-crawler(數(shù)據(jù)庫(kù)索引7)。

項(xiàng)目中遇到以下問(wèn)題:

  1. 配置兩個(gè)RedisTemplate時(shí),Spring容器找不到redisCrawlerConnectionFactory。
  2. 配置多個(gè)RedisProperties導(dǎo)致注入歧義,拋出NoUniqueBeanDefinitionException
  3. 需要一個(gè)通用的RedisCache工具類,支持動(dòng)態(tài)選擇Redis實(shí)例,同時(shí)兼容現(xiàn)有代碼。

下面,我們將逐步解決這些問(wèn)題,并展示如何優(yōu)雅地實(shí)現(xiàn)多Redis連接。

項(xiàng)目配置

1. 配置文件(application.yml)

首先,在application.yml中定義兩套R(shí)edis配置:

spring:
  redis:
    host: [REDACTED_HOST]
    port: 6379
    database: 4
    # password: [REDACTED_PASSWORD]
    timeout: 10s
    lettuce:
      pool:
        min-idle: 0
        max-idle: 8
        max-active: 8
        max-wait: -1ms
  redis-crawler:
    host: [REDACTED_HOST]
    port: 6379
    database: 7
    # password: [REDACTED_PASSWORD]
    timeout: 10s
    lettuce:
      pool:
        min-idle: 0
        max-idle: 8
        max-active: 8
        max-wait: -1ms
  • spring.redis:主Redis,數(shù)據(jù)庫(kù)索引4。
  • spring.redis-crawler:爬蟲(chóng)Redis,數(shù)據(jù)庫(kù)索引7。
  • 如果Redis需要密碼,取消password字段的注釋并設(shè)置正確值(此處已脫敏)。

2. 依賴配置(pom.xml)

確保項(xiàng)目包含以下依賴:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
    <groupId>io.lettuce</groupId>
    <artifactId>lettuce-core</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>2.0.51</version>
</dependency>
  • spring-boot-starter-data-redis:提供Redis支持。
  • lettuce-core:使用Lettuce作為Redis客戶端。
  • fastjson:用于自定義序列化(項(xiàng)目中使用了FastJson2JsonRedisSerializer)。

配置多個(gè)Redis實(shí)例

問(wèn)題1:找不到redisCrawlerConnectionFactory

最初,我們嘗試在RedisConfig.java中定義兩個(gè)RedisTemplate

@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
    // 主Redis模板
}
@Bean(name = "redisTemplateCrawl")
public RedisTemplate<Object, Object> redisTemplateCrawl(@Qualifier("redisCrawlerConnectionFactory") RedisConnectionFactory redisCrawlerConnectionFactory) {
    // 爬蟲(chóng)Redis模板
}

啟動(dòng)時(shí)拋出異常:

No qualifying bean of type 'org.springframework.data.redis.connection.RedisConnectionFactory' available

原因:Spring Boot自動(dòng)為spring.redis創(chuàng)建了一個(gè)RedisConnectionFactory,但不會(huì)為spring.redis-crawler創(chuàng)建。redisTemplateCrawl依賴的redisCrawlerConnectionFactory未定義。

解決方法:顯式定義redisCrawlerConnectionFactory和對(duì)應(yīng)的RedisProperties

@Bean(name = "redisCrawlerProperties")
@ConfigurationProperties(prefix = "spring.redis-crawler")
public RedisProperties redisCrawlerProperties() {
    return new RedisProperties();
}
@Bean(name = "redisCrawlerConnectionFactory")
public RedisConnectionFactory redisCrawlerConnectionFactory(@Qualifier("redisCrawlerProperties") RedisProperties redisCrawlerProperties) {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
    config.setHostName(redisCrawlerProperties.getHost());
    config.setPort(redisCrawlerProperties.getPort());
    config.setDatabase(redisCrawlerProperties.getDatabase());
    if (redisCrawlerProperties.getPassword() != null) {
        config.setPassword(redisCrawlerProperties.getPassword());
    }
    return new LettuceConnectionFactory(config);
}
  • redisCrawlerProperties:綁定spring.redis-crawler配置。
  • redisCrawlerConnectionFactory:根據(jù)redisCrawlerProperties創(chuàng)建連接工廠。

問(wèn)題2:RedisProperties注入歧義

配置了redisCrawlerProperties后,啟動(dòng)時(shí)又遇到新問(wèn)題:

Parameter 0 of constructor in org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration required a single bean, but 2 were found:
	- redisCrawlerProperties
	- spring.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties

原因:Spring Boot自動(dòng)為spring.redis創(chuàng)建了一個(gè)RedisProperties,而我們又定義了redisCrawlerProperties,導(dǎo)致LettuceConnectionConfiguration無(wú)法確定使用哪個(gè)RedisProperties。

解決方法:顯式定義主Redis的RedisProperties,并用@Primary標(biāo)記為默認(rèn):

@Bean(name = "redisProperties")
@Primary
@ConfigurationProperties(prefix = "spring.redis")
public RedisProperties redisProperties() {
    return new RedisProperties();
}
@Bean(name = "redisConnectionFactory")
public RedisConnectionFactory redisConnectionFactory(@Qualifier("redisProperties") RedisProperties redisProperties) {
    RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
    config.setHostName(redisProperties.getHost());
    config.setPort(redisProperties.getPort());
    config.setDatabase(redisProperties.getDatabase());
    if (redisProperties.getPassword() != null) {
        config.setPassword(redisProperties.getPassword());
    }
    return new LettuceConnectionFactory(config);
}
  • redisProperties:綁定spring.redis,用@Primary標(biāo)記為默認(rèn)。
  • redisConnectionFactory:為主Redis創(chuàng)建連接工廠,確保redisTemplate使用正確配置。

最終的RedisConfig.java

以下是完整的RedisConfig.java(敏感信息已脫敏):

package com.caven.framework.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
    @Bean(name = "redisProperties")
    @Primary
    @ConfigurationProperties(prefix = "spring.redis")
    public RedisProperties redisProperties() {
        return new RedisProperties();
    }
    @Bean(name = "redisConnectionFactory")
    public RedisConnectionFactory redisConnectionFactory(@Qualifier("redisProperties") RedisProperties redisProperties) {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(redisProperties.getHost());
        config.setPort(redisProperties.getPort());
        config.setDatabase(redisProperties.getDatabase());
        if (redisProperties.getPassword() != null) {
            config.setPassword(redisProperties.getPassword());
        }
        return new LettuceConnectionFactory(config);
    }
    @Bean(name = "redisTemplate")
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisTemplate<Object, Object> redisTemplate(@Qualifier("redisConnectionFactory") RedisConnectionFactory connectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);
        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        serializer.setObjectMapper(mapper);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
    @Bean(name = "redisCrawlerProperties")
    @ConfigurationProperties(prefix = "spring.redis-crawler")
    public RedisProperties redisCrawlerProperties() {
        return new RedisProperties();
    }
    @Bean(name = "redisCrawlerConnectionFactory")
    public RedisConnectionFactory redisCrawlerConnectionFactory(@Qualifier("redisCrawlerProperties") RedisProperties redisCrawlerProperties) {
        RedisStandaloneConfiguration config = new RedisStandaloneConfiguration();
        config.setHostName(redisCrawlerProperties.getHost());
        config.setPort(redisCrawlerProperties.getPort());
        config.setDatabase(redisCrawlerProperties.getDatabase());
        if (redisCrawlerProperties.getPassword() != null) {
            config.setPassword(redisCrawlerProperties.getPassword());
        }
        return new LettuceConnectionFactory(config);
    }
    @Bean(name = "redisTemplateCrawl")
    @SuppressWarnings(value = {"unchecked", "rawtypes"})
    public RedisTemplate<Object, Object> redisTemplateCrawl(@Qualifier("redisCrawlerConnectionFactory") RedisConnectionFactory redisCrawlerConnectionFactory) {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisCrawlerConnectionFactory);
        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        serializer.setObjectMapper(mapper);
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(serializer);
        template.setHashKeySerializer(new StringRedisSerializer());
        template.setHashValueSerializer(serializer);
        template.afterPropertiesSet();
        return template;
    }
    @Bean
    public DefaultRedisScript<Long> limitScript() {
        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptText(limitScriptText());
        redisScript.setResultType(Long.class);
        return redisScript;
    }
    private String limitScriptText() {
        return "local key = KEYS[1]\n" +
               "local count = tonumber(ARGV[1])\n" +
               "local time = tonumber(ARGV[2])\n" +
               "local current = redis.call('get', key);\n" +
               "if current and tonumber(current) > count then\n" +
               "    return tonumber(current);\n" +
               "end\n" +
               "current = redis.call('incr', key)\n" +
               "if tonumber(current) == 1 then\n" +
               "    redis.call('expire', key, time)\n" +
               "end\n" +
               "return tonumber(current);";
    }
}

實(shí)現(xiàn)通用的Redis工具類

為了簡(jiǎn)化Redis操作,我們創(chuàng)建了一個(gè)RedisCache工具類,支持動(dòng)態(tài)選擇RedisTemplate,同時(shí)兼容現(xiàn)有代碼。

問(wèn)題3:動(dòng)態(tài)選擇Redis實(shí)例

最初的RedisCache.java只注入了一個(gè)RedisTemplate

@Autowired
public RedisTemplate redisTemplate;

這導(dǎo)致無(wú)法操作爬蟲(chóng)Redis。我們希望:

  • 現(xiàn)有代碼繼續(xù)使用主Redis(redisTemplate),無(wú)需修改。
  • 新代碼可以通過(guò)參數(shù)選擇主Redis或爬蟲(chóng)Redis(redisTemplateCrawl)。

解決方法

  • 注入兩個(gè)RedisTemplateredisTemplateredisTemplateCrawl)。
  • 保留原有方法,默認(rèn)使用redisTemplate
  • 為每個(gè)方法添加帶templateName參數(shù)的重load版本,支持選擇Redis實(shí)例。

最終的RedisCache.java

package com.caven.framework.redis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.TimeUnit;
@SuppressWarnings(value = {"unchecked", "rawtypes"})
@Component
public class RedisCache {
    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate redisTemplate;
    @Autowired
    @Qualifier("redisTemplateCrawl")
    private RedisTemplate redisTemplateCrawl;
    private RedisTemplate getRedisTemplate(String templateName) {
        if ("crawl".equalsIgnoreCase(templateName)) {
            return redisTemplateCrawl;
        }
        return redisTemplate;
    }
    public <T> void setCacheObject(final String key, final T value) {
        redisTemplate.opsForValue().set(key, value);
    }
    public <T> void setCacheObject(final String templateName, final String key, final T value) {
        getRedisTemplate(templateName).opsForValue().set(key, value);
    }
    public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
        redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
    }
    public <T> void setCacheObject(final String templateName, final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
        getRedisTemplate(templateName).opsForValue().set(key, value, timeout, timeUnit);
    }
    // 其他方法類似,省略完整代碼
}

關(guān)鍵點(diǎn)

  • 使用@Qualifier注入redisTemplateredisTemplateCrawl。
  • 保留原有方法(如setCacheObject(String key, T value)),默認(rèn)使用redisTemplate。
  • 新增帶templateName的重載方法(如setCacheObject(String templateName, String key, T value)),支持選擇Redis實(shí)例。
  • getRedisTemplate方法根據(jù)templateName返回對(duì)應(yīng)的RedisTemplate"crawl"返回redisTemplateCrawl,否則返回redisTemplate)。

使用示例

Service層中:

@Service
public class MyService {
    @Autowired
    private RedisCache redisCache;
    public void example() {
        // 現(xiàn)有代碼:默認(rèn)使用主Redis (database: 4)
        redisCache.setCacheObject("key1", "value1");
        String value1 = redisCache.getCacheObject("key1");
        // 新代碼:使用爬蟲(chóng)Redis (database: 7)
        redisCache.setCacheObject("crawl", "key2", "value2");
        String value2 = redisCache.getCacheObject("crawl", "key2");
    }
}
  • 現(xiàn)有代碼無(wú)需修改,繼續(xù)使用主Redis。
  • 新代碼通過(guò)templateName="crawl"操作爬蟲(chóng)Redis。

優(yōu)化建議

使用枚舉替代字符串
為避免templateName的硬編碼,可使用枚舉:

public enum RedisInstance {
    DEFAULT,
    CRAWL
}
private RedisTemplate getRedisTemplate(RedisInstance instance) {
    return instance == RedisInstance.CRAWL ? redisTemplateCrawl : redisTemplate;
}

使用示例:

redisCache.setCacheObject(RedisInstance.CRAWL, "key2", "value2");

錯(cuò)誤處理
getRedisTemplate中添加空檢查:

private RedisTemplate getRedisTemplate(String templateName) {
    if (redisTemplate == null || redisTemplateCrawl == null) {
        throw new IllegalStateException("RedisTemplate not initialized");
    }
    return "crawl".equalsIgnoreCase(templateName) ? redisTemplateCrawl : redisTemplate;
}

連接測(cè)試
確保Redis服務(wù)器可訪問(wèn)(此處IP已脫敏):

redis-cli -h [REDACTED_HOST] -p 6379 -n 4  # 主Redis
redis-cli -h [REDACTED_HOST] -p 6379 -n 7  # 爬蟲(chóng)Redis

序列化器
確保FastJson2JsonRedisSerializer實(shí)現(xiàn)正確,支持序列化和反序列化。

總結(jié)

通過(guò)以下步驟,我們?cè)赟pring Boot項(xiàng)目中實(shí)現(xiàn)了優(yōu)雅的多Redis連接:

  1. application.yml中配置兩套R(shí)edis(spring.redisspring.redis-crawler)。
  2. RedisConfig.java中定義兩個(gè)RedisProperties、RedisConnectionFactoryRedisTemplate,使用@Primary@Qualifier解決注入歧義。
  3. 實(shí)現(xiàn)RedisCache工具類,支持動(dòng)態(tài)選擇Redis實(shí)例,同時(shí)兼容現(xiàn)有代碼。

這種方案既靈活又易于擴(kuò)展,適合需要操作多個(gè)Redis實(shí)例的場(chǎng)景。如果你有更多Redis實(shí)例,只需重復(fù)上述步驟,定義新的RedisPropertiesRedisTemplate,并在RedisCache中擴(kuò)展支持。

參考

  • Spring Boot官方文檔:https://docs.spring.io/spring-boot/docs/current/reference/html/data.html#data.redis
  • Lettuce官方文檔:https://lettuce.io/

到此這篇關(guān)于在SpringBoot項(xiàng)目中優(yōu)雅的連接多臺(tái)Redis的操作方法的文章就介紹到這了,更多相關(guān)SpringBoot連接多臺(tái)Redis內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringMVC實(shí)現(xiàn)簡(jiǎn)單跳轉(zhuǎn)方法(專題)

    SpringMVC實(shí)現(xiàn)簡(jiǎn)單跳轉(zhuǎn)方法(專題)

    這篇文章主要介紹了SpringMVC實(shí)現(xiàn)簡(jiǎn)單跳轉(zhuǎn)方法(專題),詳細(xì)的介紹了SpringMVC跳轉(zhuǎn)的幾種方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-03-03
  • Java原生操作JDBC連接以及原理詳解

    Java原生操作JDBC連接以及原理詳解

    這篇文章主要給大家介紹了關(guān)于Java原生操作JDBC連接以及原理的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Spring中的@PostConstruct注解使用方法解析

    Spring中的@PostConstruct注解使用方法解析

    這篇文章主要介紹了Spring中的@PostConstruct注解使用方法解析,@PostConstruct注解是用來(lái)處理在@Autowired注入屬性后init()方法之前,對(duì)一些零散的屬性進(jìn)行賦值的注解,需要的朋友可以參考下
    2023-11-11
  • Spring?Boot?+?Mybatis?Plus實(shí)現(xiàn)樹(shù)狀菜單的方法

    Spring?Boot?+?Mybatis?Plus實(shí)現(xiàn)樹(shù)狀菜單的方法

    這篇文章主要介紹了Spring?Boot?+?Mybatis?Plus實(shí)現(xiàn)樹(shù)狀菜單,包括實(shí)體類中添加子菜單列表和集合及構(gòu)建菜單樹(shù)的詳細(xì)代碼,代碼簡(jiǎn)單易懂,需要的朋友可以參考下
    2021-12-12
  • Feign利用自定義注解實(shí)現(xiàn)路徑轉(zhuǎn)義詳解

    Feign利用自定義注解實(shí)現(xiàn)路徑轉(zhuǎn)義詳解

    這篇文章主要講解一下如何通過(guò)注解實(shí)現(xiàn)對(duì)路由中的路徑進(jìn)行自定義編碼,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的幫助,需要的可以參考一下
    2022-06-06
  • 詳談fastjson將對(duì)象格式化成json時(shí)的兩個(gè)問(wèn)題

    詳談fastjson將對(duì)象格式化成json時(shí)的兩個(gè)問(wèn)題

    下面小編就為大家?guī)?lái)一篇詳談fastjson將對(duì)象格式化成json時(shí)的兩個(gè)問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • SpringBoot Shiro權(quán)限管理方式

    SpringBoot Shiro權(quán)限管理方式

    這篇文章主要介紹了SpringBoot Shiro權(quán)限管理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 基于maven的springboot的"過(guò)時(shí)"用法解析

    基于maven的springboot的"過(guò)時(shí)"用法解析

    這篇文章主要為大家介紹了基于maven的springboot"過(guò)時(shí)"用法示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • java商城項(xiàng)目實(shí)戰(zhàn)之購(gòu)物車功能實(shí)現(xiàn)

    java商城項(xiàng)目實(shí)戰(zhàn)之購(gòu)物車功能實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了java商城項(xiàng)目實(shí)戰(zhàn)之購(gòu)物車功能實(shí)現(xiàn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • httpclient 請(qǐng)求http數(shù)據(jù),json轉(zhuǎn)map的實(shí)例

    httpclient 請(qǐng)求http數(shù)據(jù),json轉(zhuǎn)map的實(shí)例

    下面小編就為大家?guī)?lái)一篇httpclient 請(qǐng)求http數(shù)據(jù),json轉(zhuǎn)map的實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-12-12

最新評(píng)論

新河县| 华坪县| 沈阳市| 临清市| 红河县| 泾源县| 高清| 东台市| 新丰县| 扶绥县| 云阳县| 佛冈县| 兴安县| 武鸣县| 永修县| 通山县| 建始县| 南通市| 莱阳市| 集贤县| 彩票| 潮安县| 陈巴尔虎旗| 焦作市| 如皋市| 河北省| 台东市| 乌恰县| 潍坊市| 岱山县| 苗栗市| 正安县| 长丰县| 牟定县| 应城市| 焉耆| 罗山县| 长沙市| 神池县| 巴青县| 保德县|