A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 白小托 中级黑马   /  2019-9-6 16:19  /  886 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Java web笔记
一、HTTP协议
HTTP(超文本传输协议),它是一种主流B/S架构中应用的通信协议。具有以下特点:

1、无状态

服务端不会记录客户端每次提交的请求,服务器一旦相应客户端之后,就会结束本次的通信过程。客户端下一次的请求是一个新的 连接,和上一次通信没有任何关系。

2、简单灵活

HTTP是基于请求(request)和响应(response)的模型

3、支持客户端与服务端

支持主流的B/S架构的通信以及C/S架构的通信。

注意:C/S架构可选的协议有多种,例如:TCP/IP,UDP,HTTP

​ 而B/S架构通常只支持HTTP协议

二、服务器
1、概念
服务器通常由硬件和软件部分构成,统一对用户提供多种不同的服务。

1、硬件:包括响应的CPU、内存、磁盘等等

2、软件:包括操作系统、运行环境、服务器软件、数据库等等

2、web服务器
web服务器是提供服务端程序运行的一个环境,它本身也是一个软件。

例如:将我们编写HTML文件放入到web服务器中,那么外界就可以通过浏览器访问我们的html页面

常见的web服务器有Apache,Tomcat、Jetty、Nginx等等。

而Tomcat、Jetty这些web服务器更准确的说是一个Servlet容器。

三、JavaWeb项目结构
项目根目录,例如:myweb、ch01                          通常存放静态资源文件(如:html等等)
        WEB-INF                 这个目录是当前项目私有的一个文件夹,只能提供给项目内部访问,对于客户端来说是访问不到了,通常这个目录下存放的是Java源代码、编译后的字节码文件以及Servlet的核心配置文件web.xml
                 src        存放java源代码的目录
                 classes        存放编译后的字节码文件
                 lib        lib目录存放当前项目所需要的jar文件
                 JSP        用于存放JSP动态页面
                 web.xml        项目的配置文件,用于配置Servlet的请求映射、过滤器、监听器等等信息。每一个web项目都对应一个web.xml配置文件
        META-INF                 配置应用程序、扩展程序、类加载服务等等
四、Servlet基础
1、什么是Servlet
Servlet是JavaEE中标准组件,专门用于处理客户端提交的HTTP请求。并且它必须依赖于Servlet容器才可以运行(Tomcat就是一个标准的Servlet容器),Servlet容器给Servlet提供一个运行环境,所以Servlet组件必须要这个环境中可以运行,而不能脱离这个环境而单独执行。因为Servlet的实例是由容器创建和销毁的,并不是通过我们平常使用的new关键创建出来。

2、开发一个Servlet的步骤
1.编写一个类,然后继承HttpServlet这个父类

2.重写父类的service方法,这个就是专门处理客户端请求的方法,这个方法有两个参数(HttpServletRequest,HttpServletResponse),同时这个方法会抛出两个异常(ServletException,IOException)

复制代码
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

//要让当前的类是一个Servlet,必须继承HttpServlet
public class HelloServlet extends HttpServlet{

     //重写父类的service方法,处理客户端请求,
     //这个方法私有servlet容器去调用,
     //并且request和response参数都是由servlet容器传递进来的
     public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         System.out.println("Hello Servlet");
         //响应一些信息回馈给客户端浏览器
         //1.设置要响应的类型,这里就响应简单的html文本类型
         //通过response参数来进行设置,如:text/html,text/plain
         response.setContentType("text/html;charset=utf-8");
         //2.获取输出流并写回html数据
         response.getWriter().println("<h1>Hello Servlet</h1>");
     }
}
复制代码



3.编译Servlet,需要依赖servlet-api.jar文件

4.编写web.xml,为servlet配置请求映射的URL

复制代码
<?xml version="1.0" encoding="utf-8"?>
<!-- 配置根节点 -->
<web-app>
   <!-- 配置servlet类 -->
   <servlet>
         <!-- 指定servlet的别名 -->
         <servlet-name>hello</servlet-name>
         <!-- 指定Servlet的完整类名-->
         <servlet-class>HelloServlet</servlet-class>
   </servlet>
   <!-- 配置请求映射-->
   <servlet-mapping>
          <!-- 这里的servlet-name和上面的servlet-name要一一对应 -->
         <servlet-name>hello</servlet-name>
         <!-- 配置请求映射的url,必须以“/”开头-->
         <url-pattern>/test</url-pattern>
   </servlet-mapping>
</web-app>
复制代码


5.将项目部署到Tomcat的webapps目录中

3、servlet处理请求的流程
1.浏览器发起http的请求,这个请求首先会被servlet容器(Tomcat)截获,然后容器会根据web.xml文件中配置servlet的<url-pattern>来找到相应的<servlet-name>这个别名,然后再根据这个别名找到具体Servlet的类,然后容器会创建这个Servlet类的实例并调用Servlet方法来处理这个请求。

请求网页地址: http://127.0.0.1:8080/ch02/test

4、Servlet的生命周期
所谓的生命周期,就是从Servlet的创建一直到它销毁的整个过程。并且它的 整个生命周期都是由Servlet容器(Tomcat)负责管理和维护的。(补充:在Tomcat中,Servlet是以单实例多线程的方式处理客户端请求)

4.1 Servlet对象创建的过程
当第一次请求某个Servlet的时候,容器会先查找之前有没有创建过这个Servlet的实例,如果没有则创建一个实例并缓存起来。后续 所有请求这个Servlet的时候,都会使用这个缓存的对象来处理客户端请求。(注意“这里说的是第一次请求时创建。另外一种情况则是在容器启动的时候就创建Servlet的实例,在web.xml中为Servlet指定<load-on-startup>配置,这个配置的值是一个整形,数值越小,则初始化 的优先级别越高)

4.2 生命周期方法
方法名        描述
init        在Servlet对象创建之后立即执行的初始化方法,且只执行一次
service        核心的请求处理方法,这个方法可以执行多次
destroy        容器准备销毁Servlet实例之前执行的方法,也是执行一次


5、HTTP请求报文
5.1 请求报文
请求行:请求报文的第一行就是请求行。包括请求方法、请求URL地址、HTTP协议版本

请求头:请求行之后的信息就是请求头,它是以“名称:内容”的格式体现。主要包括服务器主机地址及端口号、连接状态、接收的数据类型、编码、语言等等

请求体:请求头结束之后会有一个空行,空行之后就是请求体的内容。通常使用POST提交的数据信息会存放在请求体中,然后传递给服务器。

5.2 响应报文
状态行:主要包括HTTP协议、响应状态码(例如:200表示OK,成功响应)

响应头:主要包括服务器信息、响应的类型及编码、内容的长度、响应的时间等

响应体:服务器将信息携带到响应体中,带回客户端。

6、HTTP请求方法
在HTTP/1.1协议中,请求方法主要包括8个,下面列举常用的请求方法进行说明。

请求方法        说明
GET        向服务器请求指定的资源,并返回响应主体。一般来说GET方法应该只用于数据的读取(类似于查询)
POST        向指定的服务器提交数据(例如:表单数据的提交、文件上传等),并且提交的数据会放入请求体中(类似于新增)
PUT        向服务器提交数据,但是和POST有所区别。如果服务器不存在此资源的时候,则执行新增,如果存在则执行修改。(类似于修改)
DELETE        根据uri的表示删除服务器上的某个资源(类似于删除)
...        ...
备注:GET与POST区别:

1.GET主要用于获取数据,POST用于提交数据。

2.GET请求所带的参数是放在请求行的url地址后面,而POST这是放在请求体中。

3.通常浏览器会对GET请求的url长度有所限制 ,而POST通常在请求体中,可以提交更多的数据信息。

4.浏览器会对GET请求进行缓存。

7、Servlet的请求处理方法
方法        说明
service        可以处理任何的请求类型
doGet        处理对应的GET请求
doPOST        处理对应的POST请求
doPut        处理对应的PUT请求
doDelete        处理对应的DELETE请求
说明:通过HttpServlet的源代码得知,默认的所有请求都会先经过service方法,然后service方法根据请求的方法类型判断来决定交给doGet或者是doPOST方法来处理请求。如果子类重写了service方法同时还重写了其他的doXxx的方法,那么只有service方法会处理请求,其他方法将失效。

8、请求和响应对象
当web容器调用某个Servlet的Service方法时,会创建一个HTTPServletRequest和HTTPServletResponse对象作为参数传入到这个方法中,那么我们可以通过HTTPServletRequest来获取相关的请求内容等,而响应客户端可以利用HttpServletResponse对象来完成。

8.1 HttpServletRequest常用API
方法        说明
getParameter(String name)        获取请求参数的值,根据请求参数的name指定
getParameterValues(String name)        获取相同name的请求参数,返回的是字符串数组
getParameterMap()        获取所有请求参数,包括参数名称和值
getMethod()        获取请求方法的类型
getHeader(Stirng name)        根据请求头的名称获取响应的信息
getRemoteAddr()        获取远程客户端的IP地址
getServletPath()        获取Servlet的请求地址,也就是url-pattern
getRequestURL()        获取请求完整的URL地址
getRealPath(String path)        获取项目的绝对路径。(这个方法在request对象中已废弃,建议通过ServletContext对象获取)
其他        ...
复制代码
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        System.out.println("---------------获取参数值----------------");
        //获取请求参数,根据请求的参数名
        String name = request.getParameter("uname");
        String age = request.getParameter("age");
        System.out.println(name);
        System.out.println(age);
        //获取相同参数名的参数
        String[] addrs = request.getParameterValues("address");
        for (String addr : addrs) {
            System.out.println(addr);
        }
        System.out.println("--------------获取参数名---------------");
        //获取所有的参数名
        Enumeration<String> es = request.getParameterNames();
        //枚举使用迭代器来循环遍历
        while(es.hasMoreElements()) {
            String paramName = es.nextElement();
            System.out.println(paramName);
        }
        System.out.println("---------------获取所有的参数名和参数值-------------------");
        //map泛型的第一个参数表示请求的参数名称,第二个参数是请求的参数值,值可以有多个,所以是数组
        Map<String,String[]> map = request.getParameterMap();
        //map的key对应的是参数名,value就是参数的值
        for (String key : map.keySet()) {
            System.out.println("参数名:" + key);
            System.out.println("参数值: ");
            String[] values = (String[])map.get(key);
            for (String value : values) {
                System.out.println(value);
            }
            System.out.println("~~~~~~~~~~~");
        }
        System.out.println("-------------获取客户端的请求方法--------------");
        String method = request.getMethod();
        System.out.println("请求方法:" + method);
        System.out.println("--------------获取请求头部的信息---------------");
        String header = request.getHeader("Host");
        System.out.println("请求头信息:" + header);
        System.out.println("--------------获取远程客户端的IP地址--------------");
        String addr = request.getRemoteAddr();
        System.out.println("客户端的IP地址" + addr);
        System.out.println("------------获取Servlet的url-pattern---------------");
        String servletPath = request.getServletPath();
        System.out.println("url-pattern: " + servletPath);
        System.out.println("------------获取请求的完整URL---------------------------");
        String url = request.getRequestURL().toString();
        System.out.println(url);
        System.out.println("-------------获取项目的绝对路径------------------");
        String path = request.getServletContext().getRealPath("/");
        System.out.println(path);
    }
复制代码






8.2 HttpServletResponse常用API
方法        说明
setContentType(String str)        设置响应内容的类型及编码
getWriter()        获取响应字符输出流
getOutputStream()        获取字节输出流
setHeader(String name,String value)        设置响应头信息,如果存在响应头信息,则执行更新
addHeader(String name,String value)        设置响应头,不管存不存在都会新加入一个
setStatus(int code)        设置响应状态码
其他        ...
复制代码
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置响应的内容类型及编码,包括(text/html,text/plain,application/json)
        response.setContentType("text/html;charset=utf-8");
        //设置响应头信息
        response.addHeader("myheader", "hello header");
        response.addHeader("myheader", "my servlet");
        //设置响应的状态码
        response.setStatus(200);
        //获取字节输出流
        OutputStream os = response.getOutputStream();
        //获取响应的字符输出流
        PrintWriter pw = response.getWriter();
        pw.println("<html>");
        pw.println("<head><title>index</title></head>");
        pw.println("<body>");
        pw.println("<h3>Hello Servlet</h3>");
        pw.println("</body>");
        pw.println("</html>");
        
    }
复制代码





8.3 常见的响应状态码
状态码        说明
200        请求成功
401        禁止访问,未授权
404        找不到请求的资源
405        请求的行的方法不被支持
500        服务器内部错误
其他        ...




9、Servlet之间的通信
9.1 转发
所谓转发,就是在多个Servlet之间共享请求和响应对象,所有参与转发过程的Servlet都可以获取同一个请求对象的信息。在Servlet的API中,转发的操作是有HttpServletRequest对象完成的。

示例代码:

复制代码
public class ServletA extends HttpServlet{
   
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //获取页面提交的参数
        String name = request.getParameter("userName");
        
        //转发由HttpServletRequest完成
        //第一步先获取一个请求转发器RequestDispatcher
        //获取请求转发器的同时要告诉转发器转发到哪里,转发给谁
        //如果要转发给ServletB,那么就是对应ServletB的url-pattern
        RequestDispatcher rd = request.getRequestDispatcher("servletB");
        //调用转发器的forward方法执行转发,同时将request和response对象一并转发ServletB
        rd.forward(request, response);
        
    }
}
复制代码
复制代码
public class ServletB extends HttpServlet{

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
        //这里在同一个请求中再次获取页面的参数
        String name = request.getParameter("userName");
        System.out.println("ServletB获取请求参数:"+name);
    }
}
复制代码


转发的特点:

1、URL地址栏不会发生改变

2、转发的过程是在服务端自动完成

请求作用域:

每一个请求对象都有一个独立的空间,这个空间我们称之为请求作用域(RequestScope),可以为当前这个请求携带额外的一些数据信息,这些信息同样可以在多个Servlet之间进行共享。

示例代码:

复制代码
public class ServletA extends HttpServlet{
   
    public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        
        //在ServletA中为request对象设置请求作用域
        request.setAttribute("age", 35)
    }
}
复制代码
复制代码
public class ServletB extends HttpServlet{

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //在ServletB中获取统一个请求对象作用域的值域的值
        Integer age = (Integer)request.getAttribute("age");
    }
}
复制代码


9.2 重定向
重定向的机制和转发不同,一次重定向的过程中会有两次请求和两次响应,服务端在接收第一次请求后会先做一次302的响应(302表示重定向状态码),告诉客户端浏览器必须发起一个新的地址,服务端再次接收这个请求处理,最后再次响应客户端。





重定向特点:

1、URL地址栏会发生改变

2、重定向的操作是在客户端浏览器完成的

示例代码:

方式一:

复制代码
public class ServletC extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //执行重定向
        //方式一:设置302响应状态码,并在响应头中添加location属性指定重定向的地址
        response.setStatus(302);
        response.addHeader("location", "http://localhost:8080/ch06/servletD");
    }
}
复制代码


方式二:

复制代码
public class ServletC extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("请求到达ServletC");
        System.out.println("ServletC获取请求参数:"+request.getParameter("userName"));
        //执行重定向
        
        //方式二:使用response的sendRedirect方法
        response.sendRedirect("servletD");
    }
}
复制代码


10、会话跟踪


由于HTTP协议是无状态的,服务端并不会记录每一个客户端的状态,因此,如果想要实现服务器能记录客户端的状态的话,那么就需要会话跟踪技术。

10.1 cookie
cookie是客户端浏览器的内部的一个文本文件,专门用于记录服务器发送过来的一些文本信息,那么在每次请求的时候,客户端都把这个cookie信息由提交回给相应的服务器,那么服务器就可以获取cookie的信息,达到会话跟踪的目的。使用cookie的机制是基于客户端浏览器来维护与服务器的状态跟踪。





示例代码:

设置cookie

复制代码
public class SetCookieServlet extends HttpServlet{

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建一个Cookie的实例
        Cookie cookie = new Cookie("userId","10001");
        //将cookie对象设置到响应对象中
        response.addCookie(cookie);
        System.out.println("成功设置cookie");
    }
}
复制代码


获取cookie

复制代码
public class GetCookieServlet extends HttpServlet{

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse repsonse) throws ServletException, IOException {
        //cookie是通过request对象来得到的
        //从请求中可以获取多个cookie对象
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            //判断cookie,只获取name为userId的cookie对象
            if("userId".equals(cookie.getName())) {
                System.out.println(cookie.getValue());
            }
        }
    }   
}
复制代码




cookie保存中文:

在保存cookie的时候如果需要保存中文,那么中文信息需要经过编码后才可以写入cookIe

示例代码:

编码使用URLEncoder

String str=URLEncoder.encode("张三","utf-8");
Cookie cookie = new Cookie("userName",str);


解码使用URLDecoder

String str=URLDecoder.decode(cookie.getValue(),"utf-8");
System.out.println(str);




cookie的生命周期:

默认cookie只会保存在浏览器进程的内存中,并不会写入cookie文件,如果关闭了浏览器,那么浏览器的进程也就消失了,那么对应的内存就会释放空间,因此cookie的也就销毁。如果想将cookie写入文件,那么就必须设置cookie的生命时长,一旦设置了生命时长,那么就表示这个cookie会在文件中保留多长时间,到了这个时间之后,浏览器就会自动销毁这个cookie。

设置cookie存活时间:

复制代码
//设置为0表示立即删除cookie
cookie.setMaxAge(0);
//设置为正数表示cookie在cookie文件的存活时间,单位:秒
cookie.setMaxAge(5);
//设置为-1表示cookie只保留在浏览器的进程中,关闭浏览器之后会销毁cookie
cookie.setMaxAge(-1);
复制代码




10.2 Session
Session是基于服务端来保存用户的信息,这个是和cookie的最大区别。不同的客户端在请求服务器的时候,服务器会为每一个客户端创建一个Session对象并保存在服务器端,这个Session对象是每个客户端所独有的,相互之间不能访问。服务器为了区别不同的Session属于哪一个客户端,因此Session对象也有一个唯一标识,叫做SessionID。而这个SessionID是以cookie的机制保存在客户端浏览器。每次请求的时候,浏览器都会把这个SessionID带回服务端,服务端根据这个SessionID就可以找到对应的Session对象。

示例代码:

复制代码
public class SessionServlet extends HttpServlet{

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //HttpSession对象是在第一次调用request的getSession()方法时才会创建
        //注意:getSession()的方法会先判断之前是否为客户端创建了session实例,
        //如果创建了,则使用之前创建好的Session对象,没有则创建一个新的Session
        HttpSession session = request.getSession();
        //创建HttpSession的同时,会创建一个唯一的标识SessionID
        //这个sessionId会保存在浏览器的cookie中,每次请求会带回这个id找到相应的session对象
        String sessionId = session.getId();
        System.out.println(sessionId);
    }
}
复制代码


session的生命周期:

1. SessionId是保存在浏览器的cookie中,但是不会写入cookie文件,这也就表示当关闭浏览器之后SessionId就会销毁。SessionId销毁以后,服务端的Session就没有任何作用了。但是服务器并不会立刻销毁这个Session对象,至于什么时候销毁是由服务器自己决定的。除非我们手动调用了session.invalidate()方法,服务器就会立即销毁这个session实例。

示例代码:

HttpSession session=request.getSession();
//立即销毁session
session.invalidate();


2.Session默认也有存活时间,服务器在创建Session的时候为Session设置默认的存活时间为30分钟,如果在30分钟之内,客户端没有发起任何到服务器,那么服务器就会销毁这个Session对象。我们也可以设置Session的存活时间。可以为当前的Session设置,也可以为全局(服务器端的所有Session)的Session设置。

设置当前Session的存活时:

HttpSession session=request.getSession();
//设置当前Session的存活时间,单位:秒
session.setMaxInactiveInterval(3600);


设置 全局的Session的存活时间 :

在web.xml中进行设置

<!-- 设置全局Session的存活时间,单位:分钟 -->
<session-config>
    <session-timeout>60</session-timeout>
</session-config>


Session的作用域:

当我们需要将一些数据信息存入Session的时候,就需要操作Session作用域(SessionScope),它和请求作用域类似,也有相应setAttitude和getAttribute方法,只不过Session作用域的范围要比请求作用域更宽。请求作用域在一次请求响应只有就会消失(因为响应之后请求就会销毁)。而Session对象只要浏览器不关闭或者未超时,那么Session对象会一直驻留在服务器端,因此不管重新请求 多少次还是转发和重定向,都可以从Session中获取之前保存的数据信息。

示例代码:

复制代码
User user = new User();
user.setUid("1001");
user.setUserName("wangl");
HttpSession session = request.getSession();
//将数据保存在会话作用域中
session.setAttribute("user", user);
复制代码

从会话作用域取值

HttpSession session = request.getSession();
//取值
User user = (User)session.getAttribute("user");


URL重写:

浏览器是可以禁用cookie的,一旦禁用了cookie,那么SessionID将无法写入cookie的缓存中,这样就导致无法实现会话跟踪了,因此解决办法就是使用URL重写。URL重写的目的就是把SessionID放在请求URL地址的后面提交回服务器(类似GET请求后面带上参数,而这个参数就是一个SessionID),服务器会解析和这个URL的地址并得到SessionID。

示例代码:

//重写请求的URL地址,这个地址后面会自动带上SessionId
String url = response.encodeRedirectURL("getSession");
//重定向URL
response.sendRedirect(url);


浏览器地址演示

http://localhost:8080/ch07/getSession;jsessionid=6F1 BA8C92D7E5D7CC479ED8DD30D3ED0
注意:“;”后面跟着就是SessionID

11、Servlet上下文
web容器在启动时会为每一个web应用创建唯一的上下文对象,这个对象就是Servlet上下文对象(ServletContext),这个上下文对象可以理解为是当前项目的一个共享内存空间,为项目中的所有Servlet提供一个共享的区域。

常用API:

方法        说明
getContextPath()        获取项目的相对路径
getRealPath(String path)        获取项目的绝对路径
getInitParameter(String name)        获取上下文的初始化参数(web.xml中配置的)
setAttribute(String name, String value)        将数据放入上下文作用域
getAttribute(String name)        从上下文作用域中去获取数据
上下文作用域:

上下文作用域是为当前项目所有Servlet提供的一个共享内存区域,可以将需要的数据信息保存在作用域中。这个作用域的的范围是最大的,只要容器没有停止,它就会一直存在。

三种作用域:

结合前面所学的作用域,那么一共有三个,分别是:请求作用域,会话作用域,上下文作用域。

范围从小到大来划分:

请求作用域<会话作用域<上下文作用域

12、过滤器
过滤器可以在请求到达Servlet之前和Servlet响应客户端之前进行拦截,相当于一个拦截器,主要用于进行一些请求和响应的预处理操作。常用的场景有权限的控制、统一字符编码等等。





12.1 编写过滤器
要实现一个过滤器,必须实现一个Filter接口,只有实现了这个接口的类才称之为过滤器。

示例代码

public class DemoFilter implements Filter{
    ...
}


web.xml配置过滤器:

复制代码
<filter>
        <filter-name>demoFilter</filter-name>
        <filter-class>edu.nf.ch09.filter.DemoFilter</filter-class>
        <!-- 初始化参数 -->
        <init-param>
            <param-name>param</param-name>
            <param-value>hello</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>demoFilter</filter-name>
        <!-- 什么请求可以经过此过滤器,/*表示所有请求 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
复制代码




12.2 过滤器的生命周期
与Servlet类似,Filter同样也是有容器负责创建和销毁,与Servlet的区别在于,容器会在启动的时候最先创建所有的过滤器,并执行init方法进行初始化。

生命周期方法:

方法        说明
init        初始化方法,容器启动时执行一次
doFilter        请求过滤方法,决定请求是否放行
destroy        容器销毁过滤器之前执行的方法
示例代码:

复制代码
public class DemoFilter implements Filter{

    @Override
    public void destroy() {
        
        System.out.println("准备销毁DemoFilter");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        //FilterChain表示一个过滤链对象,因为过滤器可能会存在多个
        //同时这个对象将决定是否放行当前请求,
        //放行的话则请求会继续到达下一个过滤器或者servlet中
        System.out.println("请求经过DemoFileer..放行");
        chain.doFilter(request, response);
        System.out.println("响应前经过DemoFilter...");
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        String name = config.getInitParameter("param");
        System.out.println("初始化DemoFilter,获取初始化参数:"+name);
    }

}
复制代码




12.3 过滤链
在一个web项目中可能存在多个过滤器,当有多个过滤器存在的时候就会形成一个过滤链。请求会按照过滤器链的顺序一直传递下去,最终到达某个Servlet来处理请求。(注意:过滤链的顺序是按照web.xml中的先后配置顺序决定的)

配置示例:

复制代码
<!-- 按先后顺序配置 -->
    <!-- 配置第一个过滤器 -->
    <filter>
        <filter-name>firstFilter</filter-name>
        <filter-class>edu.nf.ch09.filter.FirstFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>firstFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    <!-- 配置第二个过滤器 -->
    <filter>
        <filter-name>secondFilter</filter-name>
        <filter-class>edu.nf.ch09.filter.SecondFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>secondFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
复制代码




13、监听器
监听器用于监听对象的上的事件发生,在Servlet中监听器主要监听请求对象、会话对象、上下文对象以及监听这些对象的作用操作。JavaEE为我们提供了一系列的监听器接口,开发时按需实现响应的接口即可。

13.1 监听作用域对象的创建于销毁
监听器        说明
ServletRequestListener        监听请求对象的创建和销毁
HttpSessionListener        监听会话对象的创建和销毁
ServletContextListener        监听Servlet上下文对象的创建和销毁

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马