javaweb笔记2

JSP
1、在webapp的根目录下新建一个index.jsp文件,访问以下地址:
    http://localhost:8080/webappName/index.jsp
    实际上访问这个index.jsp文件,底层执行的是:index_jsp.class这个程序。
    这个index.jsp会被tomcat翻译成index_jsp.java文件,然后tomcat又会将index_jsp.java编译生成index_jsp.class文件
    访问index.jsp,实际上底层执行的是index_jsp.class文件.
2、jsp实际上就是一个Servlet。
    index.jsp访问的时候,会自动翻译生成index_jsp.java,会自动编译生成index_jsp.class,那么index_jsp.java就是一个类
    index_jsp类继承HttpJspBase,而HttpJspBase继承的是HttpServlet。所以index_jsp类就是一个Servlet。【tomcat虽然比较官方,但是在这里他给我们翻译生成的这个类并没有遵循类的命名规范,首字母没有大写】
    【jsp翻译引擎将我们写的jsp代码翻译成java文件的时候做自动继承“HttpJspBase”这个抽象类。
    “HttpJspBase”这个抽象类继承自“HttpServlet”抽象类。
    所以我们写的jsp代码,最终会被翻译成一个Servlet。】
3、jsp的生命周期和Servlet的生命周期完全相同,完全就是一个东西,没有任何区别。
4、jsp第一次访问比较慢,为什么?
    为什么大部分运维人员在给客户演示项目的时候,为什么把所有的jsp文件先访问一遍?
        第一次访问比较麻烦:
            tomcat首先把jsp文件翻译成java源文件。
            java源文件编译生成class字节码文件。
            使用class通过反射机制调用无参数构造方法去创建Servlet对象。
            然后调用Servlet对象的init方法
            最后调用Servlet的service方法。
        第二次就比较快了,为什么?
            因为第二次直接调用单例Servlet对象的service方法即可。
5、什么是jsp?
    jsp是java小程序。
    jsp的全程是Java Server Pages,是一种动态网页技术。
    它使用jsp标签在HTML网页中插入Java代码。标签通常以<%开头以%>结束。
    jsp是一种java Servlet,主要用于实现java web应用程序的用户界面部分。
    网页开发者们通过结合HTML代码、XHTML代码以及嵌入JSP操作和命令来编写JSP。
    Servlet是javaEE的13个规范之一,JSP也是javaEE的13个规范之一。
    JSP是一套规范,所有的web容器/web服务器都会内置一个JSP翻译引擎。
6、JSP本质上就是一个Servlet,那么JSP和Servlet到底有什么区别呐?
    职责不同:
        Servlet的职责是收集数据。(Servlet的强项是逻辑处理,业务处理,然后连接数据库,获取/收集数据)
        JSP的职责是什么:展示数据。(JSP的强项是做数据的展示)
7、在jsp中直接编写的文字会被翻译到哪里?
    翻译到Servlet的service方法的out.write("翻译到这里"),直接翻译到双引号里,被Java程序当作普通字符串打印输出到浏览器。
    在jsp中写的html、css、js代码,这些代码对于jsp来说只是一个普通的字符串。但是jsp一旦把这个普通的字符串一旦输出到浏览器,
    浏览器就会对html、css、js进行解释执行。站是一个效果。
8、Servlet中响应到浏览器的字符串内容有两种常用的方式:
    【输出的字符串会作为http协议的响应体内容响应到浏览器,浏览器接收到响应体,会把html、css、js代码解释执行】
    1.Servlet的PrintWriter对象的print("字符串")方法。
    2.JspWriter对象的writer("字符串")方法。
    PrintWriter类和JspWriter类都是java.io.Writer类的子类。
11、在jsp文件中写的文字内容会被翻译到service方法的out.writer("这里")
    在jsp中有一行东西,就对应有一句out.writer("一行内容\n")【最后加一个\n,代表的是jsp源文件中代码有换行(也可以说输出到NetWork面板的Response面板的时候内容换行),并不是浏览器解释执行之后展示的效果换行】
    jsp中的内容作为http协议的响应体,响应到浏览器的的时候是原样输出【浏览器的NetWork面板的Response和jsp源文件的内容是一样的,包括换行的位置】。
    但是浏览器解释执行之后就不一定是原样了。【浏览器解释前端代码,有他自己的便准文档流】
12、JSP翻译引擎翻译生成的Java文件名是“我们写的jsp文件名_jsp.java”
    如果我们写的文件名是数字,因为类名是标识符所以不能以数字开头,所以jsp翻译引擎就会给我们生成“_我们写的jsp文件名_jsp.java”
13、jsp翻译成Servlet类之后的继承结构:
    我们自己写的jsp程序被tomcat内置的jsp翻译引擎翻译成java文件之后,
    继承的是:HttpJspBase类并且实现了JspSourceDependent和JspSourceImports接口。
    HttpJspBase继承HttpServlet类并且实现了HttpJspPage接口。
        HttpJspBase中有个service方法是覆盖Servlet类的方法,在这个方法中调用了“_jspService”方法。
        _jspService方法在jsp翻译引擎为我们翻译的这个servlet类的中有实现,这里使用了模板方法设计模式。
    HttpJspPage接口中有一个“_jspService”方法。
    HttpJspPage接口继承JspPage接口。JspPage接口中有两个方法jspInit和jspDestroy
14、jsp的基础语法:
    <% Java语句; %> 【<和%之间不要有空格,如果有空格那么jsp就会把当作是普通的字符串,已经不是脚本块了】
        <%%>中的内容专业术语叫做脚本块。
        在<%%>符号当中编写的被视为Java程序,被翻译到Servlet类的service方法内部。
            注意:在<%%>里面写代码的时候,要注意在方法中能写什么代码,在<%%>中就只能写什么代码。
            <% private int i = 10;%> 这样写是错误的,因为在方法体内部不能定义私有的变量
            <% static int i = 10;%> 这样写是错误的,因为在方法体内部不能定义静态的变量
            ......
            当在<%%>脚本块中写静态变量等非法内容的时候,虽然语法错误,不符合Java语法,不能编译成class文件,但是解析引擎可以给我们生成java源文件。【不仅是在<%%>脚本块中<%!%>脚本块中,其他脚本快中也是这样的规则】
        service方法中编写的代码是有顺序的,方法体当中的代码要遵循自上而下的顺序依次逐行执行。
        在一个jsp文件中<%%>脚本块可以出现多个,jsp被解析引擎翻译到java源文件的时候,按照<%%>在jsp源文件中出现的先后位置,依次翻译到Java源文件的service方法内部的先后位置
    <%! Java语句; %> 
        在<%! %>符号当中编写的被视为Java程序会自动翻译到service方法之外,Servlet类体之内。
        在jsp文件中的<%!%>脚本块可以出现多个,被jsp解析引擎翻译成Java源文件的时候,按照<%! %>在jsp源文件中出现的先后位置,一次翻译到Java源文件的Servlet类内部的先后位置
        在写<%!%>中的内容的时候,应该知道类体内部能出现什么。
        这个语法很少用,为什么?不建议使用,因为在service方法外面写静态变量和实例变量,都会存在线程安全问题
        因为jsp是servlet,servlet是单例的,多线程并发的环境下,这个静态变量或者实例变量一旦有修改操作,必然会存在线程安全问题。
    <%--注释的内容--%>
        jsp的注释不会被解析引擎翻译到Java源代码当中,Java源代码就是jsp输出的产品。【就像class是java源文件输出的产品一样,Java中的注释不会被编译到class文件中】
        对于jsp来说只有jsp的标准注释才是真正的注释内容,不会被翻译到Java文件当中。
        <!--这里写的是html的注释-->:会被翻译到Java源文件的out.writer("这里")
        /*这里写的是css注释或者JavaScript注释*/:会被翻译到Java源文件的out.writer("这里")
        // 这里是Java中的注释,会被翻译到Java源文件当中但是,不会被编译到class文件当中。
15、<%%>和<%!%>都是编写Java代码的:
    区别在于:
        <%%>是用于编写service方法体的。【_jspService】
        <%!%>是用与编写Servlet类成员的。【比如实例成员(成员变量、成员方法)静态成员(静态变量、静态方法)】
    哪怕<%!%>符号在jsp文件中出现在<%%>符号的下面,在<%!%>中定义的变量在<%%>中也可以访问,因为<%!%>中定义的属于类成员。 
16、jsp的输出语句:
    怎样向浏览器上输出一个Java变量?
        第一种:<%String name="jack";out.writer(name);%>
            注意以上代码中out是jsp的九大内置对象之一,可以直接拿来使用,jsp翻译引擎讲jsp中的字符串响应到浏览器也是使用的out.writer()这个方法
            out是JspWriter类型的对象。【out只能在service方法中使用。】
        第二种:<%response.getWriter().print("jack");%>
            response也是jsp的九大内置对象之一,可以直接拿来使用,在Servlet中经常使用这种方法往浏览器响应内容。
        因为jsp就是负责用来展示数据的,所以jsp为Java程序员提供了一种简单的输出方式:
            如果向浏览器上输出的内容没有Java代码,
                例如:如果想浏览器上输出的是一个固定的字符串可以直接在jsp中编写会被翻译到out.writer("这里")响应输出到浏览器,不需要写到<%这里%>【直接写道jsp文件中相当于jsp的翻译引擎在service方法中帮我们做了“out.writer”这件事情,我们直接写到<%这里的out.writer%>jsp翻译引擎也是帮我们翻译到service方法中,效果一样而且jsp就是专门帮我们展示数据的,所以直接输出一个字符串一般不在<%%>里面写】
            如果输出的内容中含有“Java代码”,这个时候可以使用以下的语法格式:
                <%= %>:注意: = 的后面要编写输出的内容,不要加“分号”。
                <%= %>:符号会被翻译到哪里?最终翻译成什么?
                    翻译成这个Java代码:out.print("这里");【在写=后面的内容的时候就想想“out.print("这里")”这里能写什么】
                    翻译到service方法当中了。
            什么时候使用<%= %>输出呐?输出的内容中含有Java变量,输出的内容是一个动态的内容,
            不是一个死的字符串。如果输出的是一个固定的字符串,直接编写在jsp文件中即可。
17、jsp动作元素
    1.jsp:include  在页面被请求的时候引入一个文件,【使用格式:<jsp:include page="被引入的文件"></jsp:include>】
        请求包含,动态引入
    2.jsp:useBean  实例化一个JavaBean对象【<jsp:useBean id="这个对象唯一标识" class="完整类名"></jsp:useBean>】
    3.jsp:setProperty  设置JavaBean的属性【<jsp:setProperty name="这个对象唯一标识" property="属性名" value="属性值">】
    4.jsp:getProperty  输出某个JavaBean的属性【<jsp:getProperty name="这个对象唯一标识" property="属性名">】
        property后面的属性名实际上是setter和getter方法去掉set和get首字母小写,如果遵循setter和getter的命名规范,那么property的属性值就是JavaBean的属性名。
        【如果setter和getter方法没有遵循驼峰命名规范,age属性的set方法写成setage(),虽然代码能正常执行,但是一般没人这么些】
    5.jsp:forward  把请求转发到一个新的页面
        底层使用的servlet的请求转发
18、在一个jsp页面中引入两一个jsp页面:
    第一种:静态引入,<%@include file="被引入的资源"%>
        被引入的资源可以是相对路径也可以是绝对路径
            相对路径:不以“/”开始,从当前jsp文件所在的路径下寻找
            绝对路径:以“/”开始,从webapp的根路径下寻找。
        被引入的资源不可以是一个Servlet。
        等同于:被引入的资源中的内容和当前的jsp内容在在同一个service方法中被打印输出,响应给浏览器。
        【包含页面与被包含页面合并编译为一个java源文件,所以include指令通常也称为静态引入;】
    第二种:动态引入,<jsp:include page="被引入的资源"></jsp:include>
        被引入的资源可以是相对路径也可以是绝对路径
            相对路径:不以“/”开始,从当前jsp文件所在的路径下寻找
            绝对路径:以“/”开始,从webapp的根路径下寻找。
        被引入的资源可以是一个Servlet。
        包含页面与被包含页面分别编译为两个java源文件。
19、JSP文件的扩展名必须是xxx.jsp吗?jsp文件的后缀名可以改:
    jsp文件的扩展名是可以配置的。不是固定的。
    在CLTALINA_HOME的conf目录下有一个web.xml文件,web.xml文件中
        <servlet-mapping>
            <servlet-name>jsp</servlet-name>
            <url-pattern>*.jsp</url-pattern>
            <url-pattern>*.jspx</url-pattern>
        </servlet-mapping>
    这里可以更改。
    jsp文件也是被schema约束文档所约束的。
    xxx.jsp文件对于小猫咪来说,只是一个普通的文本文件,web容器会将xxx.jsp文件最终生成java程序,最终调用的是java对象相关的方法,真正执行的时候,和jsp文件就没有关系了。
20、哪里可以加空格,哪里不可以加?
    <a href="<%= request.getContextPath()     %>/xyh">我是超链接</a>
        <%= request.getContextPath()         这里           %>   可以随意加空格
            因为request.getContextPath()这个返回的是一个字符串加入返回的是一个"/xyh"
            那么整体被翻译成    
                out.write("        <a href=\"");
                out.print( "/xyh"     );【在“<%= request.getContextPath()         这里           %>”加的空格都跑到了out.print( "/xyh"    这里   );】
                out.write(" /xyh\">我是超链接</a>\r\n");
    <a href="<%= request.getContextPath()     %>   [这里]    /xyh">我是超链接</a>是不能加空格的
21、在jsp中除了<%= 这里 %>的内容是用out.print("这里")输出的
    其他的东西全部都是由out.writer("这里")输出的
22、jsp翻译引擎是按照jsp源代码的前后顺序,逐行翻译到Java源文件中的。
    以下代码虽然看着for循环在jsp中是分开的在两个<%%>脚本块中,但是最终翻译之后,是同一个for循环。
        <table border="1px">
        <%
            for (int i = 0;i < 100;i++) {
        %>
        <tr>
            <td><%=i%></td>
        </tr>
        <%
            }
        %>
        </table>
    会被翻译Servlet成:
        out.writer("<table border=\"1px\">\r\n");
        for (int i = 0;i < 100;i++) {
            out.writer("<tr>\r\n");
            out.writer("<td>");
            out.print(i);
            out.writer("</td>\r\n");
        }
23、理解以下代码翻译:
        <a href="<%=request.getContextPath() %>/stu/list">查看所有学生列表</a>
    最终会翻译成:
        out.writer("<a href=\"");
        out.print(request.getContextPath() );
        out.writer("/stu/list\">查看所有学生列表</a>\r\n");
    <%=request.getContextPath() %> 这里的输出并不是往html代码中输出,而是往浏览器上输出。
    看翻译之后的源码也知道,眼前写的是jsp代码,脑子里想的是servlet代码。

JSP的指令:
1、指令的作用:指导JSP翻译引擎如何工作(指导当前的JSP翻译引擎如何翻译JSP文件)
2、指令可以有很多个属性,他们以键值对的形式存在,并用空格分割。
    jsp中的三种指令:
        <%@ page ... %>:定义网页依赖的属性,比如脚本语言、error页面、缓存需求等等。【<和%和@之间不能有空格】
            page指令为容器提供当前页面是使用说明。
        <%@ include ... %>:包含其他文件,被用作静态引入,两个或者多个jsp文件翻译到一个Java源文件当中【很少使用】
        <%@ taglib ... %>:引入标签库【JSTL标签库详细介绍】
    每一种指令都可以再JSP页面出现多次。
3、指令的语法格式是什么?
    <%@ page 属性名=属性值 属性名=属性值 ... %>
4、page 指令常用的属性
    1.<%@ page session="true | false" %>
        true:默认值,表示启用session,没有session对象会创建。
        false:表示不启用内置对象session,当前页面无法使用内置对象session。
    2.<%@ page contentType="text/html;charset=UTF-8" %>:设置Servlet响应的内容类型,和字符编码
      上下两句话的效果相同
      <%@ page contentType="text/html" pageEncoding="UTF-8" %>
    3.<%@ page import="java.util.List,java.util.ArrayList"%>:servlet导包语句,被翻译到包名之下类名之上的import语句
      上下两句话的效果相同
      <%@ page import="java.util.List" %>
      <%@ page import="java.util.ArrayList"%>
    4.<%@ page errorPage="/error.jsp" %>:当前页面出现异常之后,跳转到"/error.jsp"页面
        errorPage属性用来指定出错之后的跳转位置【利用请求转发跳转的】。
        跳转的位置:
            如果以“/”开始表示,从应用的根路径下开始寻找。
            不过不以“/”开始,表示从当前文件所在的位置开始寻找。
        只有被跳转到的页面使用:
            exception.printStackTrace();才可以打印堆栈异常信息
    5.<%@ page isErrorPage="true" %>:表示启用JSP的九大内置对象之一:exception
        isErrorPage默认值是false。
        exception里面封装了,因为谁的什么异常跳转过来的,错误信息都在这个里面封装着。
6、<%
    System.out.println(this.getServletContext()==application);
   %>
   虽然这里报红但是运行可以正常运行通过,只要是可以在service中写的东西在<%%>里面都写的,不用管他报不报红   
   在jsp中报红只能说明不是这么用的,一般不推荐这么用,但是你要是硬用,也可以使用。
        
JSP的九大内置对象:
1、request、response、session、application、config、page、pageContext、out、exception
3、九大内置对象所属类型:
    jakarta.servlet.jsp.PageContext pageContext  页面域对象(一个页面区域使用一个对象存储数据)
    jakarta.servlet.http.HttpServletRequest request  请求域对象(一个请求区域内使用一个对象存储数据)
    jakarta.servlet.http.HttpSession session  会话域对象(一个会话区域内使用同一个对象存储数据)
    jakarta.servlet.ServletContext application  应用域对象(一个应用区域内使用同一个对象存储数据)
    jakarta.servlet.ServletConfig config  config中封装了<servlet>标签中的数据
    jakarta.servlet.jsp.JspWriter out  负责输出
    java.lang.Object page  this,当前的servlet对象
    java.lang.Throwable exception  异常对象
    jakarta.servlet.http.HttpServletResponse response  负责响应
4、什么是域对象?
    在某个范围,某个层次内使用的一种对象,而该类型的对象,常常用作存储数据。
5、四个域对象的大小关系:
    pageContext < request < session < application
   使用的时候尽量使用较小的域对象。
6、四个域对象都有:
    void setAttribute(String name,Object obj)  向域对象中绑定数据
    Object getAttribute(String name)  从域对象中获取数据
    void removeAttrubute(String name)  从域对象中删除数据
7、config内置对象怎么使用:
    <servlet>
        <servlet-name>s1</servlet-name>
        <!--jsp-file必须以/开始代表应用的根路径-->
        <jsp-file>/test01/1.jsp</jsp-file><!--这里是jsp-file如果是servlet那就是servlet-class-->
        <init-param>
            <param-name>name</param-name>
            <param-value>xyh</param-value><!--可以通过config对象的getInitParameter(String name)方法获取-->
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>s1</servlet-name>
        <url-pattern>/test01/1.jsp</url-pattern>
    </servlet-mapping>
8、WEB-INF那些能访问哪些不能访问?
    请求转发:可以转发到一个WEB-INF下面的资源
    请求包含:可以转发到一个WEB-INF下面的资源
    重定向:不可以,因为重定向是前端直接发送过来的请求
    getRealPath:可以,因为哪怕获取的资源不存在,也会拼接成一个路径返回
    欢迎页:可以
    错误页面:可以
        
EL表达式
1、Expression Language (表达式语言)
2、EL表达式可以替代JSP中的Java代码,让JSP文件中的程序看起来更加整洁美观。
3、JSP中夹杂着各种java代码,例如<% java代码 %>、<%=%>等,导致JSP文件很混乱,不好看,不好维护。所以才有了后期的EL表达式。
4、EL表达式可以算是JSP语法的一部分。EL表达式归属于JSP。
5、EL表达式出现在JSP中主要是:
    从某个域中取出数据,然后将其转换成字符串,然后将其输出到浏览器。这就是EL表达式的作用。
        三大作用:
            1.从某个域中取出数据【EL表达式只能从某个域中取出数据】
                四个域:
                    pageContext
                    request
                    session
                    application
            2.将取出的数据转换成字符串。
                如果是一个Java对象,也会自动调用Java对象的toString方法将其转换成字符串。
            3.将字符串输出到浏览器。
                和这个一样:<%= %>,
6、EL表达式很好用,基本语法格式:
    ${表达式}
6.1、EL表达式的使用格式:
    <%--使用EL表达式取--%>
    域.setAttribute(String name,Object obj);
    ${这里写的一定是存储到域对象当中时的name,并且不带双引号}
        实例:域.setAttribute("driver","com.mysql.jdbc.Driver");
        使用EL表达式取出来:${driver}
6.2、${如果这里的内容带上双引号}
    ${"Hello World!!"}这样写EL表达式就会把它当中普通的字符串输出
    就等同于直接再jsp文件中直接写:Hello World!!,JSP翻译引擎会把它翻译到out.writer中也是当作字符串直接输出。
7、EL表达式的使用:
    1.向请求域当中存储一个数据:request.setAttribute("name","xueYingHao");
      使用普通的方式吧数据取出来:<%=request.getAttribute("name")%>    
            如果吧name写错了,写成name1了:<%=request.getAttribute("name1")%>这种方式会输出:null
      使用EL表达式:${name}
            如果吧name写错了写成name1了:${name1},这种方式什么也不输出,说明EL表达式内部对null进行了处理
            ${name1.age} :这样写什么也不输出,
                因为name1都没有,取不出来东西,
                也不会去找某个对象的getAge()或者getage()方法,系统也不会报错。
            ${name.age}:这样写会抛异常(PropertyNotFoundException),
                因为name取出来的是一个字符串类型的对象【"xueYingHao"】
                然后去调用这个对象的:getAge()或者getage()方法。
                String类明显找不到这个方法,然后就会抛出异常。
    2.因为向域中绑定数据的时候是:setAttribute(String name,Object obj),绑定的数据一定是一个引用数据类型
        当${}取出来的时候取出来的也是一个引用数据类型的对象。
        例如:${name} 取出来的是什么对象,就可以在${name[.这里点什么对象的方法]}
    3.还可以采用中括号的方式去访问属性:
        ${u1["name"]}等同于${u1.name}
        ${requestScope["u1"]["name"]}等同于${requestScope.u1.name}
            或者:${requestScope["u1"].name}
            或者:${requestScope.u1["name"]}
          规则一个“点”可以写成“省略点,一个中括号,中括号中一个双引号”
    4.如果四个域中有相同name的数据:
        EL表达式优先从小范围中读取数据。
            pageContext<request<session<application
    5.EL表达式中有四个隐式的范围:【隐式范围并不等同于内置对象(requestScope!=request)】
        pageScope 对应的是pageContext范围【pageScope并不是pageContextScope,其他三个隐式范围都是内置对象的名字加上Scope】
        requestScope 对应的是request范围
        sessionScope 对应的是session范围
        applicationScope 对应的是application范围
    6.EL表达式取数据的时候有两种形式:
        第一种:.(大部分使用这种方式)
        第二种: [] (如果存储到域的时候这个name中含有特殊的字符,可以使用[])
            request.setAttribute(“abc.def”, “zhangsan”);
            ${requestScope.abc.def} 这样是无法取值的。
            应该这样:${requestScope[“abc.def”]}
    7.掌握EL表达式从集合中取数据:
        Map集合:
            ${map.key}或者${map["key"]}
            实例:
                Map<String,String> m = new HashMap();
                m.put("name","xueyinghao");
                request.setAttribute("map",m);
                ${map.name}或者${map["name"]}【一个点可以使用一个中括号替换】
                只有在EL表达式中有这种写法“map.key”在原生Java中没有这种写法
        List或者数组中:
            ${数组[0]}
            ${list[0]}或者${list.get(0)}
            "list[0]"只有在EL表达式中才有这种写法,在原生Java中没有这种写法
        Set集合中取数据:
            和原生Java中一致,没有特殊的写法:
                可以先调用set.toArray()方法返回一个数组,使用下标的方式访问数组中的元素。
    8.page指令当中,有一个属性,可以忽略EL表达式
        <%@page contentType="text/html;charset=UTF-8" isELIgnored="true" %>
        isELIgnored="true" 表示忽略EL表达式
        isELIgnored="false" 表示不忽略EL表达式。(这是默认值)
        
        isELIgnored="true" 这个是全局的控制,表示整个jsp页面都忽略EL表达式,用的不多
        可以使用反斜杠进行局部控制:\${username} 这样也可以忽略EL表达式。
    9.通过EL表达式获取应用的根:    
        JSP的九大内置对象:
            pageContext,request,session,application,response,out,config,page,exception
        通过pageContext的getXxx()方法几乎可以获取jsp的九大内置对象中所有的对象。
            例如:pageContext.getRequest() ..... 这样可以获取jsp的request请求域对象
            jsp中本来就有request内置对象,在通过pageContext的getXxx方法取调用获取request,那不是多此一举吗?
            确实,虽然JSP中有request内置对象,但是EL表达式中没有request内置对象。
            但是EL表达式中有一个pageContext隐式对象,这个隐式对象就是JSP中的九大内置对象之一pageContext
            这样在EL表达式中可以通过pageContext隐式对象获取其他内置对象,调用其他对象的方法。
            pageContext页面作用域是JSP和EL表达式的连接通道。
        获取应用的根路径:
            在JSP中获取应用的根路径:
                <%=((HttpServletRequest)pageContext.getRequest()).getContextPath() %>
            在EL表达式中可以这么写:
                调用getRequest方法和GetContextPath方法都可以省略get首字母小写
                ${pageContext.request.contextPath}【这里的点也可以换成中括号访问】
                EL表达式对pageContext.request进行了预处理自动转换成了:HttpServletRequest
    10、EL表达式中其他的隐式对象:
        pageContext
        param
        paramValues
        initParam
        详解:
            pageContext:页面作用域对象,用来获取其他八个内置对象,pageContext页面作用域是JSP和EL表达式的连接通道
            param:用来代替jsp中的request.getParameter【因为request是jsp的内置对象,也可以说是Servlet的,因为jsp就是Servlet】
                ${param.username} <==> <%=request.getParameter("username")%> 【EL中的点也可以改成中括号】
            paramValues:用来代替jsp中的request.getParameterValues
                ${paramValues.aihao} <==> <%=request.getParameterValues("aihao")%>
            initParam:用来代替JSP中的application.getInitParameter【web.xml中为应用配置的初始化参数】
                ${initParam.pageSize} <==> <%=application.getInitParameter("pageSize")%>
8、EL表达式不但可以取数据,而且还可以调用对象的方法:
    取数据:【重要的】
        1.从域中取数据
        2.从域中的对象中取数据
    调用方法:【了解即可】
        因为EL表达式就是为了取数据而诞生的。

JSTL标签库
1、什么是JSTL标签库?
    Java Standard Tag Lib(Java标准的标签库)
    JSTL标签库通常结合EL表达式一起使用。目的是让JSP中的java代码消失。
    标签是写在JSP当中的,但实际上最终还是要执行对应的java程序。(java程序在jar包当中。)
2、dtd和schema是xml的约束文件。
   tld是标签库描述符(Tag Library Descriptor)
3、使用JSTL的步骤:
    第一步:引入JSTL标签库对应的jar包。
        tomcat10之后引入的jar包是:
            jakarta.servlet.jsp.jstl-2.0.0.jar
            jakarta.servlet.jsp.jstl-api-2.0.0.jar
        在IDEA当中怎么引入?
            在WEB-INF下新建lib目录,然后将jar包拷贝到lib当中。然后将其“Add Lib…”
            一定是要和mysql的数据库驱动一样,都是放在WEB-INF/lib目录下的。
            什么时候需要将jar包放到WEB-INF/lib目录下?如果这个jar是tomcat服务器没有的。
    第二步:在JSP中引入要使用标签库。(使用taglib指令引入标签库。)
        JSTL提供了很多种标签,你要引入哪个标签????重点掌握核心标签库。
            <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
            prefix="这里随便起一个名字就行了,核心标签库,大家默认的叫做c,你随意。"
            JSTL标签的原理:
                以上uri后面的路径实际上指向了一个xxx.tld文件。
                tld文件实际上是一个xml配置文件。
                在tld文件中描述了“标签”和“java类”之间的关系。
                以上核心标签库对应的tld文件是:c.tld文件。它在哪里。
                在jakarta.servlet.jsp.jstl-2.0.0.jar里面META-INF目录下,有一个c.tld文件。
        源码解析:配置文件tld解析
              <tag>
                <description>
                    标签的描述
                </description>
                <name>catch</name>  标签的名字
                <tag-class>org.apache.taglibs.standard.tag.common.core.CatchTag</tag-class> 标签对应的java类。
                <body-content>JSP</body-content> 标签体的内容,如果是JSP,就表示标签体中可以出现符合JSP所有语法的代码。
                <attribute>
                    <description>
                        属性的描述
                    </description>
                    <name>var</name> 属性名
                    <required>false</required> true表示必须的,false表示可以没有该属性不是必须的
                    <rtexprvalue>false</rtexprvalue> true表示属性值可以使用EL表达式,false表示不可以
                </attribute>
              </tag>        
4、在JSTL中使用EL表达式和在JSP中使用EL表达式的区别?
    某段Servlet向域中存储数据:
        User user1 = new User("xueyinghao",23);
        User user2 = new User("wangyunxia",22);
        User user3 = new User("lisi",18);
        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);
        list.add(user3);
        request.setAttribute("stuList",list);
    在JSTL中使用EL表达式取出数据:
        <c:forEach items="${stuList}" var="s" >
            姓名:${s.name},年龄:${s.age}<br> 底层实际上会将s存储到pageContext域当中,所以在这里才可以使用EL表达式将其取出来。
        </c:forEach>
        items="${stuList}" 中的${stuList}
        在JSP中是吧域中stuList对应数据取出来,调用toString方法打印到浏览器
        在JSTL标签库中只是吧这个数据取出来,并没有打印到浏览器的动作。
    上述案例中:items="这里的数据一般都是从域中取出来的,一般都要使用EL表达式"
        但是如果不是从域中取出来的话直接吧数据写到这里,中间用逗号隔开即可:
            items="1,2,3"  要遍历的集合中有三个元素,分别是:1  2  3
            如果要是有多余的符号:
                items="{1,2,3}"要遍历的集合中有三个元素,分别是:{1  2  3}
4、JSTL标签库常用的标签:
    c:if
        常用属性:
            test:true执行标签体,false不执行标签体
            var: 
            scope: 
                例如var="v",scope="request",可以将test的值以v为name存储到request域当中
        实例:<c:if test=“boolean类型,支持EL表达式,当不使用EL表达式的时候,这里只有是字符串true的时候,才执行标签体,其他的字符串都不执行标签体”></c: if>
        标签可以嵌套
            <c:if test="true">
                <h1>true</h1>
                <c:if test="true">
                    <h1>xueyinghao</h1>
                </c:if>
            </c:if>
        没有c:else我们可以写两个c:if实现同样的功能
    c:forEach 
        常用属性:
            items:要遍历的集合或者数组
            var:遍历过程中的每一项
            begin:开始
            end:结束
            step:步长
        实例:
            <c:forEach var="i" begin="1" end="10" step="1" varStatus="status" >
                序号:${status.count},${i}<br>底层实际上会将i存储到pageContext域当中,所以在这里才可以使用EL表达式将其取出来。
                varStatus的属性值也会被自动存储到域对象当中,status有一个count属性,属性值从1开始以1递增。
            </c:forEach>
            【规律只要是var的属性值都会被存储到域对象中】
            
    <c:choose> 这个类似于多分支语句
        <c:when test="">
            
        </c:when>
        <c:when test="">
            
        </c:when>
        <c:otherwise>
            
        </c:otherwise>
    </c:choose>

base标签
1、在前端HTML代码中,有一个标签,叫做base标签,这个标签可以设置整个网页的基础路径。
2、这是Java的语法,也不是JSP的语法。是HTML中的一个语法。HTML中的一个标签。通常出现在head标签中。
3、< base href=“http://localhost:8080/oa/”>
    在当前页面中,凡是路径没有以“/”开始的,都会自动将base中的路径添加到这些路径之前。
    需要注意:在JS代码中的路径,保险起见,最好不要依赖base标签。JS代码中的路径最好写上全路径。
    
Filter过滤器
1、Filter是什么,有什么用,执行原理是什么?
    Filter是过滤器。
    Filter可以在Servlet这个目标程序执行之前添加代码。也可以在Servlet执行之后添加代码。
        在chain.doFilter(request, response); 代码之前编写的代码就是请求之前的过滤规则,又叫做请求过滤【前提是在doFilter方法里面】
        在chain.doFilter(request, response); 代码之后编写的代码就是请求之后的过滤规则,又叫做响应过滤【前提是在doFilter方法里面】
    一般情况下,都是在过滤器当中编写公共代码。
2、一个过滤器怎么写那?
    第一步:编写一个Java类实现一个接口:jakarta.servlet.Filter.并且实现这个接口中的方法。
        init方法:在Filter对象第一次被创建之后调用,并且只调用一次。
            Servlet默认情况下:服务器启动阶段不会创建对象,也不会执行init方法。
            Filter默认情况下:服务器启动阶段会创建对象,并且执行init方法。
            【public void init(FilterConfig filterConfig) throws ServletException 】
        doFilter方法:只要用户发送一次请求,则执行一次。发送N此请求,则执行N次,在这个方法中编写过滤规则。
            【public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain) throws IOException,ServletException 】
        destroy方法:在Filter对象被释放/销毁之前调用,并且只调用一次。
            【public void destroy() 】
    第二步:在web.xml文件中对Filter进行配置。这个配置和Servlet很像。
        <filter>
            <filter-name>filterName</filter-name>
            <filter-class>全限定类名</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>filterName</filter-name>
            <url-pattern>*.do</url-pattern> 
        </filter-mapping>
        或者使用注释:    
            @WebFilter({"*.do"})
3、目标Servlet是否执行取决于两个条件:
    第一:在过滤器当中是否编写了:chain.doFilter(request,response);代码
    第二:用户发送的请求路径是否和Servlet的请求路径一致。
4、chain.doFilter(request, response);的作用
    执行写一个过滤器,如果下面没有过滤器了,执行Servlet。
5、Filter的优先级,天生的就比Servlet优先级高。
    /a.do 对应一个Filter,也对应一个Servlet。那么一定是先执行Filter,然后再执行Servlet。
6、关于Filter的配置路径:
    /a.do、/b.do、/dept/save。这些配置的方式都是精准匹配。
    /* 匹配所有路径,代表匹配这个项目中的所有路径【/代表应用的根路径(这种方式可以省略/),不是服务器的跟路径,*代表所有的路径】
    *.do    后缀匹配。【这种方式不以“/”开始,并且绝对不可以以“/”开始】
    /dept/* 前缀匹配。【表示匹配“/dept”路径下的所有路径】
        总结:
            只有以*开始的路径可以不以/开始。[不以/开始的路径默认都是从应用的根路径开始寻找的]
            *后面不能在跟其他路径了。
                例如:*.do/a(错误)、/*/a(错误)、*/b(错误)
7、在web.xml文件中进行配置的时候,Filter的执行顺序是什么?
    依靠filter-mapping标签的配置位置,越靠上优先级越高。
   使用@WebFilter的方式进行配置Filter的时候,Filter的执行优先级是什么?
    执行顺序是:比较Filter这个类名。
    比如:FilterA和FilterB,则先执行FilterA。
    比如:Filter1和Filter2,则先执行Filter1.
   如果web.xml和WebFilter都有配置那么web.xml起作用。
   【前提是Filter的请求路径相同。】
8、过滤器的调用顺序,遵循栈数据结构。
9、Filter的生命周期?
    和Servlet对象生命周期一致。
    唯一的区别:Filter默认情况下,在服务器启动阶段就实例化。Servlet不会。        
10、Filter过滤器这里有一个设计模式:
    责任链设计模式:
        是一种处理请求的模式,他让多个处理器都有机会处理该请求,直到其中某个处理成功为止。
        责任链模式把多个处理器串成链,然后让请求在链上传递,每一个处理器都有他自己的责任(业务处理范围)。
    过滤器最大的优点:
        在程序编译阶段不会确定调用顺序。
        因为Filter的调用顺序是配置到web.xml文件中的,只要修改web.xml配置文件中filter-mapping的顺序就可以调整Filter的执行顺序。
        显然Filter的执行顺序是在程序运行阶段动态组合的。那么这种设计模式被称为责任链设计模式。
    责任链设计模式最大的核心思想:
        在程序运行阶段,动态的组合程序的调用顺序。
        【所以过滤器一般都写在web.xml文件当中,通过调整filter-mapping的顺序,调整程序的执行顺序,不用修改Java代码,filter很少使用注解的方式进行开发】
11、java为Http专门准备了HttpFilter
    Filter
        GenericFilter
            HttpFilter
    使用和Servlet类似。

监听器(Listener)
1、什么是监听器?
    监听器是Servlet规范中的一员。
    在Servlet中所有的监听器接口都是以“Listener”结尾。
2、监听器有什么用?
    监听器实际上是Servlet规范给我们javaweb程序员的特殊时机。
    特殊的时刻如果想执行这段代码,你需要使用对应的监听器。
3、Servlet规范中提供了那些监听器?
    jakarta.servlet包下:
        ServletContextListener
            public void contextInitialized(ServletContextEvent sce) : ServletContext对象被创建的时候执行
            public void contextDestroyed(ServletContextEvent sce) : ServletContext对象被销毁的时候执行
        ServletContextAttributeListener
        ServletRequestListener
            public void requestInitialized(ServletRequestEvent sre):request对象被创建的时候调用
            public void requestDestroyed(ServletRequestEvent sre):request对象被销毁的时候调用
        ServletRequestAttributeListener
            attributeAdded:向域中绑定数据的时候Tomcat自动调用
            attributeRemoved:从域中删除数据的时候Tomcat自动调用
            attributeReplaced:将域中的数据进行替换的时候Tomcat自动调用
    jakarta.servlet.http包下:
        HttpSessionListener
            public void sessionCreated(HttpSessionEvent se):session对象被创建的时候调用
            public void sessionDestroyed(HttpSessionEvent se):session对象被销毁的时候调用
        HttpSessionAttributeListener
        HttpSessionBindingListener
            “某一个”类型实现了HttpSessionBindingListener接口中的两个方法:【“某一个”类不需要加“@WebListener注解”】
                public void valueBound :向域中绑定“某一个”类型的数据的时候会被调用
                public void valueUnbound:从session域中解绑“某一个”类型的数据的时候会被调用
        HttpSessionIdListener
        HttpSessionActivationListener
4、监听器:【监听的范围是整个项目】
    以HttpSessionListener为例:session对象是一个人一个。
    不管是谁,不管是那个人只要访问的是该项目并且创建一个session对象,那么sessionCreated就会被Tomcat自动调用。
    以ServletRequestListener为例:
        只要整个应用中有request对象被创建就会被ServletRequestListener监听器检测到。
5、一种监听器可以写多个:
    例如:ServletContextListener监听器可以写多个java类去实现这个接口。
    多个java类就是多个监听器,多个监听器就是的执行顺序是怎样的?
        根据监听器,在web.xml文件中配置的先后顺序,配置在前的先执行:
            <listener>
                <listener-class>监听器的类名</listener-class>
            </listener>
        如果要是使用注解的方式:执行顺序是:比较Listener这个类名。
            比如:ListenerA和ListenerB,则先执行ListenerA。
            比如:Listener1和Listener2,则先执行Listener1.
        如果web.xml和WebListener都有配置那么web.xml起作用。
6、注意:所有监听器中的方法都是不需要javaweb程序员调用的,由服务器来负责调用?什么时候被调用呢?
    注意:所有监听器中的方法都是不需要javaweb程序员调用的,由服务器来负责调用?什么时候被调用呢?
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛英豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值