1.Servlet中filter的执行流程可以依照web.xml中的filter配置进行顺序执行。我们知道web.xml中元素执行的顺序 context-param->listener->filter->servlet。
且无论这类元素摆放位置如何,都是遵循这个原则的。
下面看个例子
web.xml的配置:
<!-- 编码过滤器 -->
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 一个简单的sevlet读取init参数的配置 -->
<servlet>
<servlet-name>helloworld</servlet-name>
<servlet-class>com.company.strutstudy.web.servletstudy.servlet.HelloWorldServlet</servlet-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>helloworld</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!--禁用浏览器缓存的过滤器 -->
<filter>
<filter-name>nocachefilter</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>nocachefilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
执行结果:
before encoding utf-8 filter!
cache do the before!
doservice...UTF-8
doget...
dopost...
cache do the after!
after encoding utf-8 filter!
ps:servlet在filter配置之前,那filter也会进行执行,且在servlet之前。
2.在struts2中配置执行filter,经过debug源码发现,一旦这个filter配置在struts2的filterDispatcher后面,在filterDispatcher中的dofilter中会自动过滤掉该filter。
web.xml的配置:
<!-- 编码过滤器 -->
<filter>
<filter-name>setCharacterEncoding</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.EncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>setCharacterEncoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 加载struts2核心 -->
<filter>
<filter-name>StrutsFilter</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>packages</param-name>
<param-value>com.company.strutstudy.web.action</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>StrutsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--禁用浏览器缓存的过滤器 -->
<filter>
<filter-name>nocachefilter</filter-name>
<filter-class>com.company.strutstudy.web.servletstudy.filter.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>nocachefilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
EncodingFilter源码:
public class EncodingFilter implements Filter {
private String encoding;
private Map<String, String> params = new HashMap<String, String>();
// 项目结束时就已经进行销毁
public void destroy() {
System.out.println("end do the encoding filter!");
params=null;
encoding=null;
}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
//UtilTimerStack.push("EncodingFilter_doFilter:");
System.out.println("before encoding " + encoding + " filter!");
req.setCharacterEncoding(encoding);
// resp.setCharacterEncoding(encoding);
// resp.setContentType("text/html;charset="+encoding);
chain.doFilter(req, resp);
System.out.println("after encoding " + encoding + " filter!");
System.err.println("----------------------------------------");
//UtilTimerStack.pop("EncodingFilter_doFilter:");
}
// 项目启动时就已经进行读取
public void init(FilterConfig config) throws ServletException {
System.out.println("begin do the encoding filter!");
encoding = config.getInitParameter("encoding");
for (Enumeration e = config.getInitParameterNames(); e
.hasMoreElements();) {
String name = (String) e.nextElement();
String value = config.getInitParameter(name);
params.put(name, value);
}
}
}
Struts2中的FilterDipatcher中的doFilter方法源码:
/**
* 当执行完编码Filter后,filter链表对象filterchain会执行其后的配置的filterDispatcher,随后执行该filter的dofilter方法。
*/
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
ServletContext servletContext = getServletContext();
String timerKey = "FilterDispatcher_doFilter: ";
try {
UtilTimerStack.push(timerKey);
request = prepareDispatcherAndWrapRequest(request, response);
ActionMapping mapping;
try {
//得到存储Action信息的ActionMapping对象,actionMapper被注入,如何被注入待研究
mapping = actionMapper.getMapping(request, dispatcher.getConfigurationManager());
} catch (Exception ex) {
LOG.error("error getting ActionMapping", ex);
dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
return;
}
if (mapping == null) {//如果这个请求是action请求,那么这里得到的mapping不会是null
// there is no action in this request, should we look for a static resource?
String resourcePath = RequestUtils.getServletPath(request);
if ("".equals(resourcePath) && null != request.getPathInfo()) {
resourcePath = request.getPathInfo();
}
//如果请求的资源以/struts开头,则当作静态资源处里
if (serveStatic && resourcePath.startsWith("/struts")) {
findStaticResource(resourcePath, findAndCheckResources(resourcePath), request, response);
} else {
//否则继续往下传,知道没有filter为止
// this is a normal request, let it pass through
chain.doFilter(request, response);
}
// The framework did its job here
return;
}
//得到存储Action信息的ActionMapping对象
dispatcher.serviceAction(request, response, servletContext, mapping);
} finally {
try {
ActionContextCleanUp.cleanUp(req);
} finally {
UtilTimerStack.pop(timerKey);
}
}
}
NoCacheFilter的源码:
public class NoCacheFilter implements Filter{
public void destroy() {
}
public void doFilter(ServletRequest req,
ServletResponse res, FilterChain chain)
throws IOException, ServletException {
/*
并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头。
Expires数据头:值为GMT时间值,为-1指浏览器不要缓存页面
Cache-Control响应头有两个常用值: no-cache指浏览器不要缓存当前页面;
ax-age:xxx指浏览器缓存页面xxx秒。
*/
HttpServletResponse hres=(HttpServletResponse) res;
hres.setDateHeader("Expires",-1);
hres.setHeader("Cache-Control","no-cache");
hres.setHeader("Pragma","no-cache");
System.out.println("cache do the before!");
chain.doFilter(req, res);
System.out.println("cache do the after!");
}
public void init(FilterConfig config) throws ServletException {
}
}
执行结果:
before encoding utf-8 filter!
do action!
after encoding utf-8 filter!