up:: 过滤链
本篇博客介绍在项目中,过滤器的一个经典应用场景
过滤器案例:多端设备自动适配:
一:问题引入:
智能设备的种类越来越多,应用的界面在开发设计的时候就需要考虑到不同的终端,界面就至少要开发两套:PC端和手机端;
即同一个网站在不同的设备上,展示的效果是不同的;
可以设想,在实际开发时,一个系统中有非常多的界面,如果在每一个界面中都要做不同设备的判断,那么工作量太大,很麻烦;
为了解决这个问题,就可以开发一个设备适配的过滤器,通过分析客户端请求的的信息的不同,来决定是显示PC端的界面,还是移动端的界面。
二:具体案例
1.准备工作:
创建web工程,device-adapter: 注意工程的上下文路径设置成了”/” ;
在webContent目录下,新建文件夹
其中,desktop目录下的index.html是PC端需要显示的;mobile目录下的index.html是移动端需要显示的;俩index.html加载显示不同的资源;
2.编写Filter:DeviceAdapter,并在web.xml中配置;
基本思路是:(1)先判断URL中是否有/desktop或者/mobile这些明确表明是PC端还是移动端的东西;如果有直接向后传递;如果没有再后续处理
(2)根据请求中的urser-agent判断是PC端还是移动端;
(3)如果是PC端,修改url后,res.sendRedirect(targetUrl),中断本次请求,让浏览器重新发一个url为targetUrl的请求;
(4)如果是移动端,修改url后,res.sendRedirect(targetUrl),中断本次请求,让浏览器重新发一个url为targetUrl的请求;
需要注意的点:
(1)req.getRequestURI(); 获取请求的url;
(2)req.getHeader(“user-agent”);获取请求头中某字段的信息;
(3)res.sendRedirect(targetUrl);响应重定向;
(4) 注意看代码中的注释 ;
package com.imooc.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class DeviceAdapter implements Filter{
@Override
public void destroy() {
// TODO Auto-generated method stub
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
/**
* 当前程序默认首页是:/index.html;自然,在webContent根目录下没有index.html,index.html都在俩文件夹中;
* (1)如果是PC端的话,需要让路径变成/desktop/index.html,即将url重新跳转到跳转到desktop目录下的html页面;
* (2)如果是手机端,则需要变成/mobile/index.html;
* (3)同理,如果访问的是其他html,诸如访问的是/kkk.html的话,PC端:/desktop/kkk.html,手机端:/mobile/kkk.html;
*/
String url = req.getRequestURI(); //获取url
System.out.println("访问的url为:"+url);
//如果浏览器发来的请求的url中,本身就自带了/desktop或者/mobile,就代表这是一个正确的PC端或者手机端的url;
// 此时,不需要处理,直接把请求向后送就可以了;
if(url.startsWith("/desktop") || url.startsWith("/mobile")) {
chain.doFilter(request, response);
}else {
String userAgent = req.getHeader("user-agent").toLowerCase();
// 在实际中,对于移动端的判断会更复杂些;
String targetUrl = ""; // 保存真正要跳转的url
if((userAgent.indexOf("android") != -1) || userAgent.indexOf("iphone") != -1) {
targetUrl = "/mobile"+url;
System.out.println("移动端设备正在访问,重新跳转的url为:"+targetUrl);
// 上面判断完毕,修改玩targetUrl之后,并没有执行chain.doFilter()
// 而是使用了res.sendRedirect();通知客户端的浏览器重新发起一个请求;
// 由于没有使用chain.dofilter(),这个过滤器没有把请求向后传递,所以本次请求就会中断;
// 这个新请求的url就是我们修改后的targetUrl;
res.sendRedirect(targetUrl);
}else {
targetUrl = "/desktop"+url;
System.out.println("PC端设备正在访问,重新跳转的url为:"+targetUrl);
res.sendRedirect(targetUrl);
}
}
}
@Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
}
user-agent:里面的信息包含了客户端的信息;在实际中 ,为了判断客户端设备是什么,往往需要对urser-agent作更加复杂的分析;而且通常有现成的轮子可供利用;
配置过滤器:过滤范围设置成了对所有HTML;
3.效果:
4.案例的总结
(1)上面的案例过滤器过滤范围(或者说作用范围啦)设置成了HTML,所以上面的过滤器不仅仅可以作用于index.html,其可以作用于所有的html文件;
(2)当开发应用的时候,一做就做两套html,一套html是PC端,一套html是移动端的;这两套html可以放在不同的目录下,只要保证这两个目录下的文件的名称相同的,那么上面编写的过滤器就可自动地帮我们选择对应版本的文件来显示了;