我有一个简单的过滤器,它为.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üzt
</video>
</div>
</section>
</div>
</body>
</html>
感谢您的帮助!