如何在HandlerInterceptor中读取请求体? [英] How to read request body in HandlerInterceptor?

查看:17
本文介绍了如何在HandlerInterceptor中读取请求体?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有 Spring Boot,我需要在 DB 中记录用户操作,所以我写了 HandlerInterceptor:

I have Spring Boot and I need to log user action in DB, so I wrote HandlerInterceptor:

@Component
public class LogInterceptor implements HandlerInterceptor {
@Autovired
private LogUserActionService logUserActionService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 
throws IOException {
    String userName = SecurityContextHolder.getContext().getAuthentication().getName();
    String url = request.getRequestURI();
    String queryString = request.getQueryString() != null ? request.getQueryString() : "";
    String body = "POST".equalsIgnoreCase(request.getMethod()) ? new BufferedReader(new InputStreamReader(request.getInputStream())).lines().collect(Collectors.joining(System.lineSeparator())) : queryString;
    logUserActionService.logUserAction(userName, url, body);
    return true;
}
}

但是根据这个答案 在 HandlerInterceptor 处获取 RequestBody 和 ResponseBody "RequestBody 只能读取一次",因此据我所知,我读取了输入流,然后 Spring 尝试执行相同操作,但是已经读取了流,并且出现错误:缺少必需的请求主体......"

But according to this answer Get RequestBody and ResponseBody at HandlerInterceptor "RequestBody can be read only once", so as I understand I read input stream and then Spring tries to do same, but stream has been read already and I'm getting an error: "Required request body is missing ..."

所以我尝试了不同的方法来制作缓冲输入流,即:

So I tried different ways to make buffered input stream i.e.:

HttpServletRequest httpServletRequest = new ContentCachingRequestWrapper(request);
new BufferedReader(new InputStreamReader(httpServletRequest.getInputStream())).lines().collect(Collectors.joining(System.lineSeparator()))

InputStream bufferedInputStream = new BufferedInputStream(request.getInputStream());

但没有任何帮助我也尝试使用

But nothing helped Also I tried to use

@ControllerAdvice
public class UserActionRequestBodyAdviceAdapter extends RequestBodyAdviceAdapter {

但它只有正文,没有请求信息,如 URL 或请求参数也尝试使用过滤器,但结果相同.

But it has only body, no request info like URL or Request parameters Also tried to use Filters, but result same.

所以我需要一种很好的方法来从请求中获取信息,例如用户、URL、参数、正文(如果存在)并将其写入数据库.

So I need a good way to get information from request like user, URL, parameters, body (if present) and write it to DB.

推荐答案

您可以使用 Filter 来记录请求正文.

You can use Filter to log request body.

public class LoggingFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(request);
        try {
            chain.doFilter(wrappedRequest, res);
        } finally {
            logRequestBody(wrappedRequest);
        }
    }

    private static void logRequestBody(ContentCachingRequestWrapper request) {

        byte[] buf = request.getContentAsByteArray();
        if (buf.length > 0) {
            try {
                String requestBody = new String(buf, 0, buf.length, request.getCharacterEncoding());
                System.out.println(requestBody);
            } catch (Exception e) {
                System.out.println("error in reading request body");
            }
        }
    }
}

这里要注意的主要事情是你必须在过滤器链中传递ContentCachingRequestWrapper的对象,否则你将不会在其中获取请求内容.

The main thing to note here is that you have to pass object of ContentCachingRequestWrapper in filter chain otherwise you won't get request content in it.

在上面的例子中,如果你使用 chain.doFilter(req, res)chain.doFilter(request, res) 那么你不会得到请求体wrappedRequest 对象.

In above example, if you use chain.doFilter(req, res) or chain.doFilter(request, res) then you won't get request body in wrappedRequest object.

这篇关于如何在HandlerInterceptor中读取请求体?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆