过滤器监听器
过滤器概念
过滤器: 过筛子,符号条件的过去,不符号条件不能过去.
比喻: 安检,检查安全的人物通过
程序: 客户端需要访问的目标资源,在客户端和资源之间设置过滤器,
符号要求放行
实现过滤器程序
实现步骤
- 定义类,实现接口Filter
- 重写抽象方法
- web.xml配置 (注解)
public class MyFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器 Myfilter");
//放行,允许访问目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
<!--
过滤器配置
和Servlet配置的方式基本一致
-->
<filter>
<filter-name>my</filter-name>
<filter-class>com.itheima.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>my</filter-name>
<!--
url-pattern配置的是,过滤器需要过滤的资源
/* 过滤WEB应用下的所有资源
-->
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器的执行过程
过滤器的生命周期
- 过滤器对象的创建,是Tomcat服务器启动
- init(FilterConfig config)过滤器对象被创建的时候调用,FilterConfig 对象tomcat引擎创建
- 过滤器执行过滤的方法,过滤被访问资源的时候,必须是被过滤器过滤器的资源
- doFilter(request,response)
- 过滤器对象销毁的方法,销毁之前调用,服务器关闭
- destroy()
过滤器的配置
- 完全匹配
<!--
过滤资源,只有Servlet2
绝对匹配 <url-pattern/servlet2></url-pattern>
只能过滤指定的资源
-->
<url-pattern>/servlet2></url-pattern>
- 目录匹配
<!--
目录匹配,过滤器中最常见
/abc/* 过滤abc目录下的所有资源
一次过滤一片资源
过滤后台资源 /admin/*
-->
<url-pattern>/abc/*</url-pattern>
- 后缀名匹配
<!--
后缀名匹配,一般不使用
*.jsp 访问所有jsp文件
-->
拦截方式
有了上面学习的映射路径,我们可以控制过滤器过滤指定的内容,但是我们在访问资源的时候,并不是每次都是之
间访问,有时是以转发的方式访问的,这就需要我们要让过滤器可以区分不同的访问资源的方式,有不同的拦截方
式。
- dispatcher:访问的方式
- REQUEST:默认值,代表直接访问某个资源时执行filter
- FORWARD:转发时才执行filter
格式:
@WebFilter(urlPatterns="/*",dispatcherTypes={DispatcherType.REQUEST,DispatcherType.FORWARD})publicclassMyFilter1implementsFilter{
//...
}
注解配置过滤器
@WebFilter(urlPatterns="/过滤资源")
过滤器的执行顺序
web.xml配置
和配置文件的编写顺序决定运行的顺序,准确的说法是,根据mapping的顺序决定
注解开发
注解开发没有配置文件的
按照类名的自然顺序决定: A-B-C
如果存在配置文件,配置文件优先
过滤器处理中文乱码
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//在过滤器中,设置request对象的编码表
servletRequest.setCharacterEncoding("utf-8");
//设置response缓冲区的编码表,通知浏览器的解码
servletResponse.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
权限校验
支付前进行登录的校验
@WebFilter(filterName = "Filter7", urlPatterns = "/pay")
public class LoginFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
/*
从session 中 ,获取用户的信息
必须 先将 req 进行强制转换, 转换成子类类型
*/
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
HttpSession session = request.getSession();
// 获取 session 中键值对 , 来验证是否登录过
Object user = session.getAttribute("userLogin");
// 如果 不为 null ,说明 登录过 , 放行
if (user != null){
chain.doFilter(req, resp);
}else {
// 如果为null , 说明 没登录, 重定向
response.sendRedirect("/web14/login.jsp");
}
}
LoginServlet
@WebServlet(urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 获取用户名和密码
String username = request.getParameter("username");
String password = request.getParameter("password");
// 将用户信息 保存 session 中
HttpSession session = request.getSession();
session.setAttribute("userLogin" , username+"_"+password );
// 回写
response.getWriter().println("登录成功");
}
}
监听器
监听器监听某个组件变化的对象. 事件源是固定的,主要是request,session,servletcontext域对象
监听的是域对象变化, 对象的创建和销毁, 域对象中存储的数据变化
第一个维度划分: 监听的域对象request,session,servletcontext
第二个维度划分: 监听的域对象的状态
ServletContext监听器入门
ServletContextListener:用于监听ServletContext域的创建与销毁的监听器
- 应用场景:服务器启动时,加载配置信息
- ServletContext域的生命周期
- 何时创建:服务器启动创建
- 何时销毁:服务器关闭销毁
- 作用范围:整个web应用
实现步骤
- 创建类实现监听器接口 ServletContextListener
- 重写抽象方法
- web.xml配置(注解)
@WebListener
public class MyServletContextListener implements ServletContextListener {
@Override
/**
* ServletContext对象,被创建,调用
*/
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象创建");
}
@Override
/**
* ServletContext对象,被销毁前调用
*/
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("ServletContext域对象销毁");
}
}
<listener>
<listener-class>com.itheima.listener.MyServletContextListener</listener-class>
</listener>
监听器事件对象ServletContextEvent
/**
* ServletContext对象,被创建,调用
* ServletContextEvent方法参数: 域对象的事件对象
* 此对象有tomcat引擎创建ServletContext
* servletContextEvent方法: 获取到被监听的事件源
* Object getSource() 获取到被监听的事件源
* ServletContext getServletContext()获取到被监听的事件源
* 除了返回值外,功能实现是一致的
* 设计目的为了通用性
* 其他的监听器事件对象,共同的方法 getSource()
*/
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext context = (ServletContext) servletContextEvent.getSource();
System.out.println(context);
ServletContext servletContext = servletContextEvent.getServletContext();
System.out.println(servletContext);
System.out.println("ServletContext域对象创建");
}
Servlet抽取
对于一个商品数据,基本的功能4个,增删改查询
问题: Servlet会越来越多
处理Servlet过多的问题,代码量少,维护性增强
基本抽取
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取提交的参数
String md = request.getParameter("method");
//判断参数,调用不同的方法
if("login".equals(md)){
login(request,response);
}else if("register".equals(md)){
register(request,response);
}else if("updatePassword".equals(md)){
updatePassword(request,response);
}else if("loginOut".equals(md)){
loginOut(request,response);
}
}
//登录 login
public void login(HttpServletRequest request, HttpServletResponse response){
System.out.println("用户选择登录");
}
//注册 register
public void register(HttpServletRequest request, HttpServletResponse response){
System.out.println("用户选择注册");
}
//修改密码 updatePassword
public void updatePassword(HttpServletRequest request, HttpServletResponse response){
System.out.println("用户选择修改密码");
}
//退出 loginOut
public void loginOut(HttpServletRequest request, HttpServletResponse response){
System.out.println("用户选择退出登录");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
基本抽取优化(反射)
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String md = request.getParameter("method");
//换一个思考方式: 不写if 使用反射
//反射,获取方法执行 md方法名
Class clazz = this.getClass();
//获取方法
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
//执行方法,对象,实际参数
method.invoke(this,request,response);
}catch (Exception ex){ex.printStackTrace();}
}
BaseServlet抽取
public abstract class BaseServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String md = request.getParameter("method");
//换一个思考方式: 不写if 使用反射
//反射,获取方法执行 md方法名
Class clazz = this.getClass();
//获取方法
Method method = clazz.getMethod(md, HttpServletRequest.class, HttpServletResponse.class);
//执行方法,对象,实际参数
method.invoke(this,request,response);
}catch (Exception ex){ex.printStackTrace();}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
sponse.class);
//执行方法,对象,实际参数
method.invoke(this,request,response);
}catch (Exception ex){ex.printStackTrace();}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}