最近项目开通了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。

解决步骤:

  1. 创建过滤器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);
    }
}
  1. 过滤器配置

  在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转发的开关操作。

问题解答

  1. 转发和重定向的区别

  转发只能向同一web应用的组件发起请求,转发请求对客户端是不可见的,即浏览器地址栏无变化;而重定向除了可以向同一web应用的组件发起请求之外,还能向其他web应用的组件发起请求,甚至还可以向其他服务器的web组件发起请求,重定向对客户端是可见的,重定向之后,浏览器地址栏会变成定向后的地址。

  1. 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.
  1. 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的图片请求。

文章作者:admin
本文链接:https://javatech.wang/index.php/archives/22/
版本所有 ©转载时必须以链接形式注明作者和原始出处