Blu*_*oud 9 java spring spring-boot
我有一个Spring Boot应用程序。我更改每个发布请求的请求正文。是否可以在请求到达控制器之前修改请求主体。请列举一个例子。
Bij*_*ain 10
我的回答是使用HTTP Filter。
请求过滤器.java
@Component
public class RequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
RequestWrapper wrappedRequest = new RequestWrapper((HttpServletRequest) request);
chain.doFilter(wrappedRequest, response);
}
@Override
public void destroy() {
}
}
Run Code Online (Sandbox Code Playgroud)
RequestWrapper.java
public class RequestWrapper extends HttpServletRequestWrapper {
private final String body;
private ObjectMapper objectMapper = new ObjectMapper();
public RequestWrapper(HttpServletRequest request) throws IOException {
// So that other request method behave just like before
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
char[] charBuffer = new char[128];
int bytesRead = -1;
while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
stringBuilder.append(charBuffer, 0, bytesRead);
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
throw ex;
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
throw ex;
}
}
}
// Store request body content in 'requestBody' variable
String requestBody = stringBuilder.toString();
JsonNode jsonNode = objectMapper.readTree(requestBody);
//TODO -- Update your request body here
//Sample
((ObjectNode) jsonNode).remove("key");
// Finally store updated request body content in 'body' variable
body = jsonNode.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
ServletInputStream servletInputStream = new ServletInputStream() {
public int read() throws IOException {
return byteArrayInputStream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
};
return servletInputStream;
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(this.getInputStream()));
}
}
Run Code Online (Sandbox Code Playgroud)
以下是我使用 RequestBodyAdvice 实现它的方法:
@ControllerAdvice
public class CustomRequestBodyAdvice implements RequestBodyAdvice {
Run Code Online (Sandbox Code Playgroud)
A。支持:在这里,您可以控制您的目标控制器,以及通过指定请求主体的类型更好地控制哪个请求主体
@Override
public boolean supports(MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
log.info("In supports() method of {}", getClass().getSimpleName());
return methodParameter.getContainingClass() == AuthorController.class && type.getTypeName() == AuthorDTO.class.getTypeName();
}
Run Code Online (Sandbox Code Playgroud)
b. 身体准备好之前
<!-- language: lang-js -->
@Override
public HttpInputMessage beforeBodyRead(HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) throws IOException {
log.info("In beforeBodyRead() method of {}", getClass().getSimpleName());
return httpInputMessage;
}
Run Code Online (Sandbox Code Playgroud)
C。afterBodyRead:这里可以修改请求正文
<!-- language: lang-js -->
@Override
public Object afterBodyRead(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
log.info("In afterBodyRead() method of {}", getClass().getSimpleName());
if (body instanceof AuthorDTO) {
AuthorDTO authorDTO = (AuthorDTO) body;
authorDTO.setName("Test");
return authorDTO;
}
return body;
}
Run Code Online (Sandbox Code Playgroud)
d. 处理空体
<!-- language: lang-js -->
@Override
public Object handleEmptyBody(Object body, HttpInputMessage httpInputMessage, MethodParameter methodParameter, Type type, Class<? extends HttpMessageConverter<?>> aClass) {
log.info("In handleEmptyBody() method of {}", getClass().getSimpleName());
return body;
}
Run Code Online (Sandbox Code Playgroud)
来源:http ://www.javabyexamples.com/quick-guide-to-requestbodyadvice-in-spring-mvc
小智 6
Another alternative would be adding an attribute to the HttpServletRequest object. And after that you can read that attribute in the Controller class with @RequestAttribute annotation.
In the Interceptor
@Component
public class SimpleInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws ServletException, IOException {
String parameter = request.getParameter("parameter");
if (parameter == "somevalue") {
request.setAttribute("customAttribute", "value");
}
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
In the Controller
@RestController
@RequestMapping("")
public class SampleController {
@RequestMapping(value = "/sample",method = RequestMethod.POST)
public String work(@RequestBody SampleRequest sampleRequest, @RequestAttribute("customAttribute") String customAttribute) {
System.out.println(customAttribute);
return "This works";
}
}
Run Code Online (Sandbox Code Playgroud)
This has advantage of not modifying the request body.
简短回答
是的,但并不容易。
详细信息
我知道三个选项可以在请求到达控制器中的处理程序方法“之前”更改它的主体;
由于您已经在使用 spring-boot,因此选项 3,自定义 Spring HandlerInterceptor 似乎是您的最佳选择。
这里是一个Baeldung 文章的链接,该文章涵盖了 spring HandlerInterceptors。
Baeldung 文章不是您问题的完整答案,因为您只能阅读一次InputStrem
返回的内容HttpServletRequest
。
您将需要创建一个包装器类,该HttpServletRequest
包装器类在您的自定义 HandlerInterceptor 或自定义过滤器(过滤器可能是这里的方式)中扩展和包装您的包装器类中的每个请求。
包装类
HttpServletRequest
包装类构造函数中的InputStreamByteArrayOutputStream
.toByteArray
检索实际值byte[]
。getInputStream
方法。byte[]
每次getInputStream
调用 时都将 包装在 ByteArrayInputStream 中。返回此流。如何包装请求
归档时间: |
|
查看次数: |
8577 次 |
最近记录: |