项目拆分思想
1. 单体项目拆分
项目拆分的思想:在一个完整的项目中,虽然我们利用了 maven 的『多模块』知识点,将一个项目(project)拆分成了多个模块(module),各个模块单独打包,但是,整个项目的最终的『成果』、产出仍然是一个 spring boot 的 jar 包。
整个项目 │ │── 前端项目(vue-cli 项目) │ └── 后端项目 │ ├── web 项目(整个后端项目的入口和最终代码成果) │ │── xxx 模块 │ │── service │ └── dao │ │── yyy 模块 │ │── service │ └── dao │ └── zzz 模块 │── service └── dao
整个项目的『代码成果』有 2 个:
- 前端项目执行 build 命令后生成的 dist 目录下的 html、css、js 等文件;
- web 项目执行 build 命令后生成的 target 中生成的 web.jar 包。逻辑上,它是一个 war 包。
而在微服务的架构思想中,我们一个项目会被『真正地』拆分成几个项目,每个项目都有独立的 MVC 三层。那么,原来的『每个模块』,现在就变成了真正意义上的『每个项目』。
整个项目 │ │── 前端项目 - vue 项目 │ │── 后端项目 - xxx 项目(入口1和成果1) │ ├── web │ │── service │ └── dao │ │── 后端项目 - yyy 项目(入口2和成果2) │ ├── web │ │── service │ └── dao │ └── 后端项目 - zzz 项目(入口3和成果3) ├── web │── service └── dao
整个项目的『代码成果』有 N 个:
-
前端项目执行 build 命令后生成的 dist 目录下的 html、css、js 等文件;
-
xxx 项目执行 build 命令后生成的 target 中生成的 xxx.jar 包。逻辑上,它是一个 war 包。
-
yyy 项目执行 build 命令后生成的 target 中生成的 yyy.jar 包。逻辑上,它是一个 war 包。
-
zzz 项目执行 build 命令后生成的 target 中生成的 zzz.jar 包。逻辑上,它是一个 war 包。
那么,在涉及到跨模块调用时,我们就无法像以前一样从代码层面直接调用。那么怎么办?在 xxx 项目的代码中编写代码,向 B 项目发起 HTTP 请求。
#2. RestTemplate 发起 HTTP 请求
说明
你的项目只要直接或间接引入了 spring-web 包,你就可以使用 RestTemplate 。
RestTemplate 类似于 Slf4J,它本身并没有做『更多』的什么事情,它的主要功能和目的是对背后真正干活的“人”做二次包装,以提供统一的、简洁的使用方式。
在默认的(未引入其它包的)情况下,在 RestTemplate 背后真正干活的是 JDK 中的网络相关类:HttpURLConnection 。如此之外,RestTemplate 还支持使用 HttpClient 和 OkHTTP 库,前提是,你要额外引入这两个包。
Spring RestTemplate 是 Spring 提供的用于访问 Rest 服务的客端。 RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率,所以很多客户端比如 Android 或者第三方服务商都是使用 RestTemplate 请求 restful 服务。
在以前的 Spring Boot 版本中,Spring IoC 容器中已经有一个创建好了的 RestTemplate 供我们使用,不过到了新版本的 Spring Boot 中,需要我们自己创建 RestTemplate 的单例对象
@Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { return builder.build(); }
2.1 API 方法介绍
常见方法有:
请求类型 | API | 说明 |
---|---|---|
GET 请求 | getForEntity 方法 | 返回的 ResponseEntity 包含了响应体所映射成的对象 |
GET 请求 | getForObject 方法 | 返回的请求体将映射为一个对象 |
POST 请求 | postForEntity 方法 | 返回包含一个对象的 ResponseEntity ,这个对象是从响应体中映射得到的 |
POST 请求 | postForObject 方法 | 返回根据响应体匹配形成的对象 |
PUT 请求 | put 方法 | PUT 资源到特定的 URL |
DELETE 请求 | delete 方法 | 对资源执行 HTTP DELETE 操作 |
任何请求 | exchange 方法 | 返回包含对象的 ResponseEntity ,这个对象是从响应体中映射得到的 |
任何请求 | execute 方法 | 返回一个从响应体映射得到的对象 |
2.2 发起 GET 请求
回顾一下 GET 请求的特点:
-
GET 请求不用『管』header 中的 content-type 的值。
-
GET 请求的参数是『追加』到 URL 中,而不是附带在请求的 body 部分的。
因此,如果没有其他的设置请求头的要求,GET 请求在调用 exchange()
方法时,不需要 HttpEntity 参数,因为它就是用来封装请求 body 和请求 header 的。
无参情况:
@Resource private RestTemplate restTemplate; @Test public void test1() { String url = "http://localhost:8080/get1"; // RestTemplate template = new RestTemplate(); ResponseEntityresponseEntity = template.exchange(url, HttpMethod.GET, null, String.class); log.info("{}", responseEntity.getStatusCode()); log.info("{}", responseEntity.getHeaders()); log.info("{}", responseEntity.getBody()); }
有参情况传值:
//写法一:
String url1 = "http://localhost:8080/get2?username={1}&password={2}"; ResponseEntityresponseEntity1 = template.exchange(url1, HttpMethod.GET, null, String.class, "tom", 10); log.info("{}", responseEntity1.getBody());
//写法二:
String url2 = "http://localhost:8080/get2?username={xxx}&password={yyy}";
Map
map.put("xxx", "tom");
map.put("yyy", 20);
ResponseEntity
log.info("{}", responseEntity2.getBody());
2.3 发起 POST 请求
回顾一下 POST 请求的特点:
-
POST 请求的 header 中的 content-type 的值是
application/x-www-form-urlencoded
。 -
POST 请求的参数是附加到请求的 body 部分的。
因此,在调用 exchange()
方法时,需要为其提供一个 HttpEntity
类型参数。
无参情况:
String url = "http://localhost:8080/post1"; // 准备请求头部信息 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 无参数情况下,不需要设置请求 body 部分 HttpEntity<?> entity = new HttpEntity<>(null, headers); ResponseEntityresponseEntity = template.exchange(url, HttpMethod.POST, entity, String.class); log.warn("{}", responseEntity.getStatusCode()); log.warn("{}", responseEntity.getHeaders()); log.warn("{}", responseEntity.getBody());
有参情况:
// 准备请求头部信息 HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // 准备要提交的数据 MultiValueMapparameters = new LinkedMultiValueMap<>(); parameters.add("username", "tom"); parameters.add("age", 20); HttpEntity > entity = new HttpEntity<>(parameters, headers); String url = "http://localhost:8080/post2"; ResponseEntity responseEntity = template.exchange(url, HttpMethod.POST, entity, String.class); log.warn("{}", responseEntity.getBody());