Java 之 JSP

Posted 格物致知_Tony

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 之 JSP相关的知识,希望对你有一定的参考价值。

一、JSP 概述

  JSP:全称 Java Server Pages,是由 Sun 公司专门为了解决动态生成 html 文档的技术。

  JSP 其实就是 Java 服务器页面。页面中既可以指定定义 html标签,也可以定义 Java 代码,但是只能运行在服务器(Web容器中)

  作用:替代 Servlet 程序回传 HTML 页面的数据。

  原因:因为 Servlet 程序回传 HTML 页面数据是一件非常繁琐的事情,开发成本和维护成本都极高,相比于Servlet,JSP更加善于处理显示页面,而Servlet跟擅长处理业务逻辑,两种技术各有专长,所以一般我们会将Servlet和JSP结合使用,Servlet负责业务,JSP负责显示。

二、JSP的本质

  JSP 页面本质上就是一个 Servlet。

  当第一次访问 JSP 页面的时候,Tomcat 服务器会帮我们把 jsp 页面翻译成一个 Java 源文件(Servlet),并且对它进行编译生成 .class 字节码程序。

  

    其中 index_jsp.class 文件是 index_jsp 源文件编译后的字节码文件。

    打开 index_jsp.java 文件查看里面的内容。

   

     可以发现,生成的类继承与 HttpJspBase 类。这个是一个 jsp 文件生成 Servlet 程序要继承的基类!

    关联源码,查看 HttpJspBase 类的内容,从源码的类注释说明中发现:

    HttpJspBase 这个类就是所有 jsp 文件生成 Servlet程序需要去继承的基类,并且这个 HttpJspBase 类 继承了 HttpServlet 类。所以 JSP 也是一个 Servlet 小程序。

    

      再去观察翻译后的 Servlet 程序的源代码,其底层实现,也是通过输入流,把 HTML 页面数据回传给客户端。

 1 public void _jspService(final javax.servlet.http.HttpServletRequest request, final
 2     javax.servlet.http.HttpServletResponse response)
 3             throws java.io.IOException, javax.servlet.ServletException {
 4         final java.lang.String _jspx_method = request.getMethod();
 5         if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)
 6                 && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or
 7                 HEAD");
 8             return;
 9         } 
10         final javax.servlet.jsp.PageContext pageContext;
11         javax.servlet.http.HttpSession session = null;
12         final javax.servlet.ServletContext application;
13         final javax.servlet.ServletConfig config;
14         javax.servlet.jsp.JspWriter out = null;
15         final java.lang.Object page = this;
16         javax.servlet.jsp.JspWriter _jspx_out = null;
17         javax.servlet.jsp.PageContext _jspx_page_context = null;
18         try {
19             response.setContentType("text/html;charset=UTF-8");
20             pageContext = _jspxFactory.getPageContext(this, request, response,
21                     null, true, 8192, true);
22             _jspx_page_context = pageContext;
23             application = pageContext.getServletContext();
24             config = pageContext.getServletConfig();
25             session = pageContext.getSession();
26             out = pageContext.getOut();
27             _jspx_out = out;
28             out.write("\\r\\n");
29             out.write("\\r\\n");
30             out.write("<html>\\r\\n");
31             out.write("<head>\\r\\n");
32             out.write(" <title>Title</title>\\r\\n");
33             out.write("</head>\\r\\n");
34             out.write("<body>\\r\\n");
35             out.write(" a.jsp 页面\\r\\n");
36             out.write("</body>\\r\\n");
37             out.write("</html>\\r\\n");
38         } catch (java.lang.Throwable t) {
39             if (!(t instanceof javax.servlet.jsp.SkipPageException)){
40                 out = _jspx_out;
41                 if (out != null && out.getBufferSize() != 0)
42                     try {
43                         if (response.isCommitted()) {
44                             out.flush();
45                         } else {
46                             out.clearBuffer();
47                         }
48                     } catch (java.io.IOException e) {}
49                 if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
50                 else throw new ServletException(t);}
51         } finally {
52             _jspxFactory.releasePageContext(_jspx_page_context);
53         }
54     }
View Code

 

     

  原理示意图:

  

   小结:

    xxx.jsp 翻译成 Java 的全面是  xxx_jsp.java 文件;

    xxx_jsp.java 文件就是一个 Servlet 程序,原来 jsp 中的 HTML 内容都被翻译到  Servlet 类的 service 方法中原样输出。

三、JSP 指令

  1、jsp 头部的 page 指令

    jsp 的 page 指令可以修改 jsp 页面的一些重要的属性或行为。

    语法格式:

<%@ page 属性名1=属性值1 属性名2=属性值2 ... %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

   

    常用属性:

     language 属性

      表示 jsp 翻译后是什么语言文件,暂时支持 Java。

    ② contentType 属性

       表示 jsp 返回的数据类型是什么,也是源码中 response.setContentType() 参数值

       作用:设置响应体的 MIME类型以及字符集;

    ③ pageEncoding 属性

      表示当前 jsp 页面文件本身的字符集

    ④ import 属性

      和 Java 源代码中,用于导包、导类。

    ⑤ autoFlush 属性

      设置当 out 输出流缓冲区满了之后,是否自动刷新缓冲区,默认是 true。

    ⑥ buffer 属性

      设置 out 缓冲区的带下,默认是 8KB。

      属性⑤和属性⑥ 都是给 out 输出流使用的。

      缓冲区溢出错误:(如果设置autoFlush=false或buffer过小会报错)

      

     ⑦ errorPage 属性

      设置当前 jsp 页面运行时出错,自动跳转去的错误页面路径。

      注意errorPage 表示错误后自动跳转去的路径,这个路径一般都是以斜杠打头, 它表示请求地址为 http://ip:port/工程路径/ ,映射到代码的 Web 目录

    ⑧  isErrorPage 属性

      设置当前 jsp 页面是否是错误信息页面。默认是 false,如果是 true 可以获取异常信息

      取值 true:是,可以使用内置对象 Exception

      取值 false:否,默认值,不可以只使用 内置对象 Exception

    ⑨ session 属性

      设置访问当前 jsp 页面,是否会创建 HttpSession对象。默认是 true

    ⑩ extends 

      设置 jsp 翻译出来的 java 类默认继承谁

  2、include 指令

    作用:该指令用于将目标页面包含到当前页面中,用于导入页面的资源文件。

    特点:静态包含,被包含的文件不会被翻译和编译

    语法格式:

<%@include file="top.jsp"%>

  3、tablib 指令

    作用:该指令用于导入标签库。

    语法格式:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

     prefiex 表示自定义的前缀

 

三、JSP 脚本

  1、声明脚本(极少用)

    作用:可以给 jsp 翻译出来的 java 类定义属性,全局变量,方法甚至是静态代码块、内部类等。

    语法格式:

<%! 声明 java 代码 %>

    Demo:

 1 <%--1、 声明类属性--%>
 2   <%!
 3     private Integer id;
 4     private String name;
 5     private static Map<String,Object> map;
 6   %>
 7   <%--2、 声明 static 静态代码块--%>
 8   <%!
 9     static {
10       map = new HashMap<String,Object>();
11       map.put("key1", "value1");
12       map.put("key2", "value2");
13       map.put("key3", "value3");
14     }
15   %>
16   <%--3、 声明类方法--%>
17   <%!
18     public int abc(){
19       return 12;
20     }
21   %><%--4、 声明内部类--%>
22   <%!
23     public static class A {
24       private Integer id = 12;
25       private String abc = "abc";
26     }
27   %>

 

    声明脚本代码翻译对照:

    

  2、表达式脚本(常用)

    作用:向 jsp页面上输出数据。(输出语句中可以定义什么,该脚本中就可以定义什么)

    语法格式:

<%=表达式 %>

    表达式脚本的特点:

     ① 所有的表达式脚本都会被翻译到 _jspService() 方法中;

     ② 表达式脚本都会被翻译成 out.print() 输出到页面上;

     ③ 由于表达式脚本翻译的内容都在_jspService() 方法中,所以_jspService()方法中的对象都可以直接使用;

     ④ 表达式脚本中的表达式不能以分号结束;
     ⑤ 可以输出任意类型

    Demo:

1 <%=12 %> <br>
2 <%=12.12 %> <br>
3 <%="我是字符串" %> <br>
4 <%=map%> <br>
5 <%=request.getParameter("username")%

 

    翻译对照:

    

  3、代码脚本

    作用:可以在 jsp 页面中,编写需要的功能(写的是Java代码,service方法中可以定义什么,该脚本中就可以定义什么,翻译到 _jspService() 中)

    语法格式:

<%
    java 语句
%>

      代码脚本的特点是:

      ① 代码脚本翻译之后都在 _jspService() 方法中;

      ② 代码脚本由于翻译到_jspService()方法中, 所以在_jspService()方法中的现有对象都可以直接使用

      ③ 还可以由多个代码脚本块组合完成一个完整的 java 语句。

      ④ 代码脚本还可以和表达式脚本一起组合使用, 在 jsp 页面上输出数据

    Demo:

 1   <%--1.代码脚本----if 语句--%>
 2     <%int i = 13 ;
 3       if (i == 12) {
 4     %>
 5       <h1>国哥好帅</h1>
 6     <%
 7       } else {
 8     %>
 9       <h1>国哥又骗人了! </h1>
10     <%
11      }
12     %>
13   <br>
14   <%--2.代码脚本----for 循环语句--%>
15   <table border="1" cellspacing="0">
16     <%
17       for (int j = 0; j < 10; j++) {
18     %>
19     <tr>
20       <td>第 <%=j + 1%>行</td>
21     </tr>
22     <%
23       }
24     %>
25   </table>
26   <%--3.翻译后 java 文件中_jspService 方法内的代码都可以写--%>
27   <%
28     String username = request.getParameter("username");
29     System.out.println("用户名的请求参数值是: " + username);
30   %>

 

    翻译对照:

    

 

四、JSP 中的三种注释

  1、HTML 注释

    格式:

<!-- 这是 html 注释 -->      只能注释 HTML代码片段

    HTML 注释会被翻译到 Java 源代码中,在 _jspService() 方法里,以 out.writer 输出到客户端,但是不会在页面上显示。

  2、Java 注释

    格式:

<%
    // 单行 java 注释
    /* 多行 java 注释 */
%>

    Java 注释会被翻译到 Java 源代码中,不会输出到客户端

  3、jsp 注释

    格式:

<%-- 这是 jsp 注释 --%>

    jsp 注释可以注释掉 jsp 页面中所有的代码。但是这种注释是在服务器端的注释,不会把数据发送给浏览器的,通过源代码不能查看到。

     

    JSP 中三种注释的比较:

 

JSP注释

Java注释

HTML注释

JSP页面

可见

可见

可见

Java代码

不可见

可见

可见

浏览器

不可见

不可见

可见

 

五、JSP 的内置对象

  jsp 中的内置对象,是指 Tomcat 在翻译 jsp 页面称为 Servlet 源代码后,内部提供的 九大对象,称为 内置对象

  在 jsp 页面中不需要获取和创建,可以直接使用的对象。

  

 

  jsp 一共有9个内置对象。

变量名 真实类型 作用
pageContext PageContext 当前页面共享数据,还可以获取其他八个内置对象(Servlet中没有此对象)
request HttpServletRequest 一次请求访问的多个资源(转发)
session HttpSession 一次会话的多个请求间
application ServletContext(唯一) 所有用户间共享数据
response HttpServletResponse 响应对象
page Object 当前页面(Servlet)的对象  this
out JspWriter 输出对象,数据输出到页面上
config ServletConfig Servlet的配置对象
exception Throwable 异常对象

 

六、JSP 四大域对象

  域对象是可以向 Map 一样存取数据的对象,四个域对象功能一样,不同的是它们对数据的存取范围。

  四个域对象分别是:

  

域对象 真实类型 存取范围
pageContext PageContextImpl类 当前 jsp 页面范围内有效(Servlet中没有)
request HttpServletRequest类 一次请求内有效
session HttpSession类

一个会话范围内有效

(打开浏览器访问服务器,知道关闭浏览器)

application ServletContext类

整个Web 工程范围呢都有效

(只要Web工程不停止,数据就在)

  虽然四个域对象都可以存取数据,但是在使用上是有优先顺序的。

  四个域在使用的时候,优先顺序分别是:它们从小到大的方位的顺序:

pageContext ====>>> request ====>>> session ====>>> application

七、JSP 中的 out 输出和 response.getWriter 输出的区别

    response 表示响应,经常用于设置返回给客户端的内容(输出)

    out 也是给用户做输出使用的。

    两个缓冲流工作原理:

    

        out 的 writer() 方法 和 print() 方法

             

 

    由于 jsp 翻译之后, 底层源代码都是使用 out 来进行输出, 所以一般情况下,我们在 jsp 页面中统一使用 out 来进行输出,避免打乱页面输出内容的顺序。  

    response.getWriter()和out.write()的区别:

      ① 在 Tomcat 服务器真正给客户端做出响应之前,会先找 response 缓冲区数据,再找out缓冲区数据。

      ② response.getWriter()数据输出永远在out.write()之前

    out.write() 输出字符串没有问题(出去其他如int,会先转化为char类型,可能乱码)
    out.print() 输出任意数据都没有问题(都转换成为字符串后调用的 write 输出) 

     小结:在jsp 页面中,可以统一使用 out.print() 来进行输出。

 

八、jsp的常用标签

  1、jsp 静态包含

       作用:把其他的页面包含到当前页面中

    格式:

<%@ include file=""%> 
<%@ include file="/include/footer.jsp"%>

      file 属性指定要包含的 jsp 页面的路径;

       地址中第一个斜杠 / 表示为 http://ip:port/工程路径/ 映射到代码的 web 目录
     静态包含的特点:

      (1)静态包含不会翻译被包含的 jsp 页面。

      (2)静态包含其实是把被包含的 jsp 页面的代码拷贝到包含的位置执行输出。

 

  2、动态包含

    作用:动态包含会把包含的 jsp 页面单独翻译成 servlet 文件, 然后在执行到时候再调用翻译的 servlet 程序。 并把计算的结果返回。
       动态包含是在执行的时候,才会加载,所以叫动态包含。

    格式:

<jsp:include page=""></jsp:include> 动态包含

            page 属性是指定要包含的 jsp 页面的路径

      动态包含也可以向静态包含一样,把被包含的内容执行输出到包含位置

    动态包含的特点:

      (1)动态包含会把包含的 jsp 页面也翻译成为 java 代码

      (2)动态包含底层代码使用如下代码去调用被包含的 jsp 页面执行输出

          JspRuntimeLibrary.include(request, response, "/include/footer.jsp", out, false);

      (3)动态包含, 还可以传递参数

     Demo:

1 <jsp:include page="/include/footer.jsp">
2     <jsp:param name="username" value="bbj"/>
3     <jsp:param name="password" value="root"/>
4 </jsp:include>

      动态包含的底层原理:

     

    两种包含的区别:

  

  静态包含   动态包含
是否生成 java 文件 不生成 生成
service 方法中的区别 把包含的内容原封拷贝到 service JspRuntimeLibrary.include 方法
是否可以传递参数 不能 可以
编译次数 1 包含的文件 + 1
适用范围 适用包含纯静态内容(CSS,HTML,JS), 或没有
非常耗时操作。 或大量 java 代码的 jsp
包含需要传递参数。 含有大量 java代码

      静态包含应用较多。

 

九、JSP 动作标签

    JSP 动作标签是由 服务器(Tomcat)来运行的。

    动作标签语法:

<jsp: 动作名称  属性=属性值></jsp:动作名称>

  

  1、jsp 标签— 转发

    作用:处理请求转发操作

    不带参数格式:

<jsp:forward page="/scope2.jsp"></jsp:forward>

    page 属性设置请求转发的路径。注意:开始标签与结束标签之间不能有任何内容。

     带参数格式:

<jsp:forward page="NewFile.jsp">
	<jsp:param value="18" name="age"/>
</jsp:forward>

 

     上面的 <jsp:include> 也是一个动作标签。

 

以上是关于Java 之 JSP的主要内容,如果未能解决你的问题,请参考以下文章

Jsp获取Java的重定向赋值(String)

day06-jsp

JDBC操作数据库之查询数据

jsp页面被tomcat引擎运行的时候组装成java片段,但是这些java片段怎么没有main方法作为程序的入口啊?

jsp

JSP语法