下面是我整理下来的 JSP 知识点:
图上的知识点都可以在我其他的文章内找到相应内容
JSP 常见面试题
jsp 静态包含和动态包含的区别
jsp 静态包含和动态包含的区别
在讲解 request 对象的时候, 我们曾经使用过 request.getRequestDispatcher(String url).include(request,response)来对页头和页尾面进行包含
inclue 指令也是做这样的事情, 我们来试验一下吧!
这是页头
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 页头</title>
- </head>
- <body>
我是页头
- <br>
- <br>
- <br>
- </body>
- </html>
这是页尾
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 页尾</title>
- </head>
- <body>
我是页尾
- </body>
- </html>
在 1.jsp 中把页头和页尾包含进来
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 包含页头和页尾进来</title>
- </head>
- <body>
- <%@include file="head.jsp" %>
- <%@include file="foot.jsp" %>
- </body>
- </html>
访问 1.jsp
include 指令是静态包含静态包含的意思就是: 把文件的代码内容都包含进来, 再编译!, 看一下 jsp 的源代码就知道了!
上面已经提及到了, include 指令是静态包含, include 行为是动态包含其实 include 行为就是封装了 request.getRequestDispatcher(String url).include(request,response)
include 行为语法是这个样子的
<jsp:include page="" />
我们先来使用一下把, 在 1.jsp 页面中也将页头和页尾包含进来
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 包含页头和页尾进来</title>
- </head>
- <body>
- <jsp:include page="head.jsp"/>
- <jsp:include page="foot.jsp"/>
- </body>
- </html>
访问 1.jsp 页面看一下效果:
使用 jsp 行为来包含文件, jsp 源文件是这样子的:
jsp 行为包含文件就是先编译被包含的页面, 再将页面的结果写入到包含的页面中(1.jsp)
当然了, 现在有静态包含和动态包含, 使用哪一个更好呢? 答案是: 动态包含
动态包含可以向被包含的页面传递参数 (用处不大), 并且是分别处理包含页面的(将被包含页面编译后得出的结果再写进包含页面) 如果有相同名称的参数, 使用静态包含就会报错!!
模拟一下场景吧, 现在我的头页面有个名为 s 的字符串变量
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 页头</title>
- </head>
- <body>
- <%
- String s = "zhongfucheng";
- %>
我是页头呀
- <br>
- <br>
- <br>
- </body>
- </html>
我的页尾也有个名为 s 的字符串变量
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 页尾</title>
- </head>
- <body>
- <%
- String s = "zhongfucheng";
- %>
我是页尾呀
- </body>
- </html>
现在我使用静态包含看看会发生什么, 出现异常了
出现异常的原因很简单, 就是同一个文件中有两个相同的变量 s
使用动态包含就可以避免这种情况
总结
<%@include file="xxx.jsp" %>
为 jsp 中的编译指令, 其文件的包含是发生在 jsp 向 servlet 转换的时期, 而
<jsp:include page="xxx.jsp">
是 jsp 中的动作指令, 其文件的包含是发生在编译时期, 也就是将 java 文件编译为 class 文件的时期
使用静态包含只会 ** 产生一个 class 文件, 而使用动态包含会产生多个 class 文件 **
使用静态包含, 包含页面和被包含页面的 request 对象为同一对象, 因为静态包含只是将被包含的页面的内容复制到包含的页面中去; 而动态包含包含页面和被包含页面不是同一个页面, 被包含的页面的 request 对象可以取到的参数范围要相对大些, 不仅可以取到传递到包含页面的参数, 同样也能取得在包含页面向下传递的参数
jsp 有哪些内置对象? 作用分别是什么?
jsp 有哪些内置对象? 作用分别是什么?
九个内置对象:
- pageContext
- page
- config
- request
- response
- session
- application
- exception
- out
其中, requestresponsesessionapplicationconfig 这五个对象和 Servlet 的 API 是一样的这 5 个对象我就不解释了
在 JSP 中, 尤其重要的是 pageContext 对象
pageContext 是内置对象中最重要的一个对象, 它代表着 JSP 页面编译后的内容(也就是 JSP 页面的运行环境)!
pageContext 对象
既然它代表了 JSP 页面编译后的内容, 理所当然的: 它封装了对其他 8 大内置对象的引用!, 也就是说, 通过 pageContext 可以获取到其他的 8 个内置对象!
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>
获取八大内置对象
- </title>
- </head>
- <body>
- <% System.out.println(pageContext.getSession()); System.out.println(pageContext.getRequest());
- System.out.println(pageContext.getResponse()); System.out.println(pageContext.getException());
- System.out.println(pageContext.getPage()); System.out.println(pageContext.getServletConfig());
- System.out.println(pageContext.getServletContext()); System.out.println(pageContext.getOut());
- %>
- </body>
- </html>
看下效果:
pageContext 作为域对象
类似于 request,session,ServletContext 作为域对象而言都有以下三个方法:
- setAttribute(String name,Objcet o)
- getAttribute(String name)
- removeAttribute(String name)
当然了, pageContext 也不例外, pageContext 也有这三个方法!
pageContext 本质上代表的是当前 JSP 页面编译后的内容, 作为域对象而言, 它就代表着当前 JSP 页面(也就是 page)! 也就是说: pageContext 域对象只在 page 范围内有效, 超出了 page 范围就无效了!
首先来看看在 page 范围内能不能使用
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>
使用 page 域对象
- </title>
- </head>
- <body>
- <% pageContext.setAttribute( "name", "zhongfucheng"); %>
- <% String value=( String) pageContext.getAttribute( "name"); System.out.println(value);
- %>
- </body>
- </html>
效果如下:
我们现在来试验一下是不是超出了 page 范围就无效了!
在 2.jsp 中 request 域对象设置属性
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title>request 域对象设置属性</title>
- </head>
- <body>
- <%
- // 这是 request 域对象保存的内容
- request.setAttribute("name","zhongfucheng");
- %>
<%-- 跳转到 1.jsp 中 --%>
- <jsp:forward page="1.jsp"/>
- </body>
- </html>
企图在 1.jsp 中 pageContext 取出 request 存进去的属性
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 在 page 域对象获取属性</title>
- </head>
- <body>
- <%
- // 企图获取 request 域对象存进的属性
- String value = (String) pageContext.getAttribute("name");
- System.out.println(value);
- %>
- </body>
- </html>
效果如下:
pageContext 本质上代表着编译后 JSP 的内容, pageContext 还可以封装了访问其他域的方法!
上面的 pageContext 默认是 page 范围的, 但 pageContext 对象重载了 setgetremoveAttribute 这三个方法
- getAttribute(String name,int scope)
- setAttribute(String name,Object value,int scope)
- removeAttribute(String name,int scope)
多了一个设置域范围的一个参数, 如果不指定默认就是 page 当然了, pageContext 把 requestsessionapplicationpage 这几个域对象封装着了静态变量供我们使用
- PageContext.APPLICATION_SCOPE
- PageContext.SESSION_SCOPE
- PageContext.REQUEST_SCOPE
- PageContext.PAGE_SCOPE
刚才我们没有使用重载方法的时候, 使用 pageContext 是无法获取到 request 域对象设置的属性的现在我们使用重载后的方法看一下能不能获取得到!
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 在 page 域对象获取 request 域对象的属性</title>
- </head>
- <body>
- <%
- // 使用重载的方法获取 request 域对象的属性
- String value = (String) pageContext.getAttribute("name",pageContext.REQUEST_SCOPE);
- System.out.println(value);
- %>
- </body>
- </html>
效果:
pageContexst 还有这么一个方法:
findAttribute(String name)
该方法会查找各个域的属性, 从小到大开始寻找! 也就是 page>request->session->application
我们用此方法看能不能查找出 request 域对象的属性吧!
- <%@ page contentType="text/html;charset=UTF-8" language="java" %>
- <html>
- <head>
- <title > 使用 findAttribute</title>
- </head>
- <body>
- <%
- // 使用 findAttribute 查找 2.jsp 中 request 域对象的属性
- String value = (String) pageContext.findAttribute("name");
- System.out.println(value);
- %>
- </body>
- </html>
效果如下:
out 对象:
out 对象用于向浏览器输出数据, 与之对应的是 Servlet 的 PrintWriter 对象然而这个 out 对象的类型并不是 PrintWriter, 是 JspWriter
我们可以简单理解为: JspWriter 就是带缓存的 PrintWrieter
out 对象的原理如下:
只有向 out 对象中写入了内容, 且满足如下任何一个条件时, out 对象才去调用 ServletResponse.getWriter 方法, 并通过该方法返回的 PrintWriter 对象将 out 对象的缓冲区中的内容真正写入到 Servlet 引擎提供的缓冲区中:
设置 page 指令的 buffer 属性关闭了 out 对象的缓存功能
out 对象的缓冲区已满
整个 JSP 页面结束
一般我们在 JSP 页面输出都是用表达式(<%=%>), 所以 out 对象用得并不是很多!
page 对象
内置对象 page 是 HttpJasPage 对象, 其实 page 对象代表的就是当前 JSP 页面, 是当前 JSP 编译后的 Servlet 类的对象也就是说: page 对象相当于普通 java 类的 this
exception 对象
** 内置对象 exception 是 java.lang.Exception 类的对象, exception 封装了 JSP 页面抛出的异常信息 **exception 经常被用来处理错误页面
前面我们已经讲过了怎么设置错误页面了, 下面我们就来简单使用一下 exception 对象吧
1.jsp 页面
- <%@ page contentType="text/html;charset=UTF-8" language="java" errorPage="error.jsp" %>
- <html>
- <head>
- <title></title>
- </head>
- <body>
<%-- 模拟空指针异常的错误 --%>
- <%
- String sss = null;
- sss.length();
- %>
- </body>
- </html>
error.jsp 页面
- <%@ page contentType="text/html;charset=UTF-8" language="java" isErrorPage="true" %>
- <html>
- <head>
- <title > 错误页面</title>
- </head>
- <body>
- <%
- out.println("程序抛出了异常:" + exception);
- %>
- </body>
- </html>
效果:
总结
request 用户端请求, 此请求会包含来自 GET/POST 请求的参数
response 网页传回用户端的回应
pageContext 网页的属性是在这里管理, 代表的编译后 JSP 内容
session 与请求有关的会话期
application servlet 正在执行的内容
out 用来传送回应的输出
config servlet 的构架部件
page JSP 网页本身
exception 针对错误网页, 未捕捉的例外
jsp 和 servlet 的区别共同点各自应用的范围?
jsp 和 servlet 的区别共同点各自应用的范围?
JSP 是 Servlet 技术的扩展, 本质上就是 Servlet 的简易方式 JSP 编译后是类 servlet
Servlet 和 JSP 最主要的不同点在于: Servlet 的应用逻辑是在 Java 文件中, 并且完全从表示层中的 HTML 里分离开来而 JSP 的情况是 Java 和 HTML 可以组合成一个扩展名为. jsp 的文件
JSP 侧重于视图, Servlet 主要用于控制逻辑
属性作用域范围
属性作用域范围
page 只在一个页面中保存属性, 跳转页面无效
requet 只在一次请求中保存属性, 服务器跳转有效, 浏览器跳转无效
session 在一个会话范围中保存属性, 无论何种跳转均有效, 关闭浏览器后无效
application 在整个服务器中保存, 所有用户都可以使用
应用场景:
request: 如果客户向服务器发请求, 产生的数据,** 用户看完就没用了,** 像这样的数据就存在 request 域, 像新闻数据, 属于用户看完就没用的
session: 如果客户向服务器发请求, 产生的数据, 用户用完了等一会儿还有用, 像这样的数据就存在 session 域中, 像购物数据, 用户需要看到自己购物信息, 并且等一会儿, 还要用这个购物数据结帐
servletContext: 如果客户向服务器发请求, 产生的数据, 用户用完了, 还要给其它用户用, 像这样的数据就存在 servletContext 域中, 像聊天数据
写出 5 种 JSTL 常用标签
写出 5 种 JSTL 常用标签
<c:if>,<c:item>,<c:foreach>,<c:out>,<c:set>
写一个自定义标签要继承什么类
写一个自定义标签要继承什么类
来源: https://juejin.im/post/5a7a6f275188257a780d9be2