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程序员调用的,由服务器来负责调用?什么时候被调用呢?
相关文章:
javaweb笔记2
JSP 1、在webapp的根目录下新建一个index.jsp文件,访问以下地址: http://localhost:8080/webappName/index.jsp 实际上访问这个index.jsp文件,底层执行的是:index_jsp.class这个程序。 这个index.jsp会被tomcat翻译成index_jsp.j…...
【IIS搭建网站】本地电脑做服务器搭建web站点并公网访问「内网穿透」
文章目录 1.前言2.Windows网页设置2.1 Windows IIS功能设置2.2 IIS网页访问测试 3. Cpolar内网穿透3.1 下载安装Cpolar3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5.结语 1.前言 在网上各种教程和介绍中,搭建网页都会借助各种软件的帮助,比如…...
算法训练day2:哈希表
哈希表理论基础 哈希表是根据关键码的值而直接进行访问的数据结构。 当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。 但是哈希法也是牺牲了空间换取了时间,因为我们要使用额外的数组,set或者是map来存放数据&#…...
Git——利用SSH密钥本地仓库上传远程GitHub库
文章目录 1、前言2、详细步骤2.1 创建密钥2.2 进入密钥文件并复制2.3 在GitHub上添加密钥2.4 回到本地仓库文件夹,连接GitHub并上传 3. 结语 1、前言 现在想要从本地设备将本地仓库上传到GitHub上需要用到SSH密钥,接下来讲解大致的步骤,本文默…...
一起读源码 —— Fastjson 的核心方法及其实现原理
源码介绍 Fastjson 是阿里巴巴开源的一个 Java 工具库,它常常被用来完成 Java 的对象与 JSON 格式的字符串的相互转化。 此文读的源码是撰写此文时 Fastjson 的最新的发布版本,即 1.2.83 下载源码 请前去 github 找到 release 最新版下载后解压&…...
Python实现批量图片下载及去重处理
背景 在爬虫应用开发中,常常需要批量下载图片,并对图片进行去重处理。Python 是一种非常流行的编程语言,也是开发爬虫应用的首选,本文将介绍如何使用 Python 下载图片,并对下载的图片进行去重处理。 内容 首先&…...
【QA】Python代码调试之解决Segmentation fault (core dumped)问题
Python代码调试之解决Segmentation fault 问题 问题描述排查过程1. 定位错误,2. 解决办法 参考资料 问题描述 Python3执行某一个程序时,报Segmentation fault (core dumped)错,且没有其他任何提示,无法查问题。 Segmentation fa…...
C++ 迭代器之旅(Journey of Iterators)
C 迭代器之旅(Journey of Iterators) 一、引言(Introduction)C Iterator模板库简介(Overview of C Iterator Template Library)Iterator的重要性和作用(The Importance and Role of Iterators&a…...
使用全球融合CDN的10大优势
根据预估,今年的全球内容交付网络(CDN)市场预计将达到424亿美元。而由于移动应用程序的激增和人工智能尤其是ChatGPT等相关领域的快速发展将进一步带来CDN市场的快速增长,可以说全球CDN的黄金时代才刚开始。 融合CDN和多CDN战略是…...
前端学习:HTML图像、表格、列表
目录 图像 一、图像标签和源属性(Src) 二、替换文本属性(Alt) 三、设置图片样式基本属性 四、图像标签 表格 一、标签 补充: 二、表格的表头 三、表格常用标签和属性 标签 属性 列表 一、无序列表 二、有序列表 三、定义列表 四、列表常用标签属性 图像 一、…...
202305读书笔记|《因思念而沉着》——任何赞美都是身外之物唯自由可随身携带
《因思念而沉着》作者巴哑哑,忘了是什么时候加入的书架,昨天下班地铁上读完的书。是美的! 部分节选如下: 羽叶茑萝举着熄灭的花青色的小枣落了一地所以哭泣沾染上了你的脸 在没落下 当我们开始生活 就是开始患上了眼疾你独自悲伤…...
M1 M2上能安装上Autocad 2024 Mac 中文版吗 autocad m1 m2版本有啦 终于支持Ventura 13x了
AutoCAD是一款强大的工具,适合于各种领域的设计和绘图。它具有二维图形和三维建模功能、多种文件格式支持、自定义命令和样式、批处理和脚本等特点,可以帮助用户实现高质量的设计和建模。同时,还支持云端存储和共享,方便用户随时随…...
【题解】P4055 [JSOI2009] 游戏
link 题目大意 题目说得比较清楚。 题解 前置知识:二分图最大匹配、基础博弈论。 每个点只能走一次的四联通点阵,可以想到二分图匹配。 将其套路地奇偶分点,相邻两点连边(显然不能为 #)。 先求一个最大匹配。 …...
P1020 [NOIP1999 普及组] 导弹拦截
题目描述 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统…...
Makefile学习
什么是Makefile 使用 GCC 编译器在 Linux 进行 C 语言编译,通过在终端执行 gcc 命 令来完成 C 文件的编译,如果我们的工程只有一两个 C 文件还好,需要输入的命令不多,当文件有几十、上百甚至上万个的时候用终端输入 GCC 命令的方…...
2.4 随机变量函数的分布
学习目标: 学习随机变量函数的分布,我会采取以下步骤: 熟悉随机变量的基本概念和分布:在学习随机变量函数的分布之前,需要先掌握随机变量的基本概念和分布,包括离散型随机变量和连续性随机变量的概率密度…...
数据结构【一】:前缀表达式与后缀表达式的区别
在早期计息机系统中,由于没有括号规定运算顺序,因此,依靠出栈和入栈两种方式,限定元素和符号之间的关系确定了前缀表达式和后缀表达式两种运算方式,中缀表达式即为普通的运算表达式;注意,在栈结…...
搭建 PostgreSQL
端口:5432 代理备份端口:6432 下载 postgresql-15.0-1-windows-x64 乱码显示 配置环境变量 PGDATA数据目录位置 找到postgresql.conf文件, 修改参数 lc_messagesUTF8 max_connections 1000 shared_buffers4GB work_mem8MB 问题:…...
Nmap入门到高级【第四章】
预计更新Nmap基础知识 1.1 Nmap简介和历史 1.2 Nmap安装和使用方法 1.3 Nmap扫描技术和扫描选项 Nmap扫描技术 2.1 端口扫描技术 2.2 操作系统检测技术 2.3 服务和应用程序检测技术 2.4 漏洞检测技术 Nmap扫描选项 3.1 扫描类型选项 3.2 过滤器选项 3.3 探测选项 3.4 输出选项…...
c++正则表达式及其使用,超级详细
文章目录 概述正则表达式语法正则表达式操作std::regex_matchstd::regex_replacestd::regex_search 实例匹配邮箱替换 HTML 标签搜索 URL 总结 概述 正则表达式是一种用于匹配字符串的工具,可以在文本中查找特定的模式,并且可以快速地对字符串进行搜索和…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
基于开源AI智能名片链动2 + 1模式S2B2C商城小程序的沉浸式体验营销研究
摘要:在消费市场竞争日益激烈的当下,传统体验营销方式存在诸多局限。本文聚焦开源AI智能名片链动2 1模式S2B2C商城小程序,探讨其在沉浸式体验营销中的应用。通过对比传统品鉴、工厂参观等初级体验方式,分析沉浸式体验的优势与价值…...
