gpt4 book ai didi

java - 使用 HttpServletRequestWrapper 进行复制后缺少所需的请求正文

转载 作者:行者123 更新时间:2023-12-04 03:10:29 25 4
gpt4 key购买 nike

在我的项目中,我有一组 api 调用,它们应该通过某些常见的验证集进行过滤。在这种情况下,我必须在请求到达 REST Controller 之前拦截请求,读取请求正文,进行验证并在请求通过验证时将其传递给 Controller ​​。

HttpServletRequest不能反序列化多次,我使用了 HttpServletRequestWrapper复制实际请求。使用它制作的副本,我进行验证。

以下是拦截请求的配置类。

public class InterceptorConfig extends WebMvcConfigurerAdapter {

@Autowired
CustomInterceptor customInterceptor;

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(customInterceptor).addPathPatterns("/signup/**");

}
}

这是我的 preHandle里面的方法 CustomInterceptor扩展 HandlerInterceptorAdaptor 的类
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

ServletRequest copiedRequest = new HttpRequestWrapper(request);

Map<String, Object> jsonMap = mapper.readValue(copiedRequest.getInputStream(), Map.class);

if(jsonMap.containsKey("userId")){
long userId = jsonMap.get("userId");
MyClass myObject= myAutowiredService.getMyObject(userId);
if(myObject == null){
response.setStatus(HttpStatus.SC_NOT_ACCEPTABLE);
return false;
}
// some more validations which end up returning false if they are met
}
return true;
}

这是我的 HttpRequestWrapper
public class HttpRequestWrapper extends HttpServletRequestWrapper {

private byte[] requestBody;

public HttpRequestWrapper(HttpServletRequest request) throws IOException{
super(request);

try {
requestBody = IOUtils.toByteArray(request.getInputStream());
} catch (IOException ex) {
requestBody = new byte[0];
}
}

@Override
public ServletInputStream getInputStream() throws IOException {

final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody);

return new ServletInputStream() {

@Override
public boolean isFinished() {
return byteArrayInputStream.available() == 0;
}

@Override
public boolean isReady() {
return true;
}

@Override
public void setReadListener(ReadListener listener) {
throw new RuntimeException("Not implemented");
}

public int read () throws IOException {
return byteArrayInputStream.read();
}
};
}

}

现在一切就绪。现在,当我向任何具有 /signup/** 模式的 url 发送请求时,所有验证都正常进行。但是,一旦请求命中 Controller 方法,就会弹出错误,指出请求正文不可用。

Required request body is missing: public com.mypackage.myResponseObject com.mypackage.myController.myControllerMethod(com.mypackage.myDTO)



我正在努力寻找原因以及解决问题的方法。我在 RequestWrapper 类中做错了什么吗?或缺少什么?

帮我解决这个问题。

谢谢!

最佳答案

问题似乎是您正在使用拦截器来读取 HttpServletRequestInputStream并将其包裹在 HttpRequestWrapper 中但包装器永远不会返回。

我认为你应该使用 Filter

public class CustomFilter extends OncePerRequestFilter {
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ServletRequest copiedRequest = new HttpRequestWrapper(request);

Map<String, Object> jsonMap = mapper.readValue(copiedRequest.getInputStream(), Map.class);

if(jsonMap.containsKey("userId")){
long userId = jsonMap.get("userId");
MyClass myObject= myAutowiredService.getMyObject(userId);
if(myObject == null){
response.setStatus(HttpStatus.SC_NOT_ACCEPTABLE);
//return false;
}
// some more validations which end up returning false if they are met
}

filterChain.doFilter(copiedRequest, (ServletResponse) response);
}
}

您需要在 web.xml 中使用此过滤器或 WebApplicationInitializer

关于java - 使用 HttpServletRequestWrapper 进行复制后缺少所需的请求正文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45705023/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com