1.程序员在开发过程中发现 servlet 开发界面非常的不方便,于是诞生了 jsp
2.一个公式:
jsp = html + java + jsp 标签 + js + css
3.jsp + java类(service Javabean)+ servlet 就会构成 mvc 开发模式
4.jsp 是运行在服务器端的
5.jsp 的基础是 servlet (相当于是对 servlet 的包装)
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Showtime</title>
</head>
<body>
<%
out.println("hello,world");
%>
</body>
</html>
如果是第一次访问该jsp 文件 web 服务器收到请求以后,会先将这个 jsp 文件翻译成一个 servlet文件,然后在将其编译成 class 文件,然后再把 class 文件加载到内存,但是如果是第二次以后就是直接访问内存中的class 文件了,所以 jsp 是单例(当然,如果某个 jsp 文件被修改了再访问就相当于是第一次)
因此,我们调试的时候,需要找到那个他转化好的servlet 文件才能方便的进行错误定位
因为 out 是 jsp 的一个内置对象,也就是说,虽然在 jsp 页面没有定义,但是在当 jsp 转化成了 servlet 的时候,在 servlet 中给我们默认定义好了
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Showtime</title>
</head>
<body>
<%
out.println("hello,world");
%>
<%
int i = 99;
int j = i+1;
%>
<%
out.println("j = " +j);
%>
</body>
</html>
j = 100
要找到原因我们还是要看一下 servlet 文件
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class showtime_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
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("<html>/r/n");
out.write("<head>/r/n");
out.write(" <title>Showtime</title>/r/n");
out.write("</head>/r/n");
out.write("<body>/r/n");
out.println("hello,world");
out.write("/r/n");
out.write("/r/n");
int i = 99; //注意这里
int j = i+1;
out.write("/r/n");
out.write("/r/n");
out.write("/r/n");
out.println("j = " +j); //还有这里
out.write("/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 发送一个信息到容器,比如设置全局变量,设置编码,引入包等
page 中的常用属性:
(1) language = 设置语言
(2) import 引入包
(3) session = true/false 是否在 jsp 页面获取 session 对象
(4) errorpage = “相对页面” 当 jsp 页面出错时 跳转到指定的 jsp 页面(以 /开头时 表示相对 web 根目录,如果不以 / 开头则表示相对当前目录)
(5)contentType = “text/html;charset=utf-8” 指定网页以什么方式显示
(6)pageEncoding = “utf-8” 指定 servlet 引擎以什么方式翻译 jsp -> servlet ,并指定网页的显示方式
<% @ include file = "filename"%>
该指令用于引入一个 jsp 文件,并能将 两个 jsp 文件翻译成一个 servlet 文件,所以也被称为静态引入
被引入的 jsp 页面只需保留 page 指令即可,其他的 <body> 等 <html> 标签需要删除
这个指令允许在 jsp 页面使用自定义的标签
脚本元素就是 java 片段
<% java 代码 %>
<% int i = 90; %>
这个里面定义的是局部变量,如果想定义成为servlet 的成员变量的话,要使用下面介绍的 declareation
<%=java 表达式 %>
<%=rs.getString(1) %>
表达式是没有分号的,带了分号的就是语句了
<%! 变量声明 %> <%! 函数声明 %>
<%! int i = 900; %>
<%!
int jisuan(int num){
int result = 0;
for(int i =0;i<num;i++){
result = result+i;
}
}
%>
定义函数的时候,不要使用 public xxx ,因为转化成 servlet 以后就会在函数内部再创建函数,然而这个是不合规范的
这个实际上用的不是特别的多
就说几个:
<jsp:forward> 实现页面的转发
我们一般不把jsp 页面都放在项目的 web 根路径下,因为这样所有的jsp 页面都能被访问到,这是非常危险的,解决办法就是将 jsp 页面放在 WEB-INF 目录(就类似于 servlet 文件放在 src 下面一样),然后通过一个统一的入口访问,实现的方式就是通过转发、
<jsp:include>`
这个页面的包含是动态包含,和上面讲过的静态包含不同的是,动态包含会生成两个 servlet 文件,并且包含过程中没有去除 <body> 等标签的要求
<!-- 注释的内容 -->
<%-- -->
对应这 JspWriter
out.pritlen()
存放的数据在一次 request 请求中有效,对应着 servlet 中的 HttpServletRequest 类
servlet 中的 HttpServletResponse 类
存放的数据在一次回话中有效,对应着 HttpSession 这个类
存放的数据在整个 web 应用运行期间有效
放在 pageContext 的属性只在本页面生效,对应 PageContext
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Showtime</title>
</head>
<body>
<%
pageContext.setAttribute("abc","xxx");
%>
<%
String val = (String) pageContext.getAttribute("abc");
out.println(val);
%>
</body>
</html>
使用较少,对应着 Exception
相当于 servlet 的 this 使用较少
对应着 ServletConfig