1. jsp的在服务器中的内部结构
2. jsp的三种语法
a) jsp头部的page指令
b) jsp中的三种脚本
i. 声明脚本(类中(非_jspService()方法中))
ii. 表达式脚本(_jspService方法)
iii. 代码脚本(_jspService方法中)
c) jsp中的三种注释
i. html注释
ii. java注释
iii. jsp注释
3. jsp九大内置对象
4. jsp四大域对象
5. jsp中的out输出和response.getWriter输出的区别
6. jsp的常用标签
a) jsp静态包含
b) jsp标签-动态包含
c) jsp标签-转发
7. 静态包含和动态包含的区别
jsp的全称是java server pages.java的服务器页面。动态页面。
jsp主要是为了解决Servlet程序输出html页面,代码过于繁锁事情。
如下是用servlet输入的html页面
public class PrintHtml extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html; charset=UTF-8");
//获取字符输出流
PrintWriter writer = response.getWriter();
writer.write("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n");
writer.write("<html>\r\n");
writer.write(" <head>\r\n");
writer.write(" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n");
writer.write(" <title>Insert title here</title>\r\n");
writer.write(" </head>\r\n");
writer.write(" <body>\r\n");
writer.write(" this is the hello html!\r\n");
writer.write(" </body>\r\n");
writer.write("</html>");
}
}
从上面的代码可以看出其繁琐性,如果HTML页面过于复杂,则servlet就会显得臃肿
jsp技术存的主要目标,就是为了解决Servlet程序输出html过于繁锁。不方便项目的开发和后期维护。
jsp页面和hmlt页面一样。都存放在WebContent目录下。
jsp页面的和html页面的访问一样。
比如:
在WebContent目录下有:
a.html 访问的地址是:http://ip:port/工程名/a.html
c.jsp 访问的地址是:http://ip:port/工程名/c.jsp
jsp的本质是一个Servlet程序
当我们第一次访问jsp页面的时候。Tomcat服务器会把jsp页面翻译成为Servlet程序
第一次访问jsp页面的时候(即,每次更改jsp页面该目录下的_jsp.java文件不会自动刷新,需要在浏览器刷新之后,其里面的内容才会发生刷新)。我们会发现,在tomcat服务器的work目录下,会有这些的文件。

我们打开a_jsp.java源文件,我们发现。里面是:

然后根据源码中的继承关系,我们找到了HttpJspBase的实现类(源码),在源码中,不难发现。HttpJspBase其实继承了HttpServlet类,
那么 也就是,我们访问jsp的时候Tomcat服务器帮我们翻译出来的a_jsp类其实也是间接继承了httpServlet类。
那么 说明翻译出来的类,本身也是一个Servlet程序。

那么 我们翻译出来的Servlet程序的源码中,我们发现如下的代码:

又一次证明 jsp页面,是为了解决Servlet程序输出html页面过繁锁这样的事情。
a. jsp 翻译之后 是 a_jsp.java
b. jsp 翻译之后 是 b_jsp.java
2. jsp的三种语法
a) jsp头部的page指令
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
i. language属性 表示jsp翻译之后是指定的java语言内容
ii. contentType属性 设置了jsp页面输出给客户端的数据的类型。

i. pageEncoding属性 设置当前jsp页面的字符集
ii. import属性它可以导入你需要包或类
iii. autoFlush属性自动刷新 out 输出流(缓冲区)。默认值是true(不能改为false)
iv. buffer属性它是out输出流的缓冲区,设置了缓冲区的大小。默认是8kb
当autoFlush设置为false,out缓冲区满了之后不让执行flush操作,客户端就会发生如下错误,buffer缓冲区溢出。

i. errorPage属性设置当jsp运行时。出错,就会自动跳转去的页面。(为了不给用户一个差的体验)
ii. isErrorPage属性设置当前jsp页面是否是一个错误页面。它会启用Exception异常对象。默认是false
iii. session 属性设置访问jsp页面的时候,是否创建Session会话对象。默认是true。
iv. extends 属性给留服务器厂商(一般不会改动)
b) jsp中的三种脚本
i. 声明脚本(类中(非_jspService()方法中))
作用:声明为类中(非_jspService()方法中)的代码
格式脚本的格式是:
<%! %>
1. 我们可以定义全局变量。
2. 定义static静态代码块
3. 定义方法
4. 定义内部类
<body>
<!-- 1.我们可以定义全局变量。 -->
<%!
private int i = 12;
private static Map<String,Object> map;
%>
<!-- 2.定义static静态代码块 -->
<%!
static {
map = new HashMap<String,Object>();
map.put("key1", "value1");
map.put("key2", "value2");
}
%>
<!-- 3.定义方法 -->
<%!
public int abc(){
return 0;
}
%>
<!-- 4.定义内部类 -->
<%!
public static class A {
private int kkk;
}
%>
this is the hello html!<br/>
</body>
务器自动帮我们生成代码在tomca目录下的work工作区间中的对应servlet与jsp页面中的代码:

ii. 表达式脚本(_jspService方法)
作用: 在jsp页面中输出数据
表达式脚本格式是:
<%=表达式 %>
表达式脚本可以在jsp页面中输出数据。
表达式脚本被翻译之后在_jspService方法中
表达式脚本翻译之后都是out.printl输出
在_jspService方法中的对象都可以直接使用。
在表达式脚本中,表达式不能以分号结尾
1. 输出整型
2. 输出浮点型
3. 输出字符串
4. 输出对象
<!-- 1.输出整型 -->
<%=124 %><br/>
<!-- 2.输出浮点型 -->
<%=12.12 %><br/>
<!-- 3.输出字符串 -->
<%="dfsawrqwafsa" %><br/>
<!-- 4.输出对象 -->
<%=map %><br/>
<%=12==12?"12等于12":"12不等于12" %><br/>

iii. 代码脚本(_jspService方法中)
作用:
代码脚本它可以在_jspService方法中定义你需要的代码内容。
代码脚本最终会被翻译到_jspService方法中
换句话说。也就是我们能在_jspService方法中写的代码,都可以在代码脚本中编写。
格式:
<% %>
1. 代码脚本----if 语句
2. 代码脚本----for 循环语句
3. 翻译后java文件中_jspService方法内的代码都可以写
<%
int i = 12 ;
// if 语句
if (i == 12) {
System.out.println("i等于12");
} else {
System.out.println("i不等于12");
}
// for 循环语句
for (int j = 0; j < 10; j++) {
System.out.println(j);
}
String username = request.getParameter("username");
System.out.println(username);
// 获取工程名
System.out.println( application.getContextPath() );
%>

c) jsp中的三种注释
i. html注释
html注释都会被翻译到_jspService方法中,然后以out.write输出到客户端。
ii. java注释
java注释在翻译之后 ,会被翻译到java源代码中//xxxx
iii. jsp注释
jsp注释在翻译的时候会被完全忽略掉。
3. jsp九大内置对象

4. jsp四大域对象
application | ServletContext | 整个web工程(只要服务器或工程不停。数据都在) |
session | HttpSession | 览器打开到浏览器关闭 一个会话(打开浏览器请求服务器。中间,只要浏览器不关,会话都在。) |
request | HttpServletRequest | 请求对象(每次请求,由Tomcat服务器创建) |
pageContext | PageContext | 在一个jsp页面中,是jsp上下文对象 |
域对象,就是可以像map一样存取数据的对象
四个域在使用的时候,按从小到大的顺序。
pageContext --->>> request ---->>>> session ---->>>application
测试:
先运行Context1.jsp查看四种结果
Context1.jsp代码:
<%@ 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>
<%
pageContext.setAttribute("key", "pageContext");
request.setAttribute("key", "request");
session.setAttribute("key", "session");
application.setAttribute("key", "application");
%>
<h1>Context1.jsp页面</h1>
pageContext : <%=pageContext.getAttribute("key") %><br/>
request : <%=request.getAttribute("key") %><br/>
session : <%=session.getAttribute("key") %><br/>
application : <%=application.getAttribute("key") %><br/>
<%
// 转发中的斜杠 表示到http://ip:port/工程名/ 映射到代码的WebContent目录
// request.getRequestDispatcher("/context2.jsp").forward(request, response);
// 重定向的斜杠 表示到http://ip:port/
// response.sendRedirect("/Hello/context2.jsp");
%>
</body>
</html>
Context2.jsp代码
<%@ 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>
<h1>Context2.jsp页面</h1>
pageContext : <%=pageContext.getAttribute("key") %><br/>
request : <%=request.getAttribute("key") %><br/>
session : <%=session.getAttribute("key") %><br/>
application : <%=application.getAttribute("key") %><br/>
</body>
</html>
5. jsp中的out输出和response.getWriter输出的区别
在jsp页面中不管是先out输出,还是respose.getWriter()
客户端显示的输出结果都是先输出response.getWriter()再out输出
原因如下解析

在jsp页面中统一使用out进行输出,不用response。因为在 jsp翻译的源码中都是用out进行输出的javax.servlet.jsp.JspWriter out = null;
out.write 可以输出字符串
out.print 可以输出任意数据。
在jsp页面当中,我们可以使用out.print输出
6. jsp的常用标签
a) jsp静态包含
<%--
静态包含的斜杠表示到http://ip:port/工程名/ 也就是映射到WebContent目录
--%>
<%@ include file="/include/footer.jsp" %>
静态包含是把被包含的jsp页面的内容,原封不动的拷贝到静态包含的代码位置,进行输出。
静态包含,只会翻译大的jsp页面。被包含的jsp页面,不会被翻译

b) jsp标签-动态包含
<%--
动态包含的斜杠表示到http://ip:port/工程名/ 也就是映射到WebContent目录
--%>
<jsp:include page="/include/footer.jsp"></jsp:include>
动态包含是把全部的jsp页面,都翻译成为servlet程序。然后再通过代码(传递request对象,response对象,out对象给被包含的jsp页面使用)
注:request.getRequestDispatcher("/context2.jsp").forward(request, response)也是传递request对象和response对象,参数共享
源码_jspService()方法中:JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);
调用被包含的jsp页面的内容。
动态包含,还可以传递参数。
c) jsp标签-转发
<%-- 请求转发,功能跟request.getRequestDispatcher("/context2.jsp").forward(request, response); 一样 --%>
<jsp:forward page="/context2.jsp"></jsp:forward>
7. 静态包含和动态包含的区别
静态包含 | 动态包含 | |
是否生成java文件 | 不会(只翻译自己) | 会(全部) |
service方法中的区别 | 是把被包含的jsp页面的内容原封不动的拷贝到被包含的位置输出 | JspRuntimeLibrary.include |
是否可以传递参数 | 不能 | 可以 |
编译次数 | 1次 | 多次 |
适用范围 | 静态包含适用于包含那些jsp页面中,只有输出html页面数据的jsp | 动态包含适用于那些被包含的jsp页面中包含了大量的java代码,或者运行进来执行时候耗时比较长的jsp页面。 |
jsp页面在整个javaEE的框架中的定位,它的定位只是用来输出html页面数据。所以一般情况下。我们也就只使用静态包含。静态包含性能会比动态包含经微快。
例题:用jsp输出一个表格,里面有20个学生信息。
表格样式
<style type="text/css">
table{
width: 500px;
border: 1px solid red;
border-collapse: collapse;
}
th , td{
border: 1px solid red;
}
</style>

Student对象
public class Student {
private int id;
private String name;
private String phone;
private String sex;
private int age;
public Student(int id, String name, String phone, String sex, int age) {
super();
this.id = id;
this.name = name;
this.phone = phone;
this.sex = sex;
this.age = age;
}
SearchStudent程序中的代码:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 省略获取搜索关键字
// 省略到数据库中去查询
// 生for循环生成 数据库查询的结果
List<Student> stus = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
stus.add(new Student(i,"name-" + i,"phone-" + i,(i%2==1?"男":"女"), 18+i));
}
// 需要保存到request域对象中
request.setAttribute("stus", stus);
// 转发到jsp页面
request.getRequestDispatcher("/showStudent.jsp").forward(request, response);
}
jsp页面中的代码:
<%@page import="java.util.ArrayList"%>
<%@page import="java.util.List"%>
<%@page import="com.atguigu.pojo.Student"%>
<%@ 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>
<style type="text/css">
table{
width: 500px;
border: 1px solid red;
border-collapse: collapse;
}
th , td{
border: 1px solid red;
}
</style>
</head>
<body>
<%
List<Student> stus = (List<Student>) request.getAttribute("stus");
%>
<table>
<tr>
<th>编号</th>
<th>姓名</th>
<th>电话</th>
<th>性别</th>
<th>年龄</th>
<th>操作</th>
</tr>
<% for (int i = 0; i < stus.size(); i++) { %>
<% Student s = stus.get(i); %>
<tr>
<td><%=s.getId() %></td>
<td><%=s.getName() %></td>
<td><%=s.getPhone() %></td>
<td><%=s.getSex() %></td>
<td><%=s.getAge() %></td>
<td>删除,修改</td>
</tr>
<% } %>
</table>
</body>
</html>
