【问题标题】:POST not supported in custom Servlet as @Bean in Spring Boot自定义 Servlet 不支持 POST 作为 Spring Boot 中的 @Bean
【发布时间】:2015-06-25 01:15:30
【问题描述】:

我正在尝试将第 3 方 servlet 集成到我的 Spring Boot 应用程序中,当我尝试向 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 Boot 应用程序中支持另一个 Servlet?

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

谢谢!

【问题讨论】:

    标签: java spring spring-mvc servlets spring-boot


    【解决方案1】:

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

    【讨论】:

    • 修复 super.doPost 并通过真实测试尝试后,它可以与尾部斜杠一起使用。我觉得自己像个傻瓜……这是一个漫长的迟到的一天! ;) 谢谢!
    【解决方案2】:

    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!!");
        }
    }
    

    【讨论】:

    • 啊,你是对的,这使我的测试无效!哈哈。但是,我认为@dunni 的回答实际上是正确的。删除 super.doPost 后,添加尾部斜杠似乎有效。
    猜你喜欢
    • 1970-01-01
    • 2018-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-05
    • 2021-07-27
    • 2014-05-23
    • 2018-06-03
    相关资源
    最近更新 更多