一.过滤器
1.1 过滤器概述
过滤器主要用来拦截目标资源(静态资源或动态资源)的请求和响应
(类似地铁的安检)
我们访问动态或静态资源都要通过URL访问:http://localhost:8080/...
所以过滤器本质上拦截的是URL
1.2 过滤器使用步骤
a.新建一个类,这个类需要实现java.servlet.Filter,这个类就成为了一个拦截器
b. 在web.xml中配置这个过滤器类,还需要配置这个过滤器类拦截那些URL
/**
* 将一个类实现Filter接口,那么这个类就成为一个过滤器类
*/
public class FilterDemo01 implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("拦截器完成初始化");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("filterDemo01开始执行"+servletRequest+"..."+servletResponse);
filterChain.doFilter(servletRequest,servletResponse); //放行该请求
System.out.println("filterDemo01结束执行"+servletRequest+"..."+servletResponse);
}
@Override
public void destroy() {
System.out.println("拦截器被销毁");
}
}
<!-- 注册(配置)一个过滤器 -->
<filter>
<filter-name>filterDemo01</filter-name>
<filter-class>filter01.FilterDemo01</filter-class>
</filter>
<filter-mapping>
<filter-name>filterDemo01</filter-name>
<!--表示过滤器拦截哪些请求 /* 表示拦截所有请求与响应-->
<url-pattern>/*</url-pattern>
</filter-mapping>
1.3 单个过滤器原理
过滤器与被拦截目标资源使用的都是同一个request和response对象
Tomcat创建request对象和response对象==>过滤器,doFilter(request,resposne)方法 中形参==>servlet中doPost(request,resposne)中形参
1.4 多个过滤器执行原理
根据在web.xml中的匹配情况以及过滤器的注册先后顺序决定多个过滤器的拦截先后顺序
1.5 过滤器生命周期
/**
* Filter接口中的方法:
* void init(FilterConfig filterConfig):初始化过滤器方法
*
* void destroy():销毁过滤器方法
*
* void doFilter(ServletRequest request, ServletResponse response, FilterChain chain):拦截到指定的资源时候执行
*
* 1.当服务器启动的时候,就初始化web.xml中配置的过滤器
* 2.当访问被拦截的目标资源时候,就执行doFilter()方法中的第一句
* 执行目标资源
* 执行chain.doFilter(request,response)下面的语句
* 3.关闭tomcat的时候会销毁这个过滤器
*/
/**
* FilterConfig可以用来获取在过滤器中配置的初始化参数
* String getInitParameter(String name):根据参数名获取参数值
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println(request.getServletContext().getFilterRegistration("filterDemo02").getInitParameter("charset"));
}
<filter>
<filter-name>filterDemo02</filter-name>
<filter-class>filter01.FilterDemo02</filter-class>
<init-param>
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterDemo02</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
1.6 过滤器拦截路径配置
a.完全路径匹配
/aa:只有/aa路径的时候才被拦截
/aa/bb:只有访问/aa/bb路径时候,才会被拦截
b.模糊路径匹配
/*: * 匹配所有,/aa,/bb,/aa/bb,/aa/index.jsp,/aa/1.html... 都会被拦截
/aa/*: 访问/aa/bb,/aa/cc,/aa/bb/cc...都会被拦截
c.扩展名匹配
*.jsp:访问index.jsp,register.jsp,....才会被拦截
*.html:访问1.html,2.html,....才会被拦截
1.7 过滤器的注解式开发
/**
* @WebFilter属性:
* initParams:配置过滤器一些初始化参数 对应web.xml中 <init-param>
* filterName:配置过滤器名称 对应web.xml <filter-name>
* servletNames:配置拦截指定名称的Servlet 根据<servlet-name>去拦截指定的servlet
* *urlPatterns(value):配置过滤器拦截哪些路径
*/
1.8 过滤器解决全局乱码案例
@WebFilter(filterName = "FilterDemo03", urlPatterns = "/*", initParams =
@WebInitParam(name = "charset", value = "UTF-8"))
public class FilterDemo03 implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
String charset = request.getServletContext().getFilterRegistration("FilterDemo03").getInitParameter("charset");
//设置request和response的字符集
request.setCharacterEncoding(charset);
response.setContentType("text/html;charset="+charset);
chain.doFilter(request, response);
}
}
1.9 自动登录案例(基于http://t.csdnimg.cn/47Ao1进行进一步优化)
loginServlet.java
@WebServlet("/loginServlet")
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取表单传过来的参数,并将参数封装为对象
String username = request.getParameter("username");
String password = request.getParameter("password");
//将用户输入的用户名和密码封装成User对象
User user = new User(username, password);
//最终在数据库中查询到的 User对象
User finalyUser = UserServlet.getFinalyUser(user);
//判断finalyUser,若为空,则在数据库中查询不到,登录失败,反之登录成功
if (finalyUser!=null) {
request.setAttribute("statusCode", 100);
request.setAttribute("msg", "登录成功");
//将正确的user用户信息存储在session域中,当重启浏览器后,session的值将会清空
request.getSession().setAttribute("user", finalyUser);
//登录成功,将用户信息存储在cookie域中,以便实现自动登录, 设置生命周期后,cookie重启浏览器之后还能继续存在
String autoLogin = request.getParameter("autoLogin");
System.out.println(autoLogin);
if (autoLogin != null && autoLogin.equals("remember-me")) {
Cookie cookie = new Cookie("successUser", finalyUser.getUsername() + "#" + finalyUser.getPassword());
cookie.setMaxAge(7 * 24 * 60 * 60);
response.addCookie(cookie);
}
}else {
request.setAttribute("statusCode",101);
request.setAttribute("msg","用户名或密码错误");
//将来在页面回显用户输入的错误信息,方便用户进行修改
request.setAttribute("user",user);
}
//转发到login页面,与login页面公用相同的request,response对象,方便回显信息
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
autoLoginFilter.java
@WebFilter(filterName = "autoLoginFilter", value = "/*")
public class autoLoginFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
User user = (User) req.getSession().getAttribute("user");
if (user != null) {
chain.doFilter(req, res);
} else {
Cookie cookie = CookieUtils.getCookie("successUser", req.getCookies());
if (cookie == null) {
chain.doFilter(req, res);
} else {
String[] split = cookie.getValue().split("#");
User finalyUser = UserServlet.getFinalyUser(new User(split[0], split[1]));
if (finalyUser == null) {
chain.doFilter(req, res);
} else {
req.getSession().setAttribute("user", finalyUser);
chain.doFilter(req, res);
}
}
}
}
}
二.监听器
2.1 监听器概述
监听器主要用来监听某个对象状态变化
2.2 监听器分类
a.监听对象的创建和销毁
ServletRequestListener:监听Request对象的创建和销毁
HttpSessionListener:监听Session对象创建和销毁
ServletContextListener:监听ServletContext对象创建和销毁
b.监听域中属性变化(属性值修改,属性创建,属性删除)
ServletRequestAttributeListener
HttpSessionAttributeListener
ServletContextAttributeListener
2.3 监听器使用步骤
a.新建一个类,需要实现监听器接口
b.在web.xml中注册这个监听器
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext被创建");
}@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext被销毁");
}
}
<listener>
<listener-class>listener01.MyServletContextListener</listener-class>
</listener>
2.4 注解方式注册监听器
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext被创建");
}@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext被销毁");
}
}