JavaWeb重点笔记

一、开发工具

1.1 JDK安装

第一步:打开官网进行下载

在这里插入图片描述
第二步:运行程序进行安装

注意:如果自己会配置JDK,可以更改它的安装路径,那相应的环境变量也需要修改!

第三步:系统环境变量配置

此电脑 》 右键 》 属性 》 高级系统设置 》 环境变量 》 系统变量 》 新建(需要新建两个,然后修改一个)

新建两个:JAVA_HOME代表Java的安装目录、CLASSPATH代表程序运行的时候,优先加载当前目录中的类,然后再加载指定的类库

变量名变量值
JAVA_HOMEC:\Program Files\Java\jdk1.8.0_261
CLASSPATH.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;

修改一个:编辑PATH环境变量,它会打开一个窗口,新添两条路径,如下图所示

  • %JAVA_HOME%\bin
  • %JAVA_HOME%\jre\bin
    在这里插入图片描述
    第四步:测试JDK是否安装成功
    打开一个cmd命令行窗口,输入以下两个命令查看,如果有内容输出则证明已经配置成功!
  • java -version
  • javac -version

在这里插入图片描述

1.2 Tomcat 安装

第一步:打开官网进行下载和安装
在这里插入图片描述
在这里插入图片描述
第二步:系统环境变量配置
此电脑 》 右键 》 属性 》 高级系统设置 》 环境变量 》 系统变量 》 新建(需要新建两个,然后修改三个)

新建两个:CATALINA_BASE和CATALINA_HOME均代表Tomcat的安装目录

变量名变量值
CATALINA_BASEC:\DevTools\apache-tomcat-8.5.57(输入自己解压的Tomcat目录,不要照抄我的)
CATALINA_HOMEC:\DevTools\apache-tomcat-8.5.57 输入自己解压的Tomcat目录,不要照抄我的)

修改一个:编辑CLASSPATH环境变量,它会打开一个窗口,具体修改,如下所示

  • 未修改前:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
  • 修改以后:.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;%CATALINA_HOME%\lib\servlet-api.jar;

修改两个:编辑PATH环境变量,它会打开一个窗口,新添两条路径,如下所示

  • %CATALINA_HOME%\bin
  • %CATALINA_HOME%\lib
    在这里插入图片描述
    第三步:测试Tomcat是否安装成功

打开一个cmd命令行窗口,输入以下一个命令查看,如果有内容输出则证明已经配置成功!

  • catalina run

在这里插入图片描述

  • 打开浏览器,输入:http://localhost:8080/

在这里插入图片描述

1.3 IDEA创建JavaWeb项目

  1. File->new-Project-Java

在这里插入图片描述
在这里插入图片描述
2. 在项目目录下的WEB-INF中,创建lib文件夹存放jar文件的
在这里插入图片描述
3. FIle->Project Structure…进行项目配置

在这里插入图片描述
4. 配置jar文件的路径

在这里插入图片描述

1.4 IDEA集成Tomcat

第一步:打开配置
在这里插入图片描述
第二步:添加tomcat服务器
在这里插入图片描述
检查添加是否成功:
在这里插入图片描述

第三步:运行tomcat
在这里插入图片描述

二、Servlet

2.1 Servlet 语法格式

Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。

第一步:创建包(com.caochenlei.servlet.demo)

第二步:创建类(com.caochenlei.servlet.demo.MyServlet),并且需要实现Servlet接口中的所有方法

package com.caochenlei.servlet.demo;

import javax.servlet.*;
import java.io.IOException;

public class MyServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        System.out.println("MyServlet init ...");
    }

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) 
            throws ServletException, IOException {
        System.out.println("MyServlet service ...");
    }

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("MyServlet destroy ...");
    }
}

方法介绍:

  • init:Servlet初始化时调用的方法
  • getServletConfig:获取当前Servlet的配置信息
  • service:调用Servlet真正去处理逻辑的方法
  • getServletInfo:它提供有关Servlet的信息,如作者、版本、版权
  • destroy:Servlet销毁时调用的方法

第三步:配置映射(web.xml中新增以下代码)

    <servlet>
        <servlet-name>MyServlet</servlet-name>
        <servlet-class>com.caochenlei.servlet.demo.MyServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/MyServlet</url-pattern>
    </servlet-mapping>

配置介绍:

servlet标签用于配置Servlet的基本信息

  1. servlet-class:代表当前Servlet的具体类路径,注意最后不包含.java
  2. servlet-name:代表当前Servlet的别名,可以和原Servlet名称一样,也可以不一样,一般我们就一样就行了

servlet-mapping标签用于配置请求路径与具体处理Servlet的对应关系

  1. url-pattern:这里写你要匹配的地址路径
  2. servlet-name:如果匹配到请求,该交给哪一个Servlet处理,这里的servlet-name其实就是一个Servlet的别名

第四步:启动应用,然后浏览器输入地址访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyServlet)

在这里插入图片描述

第五步:正常关闭Tomcat服务器,我们会看到调用销毁方法,如下图所示:
在这里插入图片描述

2.2 Servlet执行过程

在这里插入图片描述

2.3 Servlet 生命周期

Servlet的生命周期通过javax.servlet.Servlet接口中的init()、service()和destroy()方法来表示。

Servlet的生命周期包含了下面4个阶段:

  1. 类加载和实例化
  2. 初始化:init()
  3. 请求处理:service()
  4. 销毁:destroy()

2.4 Servlet继承体系

子类HttpServlet,我们只要继承这个类重写GET、POST方法就能实现一个简单的Servlet请求处理,Servlet的继承体系如下图:
在这里插入图片描述

2.5 使用HttpServlet

第一步:创建类(com.caochenlei.servlet.demo.MyHttpServlet),并且需要继承HttpServlet实现doPost、doGet方法。

package com.caochenlei.servlet.demo;

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

public class MyHttpServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        System.out.println("doPost method 执行...");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
            throws ServletException, IOException {
        System.out.println("doGet method 执行...");
    }
}

第二步:配置映射(在web.xml文件中新增以下代码)

<servlet>
        <servlet-name>MyHttpServlet</servlet-name>
        <servlet-class>com.caochenlei.servlet.demo.MyHttpServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyHttpServlet</servlet-name>
        <url-pattern>/MyHttpServlet</url-pattern>
    </servlet-mapping>

** 第三步:重启应用,然后浏览器访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyHttpServlet),观察控制台 **
在这里插入图片描述
我们注意url-pattern它可以有多种拦截形式:

  • 全路径匹配:/a
  • 前半段匹配:/a/b/c/*
  • 扩展名匹配:*.action

2.6 ServletContext

每个web工程都只有一个ServletContext对象,它用来获取Servlet的上下文,在服务器启动的时候,会为托管的每一个web应用程序,创建一个ServletContext对象,当从服务器移除托管或者是关闭服务器时,ServletContext将会被销毁。它主要有以下几方面作用:

  • 获取全局配置参数
  • 获取web工程中的资源
  • 在servlet间共享数据域对象

2.6.1 获取全局配置参数

第一步:在web.xml中新增以下代码

    <context-param>
        <param-name>username</param-name>
        <param-value>zhangsan</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>123456</param-value>
    </context-param>

第二步:在MyHttpServlet的doGet方法中新增以下代码

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    System.out.println("doGet method invoke ...");

    // 获取全部初始化对象的名称和其对应内容
        Enumeration<String> initParameterNames = getServletContext().getInitParameterNames();
        //判断对象是否能获取
        while(initParameterNames.hasMoreElements()){
            //获取当前对象的名称
            String initParameterName = initParameterNames.nextElement();
            //根据当前对象的名称,获取对应的内容
            String initParameterValue = getServletContext().getInitParameter(initParameterName);
            System.out.println(initParameterName+":"+initParameterValue);
        }
}

第三步:重启Tomcat服务器,在浏览器中访问(http://localhost:8080/myJavaWebDemo_war_exploded/MyHttpServlet)
在这里插入图片描述

2.6.2 获取web项目的资源

第一步:在项目的 web 文件夹中右键创建 a.txt 文件
在这里插入图片描述
第二步:在MyHttpServlet的doGet方法中新增以下代码

       protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doget 方法");

        // 获取全部初始化名称和其对应的内容
        Enumeration<String> initParameterNames = getServletContext().getInitParameterNames();
        //判断是否获取对象
        while(initParameterNames.hasMoreElements()){
            //获取当前对象的名称
            String initParameterName = initParameterNames.nextElement();
            //根据当前对象的名称,获取对应的内容
            String initParameterValue = getServletContext().getInitParameter(initParameterName);
            System.out.println(initParameterName+":"+initParameterValue);
        }

		//++++++++++++++++++++++++++++++以下是新增代码++++++++++++++++++++++++++
        // 获取web工程中的资源的绝对路径
        String realPath = getServletContext().getRealPath("a.txt");
        System.out.println(realPath);

        // 获取web工程中的资源的输入流对象
        InputStream resourceAsStream = getServletContext().getResourceAsStream("a.txt");
        System.out.println(resourceAsStream);
    }

第三步:重启Tomcat服务器,在浏览器中访问
在这里插入图片描述

2.6.3 在Servlet间共享数据域对象

第一步:创建 LoginServlet类并配置请求映射
LoginServlet:

package com.caochenlei.servlet.demo;

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

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 {

    }
}

XML:

    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.caochenlei.servlet.demo.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/LoginServlet</url-pattern>
    </servlet-mapping>

第二步:在 LoginServlet的 doGet 中实现登录次数的修改,默认为1

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    // 获取当前登录次数
    Integer count = (Integer) getServletContext().getAttribute("count");
    // 如果当前登录为null,则设置默认值为1
    if (count == null) {
        getServletContext().setAttribute("count", 1);
    } else {
        getServletContext().setAttribute("count", count + 1);
    }
    System.out.println("当前登录次数是"+count);
}

第三步:在 MyHttpServlet 的 doGet 中新增以下查看代码,用于查看当前登录次数

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    System.out.println("doGet method invoke ...");

    // 获取全部初始化名称和其对应的内容
    Enumeration<String> initParameterNames = getServletContext().getInitParameterNames();
    while (initParameterNames.hasMoreElements()) {
        String initParameterName = initParameterNames.nextElement();
        String initParameterValue = getServletContext().getInitParameter(initParameterName);
        System.out.println(initParameterName + ":" + initParameterValue);
    }

    // 获取web工程中的资源的绝对路径
    String realPath = getServletContext().getRealPath("a.txt");
    System.out.println(realPath);

    // 获取web工程中的资源的输入流对象
    InputStream resourceAsStream = getServletContext().getResourceAsStream("a.txt");
    System.out.println(resourceAsStream);
    
//+++++++++++++++++++++++++++++++++以下是新增代码+++++++++++++++++++++++++++++++
    // 查看当前网站登录次数,这个数据是保存在ServletContext中的
    Integer count = (Integer) getServletContext().getAttribute("count");
    // 判断是否登录过,如果没有登录过,提示未登录,如果已经登录过,显示登录次数
    if (count == null) {
            resp.getWriter().write("没有登录,登录次数为:" + count);
    } else {
            resp.getWriter().write("登录次数为:" + count);
    }
}

第四步:重启Tomcat服务器
访问LoginServlet(/LoginServlet):
在这里插入图片描述
访问MyHttpServlet(/http):
在这里插入图片描述

2.6.4 Servlet解决web乱码问题

如上例中,修改MyHttpServlet添加文本类型与编码格式在这里插入图片描述

在这里插入图片描述

2.7 ServletConfig

通过ServletConfig对象可以获取servlet在配置的时候一些信息。
第一步:创建类(MyServletConfig)

public class MyServletConfig extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

第二步:在web.xml中配置映射关系

    <servlet>
        <servlet-name>MyServletConfig</servlet-name>
        <servlet-class>com.servlet.demo.MyServletConfig</servlet-class>
        
        <init-param>
            <param-name>drive</param-name>
            <param-value>com.mysql.jdbc.Driver</param-value>
        </init-param>
        <init-param>
            <param-name>url</param-name>
            <param-value>jdbc:mysql://localhost:3306/mysql</param-value>
        </init-param>
        <init-param>
            <param-name>username</param-name>
            <param-value>root</param-value>
        </init-param>
        <init-param>
            <param-name>password</param-name>
            <param-value>root</param-value>
        </init-param>

        <!-- Servlet的加载顺序 -->
        <load-on-startup>2</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>MyServletConfig</servlet-name>
        <url-pattern>/MyServletConfig</url-pattern>
    </servlet-mapping>

第三步:在MyServletConfig的doGet方法中新增以下代码

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取全部初始化名称和其对应的内容
        Enumeration<String> initParameterNames = getServletConfig().getInitParameterNames();
        //判断是否获取对象
        while (initParameterNames.hasMoreElements()) {
            获取当前对象的名称
            String initParameterName = initParameterNames.nextElement();
            //根据当前对象的名称,获取对应的内容
            String initParameterValue = getServletConfig().getInitParameter(initParameterName);
            System.out.println(initParameterName + ":" + initParameterValue);
        }
    }

第四步:重启Tomcat服务器,在浏览器中访问http://localhost:8080/java_war_exploded/MyServletConfig
在这里插入图片描述

2.8 HttpServletRequest

HttpServletRequest这个对象封装了客户端提交过来的一切数据。

第一步:修改 index.jsp

<form action="RequestServlet" method="get">
    账户:<input type="text" name="username"><br>
    密码:<input type="text" name="password"><br>
         <input type="submit" value="注册">
</form>

第二步:创建类(RequestServlet)

protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取客户端传递过来的头部信息
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = req.getHeader(headerName);
            System.out.println(headerName + ":" + headerValue);
        }
        System.out.println("============================================================");

        // 获取客户端传递过来的参数信息
        Enumeration<String> parameterNames = req.getParameterNames();
        while (parameterNames.hasMoreElements()) {
            String parameterName = parameterNames.nextElement();
            String parameterValue = req.getParameter(parameterName);
            // 如果值有多个请使用:request.getParameterValues(parameterName)
            System.out.println(parameterName + ":" + parameterValue);
        }
        System.out.println("=================================================");

        // 获取客户端传递过来的参数信息(以Map集合的形式)
        Map<String, String[]> parameterMap = req.getParameterMap();
        Set<String> names = parameterMap.keySet();
        for (String name : names) {
            String[] value = parameterMap.get(name);
            System.out.println(name + ":" + Arrays.toString(value));
        }
        System.out.println("========================================================");

        // 获取一些其它地址、查询等信息
        StringBuffer requestURL = req.getRequestURL();      //获取请求的URL
        String requestURI = req.getRequestURI();            //获取请求的URI
        String servletPath = req.getServletPath();          //获取
        String queryString = req.getQueryString();


        System.out.println("requestURL:" + requestURL);
        System.out.println("requestURI:" + requestURI);
        System.out.println("servletPath:" + servletPath);
        System.out.println("queryString:" + queryString);

    }

第三步:在web.xml中新增映射信息

 <servlet>
        <servlet-name>RequestServlet</servlet-name>
        <servlet-class>com.servlet.demo.RequestServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>RequestServlet</servlet-name>
        <url-pattern>/RequestServlet</url-pattern>
    </servlet-mapping>

第四步:重启Tomcat服务器,在浏览器中访问
在这里插入图片描述
控制台输出内容:
在这里插入图片描述

解决request请求数据中文乱码问题

  • GET方式
// 先用原来的编码解码再用UTF—8重新编码。
String newUsername = new String(username.getBytes("ISO-8859-1"), "UTF-8");
  • POST方式
// 这行设置一定要写在getParameter之前。
request.setCharacterEncoding("UTF-8");

2.9 HttpServletResponse

HttpServletResponse这个对象负责返回数据给客户端。

第一步:创建类(ResponseServlet)

public class ResponseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        /**
         * 注意:以下两种方式一次只能使用一种,我们就用字符流方式了,另一种自己演示
         */
        // 以字符流的方式写数据
        resp.getWriter().write("<h1>hello response 111 ...</h1>      哈哈哈");

        // 以字节流的方式写数据
        // response.getOutputStream().write("hello response 222 ...".getBytes());
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
    }
}

第二步:在web.xml文件中新增以下映射信息

    <servlet>
        <servlet-name>ResponseServlet</servlet-name>
        <servlet-class>com.servlet.demo.ResponseServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ResponseServlet</servlet-name>
        <url-pattern>/ResponseServlet</url-pattern>
    </servlet-mapping>

第三步:重启Tomcat服务器,在浏览器中访问
http://localhost:8080/java_war_exploded/ResponseServlet
在这里插入图片描述

解决response响应数据中文乱码问题

  • 字符流输出:response.getWriter()
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("你好,世界!");
  • 字节流输出:response.getOutputStream()
response.setContentType("text/html;charset=UTF-8");
response.getOutputStream().write("你好,世界!".getBytes("UTF-8"));

2.10 重定向和请求转发

1、重定向是客服端两次请求;请求转发是客服端只有一次请求;重定向会生成两个不同的request对象,请求转发只有一个。
2、重定向是客服端的跳转,请求转发是服务器的跳转。
3、重定向的URL拦会发生变化,而请求转发不会发生变化。
4、重定向:response.sendRedirect(“/URL地址”)方法
请求转发:request.getRequestDispatcher(“/URL地址”)方法
5、重定向是前一个请求结束了,一个新的请求发出来了;请求转发是同一个人请求,由最后一个转发页面向浏览器相应页面。
6、请求转发的转发者与接收者之间共享相同的request对象,response对象,他们属于同一个访问请求和响应过程;重定向的调用者与被调用者使用各自的request对象和response对象,他们属于多个独立的访问请求和响应过程

2.10.1 重定向(完全的跳转)

response.sendRedirect("/URL地址")

处理流程:

  • 客户端发送请求,Servlet做出业务逻辑处理。
  • Servlet调用response.sendReadirect()方法,把要访问的目标资源作为response响应头信息发给客户端浏览器。
  • 客户端浏览器重新访问服务器资源xxx.jsp,服务器再次对客户端浏览器做出响应。
    在这里插入图片描述

2.10.2 请求转发(内部转发)

request.getRequestDispatcher("/URL地址").forward(request, response)

处理流程:

  • 客户端发送请求,Servlet做出业务逻辑处理。
  • Servlet调用forword()方法,服务器Servlet把目标资源返回给客户端浏览器。
    在这里插入图片描述

2.11 Cookie

Cookie其实是一份小数据,它是服务器给客户端并且存储在客户端上的一份小数据。

第一步:创建类(CookieServlet)

    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取Cookie ============================================================
        Cookie[] cookies = req.getCookies();
        if (cookies.length == 1) {
            System.out.println("没有其它Cookie存在,只有JSESSIONID这个Cookie存在!");

            // 创建Cookie ============================================================
            // 创建Cookie对象
            Cookie cookie = new Cookie("username", "zhangsan");
            // 添加Cookie描述
            cookie.setComment("用户账号Cookie");
            // 正值:表示在这个数字过后,cookie将会失效。
            // 负值:关闭浏览器,那么cookie就失效,默认值是 -1。
            // 注意:Cookie是没有删除方法的,想让要Cookie失效或清除,就只要让当前值为0就可以了。
            cookie.setMaxAge(60 * 60 * 24 * 7);
            // 重新为当前的这个Cookie赋值
            cookie.setValue("lisi");
            // 只有访问域名 localhost 才会带上该Cookie
            cookie.setDomain("localhost");
            // 只有访问请求 /java_war_exploded/CookieServlet 才会带上该Cookie
            //cookie.setPath("/java_war_exploded/CookieServlet");
            // 创建Cookie ============================================================

            // 使用响应对象给浏览器响应的时候带上该Cookie
            resp.addCookie(cookie);
        } else {
            for (Cookie cookie : cookies) {
                if ("username".equals(cookie.getName())) {
                    System.out.println(cookie.getName() + "====" + cookie.getValue());
                }
            }
        }
        // 获取Cookie ============================================================
    }

第二步:在web.xml中新增映射信息

    <servlet>
        <servlet-name>CookieServlet</servlet-name>
        <servlet-class>com.servlet.demo.CookieServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>CookieServlet</servlet-name>
        <url-pattern>/CookieServlet</url-pattern>
    </servlet-mapping>

第三步:重启Tomcat服务器在浏览器中访问
http://localhost:8080/java_war_exploded/CookieServlet
在这里插入图片描述

2.12 Session

Session是数据存放在服务器端上。而Cookie是服务器返回一小份数据给客户端,并且存放在客户端上。
常见用法:

// 获取Session对象
HttpSession session = request.getSession();

// 获取SessionID
String id = session.getId();

//存值
session.setAttribute(name, value);

//取值
session.getAttribute(name);

//删值
session.removeAttribute(name);

生命周期:

  • 创建:如果有在servlet里面调用了 request.getSession()
  • 销毁:关闭服务器或者session会话时间过期。默认有效期: 30分钟。

三、Listener

Listener是监听器,监听Servlet某一个事件的发生或者状态的改变,它的内部其实就是接口回调。

3.1 监听三个作用域创建和销毁

3.1.1 ServletContextListener

监听对象:

ServletContextListener用于监听ServletContext对象作用域创建和销毁,利用它可以完成自己想要的初始化工作。

生命周期:

servletcontext创建:

  • 1、启动服务器的时候

servletContext销毁:

  • 1、关闭服务器
  • 2、从服务器移除项目

如何创建:
创建ServletContextListener类:

public class MyContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("MyContextListener 创建.......");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("MyContextListener 销毁.......");
    }
}

如何配置XML:

    <listener>
        <listener-class>com.servlet.demo.MyContextListener</listener-class>
    </listener>

3.1.2 ServletRequestListener

监听对象:

ServletRequestListener用于监听ServletRequest对象作用域创建和销毁,利用它可以判断当前受否存在请求。

生命周期:

request创建:
1、访问服务器上的任意资源都会有请求出现。
访问 html :会
访问 jsp :会
访问 servlet :会

request销毁:
1、服务器已经对这次请求作出了响应。

如何创建:
创建MyRequestListener 类:

public class MyRequestListener implements ServletRequestListener {
    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("requestDestroyed。。。。。。销毁");
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println("requestInitialized。。。。。。初始化");
    }
}

如何配置XML:

    <listener>
        <listener-class>com.servlet.demo.MyRequestListener</listener-class>
    </listener>

3.1.3 HttpSessionListener

监听对象:

HttpSessionListener用于监听HttpSession对象作用域创建和销毁,利用它可以统计在线人数。

生命周期:

session的创建:
1、只要调用getSession()方法。
html :不会
jsp :会
servlet :会

session的销毁:
1、会话超时30分钟。
2、非正常关闭服务器。
3、正常关闭服务器(序列化)

如何创建:
创建MySessionListener 类:

public class MySessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("sessionCreated。。。。。。创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("sessionCreated。。。。。。销毁");
    }
}

如何配置XML:

    <listener>
        <listener-class>com.servlet.demo.MySessionListener </listener-class>
    </listener>

3.2 监听三个作用域属性状态变更

3.2.1 ServletContextAttributeListener

主要作用:

监听ServletContext存值状态变更。

如何创建:

package com.caochenlei.servlet.demo;

import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;

public class MyContextAttributeListener implements ServletContextAttributeListener {
    @Override
    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("attributeAdded ...");
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("attributeRemoved ...");
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("attributeReplaced ...");
    }
}

3.2.2 ServletRequestAttributeListener

主要作用:

监听ServletRequest存值状态变更。

如何创建:

package com.caochenlei.servlet.demo;

import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;

public class MyRequestAttributeListener implements ServletRequestAttributeListener {
    @Override
    public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("attributeAdded ...");
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("attributeRemoved ...");
    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("attributeReplaced ...");
    }
}

3.2.3 HttpSessionAttributeListener

主要作用:

监听HttpSession存值状态变更。

如何创建:

package com.caochenlei.servlet.demo;

import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;

public class MySessionAttributeListener implements HttpSessionAttributeListener {
    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("attributeAdded ...");
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("attributeRemoved ...");
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("attributeReplaced ...");
    }
}

3.3 监听HttpSession存值状态变更

3.3.1 HttpSessionBindingListener

主要作用:

监听对象与session绑定和解除绑定的动作。

如何创建:

package com.caochenlei.servlet.demo;

import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;

public class MySessionBindingListener implements HttpSessionBindingListener {
    @Override
    public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("valueBound ...");
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("valueUnbound ...");
    }
}

如何配置:

这一类监听器不用注册。

3.3.2 HttpSessionActivationListener

主要作用:

用于监听现在session的值是钝化(序列化)还是活化(反序列化)的动作。

钝化(序列化)  :把内存中的数据存储到硬盘上。
活化(反序列化):把硬盘中的数据读取到内存中。

如何钝化

1. 在tomcat的 conf/context.xml 里面配置
		对所有的运行在这个服务器的项目生效。

2. 在tomcat的 conf/Catalina/localhost/context.xml 里面配置
		对localhost生效。

3. 在自己的web工程项目中的 META-INF/context.xml 里面配置
		只对当前的工程生效。

具体配置信息如下:
	maxIdleSwap 	: 1分钟不用就钝化。
	directory 		: 钝化后的那个文件存放的目录位置。

	<Context>
		<Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
			<Store className="org.apache.catalina.session.FileStore" directory="D:/Passivate"/>
		</Manager>
	</Context>

如何创建:

package com.caochenlei.servlet.demo;

import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionEvent;

public class MySessionActivationListener implements HttpSessionActivationListener {
    @Override
    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
        System.out.println("sessionWillPassivate ...");
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        System.out.println("sessionDidActivate ...");
    }
}

如何配置:

这一类监听器不用注册。

四、Filter

4.1 Filter概述

Filter是过滤器,就是对客户端发出来的请求进行过滤。浏览器发出请求,然后服务器派servlet处理。在中间就可以过滤,其实过滤器起到的是拦截的作用。使用过滤器可以对一些敏感词汇进行过滤、统一设置编码、实现自动登录等功能。

4.2、Filter生命周期

  • 创建:在服务器启动的时候就创建。
  • 销毁:在服务器停止的时候就销毁。

4.3、Filter语法

如何定义:

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter init ...初始化");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter foFilter ...执行过滤");

        // 放行,让请求到达下一个目标。
        filterChain.doFilter(req, resp);
    }

    @Override
    public void destroy() {
        System.out.println("MyFilter init ...销毁");
    }
}

如何配置:

    <filter>
        <filter-name>MyFilter</filter-name>
        <filter-class>com.caochenlei.servlet.demo.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>MyFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>

注意:init方法的参数 FilterConfig , 可以用于获取Filter在注册的名字以及初始化参数,其实这里的设计的初衷与ServletConfig是一样的。

4.4 Filter匹配规则

  • 全路径匹配:/a
  • 前半段匹配:/a/b/c/*
  • 扩展名匹配:*.action

4.5 Filter拦截类型

注意:针对 dispatcher 设置的选项。

  • REQUEST : 只要是请求过来都拦截,默认就是REQUEST。
  • FORWARD : 只要是转发过来都拦截。
  • ERROR : 页面出错发生跳转。
  • INCLUDE : 包含页面的时候就拦截。

4.6 Filter统一编码

public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
        // 1.强转
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;
        // 2.放行
        filterChain.doFilter(new MyRequest(request), response);
    }

    @Override
    public void destroy() {

    }


    // 增强了所有的获取参数的方法request.getParameter("name");
    // 增强了所有的获取参数的方法request.getParameterValues("name");
    // 增强了所有的获取参数的方法request.getParameterMap();
	
	//内部类MyRequest 
    public class MyRequest extends HttpServletRequestWrapper {

        private HttpServletRequest request;
        private boolean flag = true;

        /**
         * 初始化构造函数
         * @param request(请求对象)
         */
        public MyRequest(HttpServletRequest request) {
            super(request);
            this.request = request;
        }

        @Override
        public String getParameter(String name) {
            if (name == null || name.trim().length() == 0) {
                return null;
            }
            String[] values = getParameterValues(name);
            if (values == null || values.length == 0) {
                return null;
            }
            return values[0];
        }

        @Override
        public String[] getParameterValues(String name) {
            if (name == null || name.trim().length() == 0) {
                return null;
            }
            Map<String, String[]> map = getParameterMap();
            if (map == null || map.size() == 0) {
                return null;
            }
            return map.get(name);
        }

        @Override
        public Map<String, String[]> getParameterMap() {
            String method = request.getMethod();
            if ("post".equalsIgnoreCase(method)) {
                try {
                    request.setCharacterEncoding("utf-8");
                    return request.getParameterMap();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            } else if ("get".equalsIgnoreCase(method)) {
                Map<String, String[]> map = request.getParameterMap();
                if (flag) {
                    for (String key : map.keySet()) {
                        String[] arr = map.get(key);
                        for (int i = 0; i < arr.length; i++) {
                            try {
                                arr[i] = new String(arr[i].getBytes("utf-8"), "utf-8");
                            } catch (UnsupportedEncodingException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    flag = false;
                }
                return map;
            }
            return super.getParameterMap();
        }
    }
}

五、Servlet3.0

5.1 注解开发

5.1.1 servlet注解

如何创建:

@WebServlet(
        name = "AnnotationServlet",//代表servlet名称
        value = {"/AnnotationServlet"},//代表servlet映射地址,可以写多个,value与urlPatterns一样,二者不能同时出现
        loadOnStartup = 2,//代表servlet初始化顺序
        initParams = {@WebInitParam(name = "user",value = "zhangsan")},//代表servlet初始化参数,可以写多个
        asyncSupported = false//代表servlet是否支持异步,默认为false
)
public class AnnotationServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet ...AnnotationServlet 注释");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost ...");
    }
}

使用servlet注解后,不在需要配置xml文件

属性列表:

属性名类型描述
nameString指定 Servlet 的 name 属性,如果没有显式指定,则该 Servlet 的取值即为类的全限定名
valueString[]该属性等价于 urlPatterns 属性,两个属性不能同时使用
urlPatternsString[]指定一组 Servlet 的 URL 匹配模式
loadOnStartupint指定 Servlet 的加载顺序
initParamsWebInitParam[]指定一组 Servlet 初始化参数
asyncSupportedboolean声明 Servlet 是否支持异步操作模式
descriptionString该 Servlet 的描述信息
displayNameString该 Servlet 的显示名,通常配合工具使用

如何测试:

打开浏览器输入:http://localhost:8080/java_war_exploded/AnnotationServlet

检测控制台输出:
在这里插入图片描述

5.1.2 Filter注解

如何创建:

@WebFilter(
        filterName = "AnnotationFilter",//代表filter名称
        value = {"/*"},//代表filter映射路径,可以写多个,value与urlPatterns一样,二者不能同时出现
        dispatcherTypes = {DispatcherType.REQUEST},//代表filter拦截类型
        initParams = {@WebInitParam(name = "user", value = "zhansan")},//代表filter初始化参数,可以写多个
        asyncSupported = false,//代表filter是否支持异步,默认为false
        servletNames = {"AnnotationServlet"}//代表filter指定拦截哪几个servlet
)
public class AnnotationFilter implements Filter {
    @Override
    public void init(FilterConfig config) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws ServletException, IOException {
        System.out.println("doFilter ...AnnotationFilter");
        chain.doFilter(req, resp);
    }

    @Override
    public void destroy() {
    }
}

属性列表:

属性名类型描述
filterNameString指定过滤器的 name 属性
valueString[]该属性等价于 urlPatterns 属性,但是两者不应该同时使用
urlPatternsString[]指定一组过滤器的 URL 匹配模式
servletNamesString[]指定过滤器将应用于哪些 Servlet
dispatcherTypesDispatcherType指定过滤器的转发模式具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
initParamsWebInitParam[]指定一组过滤器初始化参数
asyncSupportedboolean声明过滤器是否支持异步操作模式
descriptionString该过滤器的描述信息
displayNameString该过滤器的显示名,通常配合工具使用

如何测试:

打开浏览器输入:
http://localhost:8080/java_war_exploded/AnnotationFilter
检测控制台输出:
在这里插入图片描述

5.1.3 listener注解

如何创建:

@WebListener()
public class AnnotationListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("contextInitialized ...AnnotationListener");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

        System.out.println("contextDestroyed ...AnnotationListener");
    }
}

如何测试:
在这里插入图片描述

5.1.4 注解与XML两种配置同时存在的说明

对于servlet来说:

  • 若两种配置方式的url-pattern值相同,则应用无法启动。
  • 若两种配置方式的url-pattern值相同,那么相当该servlet具有两个映射url-pattern。

对于filter来说:

  • 无论两种配置方式的url-pattern值是否相同,其都是作为独立的filter出现的。

对于listener来说:

  • 如果两种配置方式都进行了同一个listener注册,那么也只能算一个listener。

5.1.5 如何禁用注解组件

metadata-complete=“false”:表示web.xml配置和注解配置同时生效,默认是false。

metadata-complete=“true”:表示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" metadata-complete="false">
</web-app>

5.2 文件上传

前台页面:

  <form action="uploadServlet" method="post" enctype="multipart/form-data">
    选择文件:<input type="file" name="myfile" /> <br />
    上传文件:<input type="submit" value="上传" />
  </form>

前端的核心代码:

  • enctype=“multipart/form-data” //form中的数据用二进制数据传输,可以传文字,图片,。。
  • type=“file” //type 设成“file”就是文件选择按钮,自动产生一个 文本框+选择按钮
  • name=“myfile” //用于后台获取文件对象

后端上传模块:

@WebServlet(name = "UploadFileServlet", urlPatterns = "/uploadFileServlet")
@MultipartConfig
public class UploadFileServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //解决request乱码问题
        req.setCharacterEncoding("UTF-8");
        //解决response乱码问题
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType( "text/html;charset=UTF-8");
        
        //(通过请求的input标签tpye为file类型的name属性)获取请求文件对象
        Part part = req.getPart("myfile");  
        String fileName=part.getSubmittedFileName();    // 获取文件名称
        String lastName=fileName.substring(fileName.lastIndexOf('.'),fileName.length());  // 获取文件后缀
        part.write("D:/xxx"+lastName);     //将文件对象写入指定的全路径

        resp.getWriter().println("文件上传成功!");
    }
}

后台核心代码:
在这里插入图片描述
运行报错:

此错误是因为没有加注解@MultipartConfig

在这里插入图片描述

@MultipartConfig注解:

属性名类型是否可选描述
fileSizeThresholdint当数据量大于该值时,内容将被写入文件
locationString存放生成的文件地址
maxFileSizelong允许上传的文件最大值。默认值为-1,表示没有限制
maxRequestSizelong针对该multipart/form-data请求的最大数量,默认值为-1,表示没有限制

如何测试:
http://localhost:8080/java_war_exploded/
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值