SSM分布式项目之淘淘商城-第七天(IDEA)

文章大纲
一 、第七天课程计划
二、什么是SolrCloud
三、Solr集群的系统架构
四、环境准备
五、安装步骤
六、使用solrJ管理集群
七、把搜索功能切换到集群版
八、HttpClient
九、使用HttpClient调用接口
十、全局异常处理

淘淘商城课程大纲

课程大纲
一共14天课程
(1)第一天:电商介绍–互联网术语-SOA-分布式-集群介绍-环境配置-框架搭建
(2)第二天:Dubbo介绍_dubbo框架整合_商品列表查询实现_分页_逆向工程
(3)第三天:Git&.Nginx,类目选择,新增商品
(4)第四天:门户网站介绍&商城首页搭建&内容系统创建&CMS实现
(5)第五天:首页轮播图显示实现,Redis环境搭建,Redis实现缓存
(6)第六天:solr索引库搭建&solr搜索功能实现&图片显示问题解决
(7)第七天:solr集群搭建_全局异常处理
(8)第八天:activeMQ介绍_搭建_解决同步索引库问题
(9)第九天:FreeMark入门_静态化页面标签介绍_静态化页面实现
(10)第十天:Nginx代理详解…单点登录系统工程搭建_接口文档讲解
(11)第十一天:SSO系统的搭建&单点登录系统实现_用户名回显_cookie跨域问题
(12)第十二天:购物车订单系统的实现。
(13)第十三天:订单提交的功能实现&项目的部署&服务器的域名规划。
(14)项目总结。

1. 第七天课程计划

1、solr集群搭建
2、使用solrj管理solr集群
3、把搜索功能切换到集群版
4、httpclient
5、全局异常处理

说明:这文章参考老师的上课笔记,至于Solr集群,由于虚拟机内存不够,自己没有亲自尝试,所以以后有机会再搭建。而且这篇理论上的东西更多,仅供参考

2. 什么是SolrCloud

SolrCloud(solr 云)是Solr提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud。当索引量很大,搜索请求并发很高,这时需要使用SolrCloud来满足这些需求。
SolrCloud是基于Solr和Zookeeper的分布式搜索方案,它的主要思想是使用Zookeeper作为集群的配置信息中心。

2.1. zookeeper的介绍

zookeeper翻译成动物园管理员,他是用来管hadoop(大象)、Hive(蜜蜂)、pig(小猪)的管理员,这些“动物”都是一些项目, Apache Hbase和 Apache Solr 的分布式集群都用到了zookeeper;Zookeeper:是一个分布式的、开源的程序协调服务,是hadoop项目下的一个子项目

Zookeeper它有几个特色功能:

1)集中式的配置信息(数据库的属性文件,放在zookeeper中,修改后不用重启也能生效)
2)自动容错
3)近实时搜索
4)查询时自动负载均衡

2.2. zookeeper的应用场景

2.2.1. 配置中心(集中管理)
在我们的应用中除了代码外,还有一些就是各种配置。比如数据库连接等。一般我们都是使用配置文件的方式,在代码中引入这些配置文件。但是当我们只有一种配置,只有一台服务器,并且不经常修改的时候,使用配置文件是一个很好的做法,但是如果我们配置非常多,有很多服务器都需要这个配置,而且还可能是动态的话使用配置文件就不是个好主意了。这个时候往往需要寻找一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更。比如我们可以把配置放在数据库里,然后所有需要配置的服务都去这个数据库读取配置。但是,因为很多服务的正常运行都非常依赖这个配置,所以需要这个集中提供配置服务的服务具备很高的可靠性。一般我们可以用一个集群来提供这个配置服务,但是用集群提升可靠性,那如何保证配置在集群中的一致性呢?这个时候就需要使用一种实现了一致性协议的服务了。Zookeeper就是这种服务,它使用Zab这种一致性协议来提供一致性。现在有很多开源项目使用Zookeeper来维护配置,比如在HBase中,客户端就是连接一个Zookeeper,获得必要的HBase集群的配置信息,然后才可以进一步操作。还有在开源的消息队列Kafka中,也使用Zookeeper来维护broker的信息。在Alibaba开源的SOA框架Dubbo中也广泛的使用Zookeeper管理一些配置来实现服务治理。
2.2.2. 名字服务
名字服务这个可以这么理解,比如为了通过网络访问一个系统,我们得知道对方的IP地址,但是IP地址对人非常不友好,这个时候我们就需要使用域名来访问。但是计算机是不能是别域名的。怎么办呢?如果我们每台机器里都备有一份域名到IP地址的映射,这个倒是能解决一部分问题,但是如果域名对应的IP发生变化了又该怎么办呢?于是我们有了DNS这个东西。我们只需要访问一个大家熟知的(known)的点,它就会告诉你这个域名对应的IP是什么。在我们的应用中也会存在很多这类问题,特别是在我们的服务特别多的时候,如果我们在本地保存服务的地址的时候将非常不方便,但是如果我们只需要访问一个大家都熟知的访问点,这里提供统一的入口,那么维护起来将方便得多了。
2.2.3. 分布式锁
Zookeeper是一个分布式协调服务,这样我们就可以利用Zookeeper来协调多个分布式进程之间的活动。比如在一个分布式环境中,为了提高可靠性,我们的集群的每台服务器上都部署着同样的服务。但是,一件事情如果集群中的每个服务器都进行的话,那相互之间就要协调,编程起来将非常复杂。而如果我们只让一个服务进行操作,那又存在单点。通常还有一种做法就是使用分布式锁,在某个时刻只让一个服务去干活,当这台服务出问题的时候锁释放,立即fail over到另外的服务。这在很多分布式系统中都是这么做,这种设计有一个更好听的名字叫Leader Election(leader选举)。比如HBase的Master就是采用这种机制。

2.2.4. 集群管理
在分布式的集群中,经常会由于各种原因,比如硬件故障,软件故障,网络问题,有些节点会进进出出。有新的节点加入进来,也有老的节点退出集群。这个时候,集群中其他机器需要感知到这种变化,然后根据这种变化做出对应的决策。比如我们是一个分布式存储系统,有一个中央控制节点负责存储的分配,当有新的存储进来的时候我们要根据现在集群目前的状态来分配存储节点。这个时候我们就需要动态感知到集群目前的状态。还有,比如一个分布式的SOA架构中,服务是一个集群提供的,当消费者访问某个服务时,就需要采用某种机制发现现在有哪些节点可以提供该服务(这也称之为服务发现,比如Alibaba开源的SOA框架Dubbo就采用了Zookeeper作为服务发现的底层机制)。还有开源的Kafka队列就采用了Zookeeper作为Cosnumer的上下线管理。

3. Solr集群的系统架构

在这里插入图片描述

在这里插入图片描述

3.1. 物理结构

三个Solr实例( 每个实例包括两个Core),组成一个SolrCloud。

3.2. 逻辑结构

索引集合包括两个Shard(shard1和shard2),shard1和shard2分别由三个Core组成,其中一个Leader两个Replication,Leader是由zookeeper选举产生,zookeeper控制每个shard上三个Core的索引数据一致,解决高可用问题。
用户发起索引请求分别从shard1和shard2上获取,解决高并发问题。

3.2.1. collection
Collection在SolrCloud集群中是一个逻辑意义上的完整的索引结构。它常常被划分为一个或多个Shard(分片),它们使用相同的配置信息。
比如:针对商品信息搜索可以创建一个collection。
collection=shard1+shard2+…+shardX

3.2.2. Core
每个Core是Solr中一个独立运行单位,提供 索引和搜索服务。一个shard需要由一个Core或多个Core组成。由于collection由多个shard组成所以collection一般由多个core组成。
3.2.3. Master或Slave
Master是master-slave结构中的主结点(通常说主服务器),Slave是master-slave结构中的从结点(通常说从服务器或备服务器)。同一个Shard下master和slave存储的数据是一致的,这是为了达到高可用目的。
3.2.4. Shard
Collection的逻辑分片。每个Shard被化成一个或者多个replication,通过选举确定哪个是Leader。

3.3. 需要实现的solr集群架构

在这里插入图片描述

Zookeeper作为集群的管理工具。
1、集群管理:容错、负载均衡。
2、配置文件的集中管理
3、集群的入口

需要实现zookeeper 高可用。需要搭建集群。建议是奇数节点。需要三个zookeeper服务器。

搭建solr集群需要7台服务器。
zookeeper有自己的投票机制,类似于redis. 需要半数以上的节点判断其他的节点挂掉,才能算挂掉。

搭建伪分布式:
需要三个zookeeper节点
需要四个tomcat节点。

建议虚拟机的内存1G以上。

4. 环境准备

CentOS-6.4-i386-bin-DVD1.iso
jdk-7u72-linux-i586.tar.gz
apache-tomcat-7.0.47.tar.gz
zookeeper-3.4.6.tar.gz
solr-4.10.3.tgz

5. 安装步骤

第一个阶段:搭建zookeeper集群
	上传zookeeper的安装包
	创建安装的目录(solr-cloud)
        拷贝zookeeper到solr-cloud中,复制三份
	在每一个zookeeper中创建data 目录 在data创建 myid     文件中的值:123 



第二个阶段:搭建solr集群 
	搭建一个单机版的solr   copy已有的solr
        从单机版中拷贝4份tomcat 到solr-cloud
	从单机版中拷贝4份solrhome 到solr-cloud
	关联tomcat和solrhome
	修改每一个tomcat的端口
	配置sorlhome下的solr.xml
        
        需要将solrhome下的conf目录上传到zookeeper统一管理
        
        查看是否 成功,使用zookeeper客户端的命令


第三个阶段:将solr集群 和zookeeper集群关联 

       将tomcat的bin/catalina.sh 中设置 
       JAVA_OPTS="-DzkHost=192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183"





5.1. Zookeeper集群搭建

第一步:需要安装jdk环境。
第二步:把zookeeper的压缩包上传到服务器。
第三步:解压缩。
第四步:把zookeeper复制三份。

[root@localhost ~]# mkdir /usr/local/solr-cloud
[root@localhost ~]# cp -r zookeeper-3.4.6 /usr/local/solr-cloud/zookeeper01
[root@localhost ~]# cp -r zookeeper-3.4.6 /usr/local/solr-cloud/zookeeper02
[root@localhost ~]# cp -r zookeeper-3.4.6 /usr/local/solr-cloud/zookeeper03

第五步:在每个zookeeper目录下创建一个data目录。
第六步:在data目录下创建一个myid文件,文件名就叫做“myid”。内容就是每个实例的id。例如1、2、3

[root@localhost data]# echo 1 >> myid
[root@localhost data]# ll
total 4
-rw-r--r--. 1 root root 2 Apr  7 18:23 myid
[root@localhost data]# cat myid 
1

第七步:修改配置文件。把每一个zookeeper下的conf目录下的zoo_sample.cfg文件改名为zoo.cfg
在zookeeper01目录下的配置如下:(注意:配置的端口都不能冲突) 同理在zookeeper02 03下配置,注意端口不能冲突。
在这里插入图片描述

server.1=192.168.25.154:2881:3881
server.2=192.168.25.154:2882:3882
server.3=192.168.25.154:2883:3883

第八步:启动每个zookeeper实例。
a) 创建启动实例的批处理文件:在solr-cloud下创建,命令如下

[root@localhost solr-cloud]# vim zookeeper_start_all.sh

b) 使用vim 编辑内容如下:

cd /usr/local/solr-cloud/zookeeper01/bin
./zkServer.sh start

cd /usr/local/solr-cloud/zookeeper02/bin
./zkServer.sh start

cd /usr/local/solr-cloud/zookeeper03/bin
./zkServer.sh start

按ESC 
输入:wq保存
退出。

改成可执行权限:
[root@localhost solr-cloud]# chmod u+x zookeeper_start_all.sh

c)	启动所有zookeeper实例
[root@localhost solr-cloud]# ./zookeeper_start_all.sh

查看zookeeper的状态:

[root@localhost solr-cloud]# zookeeper01/bin/zkServer.sh status

效果如下:

在这里插入图片描述

5.2. Solr集群的搭建

第一步:创建四个tomcat实例。每个tomcat运行在不同的端口。8180、8280、8380、8480
第二步:部署solr的war包。把单机版的solr工程复制到集群中的tomcat中。
第三步:为每个solr实例创建一个对应的solrhome。使用单机版的solrhome复制四份。
第四步:需要修改solr的web.xml文件。把solrhome关联起来。
第五步:配置solrCloud相关的配置。每个solrhome下都有一个solr.xml,把其中的ip及端口号配置好。
在这里插入图片描述

第六步:让zookeeper统一管理配置文件。需要把solrhome/collection1/conf目录上传到zookeeper。上传任意solrhome中的配置文件即可。(需要保证zookeeper集群是启动的状态)
使用工具上传配置文件:/root/solr-4.10.3/example/scripts/cloud-scripts

/zkcli.sh
./zkcli.sh -zkhost 192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183 -cmd upconfig -confdir /usr/local/solr-cloud/solrhome01/collection1/conf -confname myconf

查看zookeeper上的配置文件:
使用zookeeper目录下的bin/zkCli.sh命令查看zookeeper上的配置文件:
注意点(如果不是默认的端口2181,要连接使用命令:

./zkCli.sh  -server 192.168.25.154:2181  

解释:
-server :指定ip地址
:2181 :指定连接的端口。

[root@localhost bin]# ./zkCli.sh 
[zk: localhost:2181(CONNECTED) 0] ls /
[configs, zookeeper]
[zk: localhost:2181(CONNECTED) 1] ls /configs
[myconf]
[zk: localhost:2181(CONNECTED) 2] ls /configs/myconf
[admin-extra.menu-top.html, currency.xml, protwords.txt, mapping-FoldToASCII.txt, _schema_analysis_synonyms_english.json, _rest_managed.json, solrconfig.xml, _schema_analysis_stopwords_english.json, stopwords.txt, lang, spellings.txt, mapping-ISOLatin1Accent.txt, admin-extra.html, xslt, synonyms.txt, scripts.conf, update-script.js, velocity, elevate.xml, admin-extra.menu-bottom.html, clustering, schema.xml]
[zk: localhost:2181(CONNECTED) 3] 
退出:
[zk: localhost:2181(CONNECTED) 3] quit

第七步:修改(4个)每一个tomcat/bin目录下的catalina.sh 文件,关联solr和zookeeper。
把此配置添加到配置文件中:

JAVA_OPTS="-DzkHost=192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183"

在这里插入图片描述

第八步:启动每个tomcat实例。要保证zookeeper集群是启动状态。
第九步:访问集群
在这里插入图片描述

第十步:创建新的Collection进行分片处理。

http://192.168.25.154:8180/solr/admin/collections?action=CREATE&name=collection2&numShards=2&replicationFactor=2

在这里插入图片描述
在这里插入图片描述

第十一步:删除不用的Collection。

http://192.168.25.154:8180/solr/admin/collections?action=DELETE&name=collection1

在这里插入图片描述

在这里插入图片描述

6. 使用solrJ管理集群

6.1. 添加文档

使用步骤:
第一步:把solrJ相关的jar包添加到工程中。
第二步:创建一个SolrServer对象,需要使用CloudSolrServer子类。构造方法的参数是zookeeper的地址列表。
第三步:需要设置DefaultCollection属性。
第四步:创建一SolrInputDocument对象。
第五步:向文档对象中添加域
第六步:把文档对象写入索引库。
第七步:提交。

@Test
	public void testSolrCloudAddDocument() throws Exception {
		// 第一步:把solrJ相关的jar包添加到工程中。
		// 第二步:创建一个SolrServer对象,需要使用CloudSolrServer子类。构造方法的参数是zookeeper的地址列表。
		//参数是zookeeper的地址列表,使用逗号分隔
		CloudSolrServer solrServer = new CloudSolrServer("192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183");
		// 第三步:需要设置DefaultCollection属性。
		solrServer.setDefaultCollection("collection2");
		// 第四步:创建一SolrInputDocument对象。
		SolrInputDocument document = new SolrInputDocument();
		// 第五步:向文档对象中添加域
		document.addField("item_title", "测试商品");
		document.addField("item_price", "100");
		document.addField("id", "test001");
		// 第六步:把文档对象写入索引库。
		solrServer.add(document);
		// 第七步:提交。
		solrServer.commit();

	}

6.2. 查询文档

创建一个CloudSolrServer对象,其他处理和单机版一致。

7. 把搜索功能切换到集群版

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans4.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context4.2.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx4.2.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util4.2.xsd">

	<!-- 单机版solr服务配置 -->
	<!-- <bean id="httpSolrServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
		<constructor-arg name="baseURL" value="http://192.168.25.154:8080/solr"></constructor-arg>
	</bean> -->
	<!-- 集群版solr服务 -->
	<bean id="cloudSolrServer" class="org.apache.solr.client.solrj.impl.CloudSolrServer">
		<constructor-arg name="zkHost" value="192.168.25.154:2181,192.168.25.154:2182,192.168.25.154:2183"></constructor-arg>	
		<property name="defaultCollection" value="collection2"></property>
	</bean>
</beans>

8. HttpClient

在这里插入图片描述

8.1. HttpClient简介

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。

HttpClient 提供的主要的功能

1)实现了所有 HTTP 的方法(GET,POST,PUT,DELETE等)
(2)支持自动转向
(3)支持 HTTPS 协议
(4)支持代理服务器等

我们所用的solrj其实就封装了HttpClient

8.2. 学习httpclient

http状态码:
在这里插入图片描述

常用的:200 201 202 400 404 405 406 415 500 501 502 503

200 OK	请求已成功,请求所希望的响应头或数据体将随此响应返回。
201 Created	请求已经被实现,而且有一个新的资源已经依据请求的需要而建立,且其 URI 已经随Location 头信息返回
202 Accepted	服务器已接受请求,但尚未处理
400 Bad Request	1、语义有误,当前请求无法被服务器理解
2、请求参数有误
403 Forbidden	服务器已经理解请求,但是拒绝执行它
404 Not Found	请求失败,请求所希望得到的资源未被在服务器上发现
405 Method Not Allowed	请求行中指定的请求方法不能被用于请求相应的资源
406 Not Acceptable	请求的资源的内容特性无法满足请求头中的条件,因而无法生成响应实体
415 Unsupported Media Type	对于当前请求的方法和所请求的资源,请求中提交的实体并不是服务器中所支持的格式,因此请求被拒绝
500 Internal Server Error	服务器遇到了一个未曾预料的状况,导致了它无法完成对请求的处理
501 Not Implemented	服务器不支持当前请求所需要的某个功能
502 Bad Gateway	作为网关或者代理工作的服务器尝试执行请求时,从上游服务器接收到无效的响应
503 Service Unavailable	由于临时的服务器维护或者过载,服务器当前无法处理请求,服务器宕机

通过此工程进行学习:

在这里插入图片描述

8.2.1. 无参数的GET请求

在这里插入图片描述

8.2.2. 带参数的GET请求

public class DoGETParam {

    public static void main(String[] args) throws Exception {

        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();

        // 定义请求的参数
        URI uri = new URIBuilder("http://www.baidu.com/s").setParameter("wd", "java").build();

        System.out.println(uri);

        // 创建http GET请求
        HttpGet httpGet = new HttpGet(uri);

        CloseableHttpResponse response = null;
        try {
            // 执行请求
            response = httpclient.execute(httpGet);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                System.out.println(content);
            }
        } finally {
            if (response != null) {
                response.close();
            }
            httpclient.close();
        }

    }
}

8.2.3. 无参数的POST请求

Public static void main(String[] args) throws Exception {

	// 创建Httpclient对象
	CloseableHttpClient httpclient = HttpClients.createDefault();

	// 创建http POST请求
	HttpPost httpPost = new HttpPost("http://www.oschina.net/");

	// 在请求中设置请求头,设置请求头,跳过开源中国的访问限制
	httpPost.setHeader("User-Agent", "");

	CloseableHttpResponse response = null;
	try {
		// 执行请求
		response = httpclient.execute(httpPost);
		// 判断返回状态是否为200
		if (response.getStatusLine().getStatusCode() == 200) {
			String content = EntityUtils.toString(response.getEntity(), "UTF-8");
			System.out.println(content);
		}
	} finally {
		if (response != null) {
			response.close();
		}
		httpclient.close();
	}
}

8.2.4. 带参数的POST请求

public class DoPOSTParam {

    public static void main(String[] args) throws Exception {

        // 创建Httpclient对象
        CloseableHttpClient httpclient = HttpClients.createDefault();

        // 创建http POST请求
        HttpPost httpPost = new HttpPost("http://www.oschina.net/search");
        
        // 设置2个post参数,一个是scope、一个是q
        List<NameValuePair> parameters = new ArrayList<NameValuePair>(0);
        parameters.add(new BasicNameValuePair("scope", "project"));
        parameters.add(new BasicNameValuePair("q", "java"));
        // 构造一个form表单式的实体
        UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters);
        // 将请求实体设置到httpPost对象中
        httpPost.setEntity(formEntity);

        CloseableHttpResponse response = null;
        try {
            // 执行请求
            response = httpclient.execute(httpPost);
            // 判断返回状态是否为200
            if (response.getStatusLine().getStatusCode() == 200) {
                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                System.out.println(content);
            }
        } finally {
            if (response != null) {
                response.close();
            }
            httpclient.close();
        }
    }
}

9. 使用HttpClient调用接口

9.1. 编写返回对象

public class HttpResult {
	// 响应的状态码
	privateint code;

	// 响应的响应体
	private String body;
get/set…
}

9.2. 封装HttpClient

public class ApiService {

	private CloseableHttpClient httpClient;

	public ApiService() {
		this.httpClient = HttpClients.createDefault();
	}

	/**
	 * 带参数的get请求
	 * 
	 * @param url
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public HttpResult doGet(String url, Map<String, Object>map) throws Exception {
		// 1.创建URIBuilder
		URIBuilder uriBuilder = new URIBuilder(url);

		// 2.设置请求参数
		if (map != null) {
			// 遍历请求参数
			for (Map.Entry<String, Object>entry : map.entrySet()) {
				// 封装请求参数
				uriBuilder.setParameter(entry.getKey(), entry.getValue().toString());
			}
		}

		// 3.创建请求对象httpGet
		HttpGet httpGet = new HttpGet(uriBuilder.build());

		// 4.使用httpClient发起请求
		CloseableHttpResponse response = this.httpClient.execute(httpGet);

		// 5.解析返回结果,封装返回对象httpResult
		// 获取状态码
		intcode = response.getStatusLine().getStatusCode();

		// 获取响应体
		// 使用EntityUtils.toString方法必须保证entity不为空
		String body;
		if (response.getEntity() != null) {
			body = EntityUtils.toString(response.getEntity(), "UTF-8");
		} else {
			body = null;
		}

		returnnew HttpResult(code, body);
	}

	/**
	 * 不带参数的get
	 * 
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public HttpResult doGet(String url) throws Exception {
		returnthis.doGet(url, null);
	}

	/**
	 * 带参数的post请求
	 * 
	 * @param url
	 * @param map
	 * @return
	 * @throws Exception
	 */
	public HttpResult doPost(String url, Map<String, Object>map) throws Exception {
		// 1. 声明httppost
		HttpPost httpPost = new HttpPost(url);

		// 2.封装请求参数,请求数据是表单
		if (map != null) {
			// 声明封装表单数据的容器
			List<NameValuePair>parameters = new ArrayList<NameValuePair>();
			for (Map.Entry<String, Object>entry : map.entrySet()) {
				// 封装请求参数到容器中
				parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
			}

			// 创建表单的Entity类
			UrlEncodedFormEntity entity = newUrlEncodedFormEntity(parameters, "UTF-8");

			// 3. 把封装好的表单实体对象设置到HttpPost中
			httpPost.setEntity(entity);
		}

		// 4. 使用Httpclient发起请求
		CloseableHttpResponse response = this.httpClient.execute(httpPost);

		// 5. 解析返回数据,封装HttpResult
		// 状态码
		intcode = response.getStatusLine().getStatusCode();

		// 响应体内容
		String body = null;
		if (response.getEntity() != null) {
			body = EntityUtils.toString(response.getEntity(), "UTF-8");
		}

		returnnew HttpResult(code, body);
	}

	/**
	 * 不带参数的post请求
	 * 
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public HttpResult doPost(String url) throws Exception {
		returnthis.doPost(url, null);
	}

	//doPut

	//dodelete

}

这样:如果手机客户端,需要搜索,则我们只需要提供给它这个APIService类,再告诉它调用的URL,以及各参数的含义。手机客户端调用这些方法,返回的JSON数据自己做处理便可以了。这样就实现了系统之间的通信。

10. 全局异常处理

10.1. 处理思路

在这里插入图片描述

全局异常处理器中的处理逻辑:
捕获整个系统中发生的异常。

1、异常写入日志文件
2、及时通知开发人员。发邮件、短信。
3、展示一个友好的错误页面,例如:您的网络异常,请重试。

10.2. 创建全局异常处理器

在taotao-search-web工程中创建全局异常处理器类:

package com.taotao.search.exception;

import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description : 全局异常处理器的类
 * @ClassName : GlobalExceptionReslover
 * @Author : LH
 * @Date: 2020-09-19 10:09
 * @Version: 1.0
 */
public class GlobalExceptionReslover implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object hanlder, Exception ex) {
        //1.日志写到日志文件中,这里打印
        System.out.println(ex.getMessage());
        ex.printStackTrace();
        //2.及时的通知开发人员  发短信 发邮件(通过第三方的接口发)
        System.out.println("发了一条短信");
        //3.给用户一个友好的提示
        ModelAndView modelAndView = new ModelAndView();
        //设置视图信息
        //设置模型数据
        modelAndView.setViewName("error/exception");//不需要带后缀 有视图解析器
        modelAndView.addObject("message","您的网络有异常,请重试");
        return modelAndView;
    }
}

10.3. Springmvc中配置异常处理器

在这里插入图片描述

10.4.出现错误运行界面

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值