白菜日记7

最近又又又打算重构白菜,缘由则是因为经常出现图片上传失败的情况,加上之前的丑陋代码实在不堪入目。。

当时用两天赶出来的所有命令的拦截器,事实证明根本没法维护,把所有参数语义化是一个原因,把所有命令放在一起拦截则是另一个更重要的原因,为了满足“通用逻辑”做了很多匪夷所思的around。。

大致打算拆分为中美两个节点,美国服务端负责获取网页、解析数据,以及代理osu的API,也包括负责每天凌晨的批量爬取数据。国内服务端则负责解析命令,生成图片并发送。


在着手编写美帝服务端时,突发奇想觉得失败重试这种大众化需求不应该由我手动实现,同时也觉得随处不在的

1
2
3
4
int count = 0;
while (count<5){
...
}

很是丑陋。不过这两年来也确实没有想到可以用面向切面的方式解决,直到看到了spring-retry这个模块……

基本满足了我的需求,提供了超时自动倍增的功能,本质和事务一样还是一个切面。


在Http客户端的挑选上遇到了一个坑,记一下:

一开始打算赶上时髦,用Java11新的那个Http客户端,研究发现本身不支持重试,反而Apache的HttpClient支持……

虽然发现Spring框架有个模块能提供重试功能(上述),然后又想起Spring的RestTemplate应该更符合我的需求(大部分是JSON交互,还有一部分需要解析网页打算还是用jsoup做)。

尝试了一下,把RestTemplate注册成Spring的Bean,并且绕过了之前公司项目踩的一个坑:

1
2
3
4
5
6
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
return restTemplate;
}

在测试的时候,发现application.yml中对Jackson的下划线转驼峰配置没有起效:

1
2
3
spring:
jackson:
property-naming-strategy: SNAKE_CASE

于是逛StackOverFlow,得出结论:

此处RestTemplate是由我自己实例化并托管给Spring的,构造方法内会另外实例化一个ObjectMapper,并不会使用Spring的Bean,因此配置自然也就不会起效了。

最后解决方法是,将MappingJackson2HttpMessageConverter注册成Bean,替换其内置的ObjectMapper为呗被Spring配置过的ObjectMapper,再将这个Converter对象替换到RestTemplate里去。

由于考虑国内服务也要使用RestTemplate,故另行编写配置类,放到common模块下。

完整配置类如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Configuration
public class RestTemplateConfig {
private ObjectMapper objectMapper;

@Autowired
public void setObjectMapper(ObjectMapper objectMapper){
this.objectMapper = objectMapper;
}

@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(StandardCharsets.UTF_8));
restTemplate.getMessageConverters().set(6, mappingJacksonHttpMessageConverter());
return restTemplate;
}

@Bean
public MappingJackson2HttpMessageConverter mappingJacksonHttpMessageConverter() {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper);
return converter;
}
}

有一说一,明明是Spring提供的Http客户端,需要手动注册成Bean来实现单例也就算了,甚至不能直接吃到配置文件中的Jackson配置,实在是不够方便,希望以后这些配置都能在yml文件中完成。。