最近项目开通了CDN,为了节省成本,公司要求只有在用户激活这一高峰阶段使用CDN,平时关闭CDN。本来这一功能可以在反向代理中实现,但是...哎!一言难尽,言归正传,基于以上目标,解决方案是使用filter将静态资源的请求重定向到CDN。在这个编码过程中,涉及到三个问题:过滤器(或servlet)的url匹配模式有哪几种?如何匹配多个请求?转发和重定向的区别?本文先阐述上述需求的实现,然后再解答提出的三个问题。
使用filter实现静态资源转发
需求详解:在配置文件中设置一个CDN开关参数cdn_status,如果cdn_status=1,表示启用CDN,所有的静态资源(css,js,图片)均从CDN获取,不同的资源对应不同的域名,js文件的CDN访问域名为js.static.aa.com,css文件的CDN访问域名为css.static.aa.com,图片的CDN访问域名为image.static.aa.com。
解决步骤:
- 创建过滤器StaticResourceDispatchFilter
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String cdn_status = filterConfig.getInitParameter("cdn_status");
if("1".equals(cdn_status)) {
String uri = request.getRequestURI();
//获取资源后缀
String ext = uri.substring(uri.lastIndexOf(".") + 1);
//根据后缀获取域名,不同后缀对应不同域名
String hostName = filterConfig.getInitParameter(ext);
//发送重定向请求
response.sendRedirect(url);
} else {
filterChain.doFilter(request, response);
}
}
- 过滤器配置
在web.xml中添加如下配置:
<filter>
<filter-name>StaticResourceDispatchFilter</filter-name>
<filter-class>com.web.filter.StaticResourceDispatchFilter</filter-class>
<init-param>
<param-name>cdn_status</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>css</param-name>
<param-value>css.static.aa.com</param-value>
</init-param>
<init-param>
<param-name>js</param-name>
<param-value>js.static.aa.com</param-value>
</init-param>
<init-param>
<param-name>jpg</param-name>
<param-value>image.static.aa.com</param-value>
</init-param>
<init-param>
<param-name>png</param-name>
<param-value>image.static.aa.com</param-value>
</init-param>
<init-param>
<param-name>gif</param-name>
<param-value>image.static.aa.com</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.css</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.js</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.jpg</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.png</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.gif</url-pattern>
</filter-mapping>
完成以上两步,即可实现静态资源CDN转发的可控操作,只要修改配置参数cdn_status参数,即可实现CDN转发的开关操作。
问题解答
- 转发和重定向的区别
转发只能向同一web应用的组件发起请求,转发请求对客户端是不可见的,即浏览器地址栏无变化;而重定向除了可以向同一web应用的组件发起请求之外,还能向其他web应用的组件发起请求,甚至还可以向其他服务器的web组件发起请求,重定向对客户端是可见的,重定向之后,浏览器地址栏会变成定向后的地址。
- filter或servlet url的匹配模式
一般分为三种模式:
- 精确匹配
/directory/file1.jsp
/directory/file2.jsp
/directory/file3.jsp
- 目录匹配
/directory/*
- 后缀匹配
*.do
*.jsp
注意:下面的不支持:
/direcotry/*.jsp
/和/*之间的区别:
<url-pattern>/</url-pattern>: 会匹配到/login这样的路径型url,不会匹配到模式为*.jsp这样的后缀型url
<url-pattern>/*</url-pattern>:会匹配所有url:路径型的和后缀型的url(包括/login , *.jsp , *.js 和 *.html 等)
<url-pattern>/</url-pattern>: 甚至会造成The requested resource () is not available.
- filter如何匹配多个请求
标准正确的写法如下:
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.jpg</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.png</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>StaticResourceDispatchFilter</filter-name>
<url-pattern>*.gif</url-pattern>
</filter-mapping>
StaticResourceDispatchFilter能够拦截处理后缀为jpg、png和gif的图片请求。