Java 如何在spring boot中到达控制器之前修改请求正文

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50932518/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 23:52:45  来源:igfitidea点击:

How to modify request body before reaching controller in spring boot

javaspringspring-boot

提问by BlueCloud

I have a spring boot application. I change the request body of every post request. Is it possible to modify the request body before the request reaches the controller. Please include an example.

我有一个弹簧启动应用程序。我更改了每个帖子请求的请求正文。是否可以在请求到达控制器之前修改请求正文。请包括一个例子。

采纳答案by DwB

Short Answer
Yes, but not easily.

简短回答
是的,但并不容易。

Details
I know of three options to change the body of a request "before" it arrives at the handler method in the controller;

详细信息
我知道三个选项可以在请求到达控制器中的处理程序方法“之前”更改它的主体;

  1. Use AOP to change the request before the method is called.
  2. Create an HTTP filter.
  3. Create a custom Spring HandlerInterceptor.
  1. 在调用方法之前使用 AOP 更改请求。
  2. 创建 HTTP 过滤器。
  3. 创建自定义 Spring HandlerInterceptor。

Since you are already using spring-boot, option 3, custom Spring HandlerInterceptor, seems like the best option for you.

由于您已经在使用 spring-boot,因此选项 3,自定义 Spring HandlerInterceptor 似乎是您的最佳选择。

Here is a link to a Baeldung Articlecovering spring HandlerInterceptors.

这里是一个Baeldung 文章的链接,该文章涵盖了 spring HandlerInterceptors。

The Baeldung article is not the full answer for your problem because you can only read the InputStremreturned by HttpServletRequestone time.

Baeldung 文章不是您问题的完整答案,因为您只能阅读一次InputStrem返回的内容HttpServletRequest

You will need to create a wrapper class that extends HttpServletRequestand wrap every request in your wrapper class within your custom HandlerInterceptor or in a custom Filter (Filter might be the way to go here).

您将需要创建一个包装类,该HttpServletRequest包装类在您的自定义 HandlerInterceptor 或自定义过滤器中的包装类中扩展和包装每个请求(过滤器可能是这里的方法)。

Wrapper Class

包装类

  1. Read the HttpServletRequestInputStream in the wrapper class constructor
  2. Modify the body per your requirements.
  3. Write the modified body to a ByteArrayOutputStream.
  4. Use toByteArrayto retrieve the actual byte[]from the stream.
  5. Close the ByteArrayOutputStream (try-with-resources is good for this).
  6. Override the getInputStreammethod.
  7. Wrap the byte[]in a ByteArrayInputStream every time the getInputStreamis called. Return this stream.
  1. 读取HttpServletRequest包装类构造函数中的InputStream
  2. 根据您的要求修改主体。
  3. 将修改后的正文写入ByteArrayOutputStream.
  4. 用于从流中toByteArray检索实际值byte[]
  5. 关闭 ByteArrayOutputStream(try-with-resources 对此有好处)。
  6. 覆盖该getInputStream方法。
  7. byte[]每次getInputStream调用 时都将 包装在 ByteArrayInputStream 中。返回此流。

How To Wrap the Request

如何包装请求

  1. In your Filter, instantiate your wrapper class and pass in the original request (which is a parameter to the doFilter method).
  2. Pass the wrapper to the chain.doFilter method (not the original request).
  1. 在您的过滤器中,实例化您的包装类并传入原始请求(它是 doFilter 方法的参数)。
  2. 将包装器传递给 chain.doFilter 方法(不是原始请求)。

回答by Abhinay Dronavally

Another alternative would be adding an attribute to the HttpServletRequestobject. And after that you can read that attribute in the Controller class with @RequestAttributeannotation.

另一种选择是向HttpServletRequest对象添加一个属性。之后,您可以使用@RequestAttribute注释在 Controller 类中读取该属性。

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;
        }

    }

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";
    }
}

This has advantage of not modifying the request body.

这具有不修改请求正文的优点。