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