记录下JSP学习内容,以免老年痴呆
JSP的执行原理
- 浏览器访问的路径虽然是以.jsp结尾,访问的是某个jsp文件,其实底层执行的是jsp对应的java程序
Tomcat服务器负责将.jsp文件翻译生成.java源程序,并将这个源程序编译生成.class字节码文件,访问.jsp,其实底层还是执行了.class文件中的程序 - Tomcat内置了一个jsp翻译引擎,专门负责jsp翻译文件,编译java源文件
- index.jsp文件被翻译成index_jsp.java文件,编译生成index_jsp.class源文件
index_jsp这个类继承HttpJspBase,而HttpJspBase继承了HttpServlet - Tomcat目录下的work文件就是存放jsp转化成的.java文件
- JSP文件后缀,默认是.jsp,JSP后缀可以通过修改CATALINA_HOME/conf/web.xml中修改
- jsp就是servlet,只不过职责不同,jsp的强项是做页面展示
- 在jsp文件中编写的所有html,css,JavaScript,对jsp来说,只不过是普通的字符串
翻译成out.write(“翻译成这里”);
jsp文件第一次访问的时候为什么这么慢?
- 启动jsp引擎,需要一个翻译的过程,需要一个编译的过程,需要servlet对象的创建过程
init方法调用,service方法调用 - 修改jsp文件不需要部署重启Tomcat文件
第二次访问jsp文件,底层直接调用service方法 - jsp也是单实例多线程环境下运行的一个servlet对象
JSP语法
1,jsp注释
2,jsp的小脚本
3,jsp的声明语法格式
4,jsp的九大内置对象
5,jsp表达式
6,jsp的指令
7,jsp的动作
1,jsp注释
<%-- jsp专业注释,使用这种注释方式,不会被翻译到java源文件中 --%>
2,jsp的小脚本
<% 在这里编写jsp脚本语句 %>
- 小脚本中的java语句被翻译到servlet的“service方法”中,所以小脚本内必须编写java语句,java语句以分号结尾
- <%%>中的Java代码是在service方法中,service方法中不能定义实例变量,方法,静态语句块
所谓的jsp规范,就是sun制定好的一些翻译规则,按照翻译规则进行翻译,生成对应的java源程序,不同的web服务器翻译的结果是完全相同的,因为这些服务器翻译的时候,都遵守了jsp翻译规范
3,jsp的声明语法格式
<%! 这里的Java语句是写在service方法之外的,可以写实例变量,静态变量,方法,静态语句块,构造函数,不能写Java语句,除非是变量声明 %>
4,jsp的九大内置对象
什么是内置对象啊
可以直接在jsp文件中拿来使用的对象引用九大内置对象有哪些?
内置对象名称 对应servlet类名 PageContext javax.servlet.jsp.PageContex 页面范围 request javax.servlet.http.HttpServletRequest 请求范围 session javax.servlet.http.HttpSession 会话范围 application javax.servlet.ServletContext 应用范围 out javax.servlet.jsp.JspWriter(与PrintWriter类似) response javax.servlet.http.HttpServletResponse config javax.servlet.ServletConfig exception java.lang.Throwable page java.lang.Object(page=this,就是指向本身)
以上内置对象只能在service方法中“直接”使用,在其他方法中无法“直接”使用,可以间接使用
四个作用域对象/范围对象
pageContext:在同一个jsp页面中共享数据,不能跨jsp页面
request:在同一个请求中共享数据
session:在同一个会话中共享数据
application:所有用户共享的数据可以放到应用范围
5,jsp表达式
登录成功,欢迎<%=username%>回来,这种格式就是jsp表达式
6,jsp的指令
指令的作用是指导jsp的翻译引擎如何翻译jsp代码
jsp中共三个指令:
page 页面指令
include 包含指令
taglib 标签库指令指令的语法格式:<%@指令名 属性名=属性值 属性名=属性值%>
关于jsp中page指令,page指令中常用的属性
contentType 设置JSP的响应内容类型,同时在响应的内容类型后面也可以指定响应的字符编码方式
<%@page contentType=”text/html;charset=utf-8”%>
和<%@page contentType=”text/html” pageEncoding=”UTF-8”%>一样pageEncoding 设置jsp响应时的字符编码方式
import 组织导入,导java类
session 设置当前jsp页面中是否可以直接使用session内置对象
- session=”true”,表示在当前jsp中可以直接使用内置对象session,程序在执行的时候获取当前session会话对象,若获取不到则新建session对象
- session=“false”,表示在当前jsp中不可以直接使用内置对象session,有时候并不想新建session,只是想获取当前session,就可以使用session=”false”,若想用session,可以自己创建一个
HttpSession session = request.getSession(false),获取当前session,获取不到返回null
若session属性不写,则默认session=”true”
errorPage 错误页面,当程序出错时,跳转到指定的错误页面,跳转使用转发技术,
errorPage="/index4.jsp",路径不包括项目名
isErrorPage 是否是错误页面,如果为true,表示当前页面为错误页面,可以使用exception对象,exception引用指向了抛出的异常
isELIgnored 是否忽略EL表达式
include指令
<%@include file=””%>, 导入其他jsp文件内容,include指令只有一个file属性,一个jsp文件可以使用多个include指令,include指令是静态联编,即两个文件组成一份java源代码
7,jsp的动作
语法格式:
<jsp:动作名 属性名=属性值 属性名=属性值></jsp:动作名>
转发动作,达到页面转发技术效果
<jsp:forward page="index2.jsp"></jsp:forward>
include动作,动态联编
<jsp:include page="/index2.jsp"></jsp:include>
与静态联编不同的是,动态联编是生成两个java文件,两个servlet对象,所以两个文件可以存在同名变量
EL表达式
在EL表达式中,jsp四大域对象都有相应的别名
application applicationScope
session sessionScope
request requestScope
pageContext pageScopeEL表达式的作用:将作用域中的数据写到响应体中,即输出用的
使用EL表达式的语法格式:${作用域.关键字}
输出高级对象中的数据:
${作用域.user.name},前提,user类中一定要提供get,set方法简化版EL表达式:
${作用域.关键字}中的作用域可以省略,EL表达式会自己去域对象中挨个找数据
查找顺序是从小到大的范围,先从pageScope中找,最后到applicationContext中查找EL表达式中除了以上四种内置对象,还有以下内置对象
param
使用:${param.请求参数名}
作用:读取请求协议包参数内容,即读取表单数据
代替:String value = request.getParameter(“请求参数名”);
out.write(value);paramValues
使用:${paramValues.请求参数名}
作用:读取请求协议包中关联多个值的请求参数,将参数内容保存到数组
代替:String[] array = request.getParameterValues(“hobby”);表单提交的数据会被自动封装到request对象中,request对象中有map集合存储这些数据
map集合的key是name,字符串类型,value是一个字符串类型的一维数组
通过map集合的key获取value,适合取复选框数据
例如:${paramValues.hobby[0]} //取爱好数组中第一个值initParam
使用:${initParam.共享数据名}
代替:String value = application.getInitParameter(“driver”);
out.write(value);
JSTL
标签的使用
<c:set>:
作用:在jsp文件上设置域对象中共享的数据
使用:<c:set scope=”session” var=”key” value=”10”/>
代替:<% session.setAttribute(“key”,”10”); %>- 属性:scope:指定操作的域对象别名
- var :指定域对象中的key
- value:设置value值
<c:if>:
作用:在jsp文件中控制哪些内容可以写到响应体中
使用:<% <c:if test="通过EL表达式进行判断"> 内容 </c:if> %>
<c:choose>:
作用:在jsp文件上实现多分支选择判断,决定哪一个内容能写到响应体
使用:<c:choose> <c:when test="EL表达式进行判断">内容1</c:when> <c:when test="EL表达式进行判断">内容2</c:when> <c:otherwise>内容3</c:otherwise> </c:choose>
<c:foreach>
作用:循环遍历第一种使用方式:
<c:foreach var="声明循环变量名称" begin="初始化循环变量" end="循环变量可以接收的最大值" step="循环变量的递增值或递减值"> 在jstl标签中,var变量被自动写入到pageContext中, 所以可以直接用EL表达式取值,${pageScope.i}或者${i} </c:foreach>
第二种使用方式List集合:
<c:foreach items="通过EL表达式获得的域对象集合" var="声明循环变量"> 取值:${循环变量.对象属性名} </c:foreach>
第三种使用方式Map集合:
<c:foreach items="通过EL表达式获得的域对象集合" var="声明循环变量"> var变量代表Map集合的键值对,EntrySet ${var.key},代表map集合一个键值对的key值 ${var.value.属性名} 代表map集合一个键值对的value值的属性值 </c:foreach>
过滤器
作用:
一般用于完成通用的操作,如:登录验证,统一编码获取,敏感字符过滤执行流程,
请求在访问服务器上的资源时,会先执行过滤器的dofilter方法,在请求返回时也要经过过滤器public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) { System.out.println("过滤器在此执行"); servletResponse.setContentType("text/html;charset=UTF-8"); //doFilter方法之前,对request进行操作 filterChain.doFilter(servletRequest,servletResponse); //doFilter方法之后,对response进行操作 //也就是说,一个访问的请求和访问都会经过doFilter方法,doFilter方法执行完, //代表一次访问结束 }
生命周期:
- init方法:服务器启动时,tomcat会创建filter对象,并调用init方法,init方法里一般会加载资源
- doFilter方法:每次请求都会被调用
- destroy方法:服务器关闭时,filter对象被销毁,如果服务器是正常关闭,则会执行destroy方法,destroy方法一般会释放资源
过滤器配置:
- 拦截路径配置
1,具体资源路径:/index.jsp 只有访问index.jsp资源时,过滤器才会被执行
2,拦截目录:/user/* 访问/user下所有资源时,过滤器都会被执行
3,后缀名拦截:*.jsp
访问所有后缀名为jsp资源时,过滤器都会被执行
4,/*
访问项目所有资源都会执行拦截器 - 拦截方式配置:资源被访问的方式:普通的请求或者服务器内部servlet之间的转发
- 注解配置:
@WebFiler中设置dispatcherTypes属性
REQUEST,默认值,浏览器直接请求资源
FORWARD,转发访问资源
INCLUDE,包含访问资源
ERROR,错误跳转资源
ASYNC,异步访问资源 - web.xml:
filter-mapping标签中有dispatcher标签
- 注解配置:
- 拦截路径配置
过滤器链(配置多个过滤器)
- 执行顺序:如果有两个过滤器,过滤器1,过滤器2
- 1,请求时,执行过滤器1,再执行过滤器2
- 2,执行资源文件
- 3,响应时,执行过滤器2,再执行过滤器1
- 过滤器先后顺序问题:什么时候让过滤器1先执行,什么时候让过滤器2先执行呢?
- 1,注解配置:按照字符串比较规则比较,值小的先执行
如:AFilter和BFilter两个过滤器类名,则AFilter先执行 - 2,web.xml配置:
谁先定义,谁先执行
- 1,注解配置:按照字符串比较规则比较,值小的先执行
- 执行顺序:如果有两个过滤器,过滤器1,过滤器2
监听器Listener
概念:web三大组件之一
事件监听机制:
- 事件:一件事情
- 事件源:事件发生的地方
- 监听器:一个对象
- 注册监听:将事件源,事件,监听器绑定在一起,当事件源上发生某个事件后,执行监听器代码