OncePerRequestFilter 无法设置不同于 404 的错误代码

OncePerRequestFilter unable to set error code different than 404

我有一个 Spring 应用程序(不使用 Spring 启动)部署到 tomcat

我正在尝试 return 错误 401 (HttpServletResponse.SC_UNAUTHORIZED) 在特定条件下使用 OncePerRequestFilter ,

但我一直收到未找到错误:

Response code: 404

我的过滤器(删除条件):

@Component
public class MyFilter extends OncePerRequestFilter {

    private static final Logger logger = Logger.getLogger(MyFilter.class);
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Not autorized");           
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            try {
                PrintWriter out = response.getWriter();
                out.write(""); // Empty
                out.flush();
            } catch (IOException e) {
                logger.error("error filtering", e);
            }
            return; // stop chain
    }    
}

我尝试使用与 previous similar answer

类似的代码

I believe you can response.sendError inside do Filter method.

编辑

如果我只是抛出一个异常,我会得到一个通用错误代码 500

Response code: 500

编辑 2

我在 onStartup 方法中添加过滤器被覆盖 WebApplicationInitializer

FilterRegistration myFilter = servletContext.addFilter("myFilter ", MyFilter.class);
myFilter.addMappingForUrlPatterns(null, false, "/myservlet/myendpoint/*");

编辑 3

@Componenet 中的过滤器及其包也包含在组件扫描中

@ComponentScan(basePackages = { "my.parent.pacakge"})

只有在 out.write

之后执行 setStatus 时,才会 return 401
PrintWriter out = response.getWriter();
out.write("");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

我试过你的代码,它有效。成功返回了不同的错误代码。虽然,我想指出几件事-

  1. 方法sendError()向客户端发送响应并清除响应缓冲区。所以,你在它之后写到响应中的任何东西都是没有用的。
  2. setStatus()也没用。当您调用 sendError().
  3. 时,HTTP 响应和 HTTP 响应代码已在上面的行中发送给客户端

现在,这就是我的假设,为什么你的代码不适合你,但它适合我——

您收到 HTTP 404 的原因可能是您的 API 不存在。这可能是由于拼写错误或可能是由于简单的无知,例如将您的 API 命名为 /foo/bar 称为 /foo/bar/,即带有额外的尾部正斜杠。我相信您的过滤器已成功执行,并且您必须在那里做一些有用的事情,而不是您在问题中解释的 sendError() 示例代码。

此外,当您在过滤器中抛出异常时,控件不会到达 API 并且 API 查找不会发生。因此,由于未处理的异常而不是 HTTP 404,默认的 HTTP 500 响应被发送到客户端。