ÀÖÓãµç¾º

½ÌÓýÐÐÒµA¹ÉIPOµÚÒ»¹É£¨¹ÉƱ´úÂë 003032£©

È«¹ú×Éѯ/ͶËßÈÈÏߣº400-618-4000

redisÁîÅÆ»úÖÆÊµÏÖÃëɱ

¸üÐÂʱ¼ä:2018Äê12ÔÂ13ÈÕ14ʱ24·Ö À´Ô´:ÀÖÓã²¥¿Í ä¯ÀÀ´ÎÊý:

¡¡¡¡Ò»¡¢Ç°ÑÔ1. Ãëɱ½éÉÜ

¡¡¡¡ÃëɱÊǵçÉÌϵͳ·Ç³£³£¼ûµÄ¹¦ÄÜÄ£¿é£¬ÊÇÉ̼ҽøÐÐÏà¹Ø´ÙÏúÍÆ¹ãµÄ³£Ó÷½Ê½¡£Ö÷ÒªÌØµãÊÇÉÌÆ·¿â´æÓÐÏÞ£¬ÇÀ¹ºÊ±¼äÓÐÏÞ¡£ÄÇôÔÚϵͳÉè¼ÆÖ®³õ¾ÍÓ¦¸Ã¿¼ÂÇÔÚÊýÁ¿ºÍʱ¼äÓÐÏÞµÄÇé¿öϵ¼ÖµÄÒ»¸ö¸ß²¢·¢ÒÔ¼°¸ß²¢·¢Ëù´øÀ´µÄ¿â´æ³¬ÂôµÄÎÊÌâ¡£

¡¡¡¡ÃëɱÐèÒª½â¾öµÄÎÊÌ⣺

¡¡¡¡1) ¿â´æ³¬Âô

¡¡¡¡½â¾ö·½°¸£º

¡¡¡¡1) ±¯¹ÛËø£ºsynchronize ¡¢ Lock

¡¡¡¡2) ÀÖ¹ÛËø£ºÊý¾Ý¿âÀÖ¹ÛËø°æ±¾ºÅ¿ØÖÆ

¡¡¡¡2) ¸ß²¢·¢Çé¿öÏÂϵͳѹÁ¦ÒÔ¼°Óû§ÌåÑé

¡¡¡¡½â¾ö·½°¸£º redis

¡¡¡¡±¾½Ì³Ì²ÉÓãºredisÖÐlistÀàÐÍ´ïµ½ÁîÅÆ»úÖÆÍê³ÉÃëɱ¡£Óû§ÇÀredisÖеÄÁîÅÆ£¬ÇÀµ½ÁîÅÆµÄÓû§²ÅÄܽøÐÐÖ§¸¶£¬Ö§¸¶³É¹¦Ö®ºó¿ÉÒÔÉú³É¶©µ¥£¬Èç¹ûÒ»¶¨Ê±¼äÖ®ÄÚûÓÐÖ§¸¶ÄÇô¾ÍÓɶ¨Ê±ÈÎÎñÀ´¹é»¹ÁîÅÆ

¡¡¡¡2. ¿ª·¢½éÉÜ

¡¡¡¡1) ¿ª·¢¹¤¾ß: IntelliJ IDEA2017.3.5

¡¡¡¡2) JDK°æ±¾£º1.7+

¡¡¡¡3) Êý¾Ý¿â£º mysql5.7 ¡¢ Redis

¡¡¡¡4) ¼¼Êõ£ºSpring¡¢Spring Data Redis¡¢mybatis

¡¡¡¡¶þ¡¢»·¾³´î½¨1. Êý¾Ý¿â±í´´½¨

/*ÉÌÆ·±í */
CREATE TABLE `goods` (
  `goods_id` int(11) NOT NULL AUTO_INCREMENT,
  `num` int(11) DEFAULT NULL,
  `goods_name` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`goods_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
insert  into `goods`(`goods_id`,`num`,`goods_name`) values (1,100,'iphone X');
 /*¶©µ¥±í */
CREATE TABLE `orders` (
  `order_id` int(11) NOT NULL AUTO_INCREMENT,
  `good_id` int(11) DEFAULT NULL,
  `user` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`order_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1163 DEFAULT CHARSET=utf8;

¡¡2. redis°²×° ( ÂÔ )

¡¡3. ´´½¨mavneÏîÄ¿,´ò°ü·½Ê½jar,pom.xmlÈçÏÂ

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <junit.version>4.12</junit.version>
    <spring.version>4.2.4.RELEASE</spring.version>
    <pagehelper.version>4.0.0</pagehelper.version>
    <mybatis.version>3.2.8</mybatis.version>
    <mybatis.spring.version>1.2.2</mybatis.spring.version>
    <mybatis.paginator.version>1.2.15</mybatis.paginator.version>
    <mysql.version>5.1.32</mysql.version>
    <druid.version>1.0.9</druid.version>
</properties>
<dependencies>
    <!-- Spring -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jms</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.9</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.28</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.11.0.GA</version>
    </dependency>
    <dependency>
        <groupId>commons-codec</groupId>
        <artifactId>commons-codec</artifactId>
        <version>1.10</version>
    </dependency>
    <dependency>
        <groupId>com.github.pagehelper</groupId>
        <artifactId>pagehelper</artifactId>
        <version>${pagehelper.version}</version>
    </dependency>
    <!-- Mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>${mybatis.version}</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>${mybatis.spring.version}</version>
    </dependency>
    <dependency>
        <groupId>com.github.miemiedev</groupId>
        <artifactId>mybatis-paginator</artifactId>
        <version>${mybatis.paginator.version}</version>
    </dependency>
    <!-- MySql -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.version}</version>
    </dependency>
    <!-- Á¬½Ó³Ø -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>${druid.version}</version>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>2.8.1</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-redis</artifactId>
        <version>1.7.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>dom4j</groupId>
        <artifactId>dom4j</artifactId>
        <version>1.6.1</version>
    </dependency>
    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>1.4.01</version>
    </dependency>
</dependencies>

¡¡¡¡4. Êý¾Ý·ÃÎʲã

¡¡¡¡ÀûÓÃmybatisÄæÏò¹¤³ÌÉú³ÉPOJO£¬ÒÔ¼°mapper½Ó¿ÚºÍmapperÓ³ÉäÎļþ¡£¸Ã²¿·Ö×ÔÐвÙ×÷

¡¡¡¡mybatisºËÐÄÅäÖÃÎļþSqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <plugins>
        <!-- com.github.pagehelper Ϊ PageHelper ÀàËùÔÚ°üÃû -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- ÉèÖÃÊý¾Ý¿âÀàÐÍ Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL ÁùÖÖÊý¾Ý¿â-->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
</configuration>
Êý¾Ý·ÃÎÊ db.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/miaosha?characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

redisÅäÖÃÊôÐÔÎļþredis-config.propertiesproperties

# Redis settings
  # server IP
  redis.host=127.0.0.1
  # server port
  redis.port=6379
  # server pass
  redis.pass=
  # use dbIndex
  redis.database=0
  redis.maxIdle=1000
  redis.maxWait=3000

¡¡¡¡5. springÅäÖÃÎļþ

¡¡¡¡applicationContext-dao.xml

<!-- ¼ÓÔØÅäÖÃÎļþ -->
        <context:property-placeholder location="classpath*:properties/*.properties" />
        <!-- Êý¾Ý¿âÁ¬½Ó³Ø -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
              destroy-method="close">
            <property name="url" value="${jdbc.url}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <property name="driverClassName" value="${jdbc.driver}" />
            <property name="maxActive" value="10" />
            <property name="minIdle" value="5" />
        </bean>
            <!-- ÈÃspring¹ÜÀísqlsessionfactory ʹÓÃmybatisºÍspringÕûºÏ°üÖÐµÄ -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <!-- Êý¾Ý¿âÁ¬½Ó³Ø -->
            <property name="dataSource" ref="dataSource" />
            <!-- ¼ÓÔØmybatisµÄÈ«¾ÖÅäÖÃÎļþ -->
            <property name="configLocation" value="classpath:mybatis/SqlMapConfig.xml" />
        </bean>
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.miaosha.demo.mapper" />
        </bean>

¡¡¡¡applicationContext-redis.xml

<context:property-placeholder location="classpath*:properties/*.properties" ignore-unresolvable="true" />  
  
   <!-- redis Ïà¹ØÅäÖà -->
   <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"
     <property name="maxIdle" value="${redis.maxIdle}" />
       <property name="maxTotal" value="2000" />
       <property name="maxWaitMillis" value="${redis.maxWait}" />
     <property name="testOnBorrow" value="true" />
   </bean
  
   <bean id="JedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
       p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.pass}" p:pool-config-ref="poolConfig"/>
   
   <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
       <!--<!–¿ªÆôÊÂÎñÖ§³Ö–>-->
       <!--<property name="enableTransactionSupport" value="true"/>-->
       <property name="connectionFactory" ref="JedisConnectionFactory" />
       <!-- ÐòÁл¯·½Ê½ ½¨Òékey/hashKey²ÉÓÃStringRedisSerializer¡£ -->
       <property name="keySerializer">
           <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
       </property>
       <property name="hashKeySerializer">
           <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
       </property>
       <property name="valueSerializer">
           <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
       </property>
       <property name="hashValueSerializer">
           <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
       </property>
</bean>

¡¡¡¡Èý¡¢´úÂëʵÏÖ

¡¡¡¡1.¶¨ÒåÃëɱҵÎñ½Ó¿Ú

/**
    * ÃëɱµÄ½Ó¿Ú
    */
   public interface MiaoShaService {
   
       /**
        * ³õʼ»¯ËùÓÐÉÌÆ·µÄÁîÅÆ
        * @return
        */
       public boolean initTokenToRedis();
   
       /**
        * ÇÀ¹ºÁîÅÆ
        * @param goodsId
        * @param user
        * @param num
        * @return
        */
       public boolean miaoshaTokenFromRedis(Integer goodsId,String user,Integer num);
   
       /**
        * Óû§Î´Ö§¸¶ ÍË»¹ÁîÅÆ
        * @param user
        * @return
        */
       public boolean returnToken(String user);
   
       /**
        * Ö§¸¶Éú³É¶©µ¥±£´æµ½Êý¾Ý¿â
        * @param user
        * @return
        */
       public boolean payTokenToOrder(String user);
   }

¡¡¡¡2.ÃëɱҵÎñʵÏÖÀà

@Service
   public class MiaoShaServiceImpl implements MiaoShaService{
       @Autowired
       private GoodsMapper goodsMapper;
       @Autowired
       private OrderMapper orderMapper;
   
   
       @Autowired
       RedisTemplate redisTemplate;
   
   
       @Override
       public boolean initTokenToRedis() {
           //²éѯËùÓÐÉÌÆ·
           //¸ù¾Ýʱ¼ä   startTime<=now<=endTime
           //¸ù¾Ý״̬   ÒÑÉóºË״̬
          List<Goods> goodsList= goodsMapper.selectByExample(null);
          for(Goods goods : goodsList){
              for(int i=0;i<goods.getNum();i++) {
                  //token_goods_1:[token_1_0,token_1_1,token_1_2 ... token_1_99]
                  //token_goods_2:[token_2_0,token_2_1,token_2_2 ... token_2_99]
                  redisTemplate.boundListOps("token_goods_" + goods.getGoodsId()).leftPush("token_" + goods.getGoodsId() + "_" +i);
              }
          }
           return false;
       }
   
       @Override
       public boolean miaoshaTokenFromRedis(Integer goodsId, String user, Integer num) {
           // »ñÈ¡ÁîÅÆ
           String token = (String)redisTemplate.boundListOps("token_goods_"+goodsId).rightPop();
           if(token == null || token.equals("")){
               return false;
           }else{
               //¼Ç¼µ±Ç°Óû§ÒѾ­ÇÀ¹ºµ½ÁîÅÆ£¬Ö¤Ã÷µ±Ç°Õâ¸öÓû§¿ÉÒÔȡ֧¸¶
               //ÓÃredis¼Ç¼
               String yes  = (String)redisTemplate.boundValueOps(token).get();
               if(yes != null && yes.equals("yes")) {
                   System.out.println("µ±Ç°tokenÒѾ­±»Ö§¸¶£¬²»ÄÜÔÙÇÀ¹º");
                   redisTemplate.boundListOps("token_goods_"+goodsId).remove(1,token);
                   return false;
               }
               System.out.println(user);
               redisTemplate.boundHashOps("user_token").put(user,token);
               return true;
           }
       }
   
       @Override
       public boolean returnToken(String user) {
           //»ñµÃµ±Ç°Óû§µÄÁîÅÆ
           String token =  (String) redisTemplate.boundHashOps("user_token").get(user);
           if(token == null || token.equals("")){
               return false;
           }else {
               //µÃµ½ÉÌÆ·id
               String goodsId = token.split("_")[1];
               redisTemplate.boundListOps("token_goods_"+goodsId).leftPush(token);
               return true;
           }
       }
   
   
       @Override
       public boolean payTokenToOrder(String user) {
           //»ñµÃµ±Ç°Óû§µÄÁîÅÆ
           String token =  (String) redisTemplate.boundHashOps("user_token").get(user);
           if(token == null || token.equals("")){
               return false;
           }else {
               //Èç¹ûÔÚµ±Ç°tokenÒѾ­±»¹ºÂò¹ý£¬ÄÇô±ðÈ˾Ͳ»ÄÜÇÀµ±Ç°µÄtoken»òÕß²»ÄÜÔÙ¶Ô¸Ãtoken½øÐÐÖ§¸¶
               //²ÉÓÃredis¼Ç¼µ±Ç°tokenÒѾ­±»Ö§¸¶
               //redisTemplate.boundValueOps("key").setIfAbsent("value")
               //Èç¹ûµ±Ç°Õâ¸ökeyÓÐÖµ£¬¸Ã·½·¨¾Í»á·µ»Øfalse,Èç¹ûûÓÐÖµ£¬¾Í»ásÉèÖÃΪ¶ÔÓ¦value£¬Í¬Ê±·µ»Øtrue
               boolean flag = redisTemplate.boundValueOps(token).setIfAbsent("yes");
               //µ±Ç°tokenµÚÒ»´Î±»Ö§¸¶ flag=true
               if(flag) {
                   //µÃµ½ÉÌÆ·id
                   String goodsId = token.split("_")[1];
                   Order order = new Order();
                   order.setUser(user);
                   order.setGoodId(Integer.parseInt(goodsId));
                   orderMapper.insert(order);
                   //Óû§¸ÕºÃÔÚÖ§¸¶Ê±£¬¶¨Ê±ÈÎÎñÖ´ÐÐ
                   redisTemplate.boundHashOps("user_token").delete(user);//ÓпÉÄÜÒѾ­¹é»¹token
   
                   redisTemplate.boundListOps("token_goods_" + goodsId).remove(1, token);//ÒÆ³ýtoken, ÓпÉÄܱ»±ðÈËÇÀµ½
               }
               return true;
           }
       }
   }
3.Ãëɱ²âÊÔÀà
package com.miaosha.test;
    
    import com.miaosha.demo.service.MiaoShaService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CountDownLatch;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring/applicationContext-*.xml"})
    public class MiaoShaTest {
    
        @Autowired
        private MiaoShaService miaoShaService;
        //²¢·¢ÊýÁ¿
        public static int bfCount = 1000;
        //¼Ç¼³É¹¦¸öÊý
        public int count =0;
        //¶àÏ̸߳¨ÖúÀ࣬¿ØÖƲ¢·¢·ÃÎÊÊýÁ¿
        CountDownLatch countDownLatch = new CountDownLatch(bfCount);
    
        @Test
        public void miaoshaToOrder() throws  Exception{
            boolean flag =  miaoShaService.initTokenToRedis();
            if(flag){
               System.out.println("³õʼ»¯token³É¹¦");
            }
            long startTime = System.currentTimeMillis();
            List<Thread> tList = new ArrayList<>();
            for(int i=0;i<bfCount;i++){
                MiaoShaThread miaoShaThread = new MiaoShaThread(1,"user_"+i,1);
                Thread thread = new Thread(miaoShaThread);
                thread.start();
                tList.add(thread);
                countDownLatch.countDown();
            }
            for (Thread t : tList){
                t.join();
            }
            long endTime = System.currentTimeMillis();
            System.out.println("Ö´ÐÐʱ¼ä£º"+(endTime-startTime) );
            System.out.println("³É¹¦µÄ¸öÊý:"+count);
        }
    
    
        @Autowired
        RedisTemplate redisTemplate;
    
        @Test
        public void getTokenFromRefis(){
            Long count = redisTemplate.boundListOps("token_goods_" + 1).size();
            System.out.println("ÁîÅÆÊýÁ¿£º"+count);
        }
    
        @Test
        public void payToOrder(){
            int count_ = 1;
            for(int i=0;i<200;i++){
               boolean b = miaoShaService.payTokenToOrder("user_"+i);
               if(b){
                   count_++;
               }
            }
            System.out.println("Ö§¸¶³É¹¦µÄÈËÊý£º"+count_);
        }
        //¶¨Ê±ÈÎÎñÿÃëÖ´ÐÐÍË»¹ÁîÅÆµÄ²Ù×÷
        // Èç¹ûÔڹ涨ʱ¼ä5·ÖÖÓÖ®ÄÚûÓÐÖ§¸¶¾ÍÐèÒªÍË»¹
        @Test
        public void returnToken(){
            for(int i=0;i<1000;i++) {
                boolean flag = miaoShaService.returnToken("user_"+i);
                if(flag){
                    System.out.println("ÍË»¹ÁîÅÆ³É¹¦");
                }
            }
    
    
        }
    
    
        class MiaoShaThread implements Runnable{
            private Integer goodsId;
            private String user;
            private Integer num;
            public MiaoShaThread(Integer goodsId,String user,Integer num){
                this.goodsId=goodsId;
                this.user=user;
                this.num=num;
            }
            public void run() {
                try {
                    countDownLatch.await();
                    //²Ù×÷redis ÇÀ¹ºtoken
                    boolean flag = miaoShaService.miaoshaTokenFromRedis(goodsId, user, num);
                    if(flag){
                        synchronized (this){
                            count++;
                        }
                    }
    
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }

¡¡¡¡×¢Òâ:Ëæ×ÅCountDownLatchÉèÖò¢·¢ÊýÁ¿Ô½¸ß£¬ÐèÒªµ÷Õûredis-config.propertiesÊôÐÔÖеÄredis.maxIdleÊôÐÔ

¡¡¡¡ËÄ¡¢×ܽá

¡¡¡¡±¾ÎĽéÉÜÁËÀûÓÃredisµÄlistÊý¾ÝÀàÐÍÄ£ÄâÁîÅÆ¶ÓÁÐÀ´Íê³ÉÃëɱ£¬Ö÷Òª½â¾ö¿â´æ³¬Âô¡¢¸ß²¢·¢½µµÍϵͳѹÁ¦Ìá¸ßÓû§ÌåÑé¡¢½â¾öÀÖ¹ÛËø²»ÄÜÏȵ½ÏȵõÄÎÊÌâ¡£ÔÚµ¥»úÉÏÔËÐÐÄܹ»¹¹½¨ÉÏÍòµÄÇëÇóÀûÓÃredisÇÀ¹º100¸öÉÌÆ·ÔÚ¼¸ÃëÖ®ÄÚ´¦ÀíÍê³É¡£±¾ÎIJ¢²»ÊÇÕæÊǵÄÃëɱҵÎñ³¡¾°£¬ÖÁÉÙÌṩһÖÖÃëɱµÄ½â¾ö˼·£¬Èç¹ûÒµÎñ´æÔÚijЩ²»È·Çеĵط½£¬»¶Ó­ÁôÑÔ½»Á÷£¬Ï໥ѧϰ¡£



×÷ÕߣºÀÖÓã²¥¿ÍJavaEEÅàѵѧԺ

Ê×·¢£ºhttp://java.itcast.cn

0 ·ÖÏíµ½£º
ºÍÎÒÃÇÔÚÏß½»Ì¸£¡
¡¾ÍøÕ¾µØÍ¼¡¿¡¾sitemap¡¿