内容简介:新年目标刚学了一章,大体就是调用中国天气网的
起步
新年目标 Spring Cloud
开始实施,打开慕课网。
刚学了一章,大体就是调用中国天气网的 api
,使用 Spring Boot
构建自己的天气预报系统,然后使用 Spring Cloud
,一步一步使用微服务的思想来演进架构。
小目标
昨天去百度抢了新年红包,感叹百度的高并发做的也是如此优秀。
阿里的双十一,百度的新年。(发现了二者的共同点,可能也是解决并发的一种思路,并发的时候只允许增加数据。)
感叹归感叹,期望着学习完 Spring Cloud
也能设计出优秀的架构,解决并发的一些问题。
遇到的问题
学习时也跟着课程进行编码,讲师讲的非常好,但是本课程的重点是后面的微服务架构,所以前面的功能有一些瑕疵,特此提出自己的实现,供大家学习交流。
功能描述
最初的功能很简单,因为后台是没有任何数据的,所以前台有请求,就直接去天气网要数据,然后再返回去。
数据序列化问题
这是天气网 api
返回来的数据格式,乍一看没啥毛病。
{ "data": { "yesterday": { "date": "4日星期一", "high": "高温 26℃", "fx": "无持续风向", "low": "低温 18℃", "fl": "<![CDATA[<3级]]>", "type": "多云" }, "city": "深圳", "forecast": [ { "date": "5日星期二", "high": "高温 25℃", "fengli": "<![CDATA[<3级]]>", "low": "低温 18℃", "fengxiang": "无持续风向", "type": "多云" }, { "date": "6日星期三", "high": "高温 26℃", "fengli": "<![CDATA[<3级]]>", "low": "低温 17℃", "fengxiang": "无持续风向", "type": "多云" }, { "date": "7日星期四", "high": "高温 27℃", "fengli": "<![CDATA[<3级]]>", "low": "低温 18℃", "fengxiang": "无持续风向", "type": "多云" }, { "date": "8日星期五", "high": "高温 26℃", "fengli": "<![CDATA[<3级]]>", "low": "低温 17℃", "fengxiang": "无持续风向", "type": "多云" }, { "date": "9日星期六", "high": "高温 24℃", "fengli": "<![CDATA[<3级]]>", "low": "低温 14℃", "fengxiang": "无持续风向", "type": "小雨" } ], "ganmao": "相对今天出现了较大幅度降温,较易发生感冒,体质较弱的朋友请注意适当防护。", "wendu": "23" }, "status": 1000, "desc": "OK" }
缺点1:有拼音; ganmao
、 wendu
。
缺点2:名称不一致;理论上来说 yesterday
与 forecast
应该是同一个实体,都表示一天的天气情况,只是名称不同。但是在 yesterday
中,风向和风力是 fx
和 fl
,在 forecast
中,名称却是 fengli
、 fengxiang
。
解决此问题,想到的思路就是使用 jackson
进行序列化与反序列化时进行配置的一些注解。
最初使用此种方法实现:
@JsonProperty("wendu") private Float temperature;
一个对象中的名字,一个 json
数据中的名字。
可以实现,但是不好。
举个例子,天气 api
返回给我 wendu
,添加了 @JsonProperty
,然后 wendu
就绑定到了 temperature
上,但是如果我前台再返回该对象,序列化后生成的名称还是 wendu
。不好!
目标是实现,反序列化时:从 wendu
能绑定到我的 temperature
,序列化时直接使用我的字段名。
get、set尝试
猜测是不是和 get
、 set
方法有关。
就把 @JsonProperty("wendu")
添加到 set
方法上,发现并没有用。
JsonAlias
后来经过查询,原来是注解用错了,此种情况应使用别名。
关于 JsonProperty
和 JsonAlias
的详细讲解,请参考 Jackson @JsonProperty and @JsonAlias Example 。
@JsonAlias("wendu") private Float temperature;
同时,可以应用多个别名:
@JsonAlias({"fengli", "fl"}) private String windForce;
发起请求
发起请求的示例代码,供以后参考。
@Autowired private RestTemplate restTemplate; @Override public Weather getWeatherByCityName(String cityName) { return this.getWeatherByUrl(BASE_URL + "?" + CITY_NAME + "=" + cityName) .getData(); } private Response getWeatherByUrl(String url) { // 发起Get请求 ResponseEntity<String> response = restTemplate.getForEntity(url, String.class); // 如果状态码非200, 抛异常 if (response.getStatusCodeValue() != 200) { throw new YunzhiNetworkException("数据请求失败"); } // 实例化对象映射对象 ObjectMapper mapper = new ObjectMapper(); // 初始化响应数据 Response data; // 从字符串转换为Response对象 try { data = mapper.readValue(response.getBody(), Response.class); } catch (IOException e) { throw new YunzhiIOException("json数据转换失败"); } // 返回 return data; }
RestTemplate配置
这里与正常的 RestTemplate
构建有些不同,通常的 RestTemplate
是使用 Spring
工具类构造的,此处使用 Apache
的 Http
组件构造,以支持更多的数据格式。
implementation 'org.apache.httpcomponents:httpclient'
同时去除了默认的对 String
的 Http
消息转换器,默认的转换器使用的不是 UTF-8
编码。
讲师原文章: Spring RestTemplate 调用天气预报接口乱码的解决
@Configuration public class BeanConfiguration { @Bean public RestTemplate restTemplate() { // 使用Apache HttpClient构建RestTemplate, 支持的比Spring自带的更多 RestTemplate restTemplate = new RestTemplate(new HttpComponentsClientHttpRequestFactory()); // 去除默认的String转换器 restTemplate.getMessageConverters().removeIf(converter -> converter instanceof StringHttpMessageConverter); // 添加自定义的String转换器, 支持UTF-8 restTemplate.getMessageConverters() .add(new StringHttpMessageConverter(StandardCharsets.UTF_8)); return restTemplate; } }
更完善的单元测试
同时,在编写单元测试的时候,看了一篇关于 AssertJ
的文章。 Testing with AssertJ assertions - Tutorial
之前学 Junit5
的时候,觉得这个东西挺好使的啊?为什么被开源社区抛弃而使用 AssertJ
呢?
原来之前用的断言都太简单,其实 AssertJ
远比我们使用的更强大。
@Test public void getWeatherByCityName() throws Exception { final String cityName = "深圳"; MvcResult mvcResult = this.mockMvc .perform(MockMvcRequestBuilders.get(BASE_URL + "/cityName/" + cityName)) .andExpect(MockMvcResultMatchers.status().isOk()) .andReturn(); String json = mvcResult.getResponse().getContentAsString(); Assertions.assertThat(json) .contains("cityName", "cold", "temperature", "windDirection", "windForce") .doesNotContain("ganmao", "wendu", "fx", "fl", "fengxiang", "fengli"); }
总结
多看英文文章, Tutorial
写得都特别好。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用 PowerShell 发起 HTTP REST请求
- golang使用fasthttp 发起http请求
- Angular 实践:如何优雅地发起和处理请求
- 「goz」开源库,在Go中快速发起HTTP请求
- 在Node.js中发起HTTP请求的5种方法
- 浏览器输入url到发起http请求所经历的过程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
编程珠玑(英文版・第2版)
[美] Jon Bentley / 人民邮电出版社 / 2010-8 / 39.00元
多年以来,当程序员们推选出最心爱的计算机图书时,《编程珠玑》总是位列前列。正如自然界里珍珠出自细沙对牡蛎的磨砺,计算机科学大师Jon Bentley以其独有的洞察力和创造力,从磨砺程序员的实际问题中凝结出一篇篇不朽的编程“珠玑”。这些文章是《ACM通讯》最受欢迎的专栏文章,最终结集为两部书出版。本书为第一卷,主要讨论计算机科学中最本质的问题:如何正确选择和高效地实现算法。 在书中,作者选取许......一起来看看 《编程珠玑(英文版・第2版)》 这本书的介绍吧!
图片转BASE64编码
在线图片转Base64编码工具
XML 在线格式化
在线 XML 格式化压缩工具