当前位置: 首页 > 知识库问答 >
问题:

如何在过滤器中修改post调用的对象?板簧罩

杨和蔼
2023-03-14

我的应用程序中有一个过滤器。

@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。这可能吗?

共有1个答案

宋育
2023-03-14

你可以使用模拟服务器请求这样的东西

@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。
  • 您将需要ServletRequest estWrapper或其子级:HttpServletRequest estWrapper,以便您可以读取HTTP请求正文,然后servlet以后仍然可以读取它。

工作流程将是

>

  • 唯一的方法是您自己在过滤器中消耗整个输入流。
  • 从中获取您想要的内容,然后为您阅读的内容创建一个新的InputStream。
  • 将该InputStream放入ServletRequest estWrapper(或HttpServletRequest estWrapper)。

    //示例包装类,您可以在其中读取正文并修改正文内容

     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主体中丢失参数

    HttpServletRequest estWrapper,setReadListener/isFinfied/isReady的示例实现?

  •  类似资料:
    • 我有这个对象,我需要过滤它。 我只需要在“数据”中输入“isEnabled”为真的值的ID

    • 问题内容: 我正在尝试遍历: …并提取中的每个元素。这是我的方法: 这里的问题是对的每次调用都会从中删除元素,从而修改其大小,从而导致以下错误: 那么…当元素动态变化时,我该如何遍历其中的元素呢? 问题答案: 其他人则提到了正确的解决方案,而没有实际阐明。所以这里是: 另外,如果您想安全地在assign函数中更改映射,则需要传入迭代器(只能使用remove函数,并且只能使用一次)或条目来更改值。

    • 假设我有一个项集合,例如,我需要检查是否有任何项从包装类中被修改,例如,任何项的属性的值通过setter被更改: 或者另一个问题,选择的答案建议使用标记,每次修改属性时都需要升起该标记。然而,我的类实际上会变得更脏,矛盾的是,我需要修改几十个修改Item属性的方法。 有没有其他方法,最好是透明的?

    • 我已经为NPE保护了第一个流,但是第二个流也可以抛出NPE,下面是代码片段: 如果getObjVal(String id)返回null,第二个流将抛出NPE。 下面的代码阻止了第二次NPE,但我觉得这不是一个好方法: 需要在另一个地方使用VAL,如果VAL不为空,将在该地方进行后续调用。有没有更好的方法来防止NPE在这里,我尝试使用可选的内部平面图,但它抛出语法错误。

    • 问题内容: 我有一个过滤器linkifyStuff,其中需要使用其他过滤器处理一些变量。我无法弄清楚从另一个调用一个过滤器的语法。 我了解过滤器链接-这不是我想要的。我想将过滤器应用于linkifyStuff过滤器中的局部变量,而不是其输入或输出。 我希望像下面这样工作,但是$ filter(’filtername’)显然不是正确的语法。 我可以为sanitizeStuff和sanitizeStu

    • 问题内容: 我的应用程序中有2个过滤器。根据某些条件,我想选择是否执行第二个过滤器。有没有办法做到这一点? 我做了一些谷歌搜索,但没有成功。我希望请求继续执行而不执行第二个过滤器。那可能吗? 任何帮助将不胜感激。 问题答案: 您可以在请求中设置一个属性,然后在第二个过滤器中对其进行检查。 您可以像这样简化上面的代码: 这样,您只需检查属性“ executeSecondFilter”的存在