做视频大赛推广的网站,信阳公司网站建设,晋江怎么交换友情链接,站长工具集前言
RequestBody 注解是我们进行JavaEE开发#xff0c;最常见的几个注解之一#xff0c;这篇博文我们以案例和源码相结合#xff0c;帮助大家更好的了解 RequestBody 注解
使用案例
1.自定义实体类
Data
NoArgsConstructor
AllArgsConstructor
public class User {priv…前言
RequestBody 注解是我们进行JavaEE开发最常见的几个注解之一这篇博文我们以案例和源码相结合帮助大家更好的了解 RequestBody 注解
使用案例
1.自定义实体类
Data
NoArgsConstructor
AllArgsConstructor
public class User {private String username;private String password;Overridepublic String toString() {return User{ username username \ , password password \ };}
}
RestController
RequestMapping(/request_body)
public class RequestBodyController {PostMapping(/entity)public String entity(RequestBody User user) {return user.toString();}} 2.使用 Map 接收
PostMapping(/map)
public String map(RequestBody MapString, User map) {return map.toString();
} 3.自定义实体类 (复杂对象)
Data
NoArgsConstructor
AllArgsConstructor
public class Complex {private String tag;private ListUser list;private User[] array;private MapString, User map;
}
PostMapping(/complex)
public String complex(RequestBody Complex complex) {return complex.toString();
} 请求参数
{tag: complex,list: [{username: anna,password: 123},{username: bob,password: 456}],array: [{username: cindy,password: 135},{username: david,password: 246}],map: {u1: {username: eric,password: 159},u2: {username: frank,password: 357}}
}
4.Content-Type 为 application/xml
添加 POM 文件
dependencygroupIdcom.fasterxml.jackson.dataformat/groupIdartifactIdjackson-dataformat-xml/artifactIdversion2.16.1/version
/dependency
接口方法 (和案例1只有方法名不一样)
PostMapping(/xml)
public String xml(RequestBody User user) {return user.toString();
}
请求头设置
将 Content-Type 设置为 application/xml 一般情况下 Content-Type 为 application/json 传递参数
Userusernametom/usernamepassword123/password
/User
响应结果 源码解析
InvocableHandlerMethod#getMethodArgumentValues 参数的处理分为两个阶段
判断当前环境中存在的resolvers是否支持解析当前参数处理参数
判断是否支持解析当前参数 我的环境中存在27个resolvers通过命名我们大概可以猜测出 RequestResponseBodyMethodProcessor 是处理 RequestBody 注解的 resolver
RequestResponseBodyMethodProcessor#supportsParameter 即如果参数上存在 RequestBody 注解则使用 RequestResponseBodyMethodProcessor 处理参数
RequestResponseBodyMethodProcessor#resolveArgument RequestResponseBodyMethodProcessor 的 resolveArgument 方法会遍历当前环境中的 HttpMessageConverters如果存在一个 HttpMessageConverter 的 canRead 方法返回 true则使用该 HttpMessageConverter 的 read 方法读取数据。
案例1、2、3 的原理其实是一样的request 的 Content-Type 为 application/jsonspring-boot-starter-web 会引入 json 相关依赖所以默认情况下SpringMVC 有把 json 对象转换成 key-value 形式数据结构的能力 案例4 我们引用了相关依赖使得 SpringMVC 有把 xml 对象转换成 key-value 形式数据结构的能力
小结
如果 request 的 Content-Type 为 xxx并且存在一个 HttpMessageConverter 支持解析 Content-Type 为 xxx 的数据通过 RequestBody 注解就可以将数据绑定到 key-value 形式的数据结构上
扩展自定义HttpMessageConverter处理指定 Content-Type 的请求
创建HttpMessageConverter
public class UserTextPlainHttpMessageConverter implements HttpMessageConverter {Overridepublic boolean canRead(Class clazz, MediaType mediaType) {return clazz User.class text.equals(mediaType.getType()) plain.equals(mediaType.getSubtype());}Overridepublic boolean canWrite(Class clazz, MediaType mediaType) {return false;}Overridepublic ListMediaType getSupportedMediaTypes() {return Collections.singletonList(MediaType.TEXT_PLAIN);}Overridepublic Object read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {try (InputStream inputStream inputMessage.getBody();BufferedReader reader new BufferedReader(new InputStreamReader(inputStream))) {String line;StringBuilder sb new StringBuilder();while ((line reader.readLine()) ! null) {sb.append(line);}ObjectMapper objectMapper new ObjectMapper();return objectMapper.readValue(sb.toString(), User.class);} catch (Exception e) {throw new RuntimeException(e);}}Overridepublic void write(Object o, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException {}
}
创建配置类
Configuration
public class MessageConfig implements WebMvcConfigurer {Overridepublic void configureMessageConverters(ListHttpMessageConverter? converters) {converters.add(new UserTextPlainHttpMessageConverter());}}
接口方法 (和案例1、4 只有方法名不一样)
PostMapping(/convert)
public String convert(RequestBody User user) {return user.toString();
}
Postman设置 Content-Type 设置为 text/plain body 传参类型为 text 接口响应