本文共 10021 字,大约阅读时间需要 33 分钟。
JSP(JavaServer Pages)用于Web开发的技术
JSP 不是直接运行的,而是要编译成出.java文件及.class文件才可以运行
说白了,JSP其实是Severlet为了更高效地开发网页而创造出来的
因为在Severlet 中要返回一个网页的话,要写很多很多的out.println()
而JSP则允许我们直接用HTML的语法来写网页,同时还可以调用Java的库
从而让Severlet 能更高效地完成业务逻辑
其中的转换工作则是由例如:Jasper 这样的JSP引擎完成的
Ps:
Orcale 官方已经不推荐JSP scriptlets 了
就是下面这个语句块
<% %>
这里是
Where possible, avoid JSP scriptlets whenever tag libraries provide equivalent functionality. This makes pages easier to read and maintain, helps to separate business logic from presentation logic, and will make your pages easier to evolve into JSP 2.0-style pages (JSP 2.0 Specification supports but deemphasizes the use of scriptlets).
主要问题是代码的可读性
Orcale 说,如果能用tag libraries 的地方,就不要用JSP scriptlets
J S P 和 J A V A \color{red}{JSP和JAVA} JSP和JAVA
下面来看看JSP和编译出来的Java文件:
JSP文件
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>Insert title here <%@ page import="java.util.List" %><%@ page import="java.util.ArrayList" %><%! List a=null; %><% List a=new ArrayList(); a.add(1);a.add(2);out.print(a);%>
编译出来的Java文件
/* * Generated by the Jasper component of Apache Tomcat * Version: Apache Tomcat/9.0.31 * Generated at: 2020-10-16 11:53:17 UTC * Note: The last modified time of this file was set to * the last modified time of the source file after * generation to assist with modification tracking. */package org.apache.jsp.scriptlets;import javax.servlet.*;import javax.servlet.http.*;import javax.servlet.jsp.*;import java.util.List;import java.util.ArrayList;public final class Import_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent, org.apache.jasper.runtime.JspSourceImports { List a=null; private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map_jspx_dependants; private static final java.util.Set _jspx_imports_packages; private static final java.util.Set _jspx_imports_classes; static { _jspx_imports_packages = new java.util.HashSet<>(); _jspx_imports_packages.add("javax.servlet"); _jspx_imports_packages.add("javax.servlet.http"); _jspx_imports_packages.add("javax.servlet.jsp"); _jspx_imports_classes = new java.util.HashSet<>(); _jspx_imports_classes.add("java.util.List"); _jspx_imports_classes.add("java.util.ArrayList"); } private volatile javax.el.ExpressionFactory _el_expressionfactory; private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map getDependants() { return _jspx_dependants; } public java.util.Set getPackageImports() { return _jspx_imports_packages; } public java.util.Set getClassImports() { return _jspx_imports_classes; } 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 { if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { final java.lang.String _jspx_method = request.getMethod(); if ("OPTIONS".equals(_jspx_method)) { response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); return; } if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) { response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS"); 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("\r\n"); out.write("\r\n"); out.write(" \r\n"); out.write(" Insert title here \r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); out.write("\r\n"); List a=new ArrayList(); a.add(1);a.add(3);out.print(a); out.write("\r\n"); out.write("\r\n"); out.write(""); } 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); } }}
说明:
1.这个Java文件中,大家可以看到servelet 的实现-----init()、destroy()、service()
对的,JSP实际上是被JSP引擎转化成了一个servelet
而我们写的逻辑代码段,则是在service()方法中
(import package 的代码段,在service()外的一个static代码块中)
static { _jspx_imports_packages = new java.util.HashSet<>(); _jspx_imports_packages.add("javax.servlet"); _jspx_imports_packages.add("javax.servlet.http"); _jspx_imports_packages.add("javax.servlet.jsp"); _jspx_imports_classes = new java.util.HashSet<>(); _jspx_imports_classes.add("java.util.List"); _jspx_imports_classes.add("java.util.ArrayList"); }
2.JSP的内置对象也可以在这里看得清清楚楚
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;
所 以 , 条 件 允 许 的 情 况 下 , 大 家 可 以 多 看 看 源 码 , 可 以 更 深 刻 地 理 解 一 些 东 西 \color{red}{所以,条件允许的情况下,大家可以多看看源码,可以更深刻地理解一些东西} 所以,条件允许的情况下,大家可以多看看源码,可以更深刻地理解一些东西
3.JSP中的变量的声明不是在service()里
<%! List a=null; %>
而是会被单独拎出来,在这个servelet 中当做成员变量被声明
所以,JSP存在变量“先使用,后声明”的情况
补充:
JSP不是预先编译好的,而是在runtime编译的
并且,当JSP中的代码被修改时,会重新进行编译(无修改,则不会重新编译)
(Jasper 引擎会对JSP进行检查和编译)
(当有请求时才会重新编译,不是一修改保存就重新编译)
J S P 的 生 命 周 期 \color{red}{JSP的生命周期} JSP的生命周期(Lifecycle)
Compilation(编译)
Initialization(初始化) Execution(执行) Cleanup(回收)
如果你仔细看过JSP编译出来的JAVA文件,你会发现里面有这么几个方法
public void _jspInit()—初始化
public void _jspService()—执行 public void _jspDestroy()—回收
在对应的生命周期,会调用上面的方法
J S P 内 置 对 象 \color{red}{JSP内置对象 } JSP内置对象 (Implicit Objects)
request、response、out 、session、application、config、pageContext、page、Exception
共9个
方 便 用 户 界 面 和 服 务 器 进 行 信 息 的 交 互 \color{blue}{方便用户界面和服务器进行信息的交互} 方便用户界面和服务器进行信息的交互
具体的我就不展开了,大家如果有需要可以到学习
值得一提的是pageContext这个内置对象
通过它你可以直接获取到request、response等的内置对象
上面的源码中也有解释:
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;
而为什么这个pageContext这么强大,大家可以参考这一篇
J S P 动 作 组 件 \color{red}{JSP动作组件} JSP动作组件(Action)
jsp:include、jsp:useBean、jsp:setProperty、jsp:getProperty、jsp:forward、jsp:plugin、jsp:element
jsp:attribute、jsp:body、jsp:text
具体的大家可以到了解
动作组件,用的比较多的是<jsp:include> 和 <jsp:param>
其他的要不就是被EL表达式,JSTL给代替了(其他的,了解了就行)
要不就是在像MVC这样的框架下用不着
J S P 的 J S T L \color{red}{JSP的JSTL} JSP的JSTL(The JavaServer Pages Standard Tag Library)
JSTL的使用导入额外的jar包,版本不同,方法略有不同
1.导入jar包
JSTL1.0和1.1:
下载压缩包后,把目录下lib里的所有jar包都放到WEB-INF/lib下
注 意 , 是 所 有 j a r 包 \color{blue}{注意,是所有jar包} 注意,是所有jar包
少一个jar包就会有这样的报错:
The absolute uri: http://java.sun.com/jstl/core cannot be resolved in either web.xml or the jar files deployed with this application
org.apache.jasper.JasperException: 无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core]
JSTL1.2:(1.2和1.0、1.1有些不一样,下载的压缩包是源码,没有lib,而是提供了独立的jar包)
进入页面后,找最下面的四个Jar包:
Impl、Spec、EL、Compat
全都下载,全部都要用
下载后,同上
2.在JSP中声明你所使用的taglib库(每个不同的前缀需要声明不同的库)
(1)Core Tags(例如:<c:out>)
<%@ taglib prefix = “c” uri = “http://java.sun.com/jsp/jstl/core” %>
(2)Formatting Tags
<%@ taglib prefix = “fmt” uri = “http://java.sun.com/jsp/jstl/fmt” %>
(3)SQL Tags
<%@ taglib prefix = “sql” uri = “http://java.sun.com/jsp/jstl/sql” %>
(4)XML tags
<%@ taglib prefix = “x” uri = “http://java.sun.com/jsp/jstl/xml” %>
(5)JSTL Functions
<%@ taglib prefix = “fn” uri = “http://java.sun.com/jsp/jstl/functions” %>
具体的学习,大家可以到
J S P 的 E L 表 达 式 \color{red}{JSP的EL表达式} JSP的EL表达式(Expression Language)
允许我们灵活使用JavaBean中的数据
也允许我们在EL表达式中进行灵活的算术和逻辑运算
EL是JSP中特别灵活的一个东西
看看例子:
This
<%= ((foo.Person) reqeust.getAttribute("person")).getDog().getName() %>
can be replaced by:
${ person.dog.name}
另外,EL表达式中也有内置对象
pageScope、requestScope、sessionScope、applicationScope
param、paramValues、header、headerValues、initParam
cookie、pageContext
具体的大家可以到了解
Jsp的优势
dynamic information
database access
have plenty of println statements that generate the HTML
Java Servlets API
J S P 的 不 足 \color{red}{JSP的不足} JSP的不足
1.Debug时无法实时查看JSP的显示结果
2.JSP无法进行预览,这对前端工程师是一件挺头疼的事情
最后这里有一份关于Servelet和JSP的文档,讲得很好~
转载地址:http://ooiyb.baihongyu.com/