简体   繁体   中英

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

I'm trying to integrate a 3rd party servlet into my Spring Boot application and when I try to submit a POST to the servlet, I see the following in the logs:

PageNotFound: Request method 'POST' not supported

I've made a simple test that show this. I started using an auto generated Spring Boot project . Then I created the following 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!!");
    }

}

Then I my created Configuration like so:

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

Then I run the application within Tomcat7. I see in the logs:

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

Then I try to hit the endpoint with cUrl like so:

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

or

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

I've tried adding a @RequestMapping, but that didn't work either. Can anyone help me figure out how to support another Servlet inside my Spring Boot application?

You can find the sample application here: https://github.com/andrewserff/servlet-demo

Thanks!

From my previous experiences you have to call the servlet with a slash at the end (like http://localhost:8080/test/ ). If you don't put the slash at the end, the request is routed to the servlet mapped to / , which is by default the DispatcherServlet from Spring (your error message comes from that servlet).

The TestServlet#doPost() implementation calls the super.doPost() - which always sends a 40x error (either 405 or 400 depending on the HTTP Protocol used).

Here's the implementation:

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

A Servlet can be registered using two ways: registering the Servlet as a Bean (your approach - which should be fine) or using a ServletRegistrationBean :

@Configuration
public class ServletConfig {

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM