解决Long类型到web端失精度引发的API接口空响应

2024-08-25 21:32

本文主要是介绍解决Long类型到web端失精度引发的API接口空响应,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

          • 事故代码
          • 触发的问题点
          • 解决空响应
          • 为什么写出response的拦截器没注册上
          • 添加@EnableWebMvc和implement WebMvcConfigurer的区别
          • 为什么单纯extends WebMvcConfigurationSupport会引发拦截器未注册
          • 其他

事故代码
@Configuration
public class LongToStringJsonConfig extends WebMvcConfigurationSupport {public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();ObjectMapper objectMapper = new ObjectMapper();SimpleModule simpleModule = new SimpleModule();simpleModule.addSerializer(Long.class, ToStringSerializer.instance);simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);objectMapper.registerModule(simpleModule);jackson2HttpMessageConverter.setObjectMapper(objectMapper);converters.add(jackson2HttpMessageConverter);}
}
  • 我最开始项目里,单纯解决Long转String需求时,写的是如上代码。好吧,诚实一点,抄的是以上代码。然而这段代码导致我所有的接口,都是空响应。
触发的问题点
  • 1,Spring的request和response的stream只能读一次,再次读取的时候,stream就为空了。
  • 2,通过debug,项目引入了一个底层包,经过了一个filter。而这个filter做了一件事:
        ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response);chain.doFilter(wrapperRequest, wrapperResponse);
  • filter将response包入到了ContentCachingResponseWrapper里边
  • 3,在底层包里,后续有一个interceptor 在afterCompletion方法中,会将ContentCachingResponseWrapper的内容写出去。
  • 4,再次debug,发现写出ContentCachingResponseWrapper的interceptor并未被注入。
解决空响应
  • 最开始的尝试chain.doFilter(wrapperRequest, wrapperResponse);将filter的这行操作,换成chain.doFilter(wrapperRequest, response);此时,接口正常响应。问题是:我项目中的空响应解决了,但底层包里interceptor想要拦截读取一些信息记录的需求实现就被破坏了。PS:虽然我连这个interceptor都没注册上吧。 所以,这个方案,是行不通的。 问题又指向于:为什么没有触发后续的interceptor去调用responseWrapper.copyBodyToResponse()方法写出响应。
  • 慢慢回顾,发现就是多了我新增的一个类,就出现空响应。去掉的话,就是正常响应。仔细看,我的类没什么特别,唯一特别的就是 extends WebMvcConfigurationSupport。 那么WebMvcConfigurationSupport被继承,会发生啥呢?
为什么写出response的拦截器没注册上
  • 我的config代码唯一的不通,就是继承了WebMvcConfigurationSupport。那么这个WebMvcConfigurationSupport是怎么工作的呢?
  • 仔细查代码,或者debug,就可以发现,在WebMvcConfigurationSupport里有个接口获取拦截器:
	/*** Provide access to the shared handler interceptors used to configure* {@link HandlerMapping} instances with.* <p>This method cannot be overridden; use {@link #addInterceptors} instead.*/protected final Object[] getInterceptors() {if (this.interceptors == null) {InterceptorRegistry registry = new InterceptorRegistry();addInterceptors(registry);registry.addInterceptor(new ConversionServiceExposingInterceptor(mvcConversionService()));registry.addInterceptor(new ResourceUrlProviderExposingInterceptor(mvcResourceUrlProvider()));this.interceptors = registry.getInterceptors();}return this.interceptors.toArray();}
  • 这个接口不可以被重写。而中间有个addInterceptors(registry)方法,所以,interceptor要注册上,至少也得是实现了这个addInterceptors(registry)方法的。 PS:这里还可以看一下WebMvcConfigurationSupport类的作用说明:

This is the main class providing the configuration behind the MVC Java config. It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an application {@link Configuration @Configuration} class. An alternative more advanced option is to extend directly from this class and override methods as necessary, remembering to add {@link Configuration @Configuration} to the subclass and {@link Bean @Bean} to overridden {@link Bean @Bean} methods.

  • 在WebMvcConfigurationSupport里,可以看到的是It is typically imported by adding {@link EnableWebMvc @EnableWebMvc} to an application {@link Configuration @Configuration} class。所以,第一个解决拦截器未注册上的方案,也就出来了。就是在我的类上,除了@Configuration外,再加一个注解@EnableWebMvc。 至此,空响应问题解决。第二个解决方案,在我的类中,实现addInterceptors(registry)的方法注入底层包里可以打印出response的interceptor。
  • 通过WebMvcConfigurationSupport 找到@EnableWebMvc和接口WebMvcConfigurer。仔细看WebMvcConfigurer接口的定义。第三个解决方案出来了,让我的类不再继承WebMvcConfigurationSupport类,而改为implement WebMvcConfigurer。
添加@EnableWebMvc和implement WebMvcConfigurer的区别
  • 区别主要从WebMvcConfigurer的addInterceptors(InterceptorRegistry registry)的方法声明定义中可以看出:

Add Spring MVC lifecycle interceptors for pre- and post-processing of controller method invocations. Interceptors can be registered to apply to all requests or be limited to a subset of URL patterns.

Note that interceptors registered here only apply to controllers and not to resource handler requests.To intercept requests for static resources either declare a {@link org.springframework.web.servlet.handler.MappedInterceptor MappedInterceptor} bean or switch to advanced configuration mode by extending {@link org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport WebMvcConfigurationSupport} and then override {@code resourceHandlerMapping}.

  • 通过WebMvcConfigurer的方式,无法拦截静态资源,但可以通过其他方式进行扩展实现。
为什么单纯extends WebMvcConfigurationSupport会引发拦截器未注册
  • 在@SpringBootApplication中,会引入@EnableAutoConfiguration,在什么都不做的时候,指:即不加@EnableWebMvc也不搞implement WebMvcConfigurer的时候,那些拦截器是怎么注册的呢?
  • 通过@EnableWebMvc找到了如下类:
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
  • 可以看到假如没有自定义的WebMvcConfigurationSupport类,类WebMvcAutoConfiguration就会执行。在此类中通过extends DelegatingWebMvcConfiguration ,再有DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport,在DelegatingWebMvcConfiguration类中,实现了addInterceptors(registry)方法。
  • 所以,关键就是WebMvcConfigurationSupport类中的addInterceptors(registry)一定要有实现。如果不继承此类,那么有默认的实现方式,如果用户自己实现类此类,就需要处理addInterceptors(registry)的实现。
其他
  • 我准备再搞搞Spring boot的自动装配,为啥@Configuration一加就妥了呢

这篇关于解决Long类型到web端失精度引发的API接口空响应的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1106705

相关文章

如何解决线上平台抽佣高 线下门店客流少的痛点!

目前,许多传统零售店铺正遭遇客源下降的难题。尽管广告推广能带来一定的客流,但其费用昂贵。鉴于此,众多零售商纷纷选择加入像美团、饿了么和抖音这样的大型在线平台,但这些平台的高佣金率导致了利润的大幅缩水。在这样的市场环境下,商家之间的合作网络逐渐成为一种有效的解决方案,通过资源和客户基础的共享,实现共同的利益增长。 以最近在上海兴起的一个跨行业合作平台为例,该平台融合了环保消费积分系统,在短

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

Java Web指的是什么

Java Web指的是使用Java技术进行Web开发的一种方式。Java在Web开发领域有着广泛的应用,主要通过Java EE(Enterprise Edition)平台来实现。  主要特点和技术包括: 1. Servlets和JSP:     Servlets 是Java编写的服务器端程序,用于处理客户端请求和生成动态网页内容。     JSP(JavaServer Pages)

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

自定义类型:结构体(续)

目录 一. 结构体的内存对齐 1.1 为什么存在内存对齐? 1.2 修改默认对齐数 二. 结构体传参 三. 结构体实现位段 一. 结构体的内存对齐 在前面的文章里我们已经讲过一部分的内存对齐的知识,并举出了两个例子,我们再举出两个例子继续说明: struct S3{double a;int b;char c;};int mian(){printf("%zd\n",s

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

【编程底层思考】垃圾收集机制,GC算法,垃圾收集器类型概述

Java的垃圾收集(Garbage Collection,GC)机制是Java语言的一大特色,它负责自动管理内存的回收,释放不再使用的对象所占用的内存。以下是对Java垃圾收集机制的详细介绍: 一、垃圾收集机制概述: 对象存活判断:垃圾收集器定期检查堆内存中的对象,判断哪些对象是“垃圾”,即不再被任何引用链直接或间接引用的对象。内存回收:将判断为垃圾的对象占用的内存进行回收,以便重新使用。

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

【VUE】跨域问题的概念,以及解决方法。

目录 1.跨域概念 2.解决方法 2.1 配置网络请求代理 2.2 使用@CrossOrigin 注解 2.3 通过配置文件实现跨域 2.4 添加 CorsWebFilter 来解决跨域问题 1.跨域概念 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。一般在springbo

深入理解RxJava:响应式编程的现代方式

在当今的软件开发世界中,异步编程和事件驱动的架构变得越来越重要。RxJava,作为响应式编程(Reactive Programming)的一个流行库,为Java和Android开发者提供了一种强大的方式来处理异步任务和事件流。本文将深入探讨RxJava的核心概念、优势以及如何在实际项目中应用它。 文章目录 💯 什么是RxJava?💯 响应式编程的优势💯 RxJava的核心概念