POST 在自定义 Servlet 中不支持作为 Spring Boot 中的 @Bean

POST not supported in custom Servlet as @Bean in Spring Boot

我正在尝试将第 3 方 servlet 集成到我的 Spring 引导应用程序中,当我尝试向 servlet 提交 POST 时,我在日志中看到以下内容:

PageNotFound: Request method 'POST' not supported

我做了一个简单的测试来证明这一点。我开始使用 auto generated Spring Boot project。然后我创建了以下 Servlet:

public class TestServlet extends HttpServlet {
    private static final Logger log = LoggerFactory.getLogger(TestServlet.class);
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp); //To change body of generated methods, choose Tools | Templates.
        log.info("doPost was called!!");
    }
    
}

然后我创建的配置如下:

@Configuration
public class ServletConfig {
    @Bean //exposes the TestServlet at /test
    public Servlet test() {
        return new TestServlet();
    }        
}

然后我运行 Tomcat7 内的应用程序。我在日志中看到:

ServletRegistrationBean: Mapping servlet: 'test' to [/test/]

然后我尝试像这样使用 cUrl 访问端点:

curl -v http://localhost:8080/test -data-binary '{"test":true}'

curl -XPOST -H'Content-type: application/json' http://localhost:8080/test -d '{"test":true}'

我试过添加@RequestMapping,但也没有用。谁能帮我弄清楚如何在我的 Spring 启动应用程序中支持另一个 Servlet?

您可以在此处找到示例应用程序:https://github.com/andrewserff/servlet-demo

谢谢!

根据我以前的经验,您必须在末尾使用斜杠调用 servlet(如 http://localhost:8080/test/)。如果你不把斜杠放在末尾,请求将被路由到映射到 / 的 servlet,默认情况下它是来自 Spring 的 DispatcherServlet(你的错误消息来自那个 servlet)。

TestServlet#doPost() 实现调用 super.doPost() - 它总是发送 40x 错误(405400 取决于所使用的 HTTP 协议) .

实现如下:

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

    String protocol = req.getProtocol();
    String msg = lStrings.getString("http.method_post_not_supported");
    if (protocol.endsWith("1.1")) {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
    } else {
        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
    }
}

Servlet 可以通过两种方式注册: 将 Servlet 注册为 Bean(您的方法 - 应该没问题)或 使用 ServletRegistrationBean:

@Configuration
public class ServletConfig {

    @Bean
    public ServletRegistrationBean servletRegistrationBean(){
        return new ServletRegistrationBean(new TestServlet(), "/test/*");
    }
}

略有改动的Servlet:

public class TestServlet extends HttpServlet {
   private static final Logger log = LoggerFactory.getLogger(TestServlet.class);

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // super.doPost(req, resp);
        log.info("doPost was called!!");
    }
}