简体   繁体   中英

Why does my method in jersey get called twice?

I have HomeService.java and when I go to the /test url it prints HomeService::test once, but when I go to the /play url it prints HomeService::play twice. How can I get my /play method to only be called once?

The urls I go to are

http://127.0.0.1:8080/Home/rest/main/test
http://127.0.0.1:8080/Home/rest/main/play

HomeService.java:

@Path("/main")
public class HomeService
{

  @GET
  @Path("/test")
  @Produces("text/plain")
  public String test()
  {
    System.out.println("HomeService::test");
    return "Running...";
  }

  @GET
  @Path("/play")
  @Produces("video/mpeg")
  public StreamingOutput play()
  {
    System.out.println("HomeService::play");
    return new StreamingOutput()
    {

    @Override
    public void write(java.io.OutputStream outputStream) {}
  }
}

Web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>Home</display-name>

    <servlet>
        <servlet-name>jersey-servlet</servlet-name>
        <servlet-class>
                      com.sun.jersey.spi.container.servlet.ServletContainer
        </servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.home</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-servlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>

If more information is need let me know.

Edit: So I ran tcpdump and this was the output:

# ./tcpdump -s 128 -A -v -i any port 8080|grep 'play'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 128 bytes
...u...uGET /Home/rest/main/play HTTP/1.1
..  ... .GET /Home/rest/main/play HTTP/1.1

and then again

........GET /Home/rest/main/play HTTP/1.1
........GET /Home/rest/main/play HTTP/1.1

It's because the client requested it twice. You may expect this behavior on media (audio/video) requests. Most media players would test if the server supports range requests, so that it could be more efficiently buffered via multiple HTTP connections. If you look closer at the request headers, you may see Range and If-Range headers. If your server had supported it, then the client would send multiple range requests requesting smaller chunks of the media file starting and ending at the specified range. Also, if the client fast-forwards to a specific moment (eg 1 minute later), then the media player could just abort the request and send a new request requesting the range starting at exactly that position.

You can't stop clients from requesting it multiple times. If your service doesn't support range requests, you'd probably better make it one. The servletcontainer's builtin default servlet supports it. So if you put the media file in public web content and let the client request it directly instead of via a web service, then it'll worry about that.

Note that this problem is completely unrelated to Jersey, although I have somewhat the impression that it's the wrong tool for the particular job of media streaming.

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