目前在写一个项目由于需要兼顾多浏览器(主要还是IE6、IE7和FF),和同学讨论使用了两套CSS来达到这一目的。这就遇到了一个问题,怎样根据不同的浏览器来加载不同的CSS文件?最开始是使用jQuery来在前台进行判断,后来否定了这个方法;之后是使用IE浏览器的条件注释来进判断,这种方法虽然可行,但总是有种剑走偏锋的感觉。于是最终方案定为在后台来根据request请求来判断,然后响应到前台页面。
使用后台判断是使用JSP的request对象,使用getHeader()方法可以获得客户端的请求头数据,然后进一步分析出浏览器的类型与版本,加载CSS。由于加载CSS几乎是每个JSP页面都要做的事情,所以如果单抽取出一个类来做这件事不是不可以,但每个Action类都要调用这个类进行一次判断,这显然是很笨拙的办法。于是决定使用Struts2的栏截器机制,把这段代码抽取到一个自定义栏截器中,是最好的方案。
首先创建一个自定义栏截器,这里叫做“BrowserInterceptor”,它继承自com.opensymphony.xwork2.interceptor.MethodFilterInterceptor,从这个类继承的好处是,不必把Action的所有方法全部栏截,只需配置我们想要栏截的方法,这比使用AbstractInterceptor类又更进了一步,具体此栏截器的讲解请参阅《Struts2权威指南》这本书。
package com.yue.interceptor;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
import com.yue.action.AjaxAction;
public class BrowserInterceptor extends MethodFilterInterceptor {
@Override
protected String doIntercept(ActionInvocation arg0) throws Exception {
AjaxAction action = (AjaxAction) arg0.getAction();
HttpServletRequest req = ServletActionContext.getRequest();
String browser = req.getHeader("User-Agent");//取得浏览器信息串进行分析
if (browser.indexOf("Firefox") != -1) { //根据不同的浏览器来加载不同的样式文件
System.out.println("Mozilla Firefox");
req.setAttribute("Browser", "");
} else if (browser.indexOf("MSIE 6.0") != -1) {
System.out.println("MSIE 6.0");
req.setAttribute("Browser", "");
} else {
System.out.println("MSIE");
req.setAttribute("Browser", "");
}
return arg0.invoke();
}
}
上面的代码原理很简单,就是分析了getHeader("User-Agent")返回的字串进行分析,但这种分析方法感觉很笨拙,希望大家有更好的判断方法可以给出,在这里我也向大家多多学习。
然后将结果赋予到request对象中,进便于前台显示。
下面配置了这个栏截器:
class="com.yue.interceptor.BrowserInterceptor">
/json.jsp
execute
上面对这个栏截器进行了配置,可以看到使用了includeMethods指定了哪些方法需要进行栏截处理,相当于白名单。
如果想指定哪些方法不被栏截,配置excludeMethods参数即可,多个方法名使用逗号分开。
JSP页面就简单了,只需在加载CSS的位置使用Struts2的标签进行输出即可:
需要注意的是,escape属性必须置为false,这是因为默认来说内容是转义的。