春季拦截器拦截晚

时间:2019-08-17 21:24:12

标签: spring filter interceptor

运行测试服务器的Spring Boot 2.1.7-需要使用url作为键来检查我的缓存中是否有命中,然后根据是否有缓存命中来进行操作。

我从浏览器发送了一个对https://localhost:8443/test/param=value的请求-我的过滤器收到了请求,然后使用SO上另一个答案的代码,该过滤器构造了url-过滤器代码看到url为{{ 3}} 大! 然后我的拦截器被击中了(这要感谢Theo),但是它认为URL是https://localhost:8443/test?param=value -怎么回事?如果我不截取原始的/ test网址,那么拦截器的数量就很少。

为了解决这个问题,在过滤器中,我将“真实” URL存储在ServletContext中,并且在拦截器中正确读取了该变量。似乎很糟糕,我必须这样做。现在,我已经硬编码了重定向到url / test2的决定,但是回到Chrome,我看到的是test1而不是test2的输出。

Chrome中的“网络”标签似乎建议:test1 output and redirection from favicon

我被重定向到test2,但是仅在插入了favicon请求之后(出于某种神秘的原因),但是如图所示,输出显然是test1,而不是test2。

我不明白的是devtools还显示了test2的响应:

test2 output in devtools

@WebFilter(urlPatterns =“ / test”,description =“测试servlet的过滤器”,initParams = {         @WebInitParam(name =“ msg”,value =“ ==>”)},filterName =“测试过滤器”) 公共类TestFilter实现了Filter {

private FilterConfig filterConfig;


@Override
public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain )
        throws IOException, ServletException
{
    String url = getCurrentUrlFromRequest( servletRequest );
    // in the debugger, url is correctly shown as
    //  https://localhost:8443/test/param=value
    if ( null != url )
    {
        ServletContext s = servletRequest.getServletContext();
        s.setAttribute( "realUrl", url );
    }
    servletResponse.getOutputStream().print( filterConfig.getInitParameter( "msg" ) );
    filterChain.doFilter( servletRequest, servletResponse );

public String getCurrentUrlFromRequest( ServletRequest request )
{
    if ( !( request instanceof HttpServletRequest ) ) return null;

    return getCurrentUrlFromRequest( (HttpServletRequest) request );
}

public String getCurrentUrlFromRequest( HttpServletRequest request )
{
    StringBuffer requestURL = request.getRequestURL();
    String queryString = request.getQueryString();

    if ( queryString == null ) return requestURL.toString();

    return requestURL.append( '?' ).append( queryString ).toString();
}

@Override
public void destroy()
{
}

@Override
public void init( FilterConfig filterConfig ) throws ServletException
{
    this.filterConfig = filterConfig;
}

}

//然后是拦截器:

@Component 公共类CheckForCacheInterceptor实现HandlerInterceptor {

@Bean
public MappedInterceptor myInterceptor()
{
    CheckForCacheInterceptor ci = new CheckForCacheInterceptor();
    ci.setRedirectMapping( "/test2" );
    return new MappedInterceptor( null, ci  );
}

private String redirectMapping;

@Override
public boolean preHandle( HttpServletRequest request, HttpServletResponse response, Object handler )
{
    String url = (String) request.getServletContext().getAttribute( "realUrl" );
    // "realUrl" has https://localhost:8443/test/param=value, but I'd like 
    // to get rid of hack.  Problem is that right here, running the same 
    // exact code (copy/paste of filter's
    // getCurrentUrlFromRequest( HttpServletRequest request ) method )
    //which gets the correct url in the filter yields 
    // https://localhost:8443/favicon.ico  -- where did that come from?

    // TODO check cache using requestUrl as key

    boolean foundInCache = false;
    if ( foundInCache ) 
    {
        // TODO: somehow write cache value to response
        // then send response
        return false;
    } else 
    {
        try
        {
            // TODO:  make direct request, 
            // get response body, then 
            response.sendRedirect( redirectMapping );
            return false;
        } catch ( IOException e )
        {
            e.printStackTrace();
        }
    }

    return false;

}

所以在我的问题浮出水面之前,我会寻求帮助-这个favicon请求是如何在我的拦截器甚至没有破解原始URL之前就潜入的,为什么我无法获得原始URL我的拦截器,并且考虑到Chrome devtools显示我正在进入test2,那么输出是如何从test1 servlet而不是test2 servlet来的?

FWIW,我在Postman中得到了完全相同的行为。非常感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

我在SO上阅读了另一个答案(对不起,我没有链接)已解决了不拦截对/ test的初始get请求的问题-它说拦截器仅拦截去往Controllers的请求,所以我需要具有映射到/ test的Controller。编写了快捷控制器后,拦截器现在可以像预期的那样进行拦截。