SpringMVC restful 注解之@RequestBody进行json与object转换_javascript技巧
由于快过年的原因,项目组没有太多任务,闲来无事研究了一下spring中restful调用。发现spring竟然已经强大到如此境界,程序员已经不需要在关心在写接口的过程中数据的转换以及调用,只需要专注业务。下面我总结一下步骤及其在研究过程的遇到的问题。
步骤:
1、git clone https://github.com/spring-guides/gs-rest-service.git 从spring官网上下载了源码
2、进行maven编译(gradle也行)
3、运行、访问http://localhost:8080/greeting
4、运行结果能把对象转换为json对象返回给页面
这时我就在思考怎样能让请求的数据自动转换为java对象呢,通过google,发现其实spring已经提供了HttpMessageConverter转换器,而且默认情况下是加载了 MappingJackson2HttpMessageConverter(json ~object转换的类)。只需要配置@RequestBody Greeting gree 即可使用。
controller层代码如下:
@RequestMapping(value = "/greeting", method = RequestMethod.POST,consumes = "application/json") public @ResponseBody Greeting greeting(@RequestBody Greeting gree) { System.out.println(gree.getContent()); return gree; }
这时候我通过谷歌的插件(postman)进行调用,死活调用不成功!
分析问题及解决问题:
这时我感觉问题的原因可能出在如下几个方面:
1、spring默认没有加载MappingJackson2HttpMessageConverter(不知道具体加载方式)
2、MappingJackson2HttpMessageConverter加载后不能工作(不知道不工作原因)
其实最后面导致不工作的原因是太相信spring的源码(对象没有提供set方法导致),带着这两疑问在网上海量搜索者找不到对应结果。没有办法只能从根本上找到问题原因,看spring源代码。
针对第一个问题:
第一步:手动重写加载类型转换器
@Configuration @EnableWebMvc public class WebConfiguration extends WebMvcConfigurerAdapter { public void configureMessageConverters(List<HttpMessageConverter<?>> messageConverters) { System.out.println("init convert is start !!!!!"); StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); stringConverter.setWriteAcceptCharset(false); messageConverters.add(new MappingJackson2HttpMessageConverter()); System.out.println("init convert is stop !!!!!"); } }
测试发现还是不能使用,这时就更不清楚原因了。只能看默认情况下spring是怎么加载类型转换器的。结果发现在WebMvcConfigurationSupport中这个方法addDefaultHttpMessageConverters(HttpMessageConverter这个关键字反射搜索到使用地方通过判断及其跟踪找到的)中如下代码:
@SuppressWarnings("deprecation") protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) { StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(); stringConverter.setWriteAcceptCharset(false); messageConverters.add(new ByteArrayHttpMessageConverter()); messageConverters.add(stringConverter); messageConverters.add(new ResourceHttpMessageConverter()); messageConverters.add(new SourceHttpMessageConverter<Source>()); messageConverters.add(new AllEncompassingFormHttpMessageConverter()); if (romePresent) { messageConverters.add(new AtomFeedHttpMessageConverter()); messageConverters.add(new RssChannelHttpMessageConverter()); } if (jaxb2Present) { messageConverters.add(new Jaxb2RootElementHttpMessageConverter()); } if (jackson2Present) { messageConverters.add(new MappingJackson2HttpMessageConverter()); } else if (jacksonPresent) { messageConverters.add(new org.springframework.http.converter.json.MappingJacksonHttpMessageConverter()); } }
已经加载了相应的默认转换器。断点调试说明默认配置是没有问题的。
只能说明是第二个问题导致的,但是不知道为什么导致这个问题(json数据问题,还是其他问题),在不知道问题的情况下,只能看request请求过来,转换器是怎么工作的。因为本人对spring不是特别了解,所以不知其原理。在这种情况下还是只能根据(HttpMessageConverter)关键类找到相应使用地方。以经验进行判断和调试。发现在AbstractMessageConverterMethodArgumentResolver中的readWithMessageConverters方法是request请求过来进行类型转换的处理方法。
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter methodParam, Type targetType) throws IOException, HttpMediaTypeNotSupportedException { MediaType contentType; try { contentType = inputMessage.getHeaders().getContentType(); } catch (InvalidMediaTypeException ex) { throw new HttpMediaTypeNotSupportedException(ex.getMessage()); } if (contentType == null) { contentType = MediaType.APPLICATION_OCTET_STREAM; } Class<?> contextClass = methodParam.getContainingClass(); Class<T> targetClass = (Class<T>) ResolvableType.forType(targetType, ResolvableType.forMethodParameter(methodParam)).resolve(); for (HttpMessageConverter<?> converter : this.messageConverters) { if (converter instanceof GenericHttpMessageConverter) { GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter; if (genericConverter.canRead(targetType, contextClass, contentType)) { if (logger.isDebugEnabled()) { logger.debug("Reading [" + targetType + "] as \"" + contentType + "\" using [" + converter + "]"); } return genericConverter.read(targetType, contextClass, inputMessage); } } if (targetClass != null) { if (converter.canRead(targetClass, contentType)) { if (logger.isDebugEnabled()) { logger.debug("Reading [" + targetClass.getName() + "] as \"" + contentType + "\" using [" + converter + "]"); } return ((HttpMessageConverter<T>) converter).read(targetClass, inputMessage); } } } throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes); }
这时候发现其实已经根据HttpMessageConverter的canRead方法已经找到了对应的类型消息转换器MappingJackson2HttpMessageConverter,而且已经开始进行转换了,只是抛出了运行时异常。因为异常没有在控制台输出。我通过断点调试发现MappingJackson2HttpMessageConverter的readJavaType方法抛出运行时异常,通过源代码发现底层是用的jackson的objectMapper进行操作的,代码如下:
try { return this.objectMapper.readValue(inputMessage.getBody(), javaType); } catch (IOException ex) { throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex); }
如是我就把代码单独拿出来在main方法里面运行,还是不行,这时我就好定位问题了。要不是类型错误,要不是输入数据错误。仔细检查发现json数据没有问题,用jsonobject也能进行转换。这时只能判断是传入的javaType有问题导致的。如是我打开发现对象(Greeting)没有set方法,我想是不是因为此jakson没法工作呢(原理不清楚)。如是乎我给此对象提供了set方法,再运行可以了。绕了一圈终于把问题解决了,但是通过这个问题让我更加清楚了spring的restful的工作机制。

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务
