java - 如何在过滤器中修改 post call 的对象。弹簧靴
问题描述
我的应用程序中有一个过滤器
@Component
@Order(2)
public class RequestResponseLoggingFilter implements Filter {
@Override
public void doFilter(
ServletRequest request,
ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// SET VALUE OF OBJECT
}
// other methods
}
我有一个使用类的 Restcall。
@RequestMapping
Class Test{
@PostMapping("/test")
public void postEntry(@Valid @RequestBody Testing testing){
}
}
Class Testing{
@NotNull(message="ERROR")
String id;
....
}
我在我的过滤器中获得了 id,我想在我的过滤器中设置测试类的 id。这可能吗?
解决方案
你可以使用MockHttpServletRequest
这样的东西
@Test
public void testAddEventWithWebAuthenticationDetails() {
HttpSession session = new MockHttpSession(null, "test-session-id");
MockHttpServletRequest request = new MockHttpServletRequest();
request.setSession(session);
request.setRemoteAddr("1.2.3.4");
WebAuthenticationDetails details = new WebAuthenticationDetails(request);
Map<String, Object> data = new HashMap<>();
data.put("test-key", details);
AuditEvent event = new AuditEvent("test-user", "test-type", data);
customAuditEventRepository.add(event);
List<PersistentAuditEvent> persistentAuditEvents = persistenceAuditEventRepository.findAll();
assertThat(persistentAuditEvents).hasSize(1);
PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0);
assertThat(persistentAuditEvent.getData().get("remoteAddress")).isEqualTo("1.2.3.4");
assertThat(persistentAuditEvent.getData().get("sessionId")).isEqualTo("test-session-id");
}
更多示例在这里
或者
如果你想这样做过滤方式
之前的几点
- 请求正文只能读取一次。
- 如果您在过滤器中读取正文,则目标 servlet 将无法重新读取它,这也会导致 IllegalStateException。
- 您将需要 ServletRequestWrapper 或其子项: HttpServletRequestWrapper 以便您可以读取 HTTP 请求正文,然后 servlet 稍后仍可以读取它。
工作流程将是
- 唯一的方法是您自己在过滤器中使用整个输入流。
- 从中获取您想要的内容,然后为您阅读的内容创建一个新的 InputStream。
将该 InputStream 放入 ServletRequestWrapper(或 HttpServletRequestWrapper)。
// 示例 Wrapper 类,您可以在其中读取正文和修改正文内容
public class SampleHttpServletRequest extends HttpServletRequestWrapper { private ByteArrayOutputStream cachedBytes; public SampleHttpServletRequest(HttpServletRequest request) { super(request); } @Override public ServletInputStream getInputStream() throws IOException { if (cachedBytes == null) cacheInputStream(); return new CachedServletInputStream(); } @Override public BufferedReader getReader() throws IOException{ return new BufferedReader(new InputStreamReader(getInputStream())); } private void cacheInputStream() throws IOException { cachedBytes = new ByteArrayOutputStream(); IOUtils.copy(super.getInputStream(), cachedBytes); } public class CachedServletInputStream extends ServletInputStream { private ByteArrayInputStream input; public CachedServletInputStream() { input = new ByteArrayInputStream(cachedBytes.toByteArray()); } @Override public int read() throws IOException { return input.read(); } } }
过滤器类
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
/* wrap the request in order to read the inputstream multiple times */
MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request);
doMyThing(multiReadRequest.getInputStream());
chain.doFilter(multiReadRequest, response);
}
}
有关更多详细信息,请参阅这些帖子
Http Servlet 请求在读取一次后从 POST 正文中丢失参数
HttpServletRequestWrapper,setReadListener / isFinished / isReady 的示例实现?
推荐阅读
- php - 如何将根域存储为 php 中的变量并使用它在文件夹之间移动
- php - Apache Unicode 处理
- database - Flutter:将数据从第一屏发送到第二屏
- amazon-web-services - 错误无法为无服务器自定义域设置基域映射
- javascript - Nativescript-vue TabView 无法呈现来自 API 的第一个项目
- regex - 用于匹配整个特定 IP 地址类集的 RegEx 模式?
- string - 从字符串转换时如何确定 []rune 的容量
- django - Django 部署:错误 403 Forbidden 您无权访问此服务器上的 /
- r - 如何迭代匹配单词序列
- javascript - 如何在过滤后的 Observable 上设置值