zoukankan      html  css  js  c++  java
  • EL&JSTL&Filter&Listener

    day24-EL&JSTL&Filter&Listener

    第一章 EL表达式

    1.概述

    EL(Express Lanuage) 表达式可以嵌入在jsp页面内部,减少jsp脚本的编写,EL出现的目的主要是代替jsp页面中输出脚本<%= 数据%>的编写

    2.格式和作用

    EL表达式的格式

    ${EL表达式内容}
    

    EL表达式的作用:

    1. 从域对象中查找制定的数据
      1. ServletContext 作用域整个web程序
      2. session 一次会话
      3. request 一次请求
      4. pageContext 当前JSP页面
    2. EL内置对象的使用
    3. 执行运算符

    3.表达式的基本使用(从域中取数据)

    1.EL表达式取数据

    格式XXXXScope.key

    1. ${applicationScope.键名} ServletContext 域对象存储键值对
    2. ${sessionScope.键名} session 域对象存储键值对
    3. ${requestScope.键名} request.域对象存储键值对
    4. ${pageScope.键名} pageContext域对象存储键值对

    2.简化方式

    EL 表达式去处域对象的数据,简化方式,推荐使用

    ${键名} 将会从最小的域对象开始查找,一旦找到,就不会再继续查找

    友好型:客户端的友好型

    <%=%> 取出域对象数据,没有此键,页面中显示null

    ${} 取出域对象中的数据 没有此键,页面中显示" "

    3.通过EL表达式,获得普通数据

    格式:

    ${key}
    

    代码演示:

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>获取域容器中的数据</title>
    </head>
    <body>
        <%
            // 1 将数据保存到域容器中
            pageContext.setAttribute("city", "北京1"); // page
            pageContext.setAttribute("city", "北京2", PageContext.REQUEST_SCOPE); // request
            pageContext.setAttribute("city", "北京3", PageContext.SESSION_SCOPE); // session
            pageContext.setAttribute("city", "北京4", PageContext.APPLICATION_SCOPE); // servletContext
    
            // 2 删除指定域数据
            /*
            pageContext.removeAttribute("city", PageContext.PAGE_SCOPE); // page
            pageContext.removeAttribute("city", PageContext.REQUEST_SCOPE); // request
            pageContext.removeAttribute("city", PageContext.SESSION_SCOPE); // session
            pageContext.removeAttribute("city", PageContext.APPLICATION_SCOPE); // servletContext
             */
            pageContext.removeAttribute("city"); // 删除所有域中的数据
        %>
    
        <h1>java</h1>
            <h3>获取数据</h3>
            <%
                out.print(pageContext.getAttribute("city")!=null?pageContext.getAttribute("city"):""); // page
                out.print(pageContext.getAttribute("city", PageContext.REQUEST_SCOPE)); // request
                out.print(pageContext.getAttribute("city", PageContext.SESSION_SCOPE)); // session
                out.print(pageContext.getAttribute("city", PageContext.APPLICATION_SCOPE)); // servletContext
            %>
    
            <h3>智能获取数据</h3>
    
            <%
                /*
                pageContext.findAttribute(key) 根据key从四个域容器中依次获取数据, 如果获取到了,取值结束; 如果都没有获取到, 返回null
                 */
                out.print(pageContext.findAttribute("city"));
            %>
    
        <h1>EL</h1>
            <h3>获取数据</h3>
            ${pageScope.city}
            ${requestScope.city}
            ${sessionScope.city}
            ${applicationScope.city}
    
        <h3>智能获取数据</h3>
            ${city}
    </body>
    </html>
    

    4. EL获得javaBean对象的值

    格式:

    ${对象.成员变量}
    

    代码演示

    <%@ page import="cn.itcast.pojo.User" %>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%
            //  EL获得javaBean对象的值
            User user = new User();
            user.setUsername("zhangsan");
            user.setPassword("abc");
    
            request.setAttribute("user", user);
        %>
    
        <h1>java</h1>
        username = <%=((User)pageContext.findAttribute("user")).getUsername()%> <br/>
        password = <%=((User)pageContext.findAttribute("user")).getPassword()%> <br/>
        nickname = <%=((User)pageContext.findAttribute("user")).getNickname()%>
    
        <hr/>
    
        <h1>EL</h1>
            username === ${user.username} <br/>
            password === ${user.password} <br/>
            nickname === ${user.nickname} <br/>
    </body>
    </html>
    
    
    public class User {
        private String username;
        private String password;
        private String nickname;
        //省略构造方法、get、set方法
    }
    

    5. EL获得List<String>的值

    格式:

    ${List集合对象[索引]}
    

    代码演示

    <%@ page import="java.util.List" %>
    <%@ page import="java.util.ArrayList" %><%--
        EL表达式作用一(从域中取出数据): EL获得 List<String> 的值
    
        格式: ${ List集合对象[索引] }
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%--1.创建 List<String>集合, 存到Request域中 --%>
        <%
            List<String> list = new ArrayList<String>();
            list.add("迪丽热巴");
            list.add("古力娜扎");
            request.setAttribute("list",list);
        %>
    
        <%--2.通过EL表达式, 获取List<String>集合中的数据--%>
        <%--jsp方式获取--%>
        <%
            List<String> names = (List<String>) request.getAttribute("list");
            out.print( names.get(0) +" === "+ names.get(1) );
        %>
        <%--EL方式获取--%>
        ${list[0]} == ${list[1]}
    
    </body>
    </html>
    
    

    6.EL获得List<User>的值

    格式:

    ${List集合对象[索引].成员变量}
    

    代码演示

    <%@ page import="java.util.List" %>
    <%@ page import="java.util.ArrayList" %>
    <%@ page import="com.itheima.pojo.User" %><%--
        EL表达式作用一(从域中取出数据): EL获得 List<User> 的值
    
        格式: ${ List集合对象[索引].成员变量 }
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%--1.创建 List<User>集合, 存到Request域中 --%>
        <%
            List<User> list = new ArrayList<User>();
            list.add(new User("迪丽热巴","123456"));
            list.add(new User("古力娜扎","abcdef"));
            request.setAttribute("list",list);
        %>
    
        <%--2.通过EL表达式, 获取 List<User>集合中的数据--%>
        <%--jsp方式获取--%>
        <%
            List<User> users = (List<User>) request.getAttribute("list");
            out.print( users.get(0).getUsername() +"=="+ users.get(0).getPassword() );
            out.print( users.get(1).getUsername() +"=="+ users.get(1).getPassword() );
        %>
        <br/>
        <%--EL方式获取--%>
        ${list[0].username} == ${list[0].password}
        ${list[1].username} == ${list[1].password}
    
    </body>
    </html>
    

    7.EL获得Map<String,User>的值

    格式:

    ${Map集合对象.key.成员变量}
    或
    ${Map集合对象['key'].成员变量}
    

    代码演示

    <%@ page import="java.util.List" %>
    <%@ page import="java.util.ArrayList" %>
    <%@ page import="java.util.HashMap" %>
    <%@ page import="com.itheima.pojo.User" %>
    <%@ page import="java.util.Map" %><%--
        EL表达式作用一(从域中取出数据): EL获得 Map<String, User> 的值
    
        格式:
            ${Map集合对象.key.成员变量 }
            或
            ${Map集合对象['key'].成员变量}
    --%>
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <%--1.创建 Map<String, User>集合, 存到Request域中 --%>
        <%
            Map<String, User> userMap = new HashMap<String, User>();
            userMap.put("user1", new User("迪丽热巴","123456"));
            userMap.put("user2", new User("古力娜扎","abcdef"));
            request.setAttribute("userMap",userMap);
        %>
    
        <%--2.通过EL表达式, 获取 Map<String, User>集合中的数据--%>
        <%--jsp方式获取--%>
        <%
            Map<String, User> map = (Map<String, User>) request.getAttribute("userMap");
            out.print( map.get("user1").getUsername() +"=="+ map.get("user1").getPassword());
            out.print( map.get("user2").getUsername() +"=="+ map.get("user2").getPassword());
        %>
        <br/>
        <%--EL方式获取--%>
        ${userMap.user1.username} == ${userMap.user1.password}
        ${userMap.user2.username} == ${userMap.user2.password}
        <br/>
        ${userMap['user1'].username} == ${userMap['user1'].password}
        ${userMap['user2'].username} == ${userMap['user2'].password}
    
    </body>
    </html>
    
    

    4.EL的内置对象pageContext

    EL的四大内置对象

    1. applicationScope ServletContext域
    2. sessionScope session域
    3. requestScope request域
    4. pageScope pageContext域

    注意

    <%pageContext%>指的是pageContext域对象

    ${pageContext}指的是EL中的一个内置对象

    JSP中一共预先定义了9个这样的对象,分别为:request、response、session、application、out、pagecontext、config、page、exception

    pageContext : WEB开发中的页面的上下文对象.

    作用:可以用来获取JSP中四个域中的数据(pageScope, requestScope, sessionScope, applicationScope)

    • 例如,在Servlet中,想获得web应用的名称:request.getContextPath();
    • 那么,在jsp页面上,想获得web应用的名称:${pageContext.request.contextPath}
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>获取WEB应用项目名称</title>
    </head>
    <body>
        <h3>获取WEB应用项目名称</h3>
        <%--JSP方式获取--%>
        <%= request.getContextPath()%>
        <%--EL方式获取--%>
        ${pageContext.request.contextPath}
    </body>
    </html>
    
    

    5.EL执行运算符

    1. 算数运算符 + , - , * , / , %

    2. 逻辑运算符 && , || , !

    3. 比较运算符 > , < , >= , <= , == , !=

    4. Null运算符 empty 判空运算

      如果判断的对象是空,结果为true

      注意:

      1. 容器判断,判断的是长度 ==0 就是空
      2. 基本类型数组,不是判断长度,判断数组容器是否存在
      3. 基本类型数组,判断是空的话只能令他 = null 结果才为true
    5. 三元运算符

      • (布尔表达式)?结果1:结果2

    示例代码

    <body>
            ${(6>9)?"漂亮":"酷"}
            <br>
            <%
                User user = new User();
                pageContext.setAttribute("user",user);
    
                String[] str = new String[0];
                request.setAttribute("str",str);
    
                List<String> list = new ArrayList<String>();
                request.setAttribute("list",list);
    
                int[] arr = {};
                request.setAttribute("arr",arr);
    
                Integer[] ar = {};
                request.setAttribute("ar",ar);
            %>
                user对象为空吗:${empty user}<br><%--false--%>
                str数组为空吗:${empty str}<br><%--true--%>
                list集合为空吗:${empty list}<br><%--true--%>
                arr数组为空吗:${empty arr}<br><%--false--%>
                ar包装类数组为空吗:${empty ar}<br><%--true--%>
        </body>
    

    6.案例

    记录上一次登录所使用的用户名

    步骤

    1. 获取提交的用户名密码
    2. 获取是否“记住用户名”
    3. 判断和tom,123 匹配
      1. 如果匹配 重定向到首页
      2. 不匹配 转发回到登录首页;获取cookie中的username值。显示在页面上

    示例代码

    login首页

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>登录页面</title>
        </head>
        <body>
            <form action="${pageContext.request.contextPath}/login" method="post">
                <%-- 从Cookie中取出  user = tom--%>
                用户名:<input type="text" name="username" value="${cookie.user.value}"><br>
                密的码:<input type="password" name="password"><br>
                <input type="checkbox" name="rem" value="remUsername">记住用户名<br>
                <input type="submit" value="登录">
            </form>
        </body>
    </html>
    
    

    处理记住用户名的操作

    1. 用户名密码的验证
    2. 记录用户名
    @WebServlet(urlPatterns = "/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            // 获取用户名和密码
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            if ("tom".equals(username) && "123".equals(password)){
                response.getWriter().write("login ok");
            }else{
                response.getWriter().write("login no");
            }
    
            // 2.记住用户名
            // 判断是否勾复选框的value值
            String rem = request.getParameter("rem");// remUsername
            System.out.println(rem);
            if(rem != null){
                // 勾选记住用户名
                Cookie cookie = new Cookie("user", username);
                cookie.setMaxAge(60*10);
                cookie.setPath(request.getContextPath());
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
    

    第二章 JSTL的核心标签库使用

    1.概述

    JSTL(JSP Standard Tag Library),jsp标准标签库,可以嵌入在jsp页面中使用标签的形式完成业务逻辑等功能。jstl出现的目的和EL相同,也是要放在jsp页面中的脚本代码。

    JSTL标准标签库有5个子库,但随着发展,目前最常用的是核心库Core

    标签库 标签库的URI 前缀
    Core http://java.sun.com/jsp/jstl/core c
    I18N http://java.sun.com/jsp/jstl/fmt fmt
    SQL http://java.sun.com/jsp/jstl/sql sql
    XML http://java.sun.com/jsp/jstl/xml x
    Functions http://java.sun.com/jsp/jstl/functions fn

    2 jstl标签的安装

    导入jar包

    javax.servlet.jsp.jstl.jar
    standard.jar
    

    使用tagelib指令在jsp页面导入要是用的jstl标签库

    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
    

    3.常用的jstl标签

    jstl目前常用的标签只有if、foreach标签

    3.1 if标签

    if标签作用:起到java代码判断的作用

    if标签的属性介绍:

    1568524664183

    • test:判断是否执行标签内的内容(true--执行标签中的内容,false,不执行)。
    • var:用来保存test属性结果(使用var属性给他取个名字),这个结果可以保存到制定的web域中,默认保存在pageContext域
    • scope:指定保存数据到哪个web域

    示例代码

    <%-- if标签的使用--%>
    <%@ taglib prefix = "c" uri="http://java.sun.com/jsp/jstl/core"%>
    <%@ page contentType="text/html;charset=utf-8" language="java"%>
    <html>
        <head>
            <title>if标签</title>
        </head>
        <body>
            <%
           	int num = 10;
            pageContext.setAttribute("num",num);
            %>
            <c:if test="${num>5}"> num大于5</c:if>
            <c:if test="${num<=5}">num 小于等于5</c:if>
            
            <%--将判断结果  保存到var属性中,并存到指定的域对象--%>
            <c:if test="${num == 100}" var = "result" scope="request"></c:if>
            <h3>
                取出域对象中的值
            </h3>
            ${result}
        </body>
    </html>
    

    3.2 forEach标签 重点

    forEach标签作用:起到java代码的for循环作用

    forEach标签属性介绍

    1568524714801

    • var:在不循环对象的时候,保存的是控制循环的变量;在循环对象的时候,保存的是被循环对象中的元素
    • items:指定要循环的对象
    • varStatus:保存了当前循环过程中的信息(循环的开始、结束、步长、次数等)
    • begin:设置循环的开始
    • end:设置循环的结束
    • step:设置步长

    小结:

    foreach标签:循环,包括传统for和增强for
    传统for for(int a = 0;a<10;a++){}
    属性:
    begin="" 相当于 a=0
    end="" 相当于 a<10(包含10)
    step="" (步长)相当于 a++
    step="2" 相当于 1,3,5...
    var = "a" 属性var,定义属性值
    含义:将循环次数变量,存储到最小域对象 pageContext中
    键名就是a
    EL 表达式取出
    <c:foreach>
    循环体
    <c:foreach>

    遍历数组,遍历集合
    属性:
    items:遍历容器
    var:遍历的容器中的每个元素,存储在pageContext域对象中
    var属性值,就是与对象的键名

    varStatus(变量状态属性):
    varStatus="vs":会将对象,存在pageContext域中
    域对象的键名就是vs
    对象,是定义了循环状态的对象
    对象中有个属性count,循环的次数

    输出循环的次数
    int count = 0;
    for(String s:str){
        count++;
        System.out.println(s);
    }
    

    示例代码

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <body>
        <%--forEach标准循环--%>
        <c:forEach begin="1" end="10" step="1" var="a">
        	<div style="color:red;font-size:28px">
            	div区域 ${pageScope.a}
            </div>
        </c:forEach>
        
        <%--遍历集合--%>
        <%
                String[] strs = {"I","Love","Java"};
                pageContext.setAttribute("strs",strs);
            %>
            <c:forEach items="${strs}" var="s" varStatus="vs">
             <%--EL 在pageContext域中取出键值对,键是s,值是数组元素--%>
            ${s} ${vs.count}<br>
            </c:forEach>
        
         <%--集合,存储User对象--%>
            <%
                List<User> list = new ArrayList<User>();
                User u1 = new User();
                u1.setUsername("张三");
                u1.setPassword("123");
    
                User u2 = new User();
                u2.setUsername("李四");
                u2.setPassword("456");
    
                list.add(u1);
                list.add(u2);
    
                pageContext.setAttribute("list",list);
            %>
            <c:forEach items="${list}" var="s">
                ${s.username} ${s.password}
            </c:forEach>
    </body>
    

    第三章 过滤器Filter

    1.Filter概念

    过滤器:过筛子,符合条件的才能过去,不符合条件的过不去

    生活比喻:安检,检查安全的人与物才可以通过放行

    程序:客户端需要访问服务器的目标资源,在客户端和服务器资源之间设置过滤器,符合要求放行

    2.入门

    需求:

    • 浏览器要访问HelloServlet
    • 途径过滤期MyFilter, 若MyFilter放行,可执行访问到HelloServlet; 若不放行,无法访问HelloServlet

    执行图解:

    实现步骤

    1. 编写Servlet, 在web.xml配置Servlet访问路径
    2. 编写Filter,定义类, 实现接口Filter, 实现接口中抽象方法, 在web.xml配置Filter的访问过滤路径

    代码:Servlet

    @WebServlet(urlPatterns = "/servlet1")
    public class Servlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            response.getWriter().write("servlet");
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
    

    代码: MyFilter

    import javax.servlet.*;
    import java.io.IOException;
    
    /**
    * 过滤器的快速入门
     * 1.定义类实现接口 Fileter
     * 2.重写接口中的抽象方法
     * 3.web.xml配置
     * */
    public class MyFilter1 implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            //放行
            filterChain.doFilter(servletRequest,servletResponse);
        }
    
        @Override
        public void destroy() {
    
        }
    }
    

    代码: web.xml

     <!-- 配置过滤器  配置方式和servlet  90%一致-->
        <filter>
            <filter-name>myFilter1</filter-name>
            <filter-class>com.zhuxu.fitle.MyFilter1</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>myFilter1</filter-name>
            <!--
                Servlet配置  <url-pattern></url-pattern> 浏览器的访问地址
                Fileter配置  <url-pattern></url-pattern> 过滤器要拦截的资源
            -->
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    

    执行流程

    Tomcat服务器启动的时候,读取配置文件web.xml(过滤器的配置)

    Tomcat引擎读取完配置文件后,创建对象 FilterChain对象,过滤器链,维护着过滤器和资源之间的顺序

    request,response对象在Tomcat引擎创建对象,调用过滤器,层层传递参数,传递到servlet

    3.Filter的生命周期

    1.创建

    对象初始化创建,调用方法init(初始化)

    方法参数 FilterConfig

    Tomcat引擎创建过滤器对象,并调用init传递参数

    Tomcat启动的时候,创建过滤器对象

    方法参数 FilterConfig,过滤器配置对象

    可以获取到过滤器的 名字等等

    方法 getServletContext() 获取到最大对象

    2.拦截方法

    拦截方法doFilter

    每次访问要拦截的对象,就运行

    访问了,非拦截对象,不运行

    3.销毁

    对象的销毁方法 destroy()

    关闭服务器的时候,过滤器对象销毁

    4.Filter的url-pattern配置

    1.完全匹配

    要过滤的资源 /servlet1

    只拦截servlet1,其他资源不拦截 几乎不用

    没有必要为一个资源,创建过滤器

    <!-- 
        过滤资源,只有hello
        绝对匹配 <url-pattern>/hello</url-pattern>
        只能过滤指定的资源
    -->
    <url-pattern>/hello</url-pattern>
    

    2.目录匹配

    过滤器最常见的配置

    一次过滤一大片 /jstl/*

    拦截下 jstl目录下的所有资源

    <!--
       目录匹配,过滤器中最常见
       /abc/*  过滤abc目录下的所有资源
       一次过滤一片资源
       过滤后台资源 /admin/*
    -->
    <url-pattern>/admin/*</url-pattern>
    

    3.后缀名匹配

    /jstl/* 值拦截后缀名是.jsp

    <!-- 
      后缀名匹配,一般不使用
      *.jsp  访问所有jsp文件
    -->
    <url-pattern>*.jsp</url-pattern>
    

    4.四种拦截形式

    默认标签体中写的是REQUEST

    1. 请求拦截:默认配置,拦截客户端发来的请求
    2. 转发拦截:FORWARD Servlet1转发到Servlet2,就会拦截
    3. 包含拦截:INCLUDE 当一个jsp页面包含另一个jsp页面,拦截
    4. 错误拦截:ERROR 程序出现500错误,跳转到一个页面去 拦截

    5.注解配置Filter

    @WebFilter(urlPatterns="/过滤资源")

    @WebFilter("/*")
    public class ChinaFilter implements Filter {
        //代码省略...
    }
    
    package cn.itcast.web.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    // 方式一
    //@WebFilter(urlPatterns = {"/hello.jsp", "/helloServlet"})
    
    // 方式二
    // @WebFilter(urlPatterns = {"/hello.jsp"})
    
    // 方式三
    // @WebFilter(urlPatterns = "/hello.jsp")
    
    // 方式四
    @WebFilter("/hello.jsp")
    public class Filter3 implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            // 因为父类不能调用子类的方法,所以向下转型
            HttpServletRequest httpServletRequest = (HttpServletRequest) req;
            String uri = httpServletRequest.getRequestURI();
            System.out.println("执行过滤器3 ... ... 访问的路径: " + uri);
    
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
    }
    

    6 Filter 处理中文乱码

    新建一个拦截器

    每次拦截都执行doFilter方法

    方法的参数 servletRequest,servletResponse传递到Servlet的doGet方法

    过滤器中,设置request对象使用的编码表

    所有的Servlet都受益

    客户端中文显示设置

    servletRequest.setCharacterEncoding("utf-8");

    服务器端中文显示设置

    servletResponse.setContentType("text/html;charset=utf-8");

    代码: ChinaServlet

    @WebServlet("/china")
    public class ChinaServlet extends HttpServlet {
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String username = request.getParameter("username");
            System.out.println("ChinaServlet , 获取请求参数 username = " + username);
        }
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    

    代码: ChinaFilter

    @WebFilter("/*")
    public class ChinaFilter implements Filter {
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
            //在过滤器中,设置request对象的编码表
            req.setCharacterEncoding("utf-8");
            //设置response缓冲区的编码表,通知浏览器的解码
            resp.setContentType("text/html;charset=utf-8");
    
            System.out.println("ChinaFilter执行了, 过滤中文,设置编码utf-8");
            chain.doFilter(req, resp);
        }
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
        public void destroy() {
        }
    }
    

    7 过滤器链 FilterChain的执行过程

    Filter中的过滤器链 FilterChain: 由Tomcat引擎创建对象

    作用: 维护过滤器执行顺序

    1568641974893

    小结: Servlet中doGet方法参数 request, response对象, 由Tomcat引擎创建, 经过多个过滤器一层层传递

    8 多个过滤器的先后执行顺序

    web.xml配置

    和配置文件的编写顺序决定运行的顺序,准确的说法是,根据mapping的顺序决定 (由上到下执行)

    注解开发

    注解开发没有配置文件的

    按照类名的自然顺序决定: A-B-C(不区分大小写) 1 2 3

    如果存在配置文件,配置文件优先

    9.过滤器案例:登录验证(权限校验)

    1.需求

    1. 访问项目的资源。验证是否登录
    2. 如果登陆了,则直接放行
    3. 如果没有登录,则跳转到登录页面,提示“尚未登录,请先登录”

    2.实现

    1.登录页面 login.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>登录页面</title>
        </head>
        <body>
            <!--登录失败的提示信息-->
            ${message}
            <form action="${pageContext.request.contextPath}/login" method="post">
                用户名:<input type="text" name="username"><br>
                密 &nbsp;&nbsp;码:<input type="password" name="password"><br>
                <input type="submit" value="登录">
            </form>
        </body>
    </html>
    

    2.登录成功界面

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
        <head>
            <title>成功界面</title>
        </head>
        <body>
            <h1>欢迎访问</h1>
        </body>
    </html>
    

    3.过滤器

    @WebFilter(urlPatterns = "/resource/*")
    public class LoginFilter implements Filter {
        /**
         * 登录的过滤,如果登录,直接放行
         * 没有登录,退到登录页面上
         * 客户端是否登录取决于session域对象
         * */
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
    
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            // 取出session域对象的值
            // ServletRequest转成子接口
            HttpServletRequest request = (HttpServletRequest)servletRequest;
            HttpServletResponse response = (HttpServletResponse)servletResponse;
    
            String username = (String) request.getSession().getAttribute("username");
            if (username == null){
                // 没有登录,退到登录页面
                request.setAttribute("message","请先登录,再访问");
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }else{
                // 登录状态直接放行
                filterChain.doFilter(request,response);
            }
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    

    4.Servlet

    /**
     * 处理客户端登录的请求
     * 用户名 密码 tom 123
     * 登录验证
     *      登录成功,页面跳转到 resource/welcome.jsp
     *      登录信息存储到session域中
     *
     *      登录失败,回到登录页面去
     * */
    @WebServlet(urlPatterns = "/login")
    public class LoginServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            String username = request.getParameter("username");
            String password = request.getParameter("password");
            if ("tom".equals(username) && "123".equals(password)){
                // 登陆成功,用户名存储在session
                request.getSession().setAttribute("username",username);
                // 页面跳转到 resource/welcome.jsp
                // 重定向,需要写web应用名称
                response.sendRedirect(request.getContextPath()+"/resource/welcome.jsp");
            }else{
                // 登录失败
                // 回到登录页面,告知用户登录失败,request域存储登录失败的信息
                request.setAttribute("message","登录失败,用户名或者密码输入错误");
                request.getRequestDispatcher("/login.jsp").forward(request,response);
            }
        }
    
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    

    第四章 监听器Listener(了解)

    1 Listener概述

    监听器Listener 是 监听某个组件变化的对象.

    • 事件源是固定的,主要是request, session, servletcontext域对象

    • 监听的是域对象变化

      • 对象的创建和销毁, 域对象中存储的数据变化
    • 第一个维度划分:

      • 监听的域对象request, session, servletcontext

        域对象 监听器
        request ServletRequestListener
        session HttpSessionListener
        servletcontext ServletContextListener
    • 第二个维度划分:

      • 监听的域对象的状态

    2 ServletContext监听器入门

    用于监听 servletcontext域对象, 对象的创建和销毁, 域对象中存储的数据变化

    实现步骤

    • 创建类实现监听器接口 ServletContextListener
    • 重写抽象方法
    • 注解方式 配置 Listener
    @WebListener
    public class MyServletContextListener implements ServletContextListener {
        @Override
        /**
         *  ServletContext对象,被创建,调用
         */
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext域对象创建");
        }
    
        @Override
        /**
         *   ServletContext对象,被销毁前调用
         */
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext域对象销毁");
        }
    }
    
    • web.xml配置方式 Listener
    <listener>
        <listener-class>com.itheima.listener.MyServletContextListener</listener-class>
    </listener>
    

    3 监听器事件对象 ServletContextEvent

    ServletContextEvent: 是ServletContext域对象的事件对象, 此对象由tomcat引擎创建ServletContext

    • 方法:
      • Object getSource() 获取到被监听的事件源
      • ServletContext getServletContext() 获取到被监听的事件源
    • 小结:
      • 两个方法 除了返回值外,功能实现是一致的, 设计目的为了通用性
      • 其他的监听器事件对象(HttpSessionEvent, ServletRequestEvent), 都有共同的方法 getSource()
    @WebListener
    public class MyServletContextListener implements ServletContextListener {
        @Override
        /**
         *  ServletContext对象,被创建,调用
         */
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext域对象创建");
            ServletContext context = (ServletContext) servletContextEvent.getSource();
            System.out.println(context);
    
            ServletContext servletContext = servletContextEvent.getServletContext();
            System.out.println(servletContext);
        }
    
        @Override
        /**
         *   ServletContext对象,被销毁前调用
         */
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("ServletContext域对象销毁");
        }
    }
    

    4 注解版

    package cn.itcast.listener;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebListener;
    import javax.servlet.http.*;
    
    // 每次请求都会创建一个新的request对象; 当响应结束后,立刻销毁request对象
    @WebListener
    public class MyRequestListener implements ServletRequestListener {
    
        @Override
        public void requestInitialized(ServletRequestEvent servletRequestEvent) {
            ServletRequest servletRequest = servletRequestEvent.getServletRequest();
            HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
            System.out.println("新的request对象创建了 .... ... 路径: " + httpServletRequest.getRequestURI());
        }
    
        @Override
        public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
            System.out.println("request对象销毁了 .... ...");
        }
    
    }
    

    重点 Servlet抽取源

    如 登录 注册 ....

    首页

    <html>
    <head>
        <title>Title</title>
        <style>
            body{
                font-size: 20px;
            }
        </style>
    </head>
    <body>
        <%--
          每个超链接上添加参数,告知服务器,我要做什么
        --%>
        <a href="${pageContext.request.contextPath}/user?operator=login">登录</a> <br>
        <a href="${pageContext.request.contextPath}/user?operator=register">注册</a> <br>
        <a href="${pageContext.request.contextPath}/user?operator=updatePassword">改密</a> <br>
        <a href="${pageContext.request.contextPath}/user?operator=findPassword">找回密码</a> <br>
    
    </body>
    </html>
    

    处理请求操作

    /**
     * 所有的客户端的用户操作请求
     * 我来实现
     * */
    @WebServlet(urlPatterns = "/user")
    public class UserServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
            // 获取客户端超链接的参数
         /*   String operator = request.getParameter("operator");
            if ("login".equals("operator")){
                login();
            }else if ("register".equals(operator)){
                register();
            }else if ("updatePassword".equals(operator)){
                updatePassword();
            }*/
            // 优化
            String operator = request.getParameter("operator");
            // 反射,获取客户端参数  opreator 是方法名
            try {
                Class cla = this.getClass();
                // 获取方法
                Method method = cla.getMethod(operator,HttpServletResponse.class,HttpServletResponse.class);
                method.invoke(this,request,response);
            }catch (Exception exception){
                exception.printStackTrace();
            }
        }
    
        // 方法处理登录
        public void login(HttpServletRequest request, HttpServletResponse response){
            System.out.println("处理登录的方法");
        }
    
        // 方法处理注册
        public void register(HttpServletRequest request, HttpServletResponse response){
            System.out.println("处理注册的方法");
        }
    
        // 方法处理改密
        public void updatePassword(HttpServletRequest request, HttpServletResponse response){
            System.out.println("处理修改密码的方法");
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            doGet(request, response);
        }
    }
    
    
  • 相关阅读:
    ERROR: Cannot set priority of registrydns process 33740
    Hbase和Phoenix部署-单机版
    ambari安装hdp时,新建的ambari-hdp-1.repo中baseurl无值
    centos7.2升级openssh到8.0
    kafka一个broker挂掉无法写入
    对cdh搭建过程错误总结及解决方法
    streamsets
    [Spark]Task not serializable
    [Kafka]How to Clean Topic data
    Postgresql Master/Slaver
  • 原文地址:https://www.cnblogs.com/anke-z/p/13269087.html
Copyright © 2011-2022 走看看