asds在进行 Java Web 应用开发对, JSP 是必不可少的。因此在学习 Java Web 应用开发对,还必须拿握 JSP 的语法。本章将向渎者介绍 JSP 语法中的 JSP 页面的基本构成、指令标识、脚本标识、注释以及动作标识等内客。
asdsadadsdsdssdasdasdsadasdasdasdsadassdasdsadasdasdsadasdsadassadasdas————《JavaWeb从入门到精通》
为什么要学习 jsp 技术
什么是 jsp?
ssdssJSP (全称 Java Server Pages) 是由 Sun 公司专门为了解决动态生成 HTML 文档的技术,是Java 的服务器页面。jsp 的主要作用是代替 Servlet 程序回传html 页面的数据。因为Servlet 程序回传html 页面数据是一件非常繁锁的事情。开发成本和维护成本都极高。
Servlet 程序输出 html 页面:
ssdss在学习 jsp 技术之前,如果我们要往客户端输出一个页面。我们可以使用 Servlet 程序来实现。具体的代码如下:
ssdsdssServlet 回传html 页面数据的代码:
public class PringHtml extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,
IOException {
// 通过响应的回传流回传html 页面数据
resp.setContentType("text/html; charset=UTF-8");
PrintWriter writer = resp.getWriter();
writer.write("<!DOCTYPE html>\r\n");
writer.write(" <html lang=\"en\">\r\n");
writer.write(" <head>\r\n");
writer.write(" <meta charset=\"UTF-8\">\r\n");
writer.write(" <title>Title</title>\r\n");
writer.write(" </head>\r\n");
writer.write(" <body>\r\n");
writer.write(" 这是html 页面数据\r\n");
writer.write(" </body>\r\n");
writer.write("</html>\r\n");
writer.write("\r\n");
}
}
ssdsdssjsp 回传一个简单html 页面的代码:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
这是html 页面数据
</body>
</html>
sdss注:上面的代码我们不难发现。通过 Servlet 输出简单的 html 页面信息都非常不方便。那我们要输出一个复杂页面的时候,就更加的困难,而且不利于页面的维护和调试。所以 sun 公司推出一种叫做 jsp 的动态页面技术帮助我们实现对页面的输出繁锁工作。jsp 页面的访问千万不能像 HTML 页面一样。托到浏览器中。只能通过浏览器访问 Tomcat 服务器再访问 jsp 页面。
如何创建一个 jsp 动态页面程序?
ssdss选中相应web目录,右键创建一个 jsp 文件,New—>JSP/JSPX,然后在body 标签中添加想要显示的文本内容。然后在浏览器中输入 jsp 页面的访问地址,就可以得到body标签中的信息。
....
<html>
<head>
<title>$Title$</title>
</head>
<body>
这是JSP文件
</body>
</html>
如何修改 jsp 文件的默认编码?
sdss注:jsp 页面是一个类似于 html 的一个页面。 jsp 直接存放到 WebContent 目录下,和 html 一样访问 jsp 的时候,也和访问 html 一样。
jsp 的运行原理
ssdssjsp 的本质上是一个 Servlet 程序。
ssdss当我们第一次访问jsp 页面的时候。Tomcat 服务器会帮我们把jsp 页面翻译成为一个java 源文件。并且对它进行编译成
为.class 字节码程序。我们打开java 源文件不难发现其里面的内容是:
ssdssadasdsasadasdas
ssdss我们跟踪原代码发现,HttpJspBase 类。它直接地继承了HttpServlet 类。也就是说。jsp 翻译出来的java 类,它间接了继承了HttpServlet 类。也就是说,翻译出来的是一个Servlet 程序
ssdss注:通过翻译的java 源代码我们就可以得到结果:jsp 就是Servlet 程序。
ssds大家也可以去观察翻译出来的Servlet 程序的源代码,不难发现。其底层实现,也是通过输出流。把html 页面数据回传
给客户端。
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF-8");
pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\r\n");
out.write("\r\n");
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write(" <title>Title</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write(" a.jsp 页面\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
jsp 的语法
jsp 头部的page 指令
dssjsp 的page 指令可以修改jsp 页面中一些重要的属性,或者行为。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
dss这是 jsp 文件的头声明。表示这是 jsp 页面:
sdsdsdsslanguage 属性 值只能是 java。 表示翻译的得到的是 java 语言的
sdsdsdsscontentType 属性 设置响应头 contentType 的内容
sdsdsdsspageEncoding 属性 设置当前 jsp 页面的编码
sdsdsdssimport 属性 给当前 jsp 页面导入需要使用的类包
---------------------------------------------------------两个属性是给 out 输出流使用-------------------------------------------------------------------------
sdsdsdssautoFlush 属性 设置是否自动刷新 out 的缓冲区,默认为 true
sdsdsdssbuffer 属性 设置 out 的缓冲区大小。默认为 8KB
sdsdsdsserrorPage 属性 设置当前 jsp 发生错误后,需要跳转到哪个页面去显示错误信息
sdsdsdssisErrorPage 属性 设置当前 jsp 页面是否是错误页面。是的话,就可以使用 exception 异常对象
sdsdsdsssession 属性 设置当前 jsp 页面是否获取 session 对象,默认为 true
sdsdsdssextends 属性 给服务器厂商预留的 jsp 默认翻译的 servlet 继承于什么类
jsp 中的三种脚本介绍
第一种,声明脚本:
sdsdsdss声明脚本格式如下:<%! 声明 java 代码 %>
sdsdsdss在声明脚本块中,我们可以干 4 件事情:
sdsdsdss1.我们可以定义全局变量。sdsdsdss2.定义 static 静态代码块sdsdsdss3.定义方法sdsdsdss4.定义内部类
sdsdsdss注:几乎可以写在类的内部写的代码,都可以通过声明脚本来实现
<%--1、声明类属性--%>
<%!
private Integer id;
private String name;
private static Map<String,Object> map;
%>
<%--2、声明static 静态代码块--%>
<%!
static {
map = new HashMap<String,Object>();
map.put("key1", "value1");
map.put("key2", "value2");
map.put("key3", "value3");
}
%>
<%--3、声明类方法--%>
<%!
public int abc(){
return 12;
}
%>
<%--4、声明内部类--%>
<%!
public static class A {
private Integer id = 12;
private String abc = "abc";
}
%>
sdsdsdss声明脚本代码翻译对照:
第二种,表达式脚本(常用):
sdsdsdss表达式脚本格式如下:<%=表达式 %>
sdsdsdss表达式脚本 用于向页面输出内容。
sdsdsdss表达式脚本的特点:
sdsdsdsddss①、所有的表达式脚本都会被翻译到_jspService() 方法中
sdsdsdsddss②、表达式脚本都会被翻译成为out.print()输出到页面上
sdsdsdsddss③、由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象都可以直接使用。
sdsdsdsddss④、表达式脚本中的表达式不能以分号结束。
第三种,代码脚本:
sdsdsdss表达式脚本格式如下:<% java 代码 %>
sdsdsdss代码脚本的作用是:可以在jsp 页面中,编写我们自己需要的功能(写的是java 语句)。
sdsdsdss代码脚本的特点是:
sdsdsdsddss①、代码脚本翻译之后都在_jspService 方法中
sdsdsdsddss②、代码脚本由于翻译到_jspService()方法中,所以在_jspService()方法中的现有对象都可以直接使用。
sdsdsdsddss③、还可以由多个代码脚本块组合完成一个完整的java 语句。
sdsdsdsddss④、代码脚本还可以和表达式脚本一起组合使用,在jsp 页面上输出数据
jsp 中的注释:
sdsdsdss// 单行 java 注释
sdsdsdss/* 多行 java 代码注释 */
sdsdsdss单行注释和多行注释能在翻译后的 java 源代码中看见。
sdsdsdss<%-- jsp 注释 --%> jsp 注释在翻译的时候会直接被忽略掉
sdsdsdss< !-- html 注释 – >html 的注释会被翻译到 java 代码中输出到 html 页面中查看
jsp 九大内置对象
ssdssjsp 中的内置对象,是指Tomcat 在翻译jsp 页面成为Servlet 源代码后,内部提供的九大对象,叫内置对象。
sdsdsdss注:九大内置对象 , 都是我们可以在 【 代码脚本 】 中或 【 表达式脚本 】 中直接使用的对象。
jsp 四大域对象
ssdss四大域对象经常用来保存数据信息。
ssdss域对象是可以像Map 一样存取数据的对象。四个域对象功能一样。不同的是它们对数据的存取范围。虽然四个域对象都可以存取数据。在使用上它们是有优先顺序的。四个域在使用的时候,优先顺序分别是,他们从小到大的范围的顺序。
ssddsdssddsdsdsdsdssspageContext ====>>> request ====>>> session ====>>> application
ssdss四个作用域的测试代码:新建两个 jsp 页面。分别取名叫:context1.jsp,context2.jsp
sdssdsscontext1.jsp 的页面代码如下:
<body>
<h1>context1.jsp 页面</h1>
<%
//往四个域中都分别保存了数据
pageContext.setAttribute("key", "pageContext-value");
request.setAttribute("key", "request-value");
session.setAttribute("key", "session-value");
application.setAttribute("key", "application-value");
%>
<%-- 测试当前页面作用域 --%>
pageContext 域是否有值:<%=pageContext.getAttribute("key") %><br/>
request 域是否有值:<%=request.getAttribute("key") %><br/>
session 域是否有值:<%=session.getAttribute("key") %><br/>
application 域是否有值:<%=application.getAttribute("key") %><br/>
<%
// 测试 request 作用域
request.getRequestDispatcher("/context2.jsp").forward(request, response);
%>
</body>
sdssdsscontext2.jsp 的页面代码如下:
<body>
<h1>context2.jsp 页面</h1>
<%=pageContext.getAttribute("key") %><br/>
<%=request.getAttribute("key") %><br/>
<%=session.getAttribute("key") %><br/>
<%=application.getAttribute("key") %><br/>
</body>
sdsdsdss测试 pageContext 作用域步骤:直接访问 context1.jsp 文件
sdsdsdss测试 request 作用域步骤:1.在 context1.jsp 文件中添加转发到 context2.jsp(有数据) 2.直接访问 context2.jsp 文件 (没有数据)
sdsdsdss测试 session 作用域步骤:1.访问完 context1.jsp 文件 2.关闭浏览器。但是要保持服务器一直开着 3.打开浏览器,直接访问 context2.jsp 文件
sdsdsdss测试 application 作用域步骤:1.访问完 context1.jsp 文件,然后关闭浏览器 2.停止服务器。再启动服务器。 3.打开浏览器访问 context2.jsp 文件
jsp 中 中 out 流 输出流 和 和 response.getwriter() 输出流
ssdss jsp 中 out 和 response 的 writer 的区别演示 :
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
// out 输出
out.write("这是 out 的第一次输出<br/>");
// out flush 之后。会把输出的内容写入 writer 的缓冲区中
out.flush();
// 最后一次的输出,由于没有手动 flush,会在整个页面输出到客户端的时候,自动写入到 writer缓冲区
out.write("这是 out 的第二次输出<br/>");
// writer 的输出
response.getWriter().write("这是 writer 的第一次输出<br/>");
response.getWriter().write("这是 writer 的第二次输出<br/>");
%>
</body>
</html>
ssdss在浏览器里输入 http://localhost:8080/day09/output.jsp 运行查看结果:
sdsdsddsdsdsdss
jsp 中 out 输出流 和 response.getwriter() 输出流
ssdss response 中表示响应,我们经常用于设置返回给客户端的内容(输出)ssdss out 也是给用户做输出使用的。
ssdss 注:由于jsp 翻译之后,底层源代码都是使用out 来进行输出,所以一般情况下。我们在jsp 页面中统一使用out 来进行输出。避免打乱页面输出内容的顺序。
ssdssout.write() 输出字符串没有问题
ssdssout.print() 输出任意数据都没有问题(都转换成为字符串后调用的write 输出)
ssdss 深入源码,浅出结论:在jsp 页面中,可以统一使用out.print()来进行输出
jsp 的常用标签
ssdss <%-- 静态包含 --%>ssdss<%-- 动态包含 --%>ssdss<%-- 转发 --%>
ssdss 静态包含 :<%@ include file=" " %> 静态包含是把包含的页面内容原封装不动的输出到包含的位置。
<%--
<%@ include file=""%> 就是静态包含
file 属性指定你要包含的jsp 页面的路径
地址中第一个斜杠/ 表示为http://ip:port/工程路径/ 映射到代码的web 目录
静态包含的特点:
1、静态包含不会翻译被包含的jsp 页面。
2、静态包含其实是把被包含的jsp 页面的代码拷贝到包含的位置执行输出。
--%>
<%@ include file="/include/footer.jsp"%>
ssdss动态包含:<jsp:include page=""></jsp:include> 动态包含会把包含的 jsp 页面单独翻译成 servlet 文件,然后在执行到时候再调用翻译的 servlet 程序。并把计算的结果返回。动态包含是在执行的时候,才会加载。所以叫动态包含。
<%--
<jsp:include page=""></jsp:include> 这是动态包含
page 属性是指定你要包含的jsp 页面的路径
动态包含也可以像静态包含一样。把被包含的内容执行输出到包含位置
动态包含的特点:
1、动态包含会把包含的jsp 页面也翻译成为java 代码
2、动态包含底层代码使用如下代码去调用被包含的jsp 页面执行输出。
JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);
3、动态包含,还可以传递参数
--%>
<jsp:include page="/include/footer.jsp">
<jsp:param name="username" value="bbj"/>
<jsp:param name="password" value="root"/>
</jsp:include>
ssdss动态包含的底层原理:
ssdss页面转发:
<%--
<jsp:forward page=""></jsp:forward> 是请求转发标签,它的功能就是请求转发
page 属性设置请求转发的路径
--%>
<jsp:forward page="/scope2.jsp"></jsp:forward>
静态包含和动态包含的区别:
ssdss 注:我们在工作中,几乎都是使用静态包含。理由很简单。因为 jsp 页面虽然可以写 java 代码,做其他的功能操作。但是由于 jsp 在开发过程中被定位为专门用来展示页面的技术。也就是说。jsp 页面中,基本上只有 html,css,js。还有一些简单的 EL,表达式脚本等输出语句。所以我们都使用静态包含。
什么是 Listener 监听器
ssdss①、Listener 监听器它是JavaWeb 的三大组件之一。JavaWeb 的三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
ssdss②、Listener 它是JavaEE 的规范,就是接口
ssdss③、监听器的作用是,监听某种事物的变化。然后通过回调函数,反馈给客户(程序)去做一些相应的处理。
ServletContextListener 监听器
ssdssServletContextListener 它可以监听ServletContext 对象的创建和销毁。ServletContext 对象在web 工程启动的时候创建,在web 工程停止的时候销毁。监听到创建和销毁之后都会分别调用ServletContextListener 监听器的方法反馈。
ssdss两个方法分别是:
public interface ServletContextListener extends EventListener {
/**
* 在ServletContext 对象创建之后马上调用,做初始化
*/
public void contextInitialized(ServletContextEvent sce);
/**
* 在ServletContext 对象销毁之后调用
*/
public void contextDestroyed(ServletContextEvent sce);
}
ssdss如何使用ServletContextListener 监听器监听ServletContext 对象。使用步骤如下:
ssdsdss1、编写一个类去实现ServletContextListener
ssdsdss2、实现其两个回调方法
ssdsdss3、到web.xml 中去配置监听器
ssdss监听器实现类:
public class MyServletContextListenerImpl implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
System.out.println("ServletContext 对象被创建了");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
System.out.println("ServletContext 对象被销毁了");
}
}
ssdssweb.xml 中的配置:
<!--配置监听器-->
<listener>
<listener-class>com.atguigu.listener.MyServletContextListenerImpl</listener-class>
</listener>