篇幅稍长,源码较多,静下心来看源码,SpringBoot参数解析和返回值处理源码分析
整理了一份Java核心知识点PDF文档需要的关注私信【555】获取资料
正文
问题
第一个问题:SpringBoot是如何解析web请求的参数?
第二个问题:SpringBoot是如何处理web请求的返回值?
示例
第一步:定义接口
@RequestMapping("/persons")public interface PersonApi { /** * list * * @return */ @GetMapping("/") List list(); /** * get * * @param id * @return */ @GetMapping("/{id}") Person get(@PathVariable("id") Integer id); /** * add * * @param person * @return */ @PostMapping("/") List add(@Valid @RequestBody Person person); /** * update * * @param person * @return */ @PutMapping("/") List update(@RequestBody Person person);}
第二步:定义接口实现
@RestControllerpublic class PersonController implements PersonApi { private static List personList = new ArrayList<>(); static { personList.add(new Person(10001, "test1")); personList.add(new Person(10002, "test2")); personList.add(new Person(10003, "test3")); personList.add(new Person(10004, "test4")); personList.add(new Person(10005, "test5")); } @Override public List list() { return personList; } @Override public Person get(Integer id) { Person defaultPerson = new Person(88888, "default"); return personList.stream().filter(person -> Objects.equals(person.getId(), id)).findFirst().orElse(defaultPerson); } @Override public List add(Person person) { personList.add(person); return personList; } @Override public List update(Person person) { personList.removeIf(p -> Objects.equals(p.getId(), person.getId())); personList.add(person); return personList; }}
源码拿新增方法来举例,通过该示例来讲解SpringBoot是如何解析请求参数并注入到Person对象中的以及是如何处理值List
源码分析
在SpringBoot请求源码分析专车中提到两个重要的对象,一个是RequestMappingHandlerMapping,用来处理请求映射;另一个是RequestMappingHandlerAdapter,用来处理请求,也是本文重点分析的对象
首先来看看RequestMappingHandlerAdapter的创建实现
创建RequestMappingHandlerAdapter:WebMvcAutoConfiguration.EnableWebMvcConfiguration#requestMappingHandlerAdapter
@Bean@Overridepublic RequestMappingHandlerAdapter requestMappingHandlerAdapter() { RequestMappingHandlerAdapter adapter = super.requestMappingHandlerAdapter(); adapter.setIgnoreDefaultModelOnRedirect(this.mvcProperties == null || this.mvcProperties.isIgnoreDefaultModelOnRedirect()); return adapter;}
调用父类创建RequestMappingHandlerAdapter:WebMvcConfigurationSupport#requestMappingHandlerAdapter
@Beanpublic RequestMappingHandlerAdapter requestMappingHandlerAdapter() { // 创建RequestMappingHandlerAdapter RequestMappingHandlerAdapter adapter = createRequestMappingHandlerAdapter(); adapter.setContentNegotiationManager(mvcContentNegotiationManager()); // 设置消息转换器 adapter.setMessageConverters(getMessageConverters()); adapter.setWebBindingInitializer(getConfigurableWebBindingInitializer()); // 设置自定义参数解析器 adapter.setCustomArgumentResolvers(getArgumentResolvers()); // 设置自定义返回值处理器 adapter.setCustomReturnValueHandlers(getReturnValueHandlers()); // 如果存在jackson if (jackson2Present) { // 设置requestBody通知 adapter.setRequestBodyAdvice(Collections.singletonList(new JsonViewRequestBodyAdvice())); // 设置responseBody通知 adapter.setResponseBodyAdvice(Collections.singletonList(new JsonViewResponseBodyAdvice())); }// ...省略部分代码 return adapter;}
如上有给RequestMappingHandlerAdapter对象设置消息转换器,那么这些消息转换器是创建的?
获取消息转换器:WebMvcConfigurationSupport#getMessageConverters
protected final List> getMessageConverters() { if (this.messageConverters == null) { this.messageConverters = new ArrayList<>(); configureMessageConverters(this.messageConverters); if (this.messageConverters.isEmpty()) { // 添加默认消息转换器 addDefaultHttpMessageConverters(this.messageConverters); } extendMessageConverters(this.messageConverters); } return this.messageConverters;}
添加默认消息转换器:WebMvcConfigurationSupport#addDefaultHttpMessageConverters
protected final void addDefaultHttpMessageConverters(List> messageConverters) { StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316 messageConverters.add(new ByteArrayHttpMessageConverter()); messageConverters.add(stringHttpMessageConverter); messageConverters.add(new ResourceHttpMessageConverter()); messageConverters.add(new ResourceRegionHttpMessageConverter()); try { messageConverters.add(new SourceHttpMessageConverter<>()); } catch (Throwable ex) { // Ignore when no TransformerFactory implementation is available... } messageConverters.add(new AllEncompassingFormHttpMessageConverter()); if (ro