web概述13

Jsp

java server page,实际上是针对Servlet生成网页比较麻烦,而且不能达到所见即所得的开发引入的新技术。就是Servlet生成网页的简化写法。究其本质实际上就是Servlet

基础语法

jsp页面在执行时会自动进行2次编译,首先jsp引擎对调用的jsp页面进行编译,将jsp页面转换为servlet类,然后应用servlet引用对生成的servlet类进行编译,生成对应的字节码文件,最后调用字节码文件,
执行生命周期方法生成html文档作为响应

原始文件test.jsp

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
index.html
</body>
</html>

访问后则自动在work目录下生成test_jsp.java文件

/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/9.0.68
* Generated at: 2022-11-08 03:19:04 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;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
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 static final java.util.Set<java.lang.String>
_jspx_imports_packages;
private static final java.util.Set<java.lang.String>
_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 = null;
}
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 java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> 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(getServ
letConfig());
}
}
}
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");
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("<!DOCTYPE html>\r\n"); //静态页面部分--模板部分内容,自动生成
out.write按照原样输出
out.write("<html>\r\n");
out.write("<head>\r\n");
out.write("<meta charset=\"UTF-8\">\r\n");
out.write("<title>馕页</title>\r\n");
out.write("</head>\r\n");
out.write("<body>\r\n");
out.write("index.html\r\n");
out.write("</body>\r\n");
out.write("</html>");
} 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);
}
}
}

还可以看到一个test_jsp.class文件,这是test_jsp.java编译生成的字节码文件。这里强调的是jsp执行时是2次编译
在这里插入图片描述

注释

jsp中的注释有html注释和jsp注释两种
html注释: <!-- 多行注释 --> ,这里需要注意的是:html注释中的jsp语法仍旧会正常解析执行,只是不在页面中显示而已

jsp页面代码

<!-- 现在时间为<%=new Date().toLocaleString()%> -->

实际执行结果为 <!-- 现在时间为2022-11-8 9:55:40 -->
注意:html注释内容jsp解析器仍旧会解析执行,所以不能出现jsp语法错误 HTTP ERROR 500
javax.servlet.ServletException:
jsp注释: <%-- 多行语句 --%> 。jsp注释会被jsp解析器所忽略

页面组成

包括html标签组成的静态模板部分【按照原样输出】和jsp语法
语法1: <%=表达式%> , 在当前位置输出表达式的计算结果。注意表达式不是合法的java语句,所以不能以分号收尾。jsp编译器编译后 out.print(表达式) ,也就是说允许出现在()中的内容才能出现在表达式的位置。

jsp页面中的内容
<%=new java.util.Date()%>
---
编译后的java文件中格式为:
out.print(new java.util.Date());

语法2: <%合法的java代码块;%> ,编译后对应的是service【jspService】方法中的一段代码,允许出现在方法中的代码就是这里允许出现的代码

<%
String path = request.getContextPath(); 获取请求上下文,例如/test
String basePath = request.getScheme()获取请求协议名称,例如http +
"://"+request.getServerName()获取服务器名称,例如localhost + ":" +
request.getServerPort()获取请求服务器的端口号 + path + "/"; 实际返回值为http://localhost:8080/test/
%>

jsp页面中的内容

<%
java.util.Random r=new java.util.Random();
out.println(r.nextInt(10)); // 在jsp代码块中可以直接使用9大默认对象
%>

生成的java代码
在 public void _jspService(final javax.servlet.http.HttpServletRequest request,final javax.servlet.http.HttpServletResponse response)throws java.io.IOException,javax.servlet.ServletException { 方法中会多出部分内容

java.util.Random r=new java.util.Random();
out.println(r.nextInt(10));

为什么在代码块中可以直接使用9大默认对象

public void _jspService(final javax.servlet.http.HttpServletRequest request,
final javax.servlet.http.HttpServletResponse response) throws
java.io.IOException, javax.servlet.ServletException { request和response是服
务器调用时自动传入的
... ...
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;
// jsp引擎生成的java代码块中自动添加了生成获取9大默认对象的方法
try {
response.setContentType("text/html");
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;

语法3: <%! 合法的java代码块; %> 编译后对应的是当前类内,所有方法之外的部分。这里可以定义属性、方法。这里的限制是没有9大默认对象,如果需要使用默认对象,应该作为参数进行传递

<%!
// 定义成员方法
public String getError(HttpServletRequest request,String key){
String res="";
Object obj=request.getAttribute("errors");
if(obj!=null && obj instanceof Map){
Map<String,String> errs=(Map<String,String>)obj;
if(errs.containsKey(key))
res=errs.get(key);
}
return res;
}
%>
调用<%=getError(request,key)%>

jsp页面中的内容

<%!
private int count=0;
public String pp(){
System.out.println(count);
return ""+count;
}
%>

生成的java代码

public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
//声明部分对应的编译结果为:当前类内,所有方法之外
private int count=0;
public String pp(){
System.out.println(count);
return ""+count;
}
}

jsp页面的三生命周期
jsp页面在第一次访问时会编译生成一个Servlet类文件

public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {

其中包含3生命周期方法

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 = null;
}
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

3大页面指令

page指令

用于配置页面全局属性
语法: <%@ page 属性名称=“值”%>
相关属性

  • language="java"用于设定当前页面种所使用的脚本语言,目前属性值只有一个java,所以配置了值为java,不配置默认值也是java
  • import="java.util." 用于导入所需要的引用依赖,这个属性允许出现多次,可以导入一个类,也可以一次性导入导入 import java.util.,java.io.*
  • pageEncoding和contentType可以相互替代
    • pageEncoding="GBK"语义是设置当前页面的编码字符集,但是实际上没有设定contentType则是设定了默认编码字符集,等价于contentType=“text/html;charset=GBK”
    • contentType语义是设定当前页面的响应内容类型,基本格式为
      contentType=“text/html;charset=GBK” ,和pageEncncoding可以相互替代

6大页面动作

9大默认对象

request用于封装用户请求,是HttpServletRequest类型
response用于封装服务器响应信息
out用于向客户端输出文档信息

数据的4大范围

传递数据的范围实际上有4种: page < request < session < application ,一般范围的选择依据为:满足需求,越小越好

  • page只能在当前页面的范围内有效
  • request在当前页面有效,如果请求转发,则当前页和转发跳转的目标页有效
  • session用于跟踪用户,在用户访问当前应用的所有页面上有效
  • application用于跨用户数据共享,在当前应用的范围内有效
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值