1. 过滤器
在多个页面需要统一执行的代码,可以通过过滤器的 web 组件来完成
英文 Filter
1) 定义过滤器
@WebFilter(urlPattern="要过滤哪些路径")
class 过滤器类 implements Filter {
// 初始化操作
public void init() { }
// 销毁操作
public void destroy() { }
// 过滤方法 子类对象 子类对象 过滤器链
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain ) throws ... {
// 要统一执行的代码
//chain.doFilter(request, response); // 调用此方法,让请求继续前进
}
}
2) 过滤路径格式
- 精确匹配 /servlet1, 只会进入servlet1之前进入过滤器
- 后缀匹配 *.jsp , 只要请求的后缀是 jsp 结尾的,就会进入过滤器
- 前缀匹配 /user/* , 例如 /user/insert /user/update, 都会经过此过滤器
只要过滤器的路径与目标路径匹配,这个过滤器就会被执行,因此,在请求前进的过程中会经过多个过滤器
顺序和过滤器的名字有关, 按名字排序
3) request和response的类型转换
filter中的request,response 声明的是父类型,有些方法没有,需要转为子类型对象(实际就是子类对象,可以安全转换)
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse resp = (HttpServletResponse) response;
4) 过滤器的应用
-
post 请求的中文乱码,可以采用字符编码过滤器来解决
req.setCharacterEncoding(“解码字符集”);
req.getParameter() -
登录检查过滤器 (见 cookie和 session的代码)
/*
req.getRequestURI 排除一些特殊的路径/user/insert.jsp
重定向到 index.jsp 如果没有加/ 是相对路径
http://localhost:8080/user/index.jsp如果加了 / ,就是相对于主机名和端口号 也就是直接在路径前加 http://localhost:8080
结论:如果路径中有多层目录,建议以 / 写一个完整路径
-
cookie 自动登录过滤器
在 LoginServlet 中登录成功后,补充代码
// 如果勾选了 自动登录
String autoLogin = req.getParameter("autoLogin");
if(autoLogin != null && autoLogin.equals("true")) {
Cookie cookie = new Cookie("up", username + ":" + password);
cookie.setMaxAge(24 * 3600);
resp.addCookie(cookie);
}
在 LoginFilter 过滤器中补充代码:
// 找到 up cookie
Cookie[] cookies = req.getCookies();
Cookie up = null;
for(Cookie c : cookies) {
if (c.getName().equals("up")) {
up = c;
break;
}
}
if(up != null) {
String[] split = up.getValue().split(":");
String name = split[0];
String password = split[1];
// 验证cookie 用户名密码是否正确
User user = userDao.findByUsername(name);
if(user!=null && user.getPassword().equals(password)) {
// 正确了,向 session中存入登录标记并放行
req.getSession().setAttribute("username", username);
chain.doFilter(req, resp);
return;
}
}
在注销时:
// 删除 自动登录 cookie
Cookie up = new Cookie("up", "");
up.setMaxAge(0);
resp.addCookie(up);
2. 监听器
Listener 没有路径,特定事件发生时,会执行监听器代码
-
ServletRequestListener 在请求对象初始化和销毁时
-
HttpSessionListener 在 session 对象创建后和销毁时
-
ServletContextListener application 对象创建和销毁时
-
ServletRequestAttributeListener 请求中作用域变量发生改变时
-
HttpSessionAttributeListener session 中作用域变量发生改变时
-
ServletContextAttributeListener application 中作用域变量发生改变时
-
HttpSessionActivationListener 在session 钝化(内存存入磁盘)和活化(从磁盘恢复到内存)
session 中存储对象,对象要实现 Serializable 接口 -
HttpSessionBindingListener