欢迎来到 Kong Xiangqun 的博客

2、Servlet系列jsp

我们之前写的一个简单登陆的一个程序

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

public class PageServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("接受到客户端的请求,返回响应的登录页面");

        String str = (String) request.getAttribute("str")==null?"":(String) request.getAttribute("str");
        System.out.println(str);
        //设置响应编码
        response.setContentType("text/html");
        //获取响应的输出流对象
        PrintWriter out = response.getWriter();
        out.write("<html>");
        out.write("<head>");
        out.write("</head>");
        out.write("<body>");
        out.write("<font color='red' size='20px'>"+str+"</font>");
        out.write("<form action='login' method='get'>");
        out.write("name:<input type='text' name='name' value='' ><br/>");
        out.write("pwd:<input type='text' name='pwd' value=''><br/>");
        out.write("<input type='submit' value='login'>");
        out.write("</form>");
        out.write("</body>");
        out.write("</html>");
    }
}

标签都是我们手动写的

servlet本质上就是一个java类

通过java代码我们一般实现的是java逻辑

但是我们这通过write返回了一堆字符串, 只不过是特殊的字符串

与html标签吻合

相应可能包含页面,我们不能每个都写成这样,这里面还有动态数据,每一次改都需要改这个类

能不能解耦???

这样就有了jsp

html是死的,jsp可以是动态界面

 

Servlet:

  优点:逻辑处理方便

  缺点:页面表现麻烦

JSP:

  优点:页面表现方便

  缺点:逻辑处理麻烦

注意:一般在web项目中,采用JSP+Servlet+JavaBean的技术(SSM)

JSP约等于java+html

一、JSP相关

1、JSP本质

JSP是一种动态网页技术

  动态生成网页数据,而不是有动态效果的网页!

  常见的几种动态网页技术:

    JSP(Java Server Page)

    ASP(Active Server Page)

    PHP(Hypertext Preprocessor) 超级文本预处理语言

本质:JSP就是Servlet,JSP也是Java类,通过JSP引擎将JSP转译成Servlet

 

2、JSP的运行原理

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    my first jsp
</body>
</html>

打印结果为:

 

 它是怎么处理流程??

上面说本质就是Servlet

 

 web.xml里没有任何配置项

web.xml针对每个web项目都有一个xml, 同时tomcat里也有个web.xml

 

 我们输入1.jsp, 映射对应了, servlet-name是jsp

 

 jsp对应的类是JspServlet, 所以说本质是JspServlet

 

所以当发送一个jsp请求时, 看起来像是访问当前项目的静态资源, 实际上依然请求的是servlet, 

只是把jsp的页面翻译成了servlet这样一个类

 

 

 

 

浏览器输入:localhost:8080/jsp/1.jsp

tomcat收到*.jsp请求,则会到org.apache.jasper.servlet.JspServlet处理

JspServlet调用相应的java类,jsp引擎根据_1_.jsp生成的java类(位于tomcat子目录work下面:_1_jsp.java,_1_jsp.class)

执行_1_.jsp.class,将HTML数据输出给tomcat,tomcat再将这些数据输出给客户端

3、jsp的page指令

page
    <%@ page contentType="text/html; charset=GBK"%>
    <%@ page import="java.util.*, java.lang.*" %> 
    <%@ page errorPage="error.jsp" %>
include
    <%@ include file=“相对位置” %>
taglib
    <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
<%@ page contentType="text/html;charset=UTF-8" language="java" import="java.util.*,java.lang.*" pageEncoding="utf-8" %>
<%@ page session="true" %>
<%@ page errorPage="error.jsp" isErrorPage="true" %>
<%--
    html注释
        也会被转译成java文件,会发送给浏览器,但是浏览器不会执行
    java注释
        也会被转译,但是不会发送给浏览器
    jsp注释
        不会被转译
--%>
<%--
    page:
        用来设置转译成servlet文件时的参数
            contentType:表示浏览器解析响应信息的时候使用的编码和解析格式
            language:表示jsp要转译成的文件类型
            import:导入需要的jar包,多个包使用逗号分隔
            pageEncoding:设置页面的编码格式
            session:用来控制sevlet中是否有session对象
            errorPage:当页面发生逻辑错误的时候,跳转的页面
            extends:需要要转译的servlet类要继承的父类(包名+类名)
--%>

4、jsp如何嵌入java代码

<%--
    局部代码块:
        可以将java代码跟页面展示的标签写到一个jsp页面中,java代码转译成的servlet文件中,java代码跟输出是保存在service方法中的
        缺点:
            代码可读性比较差,开发比较麻烦
            一般不使用
    全局代码块:
        定义公共的方法的时候需要使用全局代码块使用<%!%>、,生成的代码在servlet类中
        调用的时候需要使用局部代码块
    脚本调用方式
        使用<%=直接调用变量和方法(必须有返回值)%>
        注意:不能再变量或方法的后面添加;
--%>

局部代码块

<%
 int i = new Random().nextInt(10);
 int a = 100;
 if(i>5){
%>
<b>今天天气很好</b>
<%}else{
%>
<b>今天天气不好</b>
<%}%>

一般不适用

 

全局代码块

<%!
    String str="jsp简单";
public void  test(){
    System.out.println("我是全局代码块");
}

public String hehe(){
    return "hehe";
}
%>

<%
 int i = new Random().nextInt(10);
 int a = 100;
 if(i>5){
%>
<b>今天天气很好</b>
<%=str%>
<%}else{
%>
<b>今天天气不好</b>
<%=hehe()%>
<%}%>

5、jsp页面导入方式include

<%--
    页面导入的方式
        静态导入:
            <%@ include file="staticImport.jsp"%>  file中填写的是jsp文件的相对路径
            不会将静态导入的页面生成一个新的servlet文件,而是将两个文件合并,
            优点:运行效率高
            缺点:两个页面会耦合到一起,不利于维护,两个页面中不能存在相同名称的变量名
        动态导入:
            <jsp:include page="dynamicImport.jsp"></jsp:include>
            两个页面不会进行合并,分别生成自己的servlet文件,但是页面在最终展示的时候是合并到一起的
            优点:没有耦合,可以存在同名的变量
--%>

staticImport.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
//int a= 200;
%>
<b>我是静态导入页面</b>
</body>
</html>
staticImport.jsp

dynamicImport.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<b>我是动态导入</b>
</body>
</html>
dynamicImport.jsp
<%@ include file="staticImport.jsp"%>
<jsp:include page="dynamicImport.jsp"></jsp:include>

6、jsp请求转发forword

<%--
请求转发:
            在jsp中也可以实现servlet的请求转发功能
            <jsp:forward page="forward.jsp"></jsp:forward>  page填写的是jsp页面的相对路径
            注意:在标签中间不可以添加任何字符.除了<jsp:param name="" value="">
            在转发的页面中想要获取到属性值通过request.getParameter(String key)
--%>

forward.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<b>我是转发页面</b>
<%=request.getParameter("china")%>
<hr>
<%=request.getParameter("hebei")%>
</body>
</html>
forward.jsp
<jsp:forward page="forward.jsp">
    <jsp:param name="china" value="beijing"></jsp:param>
    <jsp:param name="hebei" value="shijiazhaung"></jsp:param>
</jsp:forward>
<%
    response.sendRedirect("forward.jsp");
%>

forward 一次请求服务端进行转发

7、jsp九大内置对象

<%--
九大对象:
                pageContext:表示页面的上下文的对象封存了其他的内置对象,封存了当前页面的运行信息
                            注意:每一个页面都有一个对应的pagecontext对象,
                            伴随着当前页面的结束而结束
                request:封装当前请求的数据,由tomcat创建,一次请求对应一个request对象
                session:用来封装同一个用户的不同请求的共享数据,一次会话对应一个session对象
                application:相当于ServletContext对象,一个web项目只有一个对象,存储着所有用户的共享数据,从服务器启动到服务器结束
                response:响应对象,用来响应请求数据,将处理结果返回给浏览器,可以进行重定向
                page:代表当前jsp对象,跟java中的this指针类似
                exception:异常对象,存储当前运行的异常信息,必须在page指令=中添加属性isErrorPage=true
                config:相当于Serlverconfig对象,用来获取web.xml中配置的数据,完成servlet的初始化操作
                out:响应对象,jsp内部使用,带有缓存区的响应对象,效率要高于repsonse
--%>

四大作用域

<%--
四大作用域:
        pageContext:表示当前页面,解决当前页面内的数据共享问题,获取其他内置对象
        request:一次请求,一次请求的servlet的数据共享,通过请求转发的方式,将数据流转到下一个servlet
        session:一次会话,一个用户发送的不同请求之间的数据共享,可以将数据从一个请求流转到其他请求
        application:项目内,不同用的数据共享问题,将数据从一个用户流转到其他用户
--%>

路径问题

<%--
路径问题:
        想要获取项目中的资源,可以使用相对路径,也可以使用绝对路径
        相对路径:相对于当前页面的路径
        问题:1、资源的位置不可以随便更改
             2、需要使用../的方式进行文件夹的跳出,如果目录结果比较深,可以操作起来比较麻烦
             绝对路径:
                在请求路径的前面加/,表示当前服务器的根路径,使用的时候要添加/虚拟项目名称/资源目录
                使用jsp中自带的全局路径声明:
                    <%
                    String path = request.getContextPath();
                        System.out.println(path);
                    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
                        System.out.println(basePath);

                    %>
                    <base href="<%=basePath%>">

         添加资源路径的时候,从当前项目的web目录下添加即可
--%>

目录层级为

 

 

 a.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    System.out.println(path);
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    System.out.println(basePath);

%>
<html>
<head>
    <base href="<%=basePath%>">

    <title>Title</title>
</head>
<body>
aaaaaaaaaaaaaaa
<a href="page.jsp">page</a>
</body>
</html>
a.jsp

b.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    System.out.println(path);
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    System.out.println(basePath);

%>
<html>
<head>
    <base href="<%=basePath%>">

    <title>Title</title>
</head>
<body>
bbbbbbbbbbbbb
<a href="page.jsp">page</a>
</body>
</html>
b.jsp

page.jsp

<html>
<head>
    <base href="<%=basePath%>">
    <title>Title</title>
</head>
<body>
    <a href="a/a.jsp">aaa</a>
    <a href="b/b.jsp">bbb</a>
</body>
</html>

二、EL表达式

传统方式

el.jsp

<%@ page import="com.mashibing.entity.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--使用传统方式获取作用域中的值-->
name:<%=request.getParameter("name")%>
pwd:<%=request.getParameter("pwd")%>
aa:<%=request.getAttribute("aa")%>
town:<%=((User)request.getAttribute("user")).getAddress().getTown()%>
武安:<%=((User)((ArrayList)request.getAttribute("list")).get(1)).getAddress().getTown()%>
mapvalue:<%=((HashMap)request.getAttribute("map")).get("china")%>
mapUser:<%=((User)((HashMap)request.getAttribute("map2")).get("a1")).getAddress().getTown()%>
<br/>
</body>
</html>
public class ELServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //设置请求响应的编码格式
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        //从请求中获取数据
        String name = request.getParameter("name");
        String pwd = request.getParameter("pwd");
        System.out.println(name);
        System.out.println(pwd);
        //给request对象单独设置属性
        request.setAttribute("aa","aaaaa");
        //给request添加对象
        User user = new User(1,"张三",new Address("北京市","北京市","海淀区"));
        User user2 = new User(2,"张三",new Address("河北省","邯郸市","武安"));

        ArrayList<User> list  =new ArrayList<>();
        list.add(user);
        list.add(user2);
        request.setAttribute("user",user);

        //给request对象设置集合
        request.setAttribute("list",list);

        //给reqeust对象设置map对象
        HashMap<String,String> map = new HashMap<>();
        map.put("china","beijing");
        map.put("hebei","shijiazhuang");

        request.setAttribute("map",map);

        HashMap<String,User> map2 = new HashMap<>();
        map2.put("a1",user);
        map2.put("a2",user2);

        request.setAttribute("map2",map2);

        //通过请求转发的方式跳转到某一个jsp页面
        request.getRequestDispatcher("el.jsp").forward(request,response);
    }
}

User.java

public class User {
    private int id;
    private String name;
    private Address address;

    public User(int id, String name, Address address) {
        this.id = id;
        this.name = name;
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", address=" + address +
                '}';
    }
}
User.java

Address.java

public class Address {
    private String province;
    private String city;
    private String town;

    public Address(String province, String city, String town) {
        this.province = province;
        this.city = city;
        this.town = town;
    }

    public String getProvince() {
        return province;
    }

    public void setProvince(String province) {
        this.province = province;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getTown() {
        return town;
    }

    public void setTown(String town) {
        this.town = town;
    }

    @Override
    public String toString() {
        return "Address{" +
                "province='" + province + '\'' +
                ", city='" + city + '\'' +
                ", town='" + town + '\'' +
                '}';
    }
}
Address.java

访问页面为:

 

<!--
使用传统方式获取request对象中的值有一下缺点
1、必须要导入包
2、进行类型的强制转换
3、层次结构比较复杂

解决办法使用EL表达式
-->

1、EL表达式的概念

/**
 * EL表达式
 *      概念;
 *          Experssion Language,一种表达式语言,语法简单
 *      作用
 *          方便jsp页面获取作用域中的属性
 *      语法规则:
 *          ${expression},可以使用.或者[]来获取属性值或者指定索引位置的对象
 *          获取值的时候,直接使用作用域中的key即可,然后使用.来引用属性,使用[]来获取指定索引位置的对象
 *
*/

el.jsp

<%@ page import="com.mashibing.entity.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--使用传统方式获取作用域中的值-->
name:<%=request.getParameter("name")%>
pwd:<%=request.getParameter("pwd")%>
aa:<%=request.getAttribute("aa")%>
town:<%=((User)request.getAttribute("user")).getAddress().getTown()%>
武安:<%=((User)((ArrayList)request.getAttribute("list")).get(1)).getAddress().getTown()%>
mapvalue:<%=((HashMap)request.getAttribute("map")).get("china")%>
mapUser:<%=((User)((HashMap)request.getAttribute("map2")).get("a1")).getAddress().getTown()%>
<br/>

<!--使用el表达式获取对象的顺序-->
<%
    pageContext.setAttribute("key","hello pageContext");
    request.setAttribute("key","hello request");
    session.setAttribute("key","hello session");
    application.setAttribute("key","hello application");
%>
key:${key}<br>
pageContext:${pageScope.key}<br>
request:${requestScope.key}<br>
session:${sessionScope.key}<br>
application:${applicationScope.key}<br>
</body>
</html>

访问页面:

 

 

 

使用EL表达式获取请求数据

  获取用户请求数据

  获取请求头数据

  获取cookie数据

使用EL表达式获取作用域数据

  获取作用域数据

  作用域查找顺序

  获取指定作用域中的数据

使用EL表达式进行运算

  算术运算

  关系运算

  逻辑运算

2、EL表达式作用域及算数运算关系运算

/**
 *      作用域:
 *          pageContext--->request--->session--->application
 *      获取作用域数据的顺序:
 *          从小的作用域开始查询,如果找到则返回对应的值,不接着向大范围寻找数据
 *          当四种作用域中存在相同key的属性的时候,可以通过pageScope,requestScope,sessionScope,applicationScope获取指定作用域的数据
*/
<%@ page import="com.mashibing.entity.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--使用el表达式获取对象的顺序-->
<%
    pageContext.setAttribute("key","hello pageContext");
    request.setAttribute("key","hello request");
    session.setAttribute("key","hello session");
    application.setAttribute("key","hello application");
%>
key:${key}<br>
pageContext:${pageScope.key}<br>
request:${requestScope.key}<br>
session:${sessionScope.key}<br>
application:${applicationScope.key}<br>
</body>
</html>

导入一下jsp-api的jar包

/**
 *      EL表达式可以进行算术运算和关系运算
 *          直接在表达式中写入算法操作即可,如果是关系运算,返回true或者false
 *          注意:在el表达式中的+表示加法操作而不是字符串连接符
 */
<%@ page import="com.mashibing.entity.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--使用EL表达式进行基本运算-->
${1+2}<br>
${1-2}<br>
${1*2}<br>
${1/2}<br>
${1%2}<br>
${1>2}<br>
${1>2?"男":"女"}
<%--${1+"abc"}--%>
</body>
</html>

 

 

 3、获取cookie和请求头信息

/**
 *      EL表达式获取header信息
 *          ${header}:获取所有请求头信息
 *          ${header[key]}:获取指定key的数据
 *          ${headerValues[key]}:获取key对应的一组数据,返回类型是数组
 *          ${headervalues[key][0]}:获取key对应数组的某一个值
 *      EL表达式获取cookie数据:
 *          ${cookie}:获取cookie中的所有数据
 *          ${cookie.key}:获取cookie中指定key的数据
 *          ${cookie.key.name}:获取cookie指定key数据的name
 *          ${cookie.key.value}:获取cookie指定key数据的value
 */
<%@ page import="com.mashibing.entity.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--获取请求头数据-->
${header}<br>
${header["host"]}<br>
${headerValues["accept-language"][0]}<br>
<!--获取cookie数据-->
${cookie}<<br>
${cookie.JSESSIONID}<br>
${cookie.JSESSIONID.name}<br>
${cookie.JSESSIONID.value}<br>
</body>
</html>

 

 

 4、逻辑运算符

<%@ page import="com.mashibing.entity.User" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--el表达式逻辑运算-->
${true&&false}<br>
${true&&true}<br>
${true||false}<br>
${true||true}<br>
</body>
</html>

 

 

三、JSTL标签库

需要给el表达式加一些判断, 也可以写入java代码,<%java代码%> ,又把逻辑处理代码和页面展示标签合到一起了,

可读性较差,可维护性也比较差

JSTL 是 apache 对 EL 表达式的扩展(也就是说 JSTL 依赖 EL),JSTL 是标签语言! JSTL 标签使用以来非常方便, 它与 JSP 动作标签一样, 只不过它不是 JSP 内置的标签, 需要我们自己导包, 以及指定标签库而已!

如果你使用 MyEclipse 开发 JavaWeb, 那么在把项目发布到 Tomcat 时, 你会发现, MyEclipse 会在 lib 目录下存放 jstl 的Jar 包! 如果你没有使用 MyEclipse 开发那么需要自己来导入这个JSTL 的 Jar 包: jstl-1.2.jar。

/*
JSTL
    帮助我们在jsp页面中添加复杂的逻辑判断,避免逻辑代码和页面标签混为一谈
    JSTL是EL的扩展,同时,JSTL依赖于EL,为了方便的从作用域中获取值

    JSTL的导入:
        添加jstl.jar,standard.jar添加到web-inf下的lib目录
        <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    标签分类:
        核心标签库:必须掌握
        格式化标签库:掌握
        函数标签库:了解
        XML标签库:了解
        SQL标签库:了解
*/

 

 

 

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

taglib 指定uri 可能飘红

File->Settings->Languages & Frameworks->Schemas and DTDs

 

 

 https://archive.apache.org/dist/jakarta/taglibs/standard/binaries/

一步一步点就进apache

https://archive.apache.org/

一次点击

Archive of public software releases

jakarta   ----- taglibs-------standard

binaries

 1、向作用域增加删除标签

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.HashMap" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<%
    request.setAttribute("str","happy");
    request.setAttribute("hello","world");
    request.setAttribute("java","1234");
%>
    <c:out value="哈哈" default="嘿嘿"></c:out><br>
    <c:out value="${str2}" default="嘿嘿"></c:out><br>
    <c:out value="${hello}"></c:out>

<!--向作用域设置属性值-->
    <c:set var="java" value="pageContext" scope="page"></c:set>
    <c:set var="java" value="request" scope="request"></c:set>
    <c:set var="java" value="session" scope="session"></c:set>
    <c:set var="java" value="application" scope="application"></c:set>

    <c:out value="${pageScope.java}"></c:out><br>
    <c:out value="${requestScope.java}"></c:out><br>
    <c:out value="${sessionScope.java}"></c:out><br>
    <c:out value="${applicationScope.java}"></c:out><br>
<!--删除作用域的数据-->
    <c:remove var="java" scope="request"></c:remove>
    <c:out value="${pageScope.java}"></c:out><br>
    <c:out value="${requestScope.java}"></c:out><br>
    <c:out value="${sessionScope.java}"></c:out><br>
    <c:out value="${applicationScope.java}"></c:out><br>

</body>
</html>
/*
        <c:out value="哈哈"></c:out>  输出标签
            value:填写要输出的值
            default:默认值
        <c:set var="java" value="pageContext"></c:set>  向作用域设置属性值
            var:表示参数的key
            value:表示参数的值
            scope:表示向哪个作用域设置属性值
            注意:当只配置这两个属性的时候,默认是向pageContext作用域中设置属性,可以通过参数来做选择向哪个作用域设置
         <c:remove var="java"></c:remove>  删除作用域中的数据
            var:表示参数的key
            scope:删除指定作用域的数据
            注意:如果没有指定scope属性,那么默认会把所有作用域中的参数都删除

*/

 

 

 

2、逻辑判断表达式

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--逻辑判断标签-->
<%
    int i =10;
    if(i>5){
%>
    jstl is easy
    <%}%>
<c:set var="a" value="6"></c:set>
<c:if test="${a>5}" var="flag" scope="request">
    <h1>jstl is easy</h1>
</c:if>
</body> 
</html>

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<c:set var="age" value="15"></c:set>
<c:choose>
    <c:when test="${age<10}">
        <h1>小孩</h1>
    </c:when>
    <c:when test="${age<20}">
        <h1>青少年</h1>
    </c:when>
    <c:when test="${age<30}">
        <h1>青年</h1>
    </c:when>
    <c:when test="${age<40}">
        <h1>中年</h1>
    </c:when>
    <c:otherwise>
        <h1> i don't know</h1>
    </c:otherwise>
</c:choose>
</body> 
</html>

/*
        <c:if test="${a>5}">        逻辑判断,if判断
            <h1>jstl is easy</h1>
        </c:if>
            test:填写逻辑判断表达式
            var:条件表达式的结果存储变量
            scope:结果变量存储的作用域
        <c:choose>          进行多重逻辑判断,类似于switch
            <c:when test="${age<10}">
                <h1>小孩</h1>
            </c:when>
            <c:when test="${age<20}">
                <h1>青少年</h1>
            </c:when>
            <c:when test="${age<30}">
                <h1>青年</h1>
            </c:when>
            <c:when test="${age<40}">
                <h1>中年</h1>
            </c:when>
            <c:otherwise>
                <h1> i don't know</h1>
            </c:otherwise>
        </c:choose>
*/

 

 3、循环标签

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<!--循环标签-->
<table border="1px">
    <tr>
        <td>1</td>
        <td>111</td>
    </tr>
    <tr>
        <td>2</td>
        <td>222</td>
    </tr>
    <tr>
        <td>3</td>
        <td>333</td>
    </tr>
</table>
<%--<% for(int i = 0;i<=3;i++)%>--%>
<c:forEach begin="0" end="3" step="1" varStatus="sta"> <--% 循环状态标识符--%>
    ${sta.index}---${sta.count}----${sta.first}---${sta.last}<br>
</c:forEach>
<%
    ArrayList<String> list = new ArrayList<String>();
    list.add("aaa");
    list.add("bbb");
    list.add("ccc");
    request.setAttribute("list",list);

    HashMap<String,String> map = new HashMap<String,String>();
    map.put("1","111");
    map.put("2","222");
    map.put("3","333");
    map.put("4","444");
    map.put("5","555");
    map.put("6","666");
    request.setAttribute("map",map);

%>
<c:forEach begin="0" end="3" step="1" varStatus="sta" var="i" items="${list}">
    ${i}
</c:forEach>
<table border="1px">
<c:forEach begin="0" end="5" step="1" var="i" items="${map}">
    <tr>
        <td>${i.key}</td>
        <td>${i.value}</td>
    </tr>
</c:forEach>
    <hr/>
    <h3>数字格式化:</h3>
    <c:set var="balance" value="120000.2309" />
    <p>格式化数字 (1): <fmt:formatNumber value="${balance}"
                                    type="currency"/></p>
    <p>格式化数字 (2): <fmt:formatNumber type="number"
                                    maxIntegerDigits="3" value="${balance}" /></p>
    <p>格式化数字 (3): <fmt:formatNumber type="number"
                                    maxFractionDigits="3" value="${balance}" /></p>
    <p>格式化数字 (4): <fmt:formatNumber type="number"
                                    groupingUsed="false" value="${balance}" /></p>
    <p>格式化数字 (5): <fmt:formatNumber type="percent"
                                    maxIntegerDigits="3" value="${balance}" /></p>
    <p>格式化数字 (6): <fmt:formatNumber type="percent"
                                    minFractionDigits="10" value="${balance}" /></p>
    <p>格式化数字 (7): <fmt:formatNumber type="percent"
                                    maxIntegerDigits="3" value="${balance}" /></p>
    <p>格式化数字 (8): <fmt:formatNumber type="number"
                                    pattern="###.###E0" value="${balance}" /></p>
    <p>美元 :
        <fmt:setLocale value="en_US"/>
        <fmt:formatNumber value="${balance}" type="currency"/></p>


</table>
</body> 
</html>

第一天记录first肯定是true 不是最后一条记录 false

中间两条肯定都是false

最后一天 last 肯定是true

/*
        <c:forEach begin="0" end="3" step="1" varStatus="sta" var="i" items="${list}">  循环标签
            ${i}
        </c:forEach>

        begin:起始值
        end:结束值
        step:步长
        varStatus:循环状态的变量值名称
        var:集合数据的每条记录的迭代值
        items:从作用域中获取的数据

        JSTL标签学习:
            https://www.runoob.com/jsp/jsp-jstl.html
*/

四、过滤器

过滤器是能够对web请求和web响应的头属性和内容体进行操作的一种特殊web组件

过滤器的特殊之处在于本身并不直接生成web响应,而是拦截web请求和响应,以便查看、提取或以某种方式操作客户机和服务器之间交换的数据

比如

1、编码格式,能不能放到过滤器,就避免了重复代码

2、什么请求让过过滤器,什么请求不让过过滤器

功能:

分析web请求,对输入数据进行预处理

阻止web请求和响应的进行

根据功能改动请求的头信息和数据体

与其他web资源协作

过滤器的API包括javax.servlet包中的Filter,FilterChain和FilterConfig三个接口

所有的过滤器都必须实现javax.servlet.Filter接口,该接口定义了init()、doFilter()和destory()三个方法

这三个方法分别对应了过滤器生命周期中的初始化、响应和销毁这三个阶段

/**
 * 自定义过滤器
 *      完成请求的拦截以及资源的统一管理功能
 *      使用方式
 *          定义普通java类,实现Filter接口
 *          重写其中的方法
 *              init    :完成初始化功能        tomcat启动的时候执行一次
 *              dofilter:进行处理               每次发送请求都会执行
 *              destory:销毁功能                tomcat关闭的时候执行
 *
 *           <filter>
 *              <filter-name>filter</filter-name>       配置filter的别名
 *              <filter-class>com.mashibing.filter.MyFilter</filter-class>  配置filter指定的类名
 *          </filter>
 *          <filter-mapping>
 *              <filter-name>filter</filter-name>       配置filter的别名,跟filter标签中的name对应
 *              <url-pattern>/*</url-pattern>           表示要匹配的请求
 *          </filter-mapping>
 *      生命周期:
 *          从tomcat启动到tomcat关闭
 */

定义两个servlet

public class FilterServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");


        HttpSession session = request.getSession();
        session.setAttribute("user","user");
        System.out.println("我是filterservlet");
        response.getWriter().write("我是filterservlet");
    }
}
FilterServlet
public class FilterServlet2 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        System.out.println("我是filterservlet2");
        response.getWriter().write("我是filterservlet2");
    }
}
FilterServlet2

定义两个过滤器

public class MyFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("我是filter init");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("我是filter逻辑处理");

        //添加此语句之后才能调用到对应的servlet
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("filter逻辑处理完成");
    }

    @Override
    public void destroy() {
        System.out.println("我是filter销毁功能");
    }
}
MyFilter
public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("第二个过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("第二个过滤器开始执行");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("第二个过滤器执行结束");
    }

    @Override
    public void destroy() {
        System.out.println("第二个过滤器销毁");
    }
}
MyFilter2

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">
    <filter>
    <filter-name>filter</filter-name>
    <filter-class>com.mashibing.filter.MyFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>filter2</filter-name>
        <filter-class>com.mashibing.filter.MyFilter2</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>filter2</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>


    <servlet>
        <servlet-name>FilterServlet</servlet-name>
        <servlet-class>com.mashibing.servlet.FilterServlet</servlet-class>
    </servlet>
   
    <servlet-mapping>
        <servlet-name>FilterServlet</servlet-name>
        <url-pattern>/filter</url-pattern>
    </servlet-mapping>

    <servlet>
        <servlet-name>FilterServlet2</servlet-name>
        <servlet-class>com.mashibing.servlet.FilterServlet2</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>FilterServlet2</servlet-name>
        <url-pattern>/filter2.do</url-pattern>
    </servlet-mapping>

</web-app>
web.xml

 

 

 

 

 

 

 

1、过滤器链及详细配置

FilterChain接口用于调用过滤器链中的一系列过滤器

 

 FilterChain接口

对于一个Servlet,用户可以定义多个Filter。这些Filter由容器组织成一个过滤器链。在每个Filter对象中,可以使用容器传入doFilter方法的FilterChain参数引用该过滤器链。 FilterChain接口定义了一个doFilter方法,用于将请求/响应继续沿链向后传送

public void doFilter(ServletReqluest request,ServletResponse response)

/**
 *      filterChain:表示过滤器链
 *          在项目中可以定义N多个过滤器,当开始执行的时候,根据用户的请求把符合规则的过滤器挨个执行
 *          建议:每个过滤器完成独立的功能,不要讲所有的逻辑处理放置到同一个过滤器中,耦合性高,不利于维护
 *
 *          在过滤器的web.xml配置文件中,可以指定过滤器过滤那些请求:
 *              /*: 匹配所有请求
 *              /*.do:  匹配所有后缀为do的请求
 *              /filter.do :匹配请求为filter.do的请求
 */

2、过滤器示例

 账号登陆:

public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("loginservlet的处理过程");
        response.getWriter().write("登陆成功");
    }
}
LoginServlet.java

过滤器设置编码格式

public class EncodingFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("编码过滤器的初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("编码过滤器的逻辑处理");
        //设置编码
        servletRequest.setCharacterEncoding("utf-8");
        servletResponse.setContentType("text/html;charset=utf-8");
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("编码过滤器执行完成");
    }

    @Override
    public void destroy() {
        System.out.println("编码过滤器被销毁");
    }
}
EncodingFilter.java

登陆过滤器

public class LoginFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("登录过滤器初始化");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("登录过滤器处理");

        HttpSession session = ((HttpServletRequest)servletRequest).getSession();
        if(session.getAttribute("user")==null){
            ((HttpServletResponse)servletResponse).sendRedirect("login.jsp");
        }else{
            filterChain.doFilter(servletRequest,servletResponse);
        }

        System.out.println("登录过滤器处理完成");
    }

    @Override
    public void destroy() {
        System.out.println("登录过滤器被销毁");
    }
}
LoginFilter.java

login.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
请登录
<%
    session.setAttribute("user","user");
%>
</body>
</html>
login.jsp

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">
    <!--设置编码过滤器-->
    <filter>
        <filter-name>encoding</filter-name>
        <filter-class>com.mashibing.filter.EncodingFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>encoding</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--登录过滤器-->
    <filter>
        <filter-name>login</filter-name>
        <filter-class>com.mashibing.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>login</filter-name>
        <url-pattern>*.do</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>LoginServlet</servlet-name>
        <servlet-class>com.mashibing.servlet.LoginServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login.do</url-pattern>
    </servlet-mapping>
</web-app>

五、监听器

 之前直接往作用域里放属性值或共享数据, 现在我想知道作用域什么时候创建的怎么办

Servlet监听器用于监听一些重要事件的发生,监听器对象可以在事情发生前、发生后可以做一些必要的处理

通过实现Servlet API提供的Listense接口,可以在监听正在执行的某一个程序,并且根据程序的需求做出适当的响应

 

Servlet2.3提供了对ServletContext和HttpSession对象的状态变化的监听器,Servlet2.4则增加了对ServletRequest对象状态变化的监听器

ServletContext对象----监听ServletContext对象,可以使web应用得知web组件的加载和卸载等运行情况

HttpSession对象----监听HttpSession对象,可以使web应用了解会话期间的状态并做出反应

ServletRequest对象----监听ServletRequest对象,可以使web应用控制web请求的生命周期

 

 

1、request监听器

ListenseServlet.java

public class ListenseServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //设置编码格式
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        System.out.println("listenseservlet逻辑处理");
        request.setAttribute("listense","listense");
//        request.removeAttribute("listense");

        response.getWriter().write("listense study");

    }
}

MyListense.java

/**
 * 监听器:
 *      监听作用域对象的创建和销毁以及属性的相关配置,可以添加一些公共的属性配置,做逻辑判断
 *
 *      主要监听三种作用域:
 *          ServletContext(application) session request
 *
 *          request
 *              接口:
 *                  ServletRequestListener:监听request对象的创建和销毁
 *                       public void requestDestroyed(ServletRequestEvent servletRequestEvent)  request对象销毁时添加的逻辑代码
 *                       public void requestInitialized(ServletRequestEvent servletRequestEvent) request对象创建时添加的逻辑代码
 *                  ServletRequestAttributeListener:监听request作用域属性的添加,删除和更改
 *                         public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent)    属性添加时要做的事情
 *                         public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent)  属性删除时要做的事情
 *                          public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent)    属性更改时要做的事情
 *
 *
 *
 */
public class MyListense implements ServletRequestListener,ServletRequestAttributeListener,ServletContextListener,ServletContextAttributeListener,HttpSessionListener,HttpSessionAttributeListener {

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("request对象被销毁---" + new Date());
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("request对象被创建---"+new Date());
    }

    @Override
    public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("向request作用域添加数据");
        System.out.println(servletRequestAttributeEvent.getName());
        System.out.println(servletRequestAttributeEvent.getValue());
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("request作用域删除数据");
        System.out.println(servletRequestAttributeEvent.getName());
        System.out.println(servletRequestAttributeEvent.getValue());
    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("request作用域属性替换");
        System.out.println(servletRequestAttributeEvent.getName());
        System.out.println(servletRequestAttributeEvent.getValue());

    }
}

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">
    <servlet>
        <servlet-name>ListenseServlet</servlet-name>
        <servlet-class>com.mashibing.servlet.ListenseServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ListenseServlet</servlet-name>
        <url-pattern>/listense</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>com.mashibing.listense.MyListense</listener-class>
    </listener>
</web-app>

打印结果为:

servlet中remove掉session键 注释打开

//        request.removeAttribute("listense");
/*
request对象被创建---Thu Apr 28 13:56:02 CST 2022
request作用域属性替换
org.apache.catalina.ASYNC_SUPPORTED
true
listenseservlet逻辑处理
向request作用域添加数据
listense
listense
request作用域删除数据
listense
listense
request对象被销毁---Thu Apr 28 13:56:02 CST 2022

*/

 

2、servletContest监听器、session监听器

ListenseServlet.java

public class ListenseServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doGet(request,response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //设置编码格式
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

//        System.out.println("listenseservlet逻辑处理");
//        request.setAttribute("listense","listense");
//        request.removeAttribute("listense");

        //向servletcontext中添加属性值
//        ServletContext sc = this.getServletContext();
//        sc.setAttribute("servletContext","servletContext--value");
        //向session作用域中添加属性
        HttpSession session = request.getSession();
        session.setAttribute("session","session--value");
        session.invalidate();
        response.getWriter().write("listense study");

    }
}
ListenseServlet.java

MyListense.java

package com.mashibing.listense;

import javax.servlet.*;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import java.util.Date;

/**
 * 监听器:
 *      监听作用域对象的创建和销毁以及属性的相关配置,可以添加一些公共的属性配置,做逻辑判断
 *
 *      主要监听三种作用域:
 *          ServletContext(application) session request
 *
 *          request
 *              接口:
 *                  ServletRequestListener:监听request对象的创建和销毁
 *                       public void requestDestroyed(ServletRequestEvent servletRequestEvent)  request对象销毁时添加的逻辑代码
 *                       public void requestInitialized(ServletRequestEvent servletRequestEvent) request对象创建时添加的逻辑代码
 *                  ServletRequestAttributeListener:监听request作用域属性的添加,删除和更改
 *                         public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent)    属性添加时要做的事情
 *                         public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent)  属性删除时要做的事情
 *                          public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent)    属性更改时要做的事情
 *           servletcontext:
 *              接口:
 *                  ServletContextListener  监听servletcontext对象的创建和销毁
 *                          public void contextInitialized(ServletContextEvent servletContextEvent) 创建对象,当启动tomcat服务器的时候创建
 *                          public void contextDestroyed(ServletContextEvent servletContextEvent)   销毁对象,关闭tomcat服务器的时候销毁
 *                  ServletContextAttributeListener 监听servletcontext对象的属性的添加和删除和更改
 *                           public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent)  添加属性
 *                            public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent)   删除属性
 *                            public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent)      更改属性
 *
 *            Session:
 *              接口;
 *                  HttpSessionListener:  监听session对象的创建和销毁
 *                          public void sessionCreated(HttpSessionEvent httpSessionEvent)  session对象创建的时候执行
 *                          public void sessionDestroyed(HttpSessionEvent httpSessionEvent)  session对象销毁的时候执行
 *                  HttpSessionAttributeListener :监听session对象中属性的添加,删除和更改
 *                          public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) 添加属性时被调用
 *                          public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) 删除属性时被调用
 *                          public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) 修改属性时被调用
 *
 *
 *
 */
public class MyListense implements ServletRequestListener,ServletRequestAttributeListener,ServletContextListener,ServletContextAttributeListener,HttpSessionListener,HttpSessionAttributeListener {

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        System.out.println("request对象被销毁---" + new Date());
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        System.out.println("request对象被创建---"+new Date());
    }

    @Override
    public void attributeAdded(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("向request作用域添加数据");
        System.out.println(servletRequestAttributeEvent.getName());
        System.out.println(servletRequestAttributeEvent.getValue());
    }

    @Override
    public void attributeRemoved(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("request作用域删除数据");
        System.out.println(servletRequestAttributeEvent.getName());
        System.out.println(servletRequestAttributeEvent.getValue());
    }

    @Override
    public void attributeReplaced(ServletRequestAttributeEvent servletRequestAttributeEvent) {
        System.out.println("request作用域属性替换");
        System.out.println(servletRequestAttributeEvent.getName());
        System.out.println(servletRequestAttributeEvent.getValue());

    }

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("servletContext创建");
    }

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

    @Override
    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("servletContext添加属性");
        System.out.println(servletContextAttributeEvent.getName());
        System.out.println(servletContextAttributeEvent.getValue());
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("servletContext删除属性");
        System.out.println(servletContextAttributeEvent.getName());
        System.out.println(servletContextAttributeEvent.getValue());
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
        System.out.println("servletContext修改属性");
        System.out.println(servletContextAttributeEvent.getName());
        System.out.println(servletContextAttributeEvent.getValue());
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("session对象被创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("session对象被销毁");
    }

    @Override
    public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("session添加属性");
        System.out.println(httpSessionBindingEvent.getName());
        System.out.println(httpSessionBindingEvent.getValue());
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("session删除属性");
        System.out.println(httpSessionBindingEvent.getName());
        System.out.println(httpSessionBindingEvent.getValue());
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("session修改属性");
        System.out.println(httpSessionBindingEvent.getName());
        System.out.println(httpSessionBindingEvent.getValue());
    }
}

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">
    <servlet>
        <servlet-name>ListenseServlet</servlet-name>
        <servlet-class>com.mashibing.servlet.ListenseServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ListenseServlet</servlet-name>
        <url-pattern>/listense</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>com.mashibing.listense.MyListense</listener-class>
    </listener>
        
</web-app>
web.xml

监听器示例:

利用监听器实现网站在线人数

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">
    <servlet>
        <servlet-name>ListenseServlet</servlet-name>
        <servlet-class>com.mashibing.servlet.ListenseServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ListenseServlet</servlet-name>
        <url-pattern>/listense</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>com.mashibing.listense.MyListense</listener-class>
    </listener>
    <listener>
        <listener-class>com.mashibing.listense.MyListense2</listener-class>
    </listener>
</web-app>

MyListense2.java

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MyListense2 implements HttpSessionListener,ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //获取application
        ServletContext sc = servletContextEvent.getServletContext();
        //设置网站在线人数的初始值
        sc.setAttribute("count",0);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("servletContext被销毁");
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        //获取application对象
       ServletContext sc =  httpSessionEvent.getSession().getServletContext();
        int count = (int)sc.getAttribute("count");
        sc.setAttribute("count",++count);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        //获取application对象
        ServletContext sc =  httpSessionEvent.getSession().getServletContext();
        int count = (int)sc.getAttribute("count");
        sc.setAttribute("count",--count);
    }
}

main.jsp

<%--
  Created by IntelliJ IDEA.
  User: Administrator
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
当前在线的人数是:${applicationScope.count}
</body>
</html>

 

posted @ 2022-04-28 17:54  kongxiangqun20220317  阅读(47)  评论(0编辑  收藏  举报