springboot RequestBodyAdvice说明
应用:处理控制器请求参数@RequestBody
*********************
相关类与接口
RequestBodyAdvice
public interface RequestBodyAdvice {
boolean supports(MethodParameter var1, Type var2, Class<? extends HttpMessageConverter<?>> var3);
//var1:方法参数,@RequestBody标注的参数
//var2:方法参数类型
//var3:使用的参数转换器(HttpMessageConverter)
//beforeBodyRead、afterBodyRead在执行之前都会调用supports
//返回true则执行,返回false不执行
HttpInputMessage beforeBodyRead(HttpInputMessage var1, MethodParameter var2, Type var3, Class<? extends HttpMessageConverter<?>> var4) throws IOException;
Object afterBodyRead(Object var1, HttpInputMessage var2, MethodParameter var3, Type var4, Class<? extends HttpMessageConverter<?>> var5);
@Nullable
Object handleEmptyBody(@Nullable Object var1, HttpInputMessage var2, MethodParameter var3, Type var4, Class<? extends HttpMessageConverter<?>> var5);
//请求体为空时调用
}
RequestBodyAdviceAdapter
public abstract class RequestBodyAdviceAdapter implements RequestBodyAdvice {
public RequestBodyAdviceAdapter() {
}
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
return inputMessage;
}
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
@Nullable
public Object handleEmptyBody(@Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
return body;
}
}
HttpInputMessage
public interface HttpInputMessage extends HttpMessage {
InputStream getBody() throws IOException;
}
MethodParameter
public class MethodParameter {
private static final Annotation[] EMPTY_ANNOTATION_ARRAY = new Annotation[0];
private final Executable executable;
private final int parameterIndex;
@Nullable
private volatile Parameter parameter;
private int nestingLevel;
@Nullable
Map<Integer, Integer> typeIndexesPerLevel;
@Nullable
private volatile Class<?> containingClass;
@Nullable
private volatile Class<?> parameterType; //参数类型
@Nullable
private volatile Type genericParameterType;
@Nullable
private volatile Annotation[] parameterAnnotations;
@Nullable
private volatile ParameterNameDiscoverer parameterNameDiscoverer;
@Nullable
private volatile String parameterName;
@Nullable
private volatile MethodParameter nestedMethodParameter;
*********************
示例
*****************
pojo 层
Person
@Data
public class Person {
private String name;
private Integer age;
}
Student
@Data
public class Student {
private String name;
private Integer age;
}
*****************
advice 层
CustomRequestBodyAdvice
@ControllerAdvice(basePackages = {"com.example.demo.controller"})
public class CustomRequestBodyAdvice extends RequestBodyAdviceAdapter {
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
System.out.println("supports methodParameter "+methodParameter.getParameter().getName());
System.out.println("supports methodParameter "+methodParameter.getParameter().getType().getName());
System.out.println("supports type "+type.getTypeName());
if (methodParameter.getParameter().getType().getSimpleName().equals("Person")){
return true;
}
return false;
}
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
System.out.println("\nbeforeBodyRead ");
byte[] bytes=new byte[inputMessage.getBody().available()];
inputMessage.getBody().read(bytes);
String s=new String(bytes);
System.out.println(s+"\n");
return new HttpInputMessage() {
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(s.getBytes());
}
@Override
public HttpHeaders getHeaders() {
return inputMessage.getHeaders();
}
};
}
@Override
public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
System.out.println("afterBodyRead "+body);
return super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
@Override
public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
System.out.println("handleEmptyBody "+body);
Person person=new Person();
person.setName("火影忍者");
person.setAge(20);
return person;
}
}
*****************
controller 层
HelloController
@RestController
public class HelloController {
@RequestMapping("/hello")
public Person hello(String name, Integer age){
Person person=new Person();
person.setName(name);
person.setAge(age);
System.out.println(person);
return person;
}
@RequestMapping("/hello2")
public Person hello2(@RequestBody Person person){
System.out.println(person);
return person;
}
@RequestMapping("/hello3")
public Student hello3(@RequestBody Student student){
System.out.println(student);
return student;
}
}
*********************
测试输出
localhost:8080/hello?name=瓜田李下&age=20,控制台输出:
2021-08-08 18:37:43.099 INFO 17136 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-08-08 18:37:43.099 INFO 17136 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
Person(name=瓜田李下, age=20)
说明:方法上没有注解@RequestBody,不会调用CustomRequestBodyAdvice
localhost:8080/hello2,控制台输出:
supports methodParameter person
supports methodParameter com.example.demo.pojo.Person
supports type com.example.demo.pojo.Person
beforeBodyRead
{
"name":"瓜田李下",
"age": 20
}
#beforeBodyRead执行之前调用supports,判断是否执行beforeBodyRead方法
supports methodParameter person
supports methodParameter com.example.demo.pojo.Person
supports type com.example.demo.pojo.Person
afterBodyRead Person(name=瓜田李下, age=20)
#afterBodyRead执行之前调用supports,判断是否执行afterBodyRead方法
Person(name=瓜田李下, age=20)
localhost:8080/hello3,控制台输出:
supports methodParameter student
supports methodParameter com.example.demo.pojo.Student
supports type com.example.demo.pojo.Student
supports methodParameter student
supports methodParameter com.example.demo.pojo.Student
supports type com.example.demo.pojo.Student
Student(name=海贼王, age=20)
说明:supports 返回的均为false,beforeBodyRead、afterBodyRead不会调用