嘿,更多碎碎念在这里:墨问小程序 😄
一个 web 请求,VO 类中的字段是 pCode,但 http 的响应信息却是 pcode,显然是 spring boot 在做序列化转换时出了问题,查了一下:
spring boot 默认使用 Jackson 实现的 HttpMessageConverter 进行消息转换,会将 pCode 转换成 pcode(我在 spring boot 2.1 和 2.5 下测试都是这个结果)。debug 时看到有下面这些转换器:
0 = {ByteArrayHttpMessageConverter@5529}
1 = {StringHttpMessageConverter@5530}
2 = {StringHttpMessageConverter@5531}
3 = {ResourceHttpMessageConverter@5532}
4 = {ResourceRegionHttpMessageConverter@5533}
5 = {SourceHttpMessageConverter@5534}
6 = {AllEncompassingFormHttpMessageConverter@5535}
7 = {MappingJackson2HttpMessageConverter@5536}
8 = {MappingJackson2HttpMessageConverter@5537}
如果想正常转换 pCode(即浏览器端显示 pCode,而不是 pcode),则需要换一个 HttpMessageConverter,比如 fastjson 实现的 FastJsonHttpMessageConverter:
@Configuration
public class ComponentsConfig implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
// 保持原始属性名,不进行命名转换
SerializeConfig serializeConfig = SerializeConfig.globalInstance;
config.setSerializeConfig(serializeConfig);
// 添加 SerializerFeature 来支持输出 null 值字段
config.setSerializerFeatures(
SerializerFeature.WriteMapNullValue // 输出 null 字段
// SerializerFeature.WriteNullStringAsEmpty, // 将 null 字符串输出为 ""
// SerializerFeature.WriteNullNumberAsZero, // 将 null 数字输出为 0
// SerializerFeature.WriteNullBooleanAsFalse // 将 null 布尔值输出为 false
);
converter.setFastJsonConfig(config);
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
converter.setSupportedMediaTypes(supportedMediaTypes);
converters.add(0, converter);
}
}
另外,这类字段在 Bean Copy 时可能也会产生相关问题,需要注意,不过我在以下版本中测试都是正常的:
cn.hutool.core.bean.BeanUtil
复制正常org.springframework.beans.BeanUtils
复制正常net.sf.cglib.beans.BeanCopier
复制正常供参考。
通过 Apache Velocity 配置模板时,只要使用注释 ##
就能抑制空行的出现 🐶
##
## 输出所有生成的定义代码
#foreach($generatedDefLine in $generatedDefinitionLines)
${generatedDefLine}
#end
##
不想上班的你,像极了数据结构中的栈(Stack):来的最晚,走的最早 🐶
鼠与虎,都一样,没天命又不认命。
小猴子你听,那风里传来的,都是求而不得的声音。
行动是打开枷锁的钥匙,是治愈的良方。
因为 Java maven 工程的 pom.xml 中配置了 <maven.test.skip>true</maven.test.skip>
,导致 vs code 一直不能显示 Junit 单元测试的测试按钮……
使用 hutool 中的 BeanUtil.copyProperties
转换对象时,如果有枚举类字段,转换时,会到对应枚举类中去查找自定义转换函数:
// cn.hutool.core.convert.impl.EnumConverter
private static Map<Class<?>, Method> getMethodMap(Class<?> enumClass) {
return VALUE_OF_METHOD_CACHE.computeIfAbsent(enumClass, (key) -> Arrays.stream(enumClass.getMethods())
.filter(ModifierUtil::isStatic)
.filter(m -> m.getReturnType() == enumClass)
.filter(m -> m.getParameterCount() == 1)
.filter(m -> false == "valueOf".equals(m.getName()))
.collect(Collectors.toMap(m -> m.getParameterTypes()[0], m -> m, (k1, k2) -> k1)));
}
所以,如果你写的自定义转换函数并不是为了用于对象转换,就需要小心了~
嗯,这并不是一个好的设计。
架构的本质是分离控制和逻辑。基础设施好了,干啥都方便,所以效率自然就高。计算机软件中的各种工具、框架和平台,都是在帮我们解决控制,那我们自己干什么呢?专注于逻辑就行,也就是你的核心业务。
只有计算机软件行业是这样吗?No,如果你想创业:从门店选址到门店管理,从物流到营销,从支付到配送,啥基础设施都为你准备好了。你只要想好干什么,再准备好 money,就可以开工了~
这就是真正的效率至上吧。门槛低了,干啥都快,而由此带来的副作用就是同质化竞争严重。不过,对我们这种小老百姓来说,也不是坏事,毕竟竞争可以带来低价 😄。
二十年前,会想到今天的我们,人手一部智能手机吗?
二十年后,是否会出现每人都有专属的 AI 机器人?
我觉得是很有可能的,很多事情都让机器人干,多好。然后我们干啥?躺平?🐶
关于 Hotspot VM 中的 PS MarkSweep,Serial Old 和 Parallel Old:
1、https://www.jianshu.com/p/624338a8d51b
在 Parallel Scavenge 收集器架构中本身有 PS MarkSweep 收集器来进行老年代收集,但由于 PS MarkSweep 与 Serial Old 实现非常接近,因此官方的许多资料都直接以 Serial Old 代替 PS MarkSweep进行讲解。
2、https://www.zhihu.com/question/56344485
Java 7/8 默认老年代回收是 PSMarkSweep(Serial-Old) 还是Parallel Old ?
这个问题的答案取决于 JDK 版本,在 2012 年默认值改变过一次。这个改进使得 HotSpot VM 在选择使用 ParallelGC(-XX:+UseParallelGC 或者是 ergonomics 自动选择)的时候,会默认开启 -XX:+UseParallelOldGC 。这个变更应该是在JDK7u4开始的JDK7u系列与JDK8系列开始生效。
3、https://xie.infoq.cn/article/2b4358255f56a3a77939b9e84
PS MarkSweep 只是回收器的别名,他可以指代 Serial Old 和 Parallel Old,毕竟他们的实现基本一样。Java 8 上 -XX:+UseParallelGC 和 -XX:+UseParallelOldGC 结果一样,都是用的 Parallel Old。
笔者总结一下:
Who am I ?
Where did I come from ?
Where do I go to find out ?