日期:2014-05-17  浏览次数:20551 次

使用Struts2拦截器实现根据不同浏览器加载CSS

目前在写一个项目由于需要兼顾多浏览器(主要还是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", "<link rel='stylesheet' href='Style/Site.css'>");
		} else if (browser.indexOf("MSIE 6.0") != -1) {
			System.out.println("MSIE 6.0");
			req.setAttribute("Browser", "<link rel='stylesheet' href='Style/Site_IE6.css'>");
		} else {
			System.out.println("MSIE");
			req.setAttribute("Browser", "<link rel='stylesheet' href='Style/Site.css'>");
		}
		return arg0.invoke();
	}

}

?

上面的代码原理很简单,就是分析了getHeader("User-Agent")返回的字串进行分析,但这种分析方法感觉很笨拙,希望大家有更好的判断方法可以给出,在这里我也向大家多多学习。

然后将结果赋予到request对象中,进便于前台显示。

下面配置了这个栏截器:

?

	<package name="default" extends="json-default">
		<interceptors>
			<interceptor name="browser"
				class="com.yue.interceptor.BrowserInterceptor">
			</interceptor>
		</interceptors>
		<action name="ajax" class="com.yue.action.AjaxAction">
			<result name="success">/json.jsp</result>
			
			<interceptor-ref name="defaultStack"></interceptor-ref>
			<interceptor-ref name="browser">
                           <!-- 这里定义了栏截的方法名,我只需栏截execute方法,别的方法不要栏截 -->
                           <param name="includeMethods">execute</param>
			</interceptor-ref>
		</action>
	</package>

?

上面对这个栏截器进行了配置,可以看到使用了includeMethods指定了哪些方法需要进行栏截处理,相当于白名单。

如果想指定哪些方法不被栏截,配置excludeMethods参数即可,多个方法名使用逗号分开。

JSP页面就简单了,只需在加载CSS的位置使用Struts2的标签进行输出即可:<s:property value="#request.Browser" escape="false"/>

需要注意的是,escape属性必须置为false,这是因为默认来说内容是转义的。