解决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

相关文章

usb接口驱动异常问题常用解决方案

《usb接口驱动异常问题常用解决方案》当遇到USB接口驱动异常时,可以通过多种方法来解决,其中主要就包括重装USB控制器、禁用USB选择性暂停设置、更新或安装新的主板驱动等... usb接口驱动异常怎么办,USB接口驱动异常是常见问题,通常由驱动损坏、系统更新冲突、硬件故障或电源管理设置导致。以下是常用解决

Mysql如何解决死锁问题

《Mysql如何解决死锁问题》:本文主要介绍Mysql如何解决死锁问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录【一】mysql中锁分类和加锁情况【1】按锁的粒度分类全局锁表级锁行级锁【2】按锁的模式分类【二】加锁方式的影响因素【三】Mysql的死锁情况【1

SpringBoot内嵌Tomcat临时目录问题及解决

《SpringBoot内嵌Tomcat临时目录问题及解决》:本文主要介绍SpringBoot内嵌Tomcat临时目录问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录SprinjavascriptgBoot内嵌Tomcat临时目录问题1.背景2.方案3.代码中配置t

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

如何解决idea的Module:‘:app‘platform‘android-32‘not found.问题

《如何解决idea的Module:‘:app‘platform‘android-32‘notfound.问题》:本文主要介绍如何解决idea的Module:‘:app‘platform‘andr... 目录idea的Module:‘:app‘pwww.chinasem.cnlatform‘android-32

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

springboot项目中常用的工具类和api详解

《springboot项目中常用的工具类和api详解》在SpringBoot项目中,开发者通常会依赖一些工具类和API来简化开发、提高效率,以下是一些常用的工具类及其典型应用场景,涵盖Spring原生... 目录1. Spring Framework 自带工具类(1) StringUtils(2) Coll

MySQL 中查询 VARCHAR 类型 JSON 数据的问题记录

《MySQL中查询VARCHAR类型JSON数据的问题记录》在数据库设计中,有时我们会将JSON数据存储在VARCHAR或TEXT类型字段中,本文将详细介绍如何在MySQL中有效查询存储为V... 目录一、问题背景二、mysql jsON 函数2.1 常用 JSON 函数三、查询示例3.1 基本查询3.2

Pyserial设置缓冲区大小失败的问题解决

《Pyserial设置缓冲区大小失败的问题解决》本文主要介绍了Pyserial设置缓冲区大小失败的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录问题描述原因分析解决方案问题描述使用set_buffer_size()设置缓冲区大小后,buf