JSP学习
JSP
JSP 全名为 Java Server Pages,中文名叫 java 服务器页面,其根 本是一个简化的 Servlet 设计,它 [1] 是由 Sun Microsystems 公司 倡导、许多公司参与一起建立的一种动态网页技术标准。
特点:
本质上还是 Servlet
跨平台,一次编写处处运行
组件跨平台
健壮性和安全性
JSP原理
tomcat的JSPServlet将jsp文件转换为servlet文件,然后执行servlet文件。内部原理基于输出流对象将内容打给浏览器
Jsp 的访问原理: 浏览器发起请求,请求 JSP,请求被 Tomcat 服务器接收,执行 JspServlet 将请求的 JSP 文件转义成为对应的 java 文件(也是 Servlet),然后执行转义好的 java 文件。
下面是一个jsp被转换为Servlet后的java文件
在tomcat目录下的work目录下打开某个项目的文件夹可以找到,jsp被转换成servlet的文件
转换后的类继承了HttpJspBase 而HttpJspBase继承了HttpServlet
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/7.0.56
* Generated at: 2020-01-09 04:52:09 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 index_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 javax.el.ExpressionFactory _el_expressionfactory;
private org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public void _jspInit() {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
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("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>$Title$</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write(" $END$\n");
out.write(" </body>\n");
out.write("</html>\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);
}
}
}
可以看出内部是使用的IO流且其转换后的servlet的文件继承了HttpJspBase类
将HttpJspBase类反编译后可以看出这个HttpJspBase继承了HttpServlet,其service方法执行的是转换后的servlet文件中的_jspService方法
Jsp的三种注释
前端语言注释:<!-- --!>
会被转译,也会被发送,但是不会被浏览器执行
java语言注释:
会被转译,但是不会被servlet执行
Jsp注释:
不会被转译。 <%-- --%>
JSP的Page指令
配置jsp文件的转译相关的参数。
<%@ page 属性名="属性值" 属性名="属性值"...%>
language:声明jsp要被转译的语言。
import:声明转译的java文件要导入的包,不同的包使用逗号隔开。
pageEncoding:设置jsp文件所保存的数据编码格式。jsp文件的编码格式是utf-8,如果保存的数据编码格式不一致就会出现乱码
contentType=“text/html; charset=utf-8” 设置jsp数据响应给浏览器时,浏览器的解析和编码格式。
session:设置转译的servlet中是否开启session支持,默认开启,true表示开启。false表示关闭。
errorPage:设置jsp运行错误跳转的页面.
extends:设置jsp转译的java文件要继承的父类(包名+类名)。
Jsp的局部代码块
局部代码块中声明的java代码会被原样转译到jsp对应的servlet文件的_JspService方法中
代码块中声明的变量都是局部变量。
使用:<% java代码 %>
使用局部代码块在jsp中进行逻辑判断,书写麻烦,阅读困难。
servlet进行请求逻辑处理,使用jsp进行页面展现。
JSP的全局代码块
声明的java代码作为全局代码转译到对应的servlet类中。
<%! 全局代码 %>
全局代码块声明的代码,需要使用局部代码块调用。
主要用于方法的声明与定义
Jsp的脚本段语句:
获取变量或者方法的返回值作为数据响应给浏览器。
<%=变量名或者方法%>
<% String str="你好" %》
<%= str %>
当转换为servlet文件时,<%= str %>会转换为out.print(str);
所以<%= str %>等同于
<% out.write(str); %>
但是这样很麻烦所以使用<%= %>
注意:不要在变量名或者方法后使用分号。
位置:除jsp语法要求以外的任意位置。
Jsp的静态引入和动态引入
当多个JSP的代码有相同时就会出现代码冗余,所以将相同的代码单独定义一个JSP文件,使用引入就会减少冗余
静态引入:
<%@include file="要引入的jsp文件的相对路径" %>
特点:
会将引入的jsp文件和当前jsp文件转译成一个java(Servlet)文件使用。在网页中也就显示了合并后的显示效果。
注意:
静态引入的jsp文化不会单独转译成java(Servlet)文件。合并的之后的jsp文件会转换为一个java(Servlet)文件
当前文件和静态引入的jsp文件中不能够使用java代码块声明同名变量。
动态引入:
<jsp:include page="要引入的jsp文件的相对路径"></jsp:include>
特点:
会将引入的jsp文件单独转译,在当前文件转译好的java文件中调用引入的jsp文件的转译文件。
在网页中显示合并后的显示效果。
注意:
动态引入允许文件中声明同名变量。
jsp的转发标签:
优点:
降低jsp代码的冗余,便于维护升级。
使用:
<jsp:forward page="要转发的jsp文件的相对路径"></jsp:forward>
转发标签的子标签
<jsp:param name="str" value="aaa" />
name属性为附带的数据的键名
value为附带的数据内容
<jsp:forward page="forward.jsp">
<jsp:param name="str" value="aaa" />
</jsp:forward>
会将子标签的数据以?的形式拼接在转发路径的后面。
所以在forward.jsp中可以通过request.getParameter(String key)获取
forward标签的特点:
一次请求
地址栏信息不改变。
类似于servlet的请求转发
JSP内置对象
在JSP转译为java(Servlet)文件后,会发现在_jspService()方法中有9个内置对象
pageContext
页面上下文对象,封存了其他内置对象。封存了当前jsp的运行信息。
注意:每个Jsp文件单独拥有一个pageContext对象。
作用域:当前页面。
request
封存当前请求数据的对象。由tomcat服务器创建。一次请求
response
响应对象,用来响应请求处理结果给浏览器的对象。设置响应头,重定向。
session
此对象用来存储用户的不同请求的共享数据的。一次会话
application
也就是ServletContext对象,一个项目只有一个。存储用户共享数据的对象,以及完成其他操作。项目内
out
响应对象,Jsp内部使用。带有缓冲区的响应对象,效率高于response对象。
page
代表当前Jsp的对象。相当于java中的this。
exception
异常对象。存储了当前运行的异常信息。
注意:使用此对象需要在page指定中使用属性isErrorPage="true"开启。
config
也就是ServletConfig,主要是用来获取web.xml中的配置数据,完成一些初始化数据的读取。
作用域
pageContext:当前页面.解决了在当前页面内的数据共享问题。获取其他内置对象。
request:一次请求。一次请求的servlet的数据共享。通过请求转发,将数据流转给下一个servlet。
session:一次会话.一个用户的不同请求的数据共享。将数据从一次请求流转给其他请求。
application:项目内.不同用户的数据共享问题。将数据从一个用户流转给其他用户。
作用:数据流转
Jsp的路径:
相对路径
在jsp中资源路径可以使用相对路径完成跳转,但是:
问题一:资源的位置不可随意更改。
问题二:需要使用…/进行文件夹的跳出。使用比较麻烦。
绝对路径
/虚拟项目名/项目资源路径
<a href="/jsp/jsp.jsp">jsp.jsp</a>
注意:在jsp中资源的第一个/表示的是服务器根目录,相当于:localhost:8080
使用jsp中自带的全局路径
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<base href="<%=basePath%>">
作用:
给资源前面添加项目路径: http://127.0.0.1:8080/虚拟项目名/