其实在Web应用中Filter对大家来说一点都不陌生,比如说在我之前项目的架构中,就使用filter做过Session是否失效、设定页面字符集、设置本地化,如:
设定本地化的Filter代码:
Cookie cookie = WebUtil.getCookie(req, INFOSYSCoreStatics.LOCALE_KEY); Locale locale = null; if(cookie == null){ locale =request.getLocale(); }else{ new Locale(cookie.getValue(), ""); } if (locale != null) { WebUtil.setLocale(req, res, locale); }
设定字符集的Filter代码:
if (encoding == null) encoding = DEFAULT_ENCODING; request.setCharacterEncoding(encoding); response.setContentType("text/html;charset=" + encoding); } // Pass control on to the next filter chain.doFilter(request, response);
好了,不多举例了,毕竟这不是本篇文章的重点,下面我们看看在Restlet里面是如何使用Filter,当然了,这两个Filter名称一样,却不是同一个东西。
我们知道,Restlet类有个handle方法:
@Override public void handle(Request request, Response response) { init(request, response); }
当Restlet类或者其子类被请求调用执行时,此方法就会被调用。Filter也是Restlet的子类,所以,上述规则同样适用于Filter。同样的,看看Filter里面的handle的方法:
@Override public final void handle(Request request, Response response) { super.handle(request, response); switch (beforeHandle(request, response)) { case CONTINUE: switch (doHandle(request, response)) { case CONTINUE: afterHandle(request, response); break; default: // Stop the processing break; } break; case SKIP: afterHandle(request, response); break; default: // Stop the processing break; } }
这个方法里面调用了另外两个方法beforeHandle和afterHandle:
protected int beforeHandle(Request request, Response response) { return CONTINUE; }
protected void afterHandle(Request request, Response response) { // To be overriden }
代码简单清晰,简要的说明一下,handle方法里,beforeHandle首先会被执行,当然如果我们创建我们自己的Filter,会覆盖这个方法,加入一些自己的逻辑代码,比如判断当前请求的是否是正确的资源,客户端IP是否是在允许的范围内?等,如果通过校验,则会返回CONTINUE. 接下来会执行我们设定的资源类,资源类执行结束,则会执行afterHandle方法。
下面我们就给出一个例子,在Filter里检查资源是否正确以及IP是否在允许的范围内:
public class CommonFilter extends Filter { private static String[] unprotectedResources = {"scripts", "styles", "images", "html"}; protected void beforeHandle(Request request, Response response) { String path = request.getResourceRef().getPath(); if (isProtectedResource(path)) { String ip = request.getClientInfo().getAddress(); try { //check whether the ip is allowed if (ip is invalid) { response.setStatus(Status.CONNECTOR_ERROR_CONNECTION); } }catch (Exception ex) {} } } private boolean isProtectedResource(String path) { for (int i = 0; i < unprotectedResources.length; i++) { if (path.indexOf(unprotectedResources[i]) == 1) { return false; } } return true; } }
搞定Filter,那么如何使用呢?还记得我们是怎么组装Guard吗?忘记了或者没有看到之前系列的文章,可以看这里
我们首先在Spring配置文件中加入Filter的定义:
<bean id="commonFilter" class="com.mycompany.restlet.filter.CommonFilter"/>
假设,系统需要先进行安全验证,然后进行过滤,则完整配置应该是:
<bean id="component" class="org.restlet.ext.spring.SpringComponent"> <property name="defaultTarget" ref="guard" /> </bean> <bean id="guard" class="com.mycompany.restlet.filter.CustomerGuardFilter"> <property name="next" ref="commonFilter"/> <property name="secretResolver" ref="customerResolver"/> </bean> <bean id="commonFilter" class="com.mycompany.restlet.filter.CommonFilter"> <property name="next" ref="restRoute"/> </bean> <bean id="customerResolver" class="com.mycompany.restlet.filter.CustomerResolver"/>
这样,如果安全验证通过以后,过滤器就会生效。