This is the 12th day of my participation in the August Text Challenge.More challenges in August
Bloggers have recently encountered requests for BodyAdvice in Spring while using annotations.
1 Overview about RequestBodyAdvice
/**
* Allows customizing the request before its body is read and converted into an
* Object and also allows for processing of the resulting Object before it is
* passed into a controller method as an {@code @RequestBody} or an
* {@code HttpEntity} method argument.
*
* <p>Implementations of this contract may be registered directly with the
* {@code RequestMappingHandlerAdapter} or more likely annotated with
* {@code @ControllerAdvice} in which case they are auto-detected.
*
* @author Rossen Stoyanchev
* @since4.2 * /
public interface RequestBodyAdvice {
boolean supports(MethodParameter methodParameter, Type targetType, Class
> converterType);
Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class
> converterType);
HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class
> converterType) throws IOException;
Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class
> converterType);
}
Copy the code
As you can see from the above source code, this interface is a new interface in Spring4.2. According to the data, this interface is mainly used to enhance the processing of parameters before and after the request body.
Look at the source of beforeBodyRead method, see RequestResponseBodyAdviceChain classes implement this interface, and call the method, and continue to see down, found AbstractMessageConverterMethodArgumentR Esolver readWithMessageConverters method call this method in an abstract class. The abstract class implements the interface HandlerMethodArgumentResolver processing parameters are given.
.for(HttpMessageConverter<? > converter :this.messageConverters) { Class<HttpMessageConverter<? >> converterType = (Class<HttpMessageConverter<? >>) converter.getClass();if (converter instanceofGenericHttpMessageConverter) { GenericHttpMessageConverter<? > genericConverter = (GenericHttpMessageConverter<? >) converter;if (genericConverter.canRead(targetType, contextClass, contentType)) {
if (logger.isDebugEnabled()) {
logger.debug("Read [" + targetType + "] as \"" + contentType + "\" with [" + converter + "]");
}
if(inputMessage.getBody() ! =null) {
// Call the implementation method under the interface
inputMessage = getAdvice().beforeBodyRead(inputMessage, parameter, targetType, converterType);
body = genericConverter.read(targetType, contextClass, inputMessage);
body = getAdvice().afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
else {
body = getAdvice().handleEmptyBody(null, inputMessage, parameter, targetType, converterType);
}
break; }}...Copy the code
HttpMessageConverter () {HttpMessageConverter ();
The realization of the AbstractMessageConverterMethodArgumentResolver abstract class subclasses
HttpEntityMethodProcessor
The method argument to handle controller is HttpEntity or RequestEntity)
/**
* Resolves {@link HttpEntity} and {@link RequestEntity} method argument values
* and also handles {@link HttpEntity} and {@link ResponseEntity} return values.
**/
Copy the code
RequestPartMethodArgumentResolver
The handler parameters are @requestPart and MultipartFile and Part
/**
* Resolves the following method arguments:
* <ul>
* <li>Annotated with {@code @RequestPart}
* <li>Of type {@link MultipartFile} in conjunction with Spring's {@link MultipartResolver} abstraction
* <li>Of type {@codeJavax.servlet.http. Part} in conjunction with servlet 3.0 multipart requests * </ul> **/
Copy the code
RequestResponseBodyMethodProcessor
The handler parameter is RequestBody
/**
* Resolves method arguments annotated with {@code @RequestBody} and handles return
* values from methods annotated with {@code @ResponseBody} by reading and writing
* to the body of the request or response with an {@link HttpMessageConverter}.
**/
Copy the code
From the above knowable, when using HandlerMethodArgumentResolver interface, can the request parameter parsed pretreatment, aftertreatment. And the supports method overrides to return True to enable parameter handling.
2 About the use of RequestBodyAdvice
1 Preparing the Environment
Build a SpringBoot environment that can run.
1 Preparing Documents
1 application.yml
server:
port: 8081
spring:
datasource:
driverClassName: com.mysql.jdbc.Driver
username: root
password: root
url: jdbc:mysql://localhost:3306/test
Copy the code
2 entity class
@Data
public class User {
private String id;
}
Copy the code
3 Controller Controller
@RestController
@RequestMapping("/consumer")
@Slf4j
public class ConsumerController {
@RequestMapping("/query")
public String queryById(@RequestBody User user) {
log.info("Request parameters =={}", user.toString());
log.info("Response parameter =={}"."H1 style of id");
return "<h1>" + user.toString() + "<h1>"; }}Copy the code
Create an interceptor class that implements the RequestBodyAdvice interface
@ControllerAdvice
@Slf4j
public class LogRequestBodyAdvice implements RequestBodyAdvice {
// Whether to enable interception True Enable false Disable
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class
> aClass) {
return true;
}
/** * Request body parsing before processing *@param httpInputMessage
* @param methodParameter
* @param type
* @param aClass
* @return
* @throws IOException
*/
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class
> aClass) throws IOException {
// Common scenarios are as follows: 1 Log recording 2 Content encryption and decryption 3 Check whether paging is enabled
log.info("Intercepted request parameter = {}",methodParameter.toString());
Method method=methodParameter.getMethod();
log.info("Request body before reading ={}==>{}==>{}==>{}",method.getDeclaringClass().getSimpleName(),method.getName(),type.toString(),aClass.getName());
return httpInputMessage;
}
/** * Request body parse after processing *@param o
* @param httpInputMessage
* @param methodParameter
* @param type
* @param aClass
* @return* /
@Override
public Object afterBodyRead(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class
> aClass) {
Method method=methodParameter.getMethod();
log.info("Request body read after ={}.{}:{}",method.getDeclaringClass().getSimpleName(),method.getName(),o.toString());
return o;
}
/** * Processing has no arguments *@param o
* @param httpInputMessage
* @param methodParameter
* @param type
* @param aClass
* @return* /
@Override
public Object handleEmptyBody(Object o, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class
> aClass) {
Method method=methodParameter.getMethod();
log.info("No arguments ={}.{}",method.getDeclaringClass().getSimpleName(),method.getName());
return o;
}
Copy the code
3 Use the Postman tool
1 Postman sends a request
2 Project Logs
3 summary
The interception before and after the parsing of the request body parameters can better help realize business functions without invading the code logic. Common usage scenarios are as follows:
-
1 Recording Logs
-
2 Content encryption and decryption
-
3 Check whether paging is enabled