1.商品上架

1.商品Mapping
创建一个product索引和指定映射关系

PUT product
{
  "mappings": {
    "properties": {
      "skuId": {
        "type": "long"
      },
      "spuId": {
        "type": "keyword"
      },
      "skuTitle": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "skuPrice": {
        "type": "keyword"
      },
      "skuImg": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "saleCount": {
        "type": "long"
      },
      "hasStock": {
        "type": "boolean"
      },
      "hotScore": {
        "type": "long"
      },
      "brandId": {
        "type": "long"
      },
      "catalogId": {
        "type": "long"
      },
      "brandName": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "brandImg": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "catalogName": {
        "type": "keyword",
        "index": false,
        "doc_values": false
      },
      "attrs": {
        "type": "nested",
        "properties": {
          "attrId": {
            "type": "long"
          },
          "attrName": {
            "type": "keyword",
            "index": false,
            "doc_values": false
          },
          "attrValue": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

2.首页

项目的页面视图部署在对应的微服务项目的静态资源中
image.png

2.2.1整合thymeleaf

添加thymeleaf的依赖
<!-- thymeleaf-->

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

将资料中的静态资源放在微服务工程的对应位置,并在配置文件中加入对应的配置
image.png
首页页面
image.png
如果首页样式乱或者没显示两种解决方案:
1.可以在product服务config包添加如下配置

package com.yxw.gulimall.product.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * Simple to Introduction
 * className: WebMVCConfig
 *
 * @author yanxw
 * @version 2023/12/14 7:57 AM
 */
@Configuration
public class WebMVCConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }
}

2.去掉index.html路径里面的static
image.png

2.2.2搭建域名访问环境

编辑操作hosts文件

  192.168.0.88 gulimall.com

保存成功之后可以直接访问域名,解析到虚拟机的ip
Tips:有科学上网的测试的时候要先关闭科学上网的软件
安装了ES的访问gulimall.com:9200可以看到相应的内容
image.png
正式搭建项目的域名访问环境
image.png
1.nginx的配置文件
image.png
配置nginx

#切换到nginx挂载在本机的配置文件所在的目录
cd /mydata/nginx/conf
#切换到nginx的分配置文件下复制一份 定义gulimall的配置,主配置文件中有include /etc/nginx/conf.d/*.conf;这么一段配置,主配置文件
#会包含conf.d目录下的所有配置
cd /mydata/nginx/conf/conf.d
cp default.conf gulimall.conf 复制一份
#在gulimall.conf配置文件中配置我们的配置
#配置如下配置

niginx的配置文件如下

server {
    listen       80;
    server_name  gulimall.com;

    location / {
        #服务的IP 192.168.0.112
        #服务的端口: 10000
        proxy_pass http://192.168.0.112:10000;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

image.png
重启nginx:

docker restart nginx

2.让nginx代理到网关
在nginx.conf配置文件中加上如下的配置

#gulimall是上游服务器的组名
upstream gulimall{
  #网关的地址   注意这里是自己本机的ip,不是服务器ip
  server 192.168.0.112:88;
}

image.png
修改gulimall.conf中的配置

server {
    listen       80;
    server_name  gulimall.com;

    location / {
        proxy_pass http://gulimall;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

image.png

在网关的配置文件中加上以下的配置

- id: gulimall_host_route
  uri: lb://mall-product
  predicates:
    - Host=**.gulimall.com

这时我们重启网关的时候发现无法访问到相应的页面 是由于nginx访问网关的时候丢了host
这时我们需要加上如下的配置

proxy_set_header Host $host;

image.png

3.性能压测

3.1性能监控

jconsole
jvisualvm

我用的是jvisualvm
image.png

3.2jvisualvm 能干什么

监控内存泄露,跟踪垃圾回收,执行时内存、cpu 分析,线程分析...
image.png
运行:正在运行的
休眠:sleep
等待:wait 驻留:线程池里面的空闲线程 监视:阻塞的线程,正在等待锁

3.3安装插件方便查看 gc

 Cmd启动jvisualvm
 工具->插件
image.png
image.png
 如果503错误解决:
 打开网址https://visualvm.github.io/pluginscenters.html  cmd查看自己的jdk版本,找到对应的
image.png
复制下面查询出来的链接。并重新设置上即可
image.png

4.nginx动静分离

现在服务器nginx目录创建文件夹如下
image.png
将mall-product服务下的index文件夹上传到刚才创建的static文件夹下,同时删除mall-product服务下的index文件夹
image.png
修改nginx配置
image.png
修改nginx后要重启 docker restart nginx

5.SpringBoot整合redis

1.Redis的介绍

​ Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区。

中文文档:https://www.redis.net.cn/

2.入门

2.1 引入依赖

<!-- redis -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<!-- spring2.X集成redis所需common-pool2-->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.6.0</version>
</dependency>    

2.2 添加配置类

package com.atguigu.yygh.common.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.lang.reflect.Method;
import java.time.Duration;

/**
 * @author GongChangjiang
 * @version 1.0
 * @Date 2023/4/14
 * @Description
 */
@Configuration
@EnableCaching
public class RedisConfig {

    /**
     * 自定义key规则
     */
    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }

    /**
     * 设置RedisTemplate规则
     *
     */
    @Bean
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        //序列号key value
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    /**
     * 设置CacheManager缓存规则
     * 缓存的时间
     * 乱码的处理
     */
    @Bean
    public CacheManager cacheManager(RedisConnectionFactory factory) {
        RedisSerializer<String> redisSerializer = new StringRedisSerializer();
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);

        //解决查询缓存转换异常的问题
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        // 配置序列化(解决乱码的问题),过期时间600秒
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(600))
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
                .disableCachingNullValues();

        RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
                .cacheDefaults(config)
                .build();
        return cacheManager;
    }

}

说明:
@EnableCaching:标记注解 @EnableCaching,开启缓存,并配置Redis缓存管理器。@EnableCaching 注释触发后置处理器, 检查每一个Spring bean 的 public 方法是否存在缓存注解。如果找到这样的一个注释, 自动创建一个代理拦截方法调用和处理相应的缓存行为。

2.3 配置文件中加入redis的配置

application.properties

spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database= 0
spring.redis.timeout=1800000

spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
#最大阻塞等待时间(负数表示没限制)
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
2.4 使用Spring Cache + Redis执行缓存操作

2.1.2 @Cacheable
​ 根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。
image.png
2.1.2 @CachePut
​ 使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
image.png
2.1.3 @CacheEvict
​ 使用该注解标志的方法,会清空指定的缓存。一般用在更新或者删除方法上
image.png

3.示例

下面的第一个方法是查询数据位list集合

​ @Cacheable(value = “dict”,keyGenerator = “keyGenerator”) 对方法的结果进行缓存

​ value属性表示key的前缀

​ keyGenerator表示key的生成规则,生成规则在配置文件中配置,这里我们使用的是方法的全类名作为key的后缀

第二个方法是添加数据 添加数据会造成数据库中数据的变化 我们要清除缓存

​ @CacheEvict(value = “dict”,allEntries = true) 清空指定的缓存

​ value属性表示清空以dict为前缀的所有缓存

​ allEntries 属性表示是否清空所有缓存,默认为 false。如果指定为 true,则方法调用后将立即清空所有的缓存

@Override
@Cacheable(value = "dict",keyGenerator = "keyGenerator")
public List<Dict> findByParentId(Long parentId) {
    LambdaQueryWrapper<Dict> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.eq(Dict::getParentId, parentId);
    List<Dict> dictList = dictMapper.selectList(queryWrapper);
    for (Dict dict : dictList) {
        dict.setHasChildren(this.isHasChildren(dict.getId()));
    }
    return dictList;
}

@CacheEvict(value = "dict",allEntries = true)
public void importDictData(MultipartFile file) {
    try {
        EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(dictMapper)).sheet().doRead();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

6.项目中使用Redis

6.1引入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

6.2 添加配置

spring:
  redis:
    host: 192.168.0.88
    port: 6379

6.3 测试使用

@Autowired
private StringRedisTemplate stringRedisTemplate;

@Test
void testRedis(){
    ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
    ops.set("hello","word_"+ UUID.randomUUID().toString());
    String hello = ops.get("hello");
    System.out.println(hello);
}

image.png
lettuce堆外内存溢出bug
产生原因:

1)、springboot2.0以后默认使用 lettuce作为操作redis的客户端,它使用netty进行网络通信

2)、lettuce的bug导致netty堆外内存溢出。netty如果没有指定堆外内存,默认使用Xms的值,可以使用-Dio.netty.maxDirectMemory进行设置

解决方案:由于是lettuce的bug造成,不要直接使用-Dio.netty.maxDirectMemory去调大虚拟机堆外内存,治标不治本。

1)、升级lettuce客户端
2)、切换使用jedis
修改依赖文件,使用jedis作为客户端工具

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
    <exclusions>
        <exclusion>
            <groupId>io.lettuce</groupId>
            <artifactId>lettuce-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
</dependency>

6.4高并发下缓存失效问题

缓存穿透
image.png
缓存雪崩
image.png
缓存击穿
image.png

7.检索服务

7.1整合页面

在nginx里面放入如下文件
image.png

7.2配置域名访问

image.png

7.3Nginx的配置

server {

listen       80;
server_name  *.gulimall.com;

location / {
    proxy_set_header Host $host;
    proxy_pass http://gulimall;
}

error_page   500 502 503 504  /50x.html;
location = /50x.html {
    root   /usr/share/nginx/html;
}

}

image.png
重启nginx docker restart nginx
配置本机的host文件
image.png
ip写对应自己的服务器ip

网关配置
image.png

7.4首页和搜索页相互跳转

修改nginx配置
image.png

8.检索DLS测试

按照条件查询

GET gulimall_product/_search
{
  "query": {
    "match_all": {

    }
  },
  "aggs": {
    "brand_agg": {
      "terms": {
        "field": "brandId",
        "size": 10
      },
      "aggs": {
        "brand_name_aggs": {
          "terms": {
            "field": "brandName",
            "size": 10
          }
        }
      }
    },
    "catalog_agg": {
      "terms": {
        "field": "catalogId",
        "size": 10
      }
    }
  }
}

报错不能加载brandName数据,因为这个数据不支持keyword类型,
image.png
解决办法修改映射和迁移数据:
创建索引mall_product

PUT mall_product
{
"mappings": {
"properties": {
  "skuId": {
    "type": "long"
  },
  "spuId": {
    "type": "keyword"
  },
  "skuTitle": {
    "type": "text",
    "analyzer": "ik_smart"
  },
  "skuPrice": {
    "type": "keyword"
  },
  "skuImg": {
    "type": "keyword"
  },
  "saleCount": {
    "type": "long"
  },
  "hasStock": {
    "type": "boolean"
  },
  "hotScore": {
    "type": "long"
  },
  "brandId": {
    "type": "long"
  },
  "catalogId": {
    "type": "long"
  },
  "brandName": {
    "type": "keyword"
  },
  "brandImg": {
    "type": "keyword"
  },
  "catalogName": {
    "type": "keyword"
  },
  "attrs": {
    "type": "nested",
    "properties": {
      "attrId": {
        "type": "long"
      },
      "attrName": {
        "type": "keyword"
      },
      "attrValue": {
        "type": "keyword"
      }
    }
  }
}
  }
}

数据迁移:

POST _reindex
{
  "source": {
    "index": "gulimall_product"
  },
  "dest": {
    "index": "mall_product"
  }
}

完整的dsl语句:

GET mall_product/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "skuTitle": "华为"
          }
        }
      ],
      "filter": [
        {
          "term": {
            "catalogId": "225"
          }
        },
        {
          "terms": {
            "brandId": [
              "1",
              "2",
              "9"
            ]
          }
        },
        {
          "term": {
            "attrs.attrId": "15"
          }
        },
        {
          "nested": {
            "path": "attrs",
            "query": {
              "bool": {
                "must": [
                  {
                    "term": {
                      "attrs.attrId": {
                        "value": "15"
                      }
                    }
                  },
                  {
                    "terms": {
                      "attrs.attrValue": [
                        "系统",
                        "安卓"
                      ]
                    }
                  }
                ]
              }
            }
          }
        }
      ]
    }
  },
  "sort": [
    {
      "skuPrice": {
        "order": "desc"
      }
    }
  ],
  "from": 0,
  "size": 1,
  "highlight": {
    "fields": {
      "skuTitle": {}
    },
    "pre_tags": "<b style='color:red'>",
    "post_tags": "</b>"
  },
  "aggs": {
    "brand_agg": {
      "terms": {
        "field": "brandId",
        "size": 10
      },
      "aggs": {
        "brand_name_agg": {
          "terms": {
            "field": "brandName",
            "size": 10
          }
        },
        "brand_img_agg": {
          "terms": {
            "field": "brandImg",
            "size": 10
          }
        }
      }
    },
    "catalog_agg": {
      "terms": {
        "field": "catalogId",
        "size": 10
      },
      "aggs": {
        "catalog_name_agg": {
          "terms": {
            "field": "catalogName",
            "size": 10
          }
        }
      }
    },
    "attr_agg": {
      "nested": {
        "path": "attrs"
      },
      "aggs": {
        "attr_id_agg": {
          "terms": {
            "field": "attrs.attrId",
            "size": 10
          },
          "aggs": {
            "attr_name_agg": {
              "terms": {
                "field": "attrs.attrName",
                "size": 10
              }
            },
            "attr_value_agg": {
              "terms": {
                "field": "attrs.attrValue",
                "size": 10
              }
            }
          }
        }
      }
    }
  }
}

9.认证服务

1.环境搭建

创建mall-auth-server服务
image.png
启动类:

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class MallAuthServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(MallAuthServerApplication.class, args);
    }

}

application.yml

server:
  port: 20000
spring:
  application:
    name: mall-auth-server
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

将注册和登录hmtl导入进来
image.png

2.修改host文件

192.168.0.88 auth.gulimall.com
在服务器创建文件夹
image.png
注册
image.png
登录
image.png
修改login页面
image.png
image.png
修改reg页面
image.png
image.png
将login.html修改index.html
重新启动服务访问:http://auth.gulimall.com/
image.png

3.登录和注册相互跳转

修改application.yml

thymeleaf:
    cache: false

创建LoginController

package com.yxw.gulimall.auth.controller;

import com.alibaba.fastjson.TypeReference;
import com.yxw.common.utils.R;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

/**
 * Simple to Introduction
 * className: LoginController
 *
 * @author yanxw
 * @version 2023/12/31 3:51 PM
 */
@Controller
public class LoginController {


    @GetMapping(value = "/login.html")
    public String login() {

        return "login";
    }


    @GetMapping(value = "/reg.html")
    public String regPage() {

        return "reg";
    }

}

将index.html修改login.html
修改login.html

<span><a href="http://auth.gulimall.com/reg.html">立即注册</a></span>

image.png
修改reg.html
image.png

4.验证码

创建GulimallWebConfig类

package com.yxw.gulimall.auth.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * Simple to Introduction
 * className: GulimallWebConfig
 *
 * @author yanxw
 * @version 2023/12/31 5:22 PM
 */
@Configuration
public class GulimallWebConfig implements WebMvcConfigurer {

    /**·
     * 视图映射:发送一个请求,直接跳转到一个页面
     * @param registry
     */
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {

        registry.addViewController("/login.html").setViewName("login");
        registry.addViewController("/reg.html").setViewName("reg");
    }
}

注释LoginController中那两个方法

5.开通短信服务

登录阿里云
image.png
image.png
image.png
image.png
测试代码

@Test
    public void sendSms() {
        String host = "https://dfsns.market.alicloudapi.com";
        String path = "/data/send_sms";
        String method = "POST";
        String appcode = "6e568a4ef5b788899970e1028c872";
        Map<String, String> headers = new HashMap<String, String>();
        //最后在header中的格式(中间是英文空格)为Authorization:APPCODE 83359fd73fe94948385f570e3c139105
        headers.put("Authorization", "APPCODE " + appcode);
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();
        bodys.put("content", "code:666666");
        bodys.put("template_id", "CST_ptdie100");  //该模板为调试接口专用,短信下发有受限制,调试成功后请联系客服报备专属模板
        bodys.put("phone_number", "13263275555");
//        bodys.put("skin", "1");
//        bodys.put("sign", "1");
        //JDK 1.8示例代码请在这里下载:  http://code.fegine.com/Tools.zip
        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 或者直接下载:
             * http://code.fegine.com/HttpUtils.zip
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             * 相关jar包(非pom)直接下载:
             * http://code.fegine.com/aliyun-jar.zip
             */
            HttpResponse response = HttpUtils.doPost(host, path, method, headers, querys, bodys);
            //System.out.println(response.toString());如不输出json, 请打开这行代码,打印调试头部状态码。
            //状态码: 200 正常;400 URL无效;401 appCode错误; 403 次数用完; 500 API网管错误
            //获取response的body
            System.out.println("-----" + EntityUtils.toString(response.getEntity()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


great
1 声望0 粉丝