1. Filter的作用
过滤器是JavaWeb三大组件之一,它与Servlet很相似,但是过滤器是用来拦截请求的,而不是处理请求的,常用来实现权限管理的功能。
当用户请求某个Servlet时,会先执行部署在这个请求上的Filter,如果Filter“放行”,那么会继承执行用户请求的Servlet;如果Filter不“放行”,那么就不会执行用户请求的Servlet。
其实可以这样理解,当用户请求某个Servlet时,Tomcat会去执行Filter,而是否“放行”由Filter来决定。可以理解为,Filter来决定是否调用Servlet。当执行完成Servlet的代码后,还会继续执行Filter后面的代码。
2.Filter生命周期
容器启动时就创建Filter实例,先执行构造方法,然后执行init()方法,这两步是在容器创建时就已经执行了的。在此之后,每次拦截到需要过滤的请求都会执行doFilter()方法。在容器关闭时,执行destroy()方法。
public class GlobalFilter implements Filter {
public GlobalFilter() { //容器创建时执行
}
@Override
public void init(FilterConfig filterConfig) throws ServletException { //容器创建时执行
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { //拦截到请求时执行
}
@Override
public void destroy() { //容器销毁时执行
}
}
3.Filter的实现
3.1 Java代码
我们知道用户的会话信息是存在Session中的,所以权限管理时我们可以基于Session中保存的信息对于不同权限的用户进行不同的管理。这里我们主要研究doFilter方法即可:
- servletRequest类并没有直接获取Session的方法,我们可以将servletRequest强制转换为其父类HttpServletRequest,利用父类的getSession()方法来获取,并且新建一个对象用于存储用户信息;
- 根据用户信息进行判断其权限,并根据其权限决定是否“放行”;
- 若“放行”,则使用filterChain访问用户所请求的资源;若“拦截”,则将用户请求转发至特定页面(例如未登录情况下强行跳转至登录界面)。要注意的是,在请求转发后一定要添加return;,否则在请求转发完成后会顺序执行后续代码。
- 若登录页、注册页与过滤目录在同一目录下,必须将其排除在过滤名单之外,具体可以使用很多方法实现,这里用了indexOf函数来判断url中是否有某些页面的字段以将其排除。
具体代码示例如下:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
Object user = httpServletRequest.getSession().getAttribute("user");
String path = httpServletRequest.getRequestURI();
if (!(path.indexOf("/login.jsp") + path.indexOf("/register.jsp") + path.indexOf("/pleaselogin.jsp") > -1)) {
filterChain.doFilter(servletRequest, servletResponse);
return;
}
if (user == null) {
servletRequest.setAttribute("msg", "请先登录!");
// servletRequest.getRequestDispatcher("/pages/user/login.jsp").forward(servletRequest,servletResponse); //请求转发
httpServletResponse.sendRedirect("/test/pages/pleaselogin.jsp"); //页面重定向
return;
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
3.2 web.xml 配置
<filter>
<filter-name>GlobalFilter</filter-name> <!---过滤器名->
<filter-class>com.renhouse.filter.GlobalFilter</filter-class> <!---过滤器类->
</filter>
<filter-mapping> <!---配置需要过滤的页面->
<filter-name>GlobalFilter</filter-name>
<url-pattern>/pages/*</url-pattern>
<url-pattern>/houseServlet</url-pattern>
</filter-mapping>
以上仅为个人学习过程中的学习记录,在开发过程中会持续完善。若有理解错误的地方欢迎指正。