博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 面试准备 JSP
阅读量:2208 次
发布时间:2019-05-04

本文共 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} JSPJAVA

下面来看看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} JSPJSTL(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表达式} JSPEL(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/

你可能感兴趣的文章
深入理解JVM虚拟机11:Java内存异常原理与实践
查看>>
深入理解JVM虚拟机12:JVM性能管理神器VisualVM介绍与实战
查看>>
深入理解JVM虚拟机13:再谈四种引用及GC实践
查看>>
Spring源码剖析1:Spring概述
查看>>
Spring源码剖析2:初探Spring IOC核心流程
查看>>
Spring源码剖析3:Spring IOC容器的加载过程
查看>>
Spring源码剖析4:懒加载的单例Bean获取过程分析
查看>>
Spring源码剖析5:JDK和cglib动态代理原理详解
查看>>
Spring源码剖析6:Spring AOP概述
查看>>
Spring源码剖析7:AOP实现原理详解
查看>>
Spring源码剖析8:Spring事务概述
查看>>
Spring源码剖析9:Spring事务源码剖析
查看>>
重新学习Mysql数据库1:无废话MySQL入门
查看>>
探索Redis设计与实现2:Redis内部数据结构详解——dict
查看>>
探索Redis设计与实现3:Redis内部数据结构详解——sds
查看>>
探索Redis设计与实现4:Redis内部数据结构详解——ziplist
查看>>
探索Redis设计与实现6:Redis内部数据结构详解——skiplist
查看>>
探索Redis设计与实现5:Redis内部数据结构详解——quicklist
查看>>
探索Redis设计与实现8:连接底层与表面的数据结构robj
查看>>
探索Redis设计与实现7:Redis内部数据结构详解——intset
查看>>