欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > 文章正文

JavaWeb,Tomcat(Apa

来源: javaer 分享于  点击 4561 次 点评:221

JavaWeb,Tomcat(Apa


JavaWeb

什么是JavaWeb?

  • JavaWeb就是指所有通过Java语言编写可以通过浏览器访问的程序的总称;
  • 一个JavaWeb程序由多个静态web资源和动态资源组成,web程序开发完成后,若要被外界访问,就要把web应用所在的目录交给web服务器管理(虚拟目录的映射);
  • JavaWeb是基于请求和响应来开发的;

静态Web

  • 指任何时候访问的内容都一致的Web界面,没有交互;
  • 静态资源:html、CSS、js、txt、mp4...

动态Web

  • 只访问内容随时间改变的Web界面,有交互,一般是与数据库交互;
  • 动态资源:jsp页面、Servlet程序...

什么是请求和响应?

请求

  • 请求是指客户端向服务器发送数据,Request;

响应

  • 响应是指服务器给客户端返回数据,Response;

请求和响应是成对出现的,有请求就有响应;

常用的Web服务器

Web服务器主要用来接收客户端发送的请求和响应客户端的请求;

  1. Web服务器主要用来接收客户端发送的请求和响应客户端请求。

  2. Tomcat(Apache)( 我们主要撸这只猫 ):当前应用最广的JavaWeb服务器;

  3. JBoss(Redhat红帽):支持JavaEE,应用比较广EJB容器 –> SSH轻量级的框架代替

  4. GlassFish(Orcale):Oracle开发JavaWeb服务器,应用不是很广;

  5. Resin(Caucho):支持JavaEE,应用越来越广;

  6. Weblogic(Orcale):要钱的!支持JavaEE,适合大型项目;

  7. Websphere(IBM):要钱的!支持JavaEE,适合大型项目

Tomcat服务器

安装教程:

目录介绍

  • backup:存放配置文件,是在第一次运行了Tomcat服务器之后产生的,和conf目录下的内容基本一致;
  • bin:存放Tomcat服务器的可执行程序,核心包;
  • conf:存放Tomcat服务器的配置文件;
  • lib:存放Tomcat服务器的jar包;
  • logs:存放Tomcat服务器运行时输出的日记信息;
  • temp:存放Tomcat服务器运行时产生的临时数据;
  • webapps:存放部署的Web工程,里面的一个文件夹就是一个Web工程;
  • work:是Tomcat工作时的目录,用来存放Tomcat运行时jsp翻译为Servlet的源码,和Session钝化的目录;

启动Tomcat服务器

  1. 找到Tomcat安装目录下的bin目录下的startup.bat文件,双击即可启动Tomcat服务器;
  2. cmd命令行下,进入bin目录下,输入catalina run回车,即可启动;

启动Tomcat一闪而过问题解决:检查JDK的环境配置

测试Tomcat服务器是否开启成功

  • 在浏览器中输入以下地址进行测试:
    • http://localhost:8080
    • http://127.0.0.1:8080
    • http://真实IP:8080

关闭Tomcat服务器

  1. 右上角X号;
  2. 快捷键Ctrl+C;
  3. Tomcat的bin目录下的shutdown.bat,双击;

修改Tomcat的端口号

  1. 找到Tomcat目录下的conf目录下的server.xml配置文件;
  2. 找到Connector标签,port就是端口号设置,修改它;

  • Tomcat默认的端口号是8080;
  • HTTP协议默认的端口号是:80;

将web工程部署到Tomcat服务器上

  • 将Web工程拷贝到Tomcat安装路径的webapps目录中

    • 访问Tomcat中的web工程:浏览器中输入http://ip:port/工程名/目录名/文件名
  • 找到Tomcat安装目录中的conf目录下的Catalina目录下的localhost下,创建配置文件XXX.xml

    • <!-- 文件内容:
      	Context 表示一个工程上下文
      	path 表示工程的访问路径:/abc
      	docBase 表示你的工程目录在哪里-->
      <Context path="/abc" docBase="E:\book" />
      
    • 访问Tomcat中的web工程:浏览器中输入http://ip:port/abc/ 就代表进入到了E:\book目录下,先要继续访问book文件中的信息,就继续/输入

手托html页面到浏览器与在浏览器输入框http://ip:port:工程名/访问的区别

地址栏的默认访问

  • 浏览器地址栏如果输入http://ip:port/ 没有工程名,默认访问的就是Tomcat中的webapps目录下的ROOT工程
  • 浏览器地址栏中输入http://ip:port/工程名/ 没有资源名,默认访问的就是该工程下的index.html文件

部署在IDEA或者eclipse上

https://blog.csdn.net/weixin_44775516/article/details/109522779

Web工程的目录介绍

  • src:存放java代码;
  • web:存放web工程的资源文件,html、css...
  • WEB-INF:是一个受服务器保护的目录,浏览器无法直接访问到此目录中
  • lib:存放第三方jar包,jar包需要配置
  • web.xml:是整个动态web工程的配置部署文件,可以配置Servlet程序、Filter过滤器、Listener监听器、Session超时...组件

Web 中的相对路径和绝对路径

  • 相对路径是:

    • . 表示当前目录
    • .. 表示上一级目录
    • 资源名 表示当前目录/资源名
  • 绝对路径:

    • http://ip:port/工程路径/资源路径

web 中/ 斜杠的不同意义

  • 在web中,/斜杠是一种绝对路径
  • /斜杠在浏览器中被解析,地址是:http://ip:port/
    • <a href="/">斜杠</a>
  • / 斜杠如果被服务器解析,得到的地址是:http://ip:port/工程路径
    • <url-pattern>/servlet1</url-pattern>
    • servletContext.getRealPath(“/”);
    • request.getRequestDispatcher(“/”);
  • 特殊情况: response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到http://ip:port/

Servlet

什么是Servlet?

  • Servlet(Server Applet),全称Java Servlet;
  • Servlet是JavaEE规范之一,就是接口,是用java编写的服务端程序;
  • Servlet是JavaWeb三大组件之一,都有:Servlet程序、Filter过滤器、Listener监听器;
  • Servlet是运行在服务器上的一个Java小程序,它可以接受客户端发送过来的请求,并响应数据给客户端;

第一个Servlet程序

  1. 编写一个类要实现Servlet接口
  2. 实现接口中的service()方法,用于处理请求与响应数据
  3. 在web.xml中配置Servlet程序的访问地址

这种方式一般不使用,我们继承他的实现类HttpServlet

JAVA代码:

public class Servlet1 implements Servlet {
    @Override//初始化
    public void init(ServletConfig servletConfig) throws ServletException {
    }
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    /**
     * service方法是用来专门处理请求和响应的
     * @param servletRequest
     * @param servletResponse
     * @throws ServletException
     * @throws IOException
     */
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override//销毁
    public void destroy() {
    }
}

web.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
     <!--welcome-file-list标签是当Tomcat服务启动时,默认跳到哪个资源,
    其实这个不用设置,默认也会跳转到index.html或者index.jsp资源的
    -->
    <welcome-file-list>
        <!--welcome-file标签就是要跳转的资源-->
        <welcome-file>HolleWord.html</welcome-file>
    </welcome-file-list>
    
    <!--service标签是给Tomcat配置Servlet程序的 -->
    <servlet>
        <!--servlet-name标签是给Servlet程序起一个别名-->
        <servlet-name>Servlet1</servlet-name>
        <!--servlet-class标签是Servlet程序的全类名-->
        <servlet-class>com.mlyr.Servlet1</servlet-class>
    </servlet>
    <!--servlet-mapping标签给Servlet程序配置访问地址-->
    <servlet-mapping>
        <!--servlet-name标签的作用是告诉服务器,当前配置的地址给谁用-->
        <servlet-name>Servlet1</servlet-name>
        <!--
            url-pattern标签配置访问地址
            /  在服务器解析时,会被解析为http://ip:port/工程名
            /servlet1表示地址为:http://ip:port/工程名/servlet1
        -->
        <url-pattern>/servlet1</url-pattern>
    </servlet-mapping>
</web-app>

URL地址到Servlet程序的访问

Servlet的生命周期

  1. 第一步:执行Servlet构造器方法;
  2. 第二步:执行init()初始化方法;
  3. 第三步:执行service()方法;
  4. 第四步:执行destroy()销毁方法;

第一部与第二步,只在第一次访问,创建Servlet程序的时候会执行;

第三步,每次访问Servlet程序的时候都会执行;

第四步,只当web工程停止的时候,会执行;

GET、POET请求的分发处理

  • getMethod():可以获取请求过来的方式,是GET请求还是POST请求
 @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //类型转换,HttpServletRequest有getMethod()方法,
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //可以获取请求的方式
        String method = request.getMethod();
        //将不同的请求,分为两个方法,分别处理
        if (method.equals("GET")){
            doGet();
        }else if (method.equals("POST")){
            doPost();
        }
    }
    private void doPost() {
        System.out.println("POST请求");
    }
    private void doGet() {
        System.out.println("GET请求");
    }

主要类与方法

HttpServlet类

  • 一般实现Servlet程序,都是使用继承HttpServlet类的方式来开发;
  • 它在Servlet接口的基础上,分开了请求方式,还有一系列方法;
  1. 编写一个类继承HttpServlet类
  2. 重写它的doGet()、doPost()方法;
  3. 到web.xml文件中配置Servlet程序的访问地址

HttpServlet类的方法:

  • doPost():处理post请求;
  • doGet():处理get请求;

java代码

public class Servlet2 extends HttpServlet {
    /**
     * 只有在post请求时调用
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("HelloServlet2 doPost 方法");
    }

    /**
     * 只有在get请求时调用
     * @param request
     * @param response
     * @throws ServletException
     * @throws IOException
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("HelloServlet2 doGet 方法");
    }
}

web.xml文件配置

<servlet>
    <servlet-name>Servlet2</servlet-name>
    <servlet-class>com.mlyr.Servlet2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>Servlet2</servlet-name>
    <url-pattern>/servlet2</url-pattern>
</servlet-mapping>

html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="servlet2" method="post">
    <input type="submit">
</form>
</body>
</html>
  • 当表单请求是post方法,只会调用Servlet2类中的doPost()方法!

IDEA中能够一键生成Servlet程序:右击包->点击NEW->Create New Servlet(在下面找)->Name框(自定义类名)

根据IDEA版本不同,会注解声明访问地址或者web.xml文件中声明

@WebServlet(name="Servlet3",urlPatterns = "/servlet3")这就是注解声明访问地址,idea自动生成的有问题,要自行修改

Servlet类的继承体系

ServletConfig类

  • ServletConfig类是Servlet程序的配置信息类;
  • Servlet程序和ServletConfig对象都是由Tomcat负责创建的,Servlet程序是第一次访问的时候创建,ServletConfig是每个Servlet程序创建时,就创建一个对应的ServletConfig对象;

ServletConfig类的作用

  • 可以获取Servlet程序的别名,就是servlet-name标签中的值;
  • 获取初始化参数init-param标签中的值;
    • init-param标签只能在servlet标签中定义,它只属于它所在的Servlet程序;
    • 只能被ServletConfig对象获取;
  • 获取ServletContext对象;

ServletConfig类中的方法:

  • getServletName():获取web.xml配置文件中servlet-name标签的值;
  • getInitParameter(参数):获取init-param标签中的值;
    • 参数:param-name标签
    • 获取到param-value标签的值,这两个标签好比键值对
  • getServletContext():返回ServletContext对象;

web.xml文件配置

<servlet>
    <servlet-name>Servlet2</servlet-name>
    <servlet-class>com.mlyr.Servlet2</servlet-class>
    <!--init-param标签是初始化参数,这个只属于Servlet2程序中的,别的程序访问不到-->
    <init-param>
        <!--参数的名字-->
        <param-name>username</param-name>
        <!--参数的值-->
        <param-value>root</param-value>
    </init-param>
    <init-param>
        <!--参数的名字-->
        <param-name>password</param-name>
        <!--参数的值-->
        <param-value>123456</param-value>
    </init-param>
</servlet>
<servlet-mapping>
    <servlet-name>Servlet2</servlet-name>
    <url-pattern>/servlet2</url-pattern>
</servlet-mapping>

Java代码

public class Servlet2 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //获取Servlet程序的别名,就是servlet-name标签的值
        System.out.println(servletConfig.getServletName());
        //获取初始化参数,init-param标签中的
        System.out.println("username:"+servletConfig.getInitParameter("username"));
        System.out.println("password:"+servletConfig.getInitParameter("password"));
        //获取ServletContext对象
        System.out.println(servletConfig.getServletContext());
    }
}

上方的是实现了Servlet接口,init()方法自然会重写Servlet接口中的方法;

下方:如果继承了HttpServlet类,它的父抽象类GenericServlet中有两个init()方法,一个是从接口Servlet中实现的有参方法,还有一个无参init()方法是独有的,如果自定义的类要重写HttpServlet类中的init()有参方法,一定要调用super.init(config);不然会在使用ServletConfig对象的时候会报500错误(内部服务器错误),空指针异常;

ServletContext类

  • ServletContext是一个接口,表示Servlet上下文对象;
  • 一个web工程只有一个ServletContext对象;
  • ServletContext对象是一个域对象;
    • 域对象,是可以像Map一样存取数据的对象;
存数据 取数据 删除数据
Map put() get() remove()
域对象 setAttribute() getAttribute() removeAttribute()
  • ServletContext在web工程启动的时候创建,在web工程停止的时候销毁;

ServletContext类的作用

  • 获取web.xml中配置的上下文参数context-param标签;
    • context-param标签是不能在servlet标签中的,只能在最外面,属于整个web工程,不单单只属于哪一个Servlet程序;
    • 只能被ServletContext对象获取;
  • 获取当前工程路径
  • 获取工程部署后在服务器硬盘上的绝对路径;
  • 像Map一样存取数据;

ServletContext类中的方法

  • getInitParameter(参数):获取context-param标签中的数据;
  • getContextPath():获取当前工程的路径;
  • getRealPath(参数):获取工程部署后在服务器硬盘上的绝对路径;
    • 参数/: 斜杠在服务器上会被解析为http://ip:port/工程名/ 就是映射到IDEA代码的web目录
    • sc.getRealPath("/img"):表示获取该工程下的img目录在工程部署后在服务器硬盘上的绝对路径;
  • setAttribute(别名,对象):将一个对象存储到ServletContext对象中,起个别名;
  • getAttribute(别名):通过别名获取存入其中的对象;
  • removeAttribute(别名):删除该别名中的对象;

web.xml文件配置

<!--context-param是上下文参数,属于整个web工程,都能访问到-->
<context-param>
    <!--param-name与param-value是存储数据的标签-->
    <param-name>name</param-name>
    <param-value>ROOT</param-value>
</context-param>
<context-param>
    <param-name>PSW</param-name>
    <param-value>123</param-value>
</context-param>

Java代码

public class Servlet4 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取ServletContext 对象
        ServletContext sc = getServletContext();
        //获取web.xml中配置的上下文参数,context-param标签中的数据
        System.out.println("name:"+sc.getInitParameter("name"));//name:ROOT
        System.out.println("PSW:"+sc.getInitParameter("PSW"));//PSW:123
        //获取当前的工程路径
        System.out.println("当前工程路径"+sc.getContextPath());//当前工程路径/JavaWeb_4
        //获取工程部署后在服务器硬盘上的绝对路径
        //   / 斜杠在服务器上会被解析为http://ip:port/工程名/   就是映射到IDEA代码的web目录
        System.out.println("工程部署的路径是:"+sc.getRealPath("/"));//工程部署的路径是:E:\IDEA\JavaWeb_4\out\artifacts\JavaWeb_4_war_exploded\
        System.out.println("工程下img目录的绝对路径是:"+sc.getRealPath("/img"));//工程下img目录的绝对路径是:E:\IDEA\JavaWeb_4\out\artifacts\JavaWeb_4_war_exploded\img
        System.out.println("工程下img目录下的1.jpg文件的绝对路径是:"+sc.getRealPath("/img/1.jpg"));//工程下img目录下的1.jpg文件的绝对路径是:E:\IDEA\JavaWeb_4\out\artifacts\JavaWeb_4_war_exploded\img\1.jpg

        // 获取ServletContext 对象
        ServletContext context = getServletContext();
        System.out.println(context);
        System.out.println("保存之前:获取key的值是:"+ context.getAttribute("key"));//保存之前:获取key的值是:null
        //在key中存储一个对象
        context.setAttribute("key", "value");
        System.out.println("存储之后:获取域数据key的值是:"+ context.getAttribute("key"));//存储之后:获取域数据key的值是:value
        //删除key里面存储的对象
        context.removeAttribute("key");
        //上面的删除了key里面的对象,下面将获取不到
        System.out.println("存储之后:获取域数据key的值是:"+ context.getAttribute("key"));//存储之后:获取域数据key的值是:null

    }
}

这个上面的工程路径是IDEA整合Tomcat之后,Tomcat被拷贝的一些副本内容,就是将IDEA实际存在的项目,映射进Tomcat服务器中;

setAttribute存储的对象,要先存进去,然后整个web工程中所有Servlet程序才能够访问到,没有存储到ServletContext对象中,是获取不到的;

HttpServletRequest类

  • 每次只要有请求进入Tomcat服务器,Tomcat服务器就会把请求过来的HTTP协议信息解析好封装到Request对象中,然后传递到service方法(doGet、doPost方法)中供我们使用;
  • 通过HTTPServletRequest对象,可以获取所有请求的信息;

HTTPServletRequest类的方法

  • getRequestURI() 获取请求的资源路径
  • getRequestURL() 获取请求的统一资源定位符(绝对路径)
  • getRemoteHost() 获取客户端的ip 地址
  • getHeader(参数) 获取请求头
    • 参数:要获取的请求头名称
  • getMethod() 获取请求的方式GET 或POST
  • getParameter(参数) 获取请求的参数
    • 参数:要请求哪一个参数的值
  • getParameterValues(参数) 获取请求的多个参数
    • 参数:要请求哪一个参数的值
  • setAttribute(别名,对象) 将对象作为request对象的一个属性存放到request对象中;
    • 别名:String类型,就相当于request对象中的一个属性,自己起名;
    • 对象:Object类型
  • getAttribute(别名) 获取request对象中该别名的值(这个值可以是任何类型)
  • getRequestDispatcher(参数) 获取请求转发对象
    • 参数:就是要转发给谁
  • getRequestDispatcher(参数).forward(request,response) 转发

java代码

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取请求的资源路径
  System.out.println("URI:"+request.getRequestURI());//URI:/JavaWeb_4/servlet5
    //获取请求的统一资源定位符(绝对路径)
  System.out.println("URL:"+request.getRequestURL());//URL:http://localhost:8080/JavaWeb_4/servlet5
    //获取客户端的ip 地址
    //IP:0:0:0:0:0:0:0:1      客户端localhost:8080访问,这个是ipv6的表现形式,对应ipv4来说相当于127.0.0.1
    //IP:192.168.137.1        使用真实IP地址访问
    //IP:127.0.0.1            客户端127.0.0.1:8080访问
    System.out.println("IP:"+request.getRemoteHost());
    //获取请求头
    System.out.println("User-Agent请求头"+request.getHeader("User-Agent"));//User-Agent请求头Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36
    System.out.println("Accept-Language请求头"+request.getHeader("Accept-Language"));//Accept-Language请求头zh-CN,zh;q=0.9
    //获取请求的方式GET 或POST
    System.out.println(request.getMethod());//GET
    ////////////////////////////////////////////////////////////////
    //获取请求参数,就是获取表单提交过来的参数值
    System.out.println("用户名:"+request.getParameter("username"));//用户名:MLYR
    System.out.println("密码:"+request.getParameter("password"));//密码:123
    //获取请求的多个参数
    String[] hobby = request.getParameterValues("hobby");
    System.out.println("兴趣爱好:"+ Arrays.toString(hobby));//兴趣爱好:[java, js]
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //设置请求的字符集编码为UTF-8,如果不设置,输入中文会乱码
    req.setCharacterEncoding("UTF-8");
    //获取当前请求的字符编码,需要提前设置,不然是null
    System.out.println(req.getCharacterEncoding());//UTF-8
    //获取请求参数,就是获取表单提交过来的参数值
    System.out.println("用户名:"+req.getParameter("username"));//用户名:中
    System.out.println("密码:"+req.getParameter("password"));//密码:1212
    //获取多个请求的参数
    String[] hobby = req.getParameterValues("hobby");
    System.out.println("兴趣爱好:"+ Arrays.toString(hobby));//兴趣爱好:[cpp, java]
}

表单代码

<form action="servlet5" method="get">
    用户名:<input type="text" name="username"><br/>
    密码:<input type="password" name="password"><br/>
    兴趣爱好:<input type="checkbox" name="hobby" value="cpp">C++
    <input type="checkbox" name="hobby" value="java">Java
    <input type="checkbox" name="hobby" value="js">JavaScript<br/>
    <input type="submit">
</form>

doGet()请求一般不会乱码,如果有,按照下面的方法解决:

String username = request.getParameter("username");
//先以iso-8859-1进行编码,再以utf-8进行解码
username = new String(username.getBytes("iso-8859-1"),"UTF-8");
//获取请求参数,就是获取表单提交过来的参数值
System.out.println("用户名:"+username);

HttpServletResponse类

  • HttpServletResponse类和HttpServletRequest类一样,每一次请求进来,Tomcat服务器都会创建一个Response对象和Request对象;
  • HttpServletResponse表示所有的响应信息,HttpServletRequest表示请求过来的信息;
  • 要返回给客户端信息,都是通过Response对象进行设置;

两个输出流

  • getOutputStream() 字节流,常用于下载,传递二进制;
  • getWriter() 字符流,常用于回传字符串
  • 两个流不能同时使用;

HttpServletResponse类的方法

  • setContentType() 同时设置服务器和客户端的编码格式
  • setCharacterEncoding() 设置服务器的编码格式
  • setStatus(参数) 设置响应状态吗,表示重定向
  • setHeader() 通过响应头设置浏览器的编码格式
  • getWriter() 获取字符输出流对象PrintWriter
    • writer(参数) 写数据,参数可以是Object、int、String、数组、double...
  • getOutputStream() 获取字节输出流对象ServletOutputStream
    • print(参数) 写数据,,参数可以是int、String、数组、double...不能写对象
  • sendRedirect(参数) 重定向
    • 参数:要重定向的路径

java代码

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //它会同时设置服务器和客户端都使用UTF-8 字符集,还设置了响应头
    //此方法一定要在获取流对象之前调用才有效
    response.setContentType("text/html; charset=UTF-8");
    //设置服务器字符集为UTF-8
    response.setCharacterEncoding("UTF-8");
    //通过响应头,设置浏览器也使用UTF-8 字符集
    response.setHeader("Content-Type", "text/html; charset=UTF-8");
    //CharConversionException: 不是ISO 8859-1字符:[啦]
    System.out.println("doGet方法");
    //获取字符输出流对象
    //PrintWriter writer = response.getWriter();
    //写数据
    //writer.println("啦啦啦lll");
    //获取字节输出流对象
    ServletOutputStream os = response.getOutputStream();
    //写数据
    os.print(121212121);
}   

java.lang.IllegalStateException: 当前响应已经调用了方法getOutputStream()

两个流一起使用报错

请求转发与重定向

请求转发

  • 服务器收到请求后,从一次资源跳转到另一个资源的操作,叫做请求转发;

表单

<form action="servlet6" method="post">
    信息:<input type="text" name="xinxi"><br/>
    <input type="submit">
</form>

Servlet6

@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    //设置请求的字符集编码
    req.setCharacterEncoding("UTF-8");
    //获取请求参数
    String xinxi = req.getParameter("xinxi");
    System.out.println(xinxi);//陌路邑人
    //设置数据域,就是将一个对象放进数据域中,起个别名key
    req.setAttribute("key","来自Servlet6");
    //获取要转发给的地址对象(一般与下面执行转发是一步编写)  /servlet7就是http://localhost:8080/JavaWeb_4/servlet7
    RequestDispatcher rd = req.getRequestDispatcher("/servlet7");
    //执行转发操作
    rd.forward(req,resp);
}

Servlet7

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //doPost方法中,必须是POST请求,才能被获取
    //获取请求参数
    String xinxi = request.getParameter("xinxi");//陌路邑人
    System.out.println(xinxi);
    //获取Servlet6转发过来的对象
    Object key = request.getAttribute("key");
    System.out.println("Servlet7获取到Servlet6转发过来的对象:"+key);//Servlet7获取到Servlet6转发过来的对象:来自Servlet6
}

表单中的提交是post请求方式,所以在两个Servlet程序中,想要获取表单提交的数据,必须也是doPost方法进行获取;

a标签的转发

web工程下d.html

<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<!--下方的可以与HTML下的e.html互相跳转-->
<a href="HTML/e.html">b.html</a>
<!--该标签跳转到servlet7程序配置的路径上-->
<a href="servlet7">请求转发</a>
</body>

HTML下e.html

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!--base 标签设置页面相对路径工作时参照的地址href 属性就是参数的地址值-->
    <base href="http://localhost:8080/JavaWeb_4/HTML/e.html">
</head>
<body>
    <a href="../d.html">回到首页</a>
</body>

Servlet7

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("经过了Servlet7程序");
    //如果有请求到这,进行转发到HTML下的e.html
  request.getRequestDispatcher("/HTML/e.html").forward(request,response);
}

这种情况没有base标签给e.html进行参照路径的话,他就会报错,找不到文件;

下面解释:

  1. 当首先访问web工程下的d.html文件时,它的绝对路径是http://localhost:8080/JavaWeb_4/d.html;
  2. 当点击请求转发连接时,他就会跳到Servlet7程序所配置的路径上:http://localhost:8080/JavaWeb_4/servlet7;
  3. 然后当点击回到首页连接时,它相当于将a标签中的../d.html路径与他现在所在的路径进行拼接跳转,就会跳转到http://localhost:8080/JavaWeb_4/d.html(http://localhost:8080/JavaWeb_4/servlet7../d.html,../相当于与前面的目录相抵消)路径,当然找不到文件;
  4. 当base标签给e.html文件给定一个绝对路径http://localhost:8080/JavaWeb_4/HTML/e.html,就是该文件的绝对路径,不管怎么与a标签上的../d.html进行拼接,他就可以找到正确的路径

重定向

  • 请求重定向,是指客户端给服务器发送请求后,返回服务器给客户端一个新地址,让客户端重新去访问新地址;

java代码

//Servlet9 
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    System.out.println("来晚了");
        /*request.setAttribute("kk","KKKKKK");
        //第一种重定向方式
        //设置响应状态吗,表市重定向
        response.setStatus(302);
        //设置响应头,说明新地址
        response.setHeader("Location","servlet8");*/
    //第二种重定向,参数不能加/斜杠,这里的/会被服务器解析为http://localhost:8080/
    response.sendRedirect("servlet8");
}
//Servlet8
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    System.out.println("Servlet8doGet方法");
    //重定向不共享Request对象中的数据域
    System.out.println(req.getAttribute("kk"));
}

转发与重定向的区别

  • 路径区别
    • 相对路径没有区别;
    • 绝对路径:
      • 转发:中的/表示:http://ip:port/工程路径;
      • 重定向:中的/表示:http://ip:port/;
  • 地址栏的变化
    • 转发:地址栏不会显示出转发后的地址;
    • 重定向:则是完全跳转到新地址,地址栏也就是新地址;
  • Request对象中的数据
    • 转发:不会丢失数据;
    • 重定向:会丢失数据;
  • 请求次数
    • 转发:客户端只向服务器发送一次请求;
    • 重定向:客户端发送了两次请求给服务器;
  • 跳转位置
    • 转发:在服务器中跳转;
    • 重定向:返回给客户端新地址,客户端跳转;
  • 访问域
    • 转发:只能在web工程中访问跳转;
    • 重定向:可以跨域访问跳转;就是随便跳;
  • 能否访问web工程的WEB-INF目录
    • 转发:可以访问;
    • 重定向:不可以访问;

监听器

什么是监听器?

  • Listener监听器是JavaWeb的三大组件之一;
  • 作用:监听某种事物的变化,然后通过回调函数,反馈给客户;

ServletContextListener监听器

  • ServletContextListener 它可以监听ServletContext 对象的创建和销毁
  • ServletContext 对象在web 工程启动的时候创建,在web 工程停止的时候销毁。
  • 监听到创建和销毁之后都会分别调用ServletContextListener 监听器的方法反馈
public interface ServletContextListener extends EventListener {
//在ServletContext 对象创建之后马上调用,做初始化
public void contextInitialized(ServletContextEvent sce);
//在ServletContext 对象销毁之后调用
public void contextDestroyed(ServletContextEvent sce);
}

如何实现ServletContextListener监听器监听ServletContext对象

public class Listener1 implements ServletContextListener{
    //ServletContext对象在创建的时候执行
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext对象创建了");
    }
    //ServletContext对象在销毁的时候被执行
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext对象销毁了");
    }
}
<!--配置监听器-->
<listener>
    <listener-class>com.mlyr.listener.Listener1</listener-class>
</listener>

ServletContextListener监听器的主要作用

  • 初始化工作:初始化对象,初始化数据,比如加载数据库驱动,对连接池的初始化。
  • 加载一些初始化的配置文件;

Cookie

什么是Cookie?

  • Cookie 是一小段文本信息,伴随着用户请求和页面在 Web 服务器和浏览器之间传递。Cookie 包含每次用户访问站点时 Web 应用程序都可以读取的信息;

为什么需要Cookie?

  • 因为HTTP协议是无状态的,对于一个浏览器发出的多次请求,WEB服务器无法区分是否来源于同一个浏览器;
  • 所以,需要额外的数据用于维护会话;Cookie正是这样一段随HTTP请求一起被传递的额外数据;

Cookie的注意点

能不能一次发送多个Cookie?

  • 可以,可以创建多个Cookie对象,使用response调用多次addCookie方法发送即可;

Cookie能不能存中文?

  • 在Tomcat8之前不能存中文,要进行URL编码(%E3)或者BASE64编码将中文数据转码
  • 在Tomcat8之后支持中文数据,但是特殊字符还是不支持;

Cookie大小限制

  • 浏览器对于单个cookie 的大小有限制(4kb) 以及 对同一个域名下的总cookie数量也有限制(20个)

Cookie的创建、获取、修改

html页面

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="pragma" content="no-cache" />
    <meta http-equiv="cache-control" content="no-cache" />
    <meta http-equiv="Expires" content="0" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Cookie</title>
    <base href="http://localhost:8080/JavaWeb_4/">
    <style type="text/css">
        ul li {
            list-style: none;
        }
    </style>
</head>
<body>
<iframe name="target" width="500" height="500" ></iframe>
<div >
    <ul>
        <li><a href="cookie1?action=createCookie" target="target">Cookie的创建</a></li>
        <li><a href="cookie1?action=getCookie" target="target">Cookie的获取</a></li>
        <li><a href="cookie1?action=updateCookie" target="target">Cookie值的修改</a></li>
        <li>Cookie的存活周期</li>
        <li>
            <ul>
                <li><a href="cookie1?action=defaultLife" target="target">Cookie的默认存活时间(会话)</a></li>
                <li><a href="cookie1?action=deleteNow" target="target">Cookie立即删除</a></li>
                <li><a href="cookie1?action=life3600" target="target">Cookie存活3600秒(1小时)</a></li>
            </ul>
        </li>
        <li><a href="cookie1?action=testPath" target="target">Cookie的路径设置</a></li>
        <li><a href="" target="target">Cookie的用户免登录练习</a></li>
    </ul>
</div>
</body>
</html>

java代码

package com.mlyr.Cookie;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class Cookie1 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 {
        response.setCharacterEncoding("UTF-8");
        String action = request.getParameter("action");
        switch (action){
            case "createCookie":
                createCookie(request,response);
                break;
            case "getCookie":
                getCookie(request,response);
                break;
            case "updateCookie":
                updateCookie(request,response);
                break;
        }
    }
// Cookie的创建
    protected void createCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //创建Cookie对象
        Cookie cookie1 = new Cookie("key1", "value1");
        Cookie cookie2 = new Cookie("key2", "value2");
        //保存到客户端
        response.addCookie(cookie1);
        response.addCookie(cookie2);
        //返回信息给客户端页面
        response.getWriter().write("Cookie创建成功{Cookie1:"+cookie1+"-->Cookie2:"+cookie2+"}");
    }
// Cookie的获取
    protected void getCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通过请求获取客户端中的Cookie数组
        Cookie[] cookies = request.getCookies();
        for (Cookie cookie : cookies) {
            //getName():获取到Cookie的key值
            //getValue():获取到Cookie的value值
            response.getWriter().write("key=="+cookie.getName()+"-->value=="+cookie.getValue()+"\n");
        }
        Cookie key1 = CookieUtils.findCookie("key1", cookies);
        String value = key1.getValue();
        response.getWriter().write("key1=="+value);
    }
// Cookie的修改
    protected void updateCookie(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //第一种方式:直接创建一个新的Cookie对象,key值与要修改的一样,直接覆盖掉原来的
        Cookie cookie = new Cookie("key1", "我改了");
        response.addCookie(cookie);
        //第二种方式:先找到要修改的Cookie对象,调用setValue()方法修改值
        Cookie key2 = CookieUtils.findCookie("key2", request.getCookies());
        if (key2!=null){
            //修改
            key2.setValue("人傻了");
            //通知客户端
            response.addCookie(key2);
        }else {
            System.out.println("没找到");
        }
    }
}

查找Cookie

import javax.servlet.http.Cookie;
// Cookie工具类
public class CookieUtils {
    public static Cookie findCookie(String name,Cookie[] cookies ){
        //判断当名字、Cookie数组任意一个为null时,就没有必要查询了
        if (name == null || cookies == null || cookies.length ==0){
            return null;
        }
        //循环遍历Cookie数组
        for (Cookie cookie : cookies) {
            //当name与cookie中的key值相同就返回它
            if (name.equals(cookie.getName())) {
                return cookie;
            }
        }
        return null;
    }
}

Cookie的生命周期

  • setMaxAge(int seconds):这个方法就是设置Cookie的保存时间的方法;
    • 正数:要保存的时间秒数,将Cookie数据写到硬盘中;
    • 负数:默认值,当浏览器关闭,Cookie数据被销毁;
    • 零:删除Cookie信息;
//Cookie的立即删除
private void deleteNow(HttpServletRequest request, HttpServletResponse response) throws IOException {
    Cookie key3 = CookieUtils.findCookie("key3", request.getCookies());
    if (key3!=null){
        key3.setMaxAge(0);
        response.addCookie(key3);
        response.getWriter().write("Key3已经删除!!!");
    }
}
//保存3600秒
private void life3600(HttpServletRequest request, HttpServletResponse response) throws IOException {
    Cookie key4 = new Cookie("key4", "3600");
    //设置保存key4的时间
    key4.setMaxAge(60*60);
    response.addCookie(key4);
    response.getWriter().write("Key4已经设置保存时间1小时");
}

Cookie的共享设置

  • 默认的Cookie只能在一个应用中共享,即一个Cookie只能由创建它的应用获得。
  • setPath():设置cookie的共享范围;
    • cookie.setPath("/"):可在同一应用服务器内共享方法
    • cookie.setPath(request.getContextPath()+"/HTML");只在该工程的HTML下共享,别的目录下获取不到
private void testPath(HttpServletRequest request, HttpServletResponse response) throws IOException {
    Cookie cookie = new Cookie("key5", "有效路径");
    cookie.setPath(request.getContextPath()+"/HTML");
    response.addCookie(cookie);
    response.getWriter().write("创建了一个带有路径的cookie");
}

免输入用户名登录

java代码

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //获取到请求进来的用户名与密码
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    //先给定一个死的值
    if ("111111".equals(username) && "111111".equals(password)){
        //将请求进来的用户名放入Cookie对象中
        Cookie cookie = new Cookie("username",username);
        //设置它的保存时间
        cookie.setMaxAge(60*60*60);
        //返回给客户端
        response.addCookie(cookie);
        System.out.println("登陆成功");
    }else{
        System.out.println("登录失败");
    }
}

jsp页面

  • jap页面中的用户名输入框中的value值就在cookie域中拿就行,第一次没有默认就为空,第二次访问时,Cookie域中就会保存有用户名,当访问时就有了用户名
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="http://localhost:8080/JavaWeb_4/cookie2" method="get">
    用户名:<input type="text" name="username" value="${cookie.username.value}"> <br>
    密码:<input type="password" name="password"> <br>
    <input type="submit" value="登录">
</form>
</body>
</html>

Session

什么是Session?

  • Session 就是会话。它是用来维护一个客户端和服务器之间关联的一种技术;
  • Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。
  • 客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了

创建Session对象、Session域中的存取

HTML页面

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="pragma" content="no-cache" />
        <meta http-equiv="cache-control" content="no-cache" />
        <meta http-equiv="Expires" content="0" />
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Session</title>
        <base href="http://localhost:8080/JavaWeb_4/">
        <style type="text/css">
            ul li {
                list-style: none;
            }
        </style>
    </head>
    <body>
        <iframe name="target" width="500" height="500" ></iframe>
        <div >
            <ul>
                <li><a href="session1?action=createOrGetSession" target="target">Session的创建和获取(id号、是否为新创建)</a></li>
                <li><a href="session1?action=setAttribute" target="target">Session域数据的存储</a></li>
                <li><a href="session1?action=getAttribute" target="target">Session域数据的获取</a></li>
                <li>Session的存活</li>
                <li>
                    <ul>
                        <li><a href="session1?action=defaultLife" target="target">Session的默认超时及配置</a></li>
                        <li><a href="session1?action=life3" target="target">Session3秒超时销毁</a></li>
                        <li><a href="session1?action=deleteNow" target="target">Session马上销毁</a></li>
                    </ul>
                </li>
                <li><a href="" target="target">浏览器和Session绑定的原理</a></li>
            </ul>
        </div>
    </body>
</html>

java代码

package com.mlyr;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/session1")
public class Session1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        String action = request.getParameter("action");
        switch (action){
            case "createOrGetSession":
                createOrGetSession(request,response);
                break;
            case "setAttribute":
                setAttribute(request,response);
                break;
            case "getAttribute":
                getAttribute(request,response);
                break;
        }
    }
      //Session的创建和获取(id号、是否为新创建)
    protected void createOrGetSession(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //创建Session对象
        HttpSession session = request.getSession();
        //获取Session对象的ID值
        String id = session.getId();
        //判断Session是否刚刚创建的
        boolean aNew = session.isNew();
        //将结果响应给页面
        response.getWriter().write("Session对象:"+session+"\n");
        response.getWriter().write("Session对象的ID值:"+id+"\n");
        response.getWriter().write("判断Session是否刚刚创建的:"+aNew+"\n");
    }
    //Session域数据的存储
    protected void setAttribute(HttpServletRequest request, HttpServletResponse response) throws IOException {
        //向Session域中存放数据
        request.getSession().setAttribute("key1","value1");
        response.getWriter().write("Session域数据的存储完成");
    }
    //Session域数据的获取
    protected void getAttribute(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
        //获取Session域中的数据
        Object key1 = request.getSession().getAttribute("key1");
        response.getWriter().write("获取Session域中的数据:"+key1);
    }
}

Session生命周期

  • public void setMaxInactiveInterval(int interval) 设置Session 的超时时间(以秒为单位),超过指定的时长,Session就会被销毁。
    • 值为正数的时候,设定Session 的超时时长。
    • 负数表示永不超时(极少使用)
  • public int getMaxInactiveInterval()获取Session 的超时时间
  • public void invalidate() 让当前Session会话马上超时无效

Session的默认Session超时时长

  • IDEA中Using CATALINA_BASE整合后的路径下,web.xml配置文件中默认配置了Session的超时时长为30分钟
<session-config>
    <session-timeout>30</session-timeout>
</session-config>
  • 如果想修改整个Web工程的所有Session超时时长,可以在Web工程下的web.xml配置文件中添加配置,就是上面的
  • 如果只想修改个别Session的超时时长,使用setMaxInactiveInterval()方法单独设置
//Session的默认超时及配置
protected void defaultLife(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
    int maxInactiveInterval = request.getSession().getMaxInactiveInterval();
    response.getWriter().write("Session的默认超时时长:"+maxInactiveInterval);
}
//Session3秒超时销毁
protected void life3(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {
    request.getSession().setMaxInactiveInterval(3);
    response.getWriter().write("已经设置Session的超时时长为3秒");
}
//Session马上销毁
protected void deleteNow(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
    request.getSession().invalidate();
    response.getWriter().write("设置Session立即销毁");
}

Session的实现原理

  • Session 技术,底层其实是基于Cookie 技术来实现的。

sessioncookie的联系和区别

  • session和cookie都可以保存跟特定会话关联的信息
  • session的信息是存放在服务器端的,cookie的信息是存放在浏览器端
  • session中可以存放Object,cookie只能存放字符串信息

过滤器

是什么过滤器?

  • Filter过滤器是JavaWeb的三大组件之一;
  • 过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理,通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理;
  • 它的作用:拦截请求,过滤响应;
    • 拦截请求的常见应用场景:权限检查、日记操作、事务管理...

创建一个Filter过滤器

  • 权限设定,没有登录的不能直接访问web工程下的HTML目录下的所有资源

首先一个登陆页面

  • 提交到LoginServlet程序
<form action="http://localhost:8080/JavaWeb_4/loginservlet" method="get">
    用户名:<input type="text" name="username"/><br/>
    密  码:<input type="password" name="password"/><br/>
    <input type="submit"/>
</form>

LoginServlet程序

@WebServlet(name = "LoginServlet",urlPatterns = "/loginservlet")
public class LoginServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //处理响应乱码
        response.setContentType("text/jsp;charset=UTF-8");
        //获取输入的用户名以及密码
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //先给定一个值
        if ("abcdef".equals(username) && "123456".equals(password)){
            //如果用户名密码正确,将用户名保存在Session域中
            request.getSession().setAttribute("username",username);
            response.getWriter().write("登陆成功!!!");
        }else {
            request.getRequestDispatcher("/index.jsp").forward(request,response);
        }
    }
}

登陆成功之后将用户名放入到Session域中

创建Filter过滤器

public class Filter1 implements Filter {
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //通过ServletRequest请转获取到HttpServletRequest请求
        HttpServletRequest request = (HttpServletRequest) req;
        //通过request请求再获取Session域
        HttpSession session = request.getSession();
        //查询Session与中是否有用户名信息,有说明已经登录,可访问HTML下的
        Object username = session.getAttribute("username");
        //为null,就说明没有登录
        if (username == null) {
            //没有登录就重定向到登录页面
            req.getRequestDispatcher("/index.jsp").forward(req, resp);
        } else {
            //登录的话,就放行,该请求哪里就让他到哪里
            chain.doFilter(req, resp);
        }
    }
}

当Session域中没有用户名的时候(用户没有登录),放强行访问HTML下的资源时,就会被过滤器重定向到登录页面,只有当Session域中存在用户名时,才会被过滤器放行允许其访问HTML下的资源

Filter过滤器的web配置

<!--filter 标签用于配置一个Filter 过滤器-->
<filter>
    <!--给filter起一个别名-->
    <filter-name>Filter1</filter-name>
    <!--配置filter的全类名-->
    <filter-class>com.mlyr.filter.Filter1</filter-class>
</filter>
<!--filter过滤器拦截的路径-->
<filter-mapping>
    <!--给那个filter过滤器使用-->
    <filter-name>Filter1</filter-name>
    <!--url-pattern:配置filter的拦截路径
            /  表示http://ip:port/工程路径/   映射到web目录
            /HTML/*</  表示拦截http://ip:port/工程路径/HTML/目录下的所有文件及目录
        -->
    <url-pattern>/HTML/*</url-pattern>
</filter-mapping>

Filter的生命周期

public class Filter2 implements Filter {
    //构造方法
    public Filter2() {}
    @Override//init()初始化方法
    public void init(FilterConfig filterConfig) throws ServletException {}
    @Override//doFilter()过滤方法
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}
    @Override//destroy()销毁方法
    public void destroy() {}
}

构造方法与init()初始化方法在web工程启动的时候执行

doFilter()过滤方法在每次拦截到请求时执行

destroy()销毁方法在停止web工程的时候执行

FilterConfig类

  • 它是Filter过滤器的配置文件类
  • 当web工程创建Filter过滤器时,同时会创建一个FilterConfig类
  • 它的作用:获取Filter过滤器的配置内容
    • 获取Filter的名称,也就是filter-name标签中的内容
    • 获取Filter中配置的init-param初始化的内容
    • 获取ServletContext对象
public void init(FilterConfig config) throws ServletException {
    //获取Filter过滤器名字
    System.out.println(config.getFilterName());//Filter3
    //获取init初始化内容
    System.out.println(config.getInitParameter("name"));//张三
    //获取ServletContext对象
    ServletContext servletContext = config.getServletContext();
}
<filter>
    <filter-name>Filter3</filter-name>
    <filter-class>com.mlyr.filter.Filter3</filter-class>
    <init-param>
        <param-name>name</param-name>
        <param-value>张三</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>Filter3</filter-name>
    <url-pattern>/</url-pattern>
</filter-mapping>

FilterChain过滤链

  • 如果有多个过滤器,它就形成了一个FilterChain过滤器链
  • 那个Filter先执行与Filter的配置相关,在web.xml配置文件中,那个配置在最前方,那个就先执行
  • 第一个执行到doFilter时,会进行判断,如果有下一个Filter,就去执行下个Filter;没有的话,就直接执行资源文件,然后返回Filter执行doFilter后面的代码
  • 所有的Filter和目标资源默认在同一个线程中;多个Filter执行的时候,他们使用同一个Request对象

Filter的拦截路径分类

精确匹配

  • 只会拦截HTML下的a.html的请求
<url-pattern>/HTML/a.html</url-pattern>

目录匹配

  • 只会拦截HTML下的所有请求
<url-pattern>/HTML/*</url-pattern>

后缀名匹配

  • 只会拦截以.html结尾的请求
<url-pattern>*.html</url-pattern>

Filter过滤器只关心请求的地址是否匹配,不关心请求的资源是否存在

不经风雨,怎见彩虹?

相关文章

    暂无相关文章
相关栏目:

用户点评