如何避免ServletFilter被调用两次?

时间:2020-06-10 19:59:32

标签: java servlet-filters payara

我有一个简单的过滤器,它为.mp4和.png文件设置了有效期和内容类型。这与Frontend一起部署在Payara服务器上,我从中调用所需的媒体文件。然后发生的是,对视频的请求发送了两次。然后,第二个请求将引发异常,因为该资源的连接已在该点关闭。

StackTrace看起来像这样:

  Going into filter! URL: http://localhost:8080/application/video/app.mp4|#]
  Filter img or video!|#]
  Going into filter! URL: http://localhost:8080/application/video/projectcage.mp4|#]
  Filter img or video!|#]
  StandardWrapperValve[default]: Servlet.service() for servlet default threw exception
java.io.IOException: Connection is closed
    at org.glassfish.grizzly.nio.NIOConnection.assertOpen(NIOConnection.java:441)
    at org.glassfish.grizzly.http.io.OutputBuffer.write(OutputBuffer.java:663)
    at org.apache.catalina.connector.OutputBuffer.writeBytes(OutputBuffer.java:338)
    at org.apache.catalina.connector.OutputBuffer.write(OutputBuffer.java:325)
    at org.apache.catalina.connector.CoyoteOutputStream.write(CoyoteOutputStream.java:158)
    at org.apache.catalina.servlets.DefaultServlet.copyRange(DefaultServlet.java:2396)
    [...]
Caused by: java.io.IOException: Eine vorhandene Verbindung wurde vom Remotehost geschlossen
    at sun.nio.ch.SocketDispatcher.write0(Native Method)
    at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:51)
    at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
    at sun.nio.ch.IOUtil.write(IOUtil.java:51)
    at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
    at org.glassfish.grizzly.nio.transport.TCPNIOUtils.flushByteBuffer(TCPNIOUtils.java:125)
    at org.glassfish.grizzly.nio.transport.TCPNIOUtils.writeCompositeBuffer(TCPNIOUtils.java:64)
    [...]

我的Servlet代码如下:

public class ExpiresFilter implements Filter
{
    private Integer days = -1;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse rep = (HttpServletResponse) response;

        String url = req.getRequestURL().toString();
        System.out.println("Going into filter! URL: "+url);

        if ( days > -1  && URLIsImageOrVideo(url)) {
            System.out.println("Filter img or video!");

            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.DATE, days);

            //HTTP header date format: Thu, 01 Dec 1994 16:00:00 GMT
            String expireDate = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss zzz").format(calendar.getTime());
            rep.setHeader("Expires", expireDate );
            String ct = "";
            if(URLIsImage(url))
            {
                ct = "image/png";

            } else if(URLIsVideo(url)) {
                ct = "video/mp4";
            }
            rep.setHeader("Content-Type", ct);
            rep.setHeader("ContentType", ct);

            rep.setStatus(401);
        }

        chain.doFilter(request, response);
        return;
    }

    @Override
    public void init(FilterConfig filterConfig) {        
        String expiresAfter = filterConfig.getInitParameter("days");
        if (expiresAfter != null) {
            try {
                days = Integer.parseInt(expiresAfter);
            }
            catch (NumberFormatException nfe) {
                days = -1;
            }                       
        }
    }

    private boolean URLIsImageOrVideo(String url) {
        return URLIsImage(url) || URLIsVideo(url);
    }

    private boolean URLIsImage(String url) {
        return url.endsWith(".png");
    }

    private boolean URLIsVideo(String url){
        return url.endsWith(".mp4");
    }
}
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
    <filter>
        <description>Set cache expiry for static content</description>
        <filter-name>ExpiresFilter</filter-name>
        <filter-class>com.codingforce.pc.ExpiresFilter</filter-class>
        <init-param>
            <description>Add an Expires Header</description>
            <param-name>days</param-name>
            <param-value>30</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>ExpiresFilter</filter-name>
        <url-pattern>/images/*</url-pattern>
        <url-pattern>/video/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
</web-app>

HTML(已缩短)可以加载应该通过过滤器的某些数据。

<html lang="de">
  <head>
    <title>Application</title>
    <meta charset="utf-8" />
  <body>    
    <header id="ph">
        <picture class="himg">
            <source media="(min-width: 1920px)" srcset="/Projectcage/images/1920.png">
            <source media="(min-width: 1280px)" srcset="/Projectcage/images/1280.png">
            <source media="(min-width: 640px)" srcset="/Projectcage/images/640.png">
            <img src="/Projectcage/images/320.png" alt="Default">
        </picture>

    </header>
        <section>
            <div id="midcontainer">

                <video width="700" height="400" controls>
                    <source src="/Projectcage/video/application.mp4" type="video/mp4">
                    Video vom Browser nicht unterst&uuml;zt
                </video>
            </div>
        </section>
    </div>

  </body>
</html>

感谢您的帮助!

0 个答案:

没有答案