• Java Web学习总结(7)JSP(一)


    一,JSP基础语法

    1,JSP模板元素

    JSP页面中的HTML内容称之为JSP模版元素。

    JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。

    2,JSP脚本片段

    JSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码(在<%%>不能定义方法)。语法:<%多行java代码 %>

    例如:

    <%
        int num = 0;
        num = ++num;
        out.println("num:" + num);
    %>

    注意:

    1,JSP脚本片断中只能出现java代码,不能出现其它模板元素, JSP引擎在翻译JSP页面中,会将JSP脚本片断中的Java代码将被原封不动地放到Servlet的_jspService方法中。

    2,JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每执行语句后面必须用分号(;)结束。

    3,在一个JSP页面中可以有多个脚本片断,在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。

    4,多个脚本片断中的代码可以相互访问

    3,JSP表达式

    JSP脚本表达式(expression)用于将程序数据输出到客户端,语法:<%=变量或表达式 %>

    例如:

    <%="123" %>

    4,JSP声明

    JSP页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。语法:<%!java代码 %>

    JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法。

    例如:

    <%!
    static { 
        System.out.println("静态代码块"); 
    }
     
    private String name = "Zender";
     
    public void TestFun(){
        System.out.println("成员方法!");
    }
    %>
    <%
        TestFun();
        out.println("name:" + name);
    %>

    控制台:

    页面:

    5,JSP注释

    在JSP中,注释有显式注释, 隐式注释,JSP自己的注释:

    显式注释

    直接使用HTML风格的注释:<!- - 注释内容- ->

    隐式注释

    直接使用JAVA的注释://、/*……*/

    JSP自己的注释

    <%- - 注释内容- -%>

    区别:

    HTML的注释在浏览器中查看源文件的时候是可以看得到的,而JAVA注释和JSP注释在浏览器中查看源文件时是看不到注释的内容的。

    二,JSP原理

    1,Web服务器是如何调用并执行一个jsp页面的?

    浏览器向服务器发请求,不管访问的是什么资源,其实都是在访问Servlet,所以当访问一个jsp页面时,其实也是在访问一个Servlet,服务器在执行jsp的时候,首先把jsp翻译成一个Servlet,所以我们访问jsp时,其实不是在访问jsp,而是在访问jsp翻译过后的那个Servlet。

    例如下面的代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
        String path = request.getContextPath();
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <base href="<%=basePath%>">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Insert title here</title>
    </head>
    <body>
        <%!
        static { 
            System.out.println("静态代码块"); 
        }
     
        private String name = "Zender";
     
        public void TestFun(){
            System.out.println("成员方法!");
        }
        %>
        <%
            TestFun();
            out.println("name:" + name);
        %>
    </body>
    </html>

    当我们通过浏览器访问index.jsp时,服务器首先将index.jsp翻译成一个index_jsp.class,在Tomcat服务器的workCatalinalocalhost项目名orgapachejsp目录下可以看到index_jsp.class的源代码文件index_jsp.java

    index_jsp.java的代码如下:

    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 {
     
     
        static { 
            System.out.println("静态代码块"); 
        }
     
        private String name = "Zender";
     
        public void TestFun(){
            System.out.println("成员方法!");
        }
        
      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 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 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 {
     
        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("
    ");
          out.write("<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    ");
          out.write("<html>
    ");
          out.write("<head>
    ");
          out.write("<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    ");
          out.write("<title>Insert title here</title>
    ");
          out.write("</head>
    ");
          out.write("<body>
    ");
          out.write("	");
          out.write('
    ');
          out.write('
    ');
          out.write('   ');
     
            TestFun();
            out.println("name:" + name);
        
          out.write("
    ");
          out.write("</body>
    ");
          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);
        }
      }
    }
    源码

    index_jsp这个类是继承org.apache.jasper.runtime.HttpJspBase这个类的,通过查看HttpJspBase源代码,可以知道HttpJspBase类是继承HttpServlet的,所以HttpJspBase类是一个Servlet,而index_jsp又是继承HttpJspBase类的,所以index_jsp类也是一个Servlet,所以当浏览器访问服务器上的index.jsp页面时,其实就是在访问index_jsp这个Servlet,index_jsp这个Servlet使用_jspService这个方法处理请求。

    HttpJspBase源码如下:

    import java.io.IOException;
     
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.jsp.HttpJspPage;
    import javax.servlet.jsp.JspFactory;
     
    import org.apache.jasper.compiler.Localizer;
     
    public abstract class HttpJspBase extends HttpServlet implements HttpJspPage{
       
        protected HttpJspBase() {
        }
     
        public final void init(ServletConfig config) 
        throws ServletException 
        {
            super.init(config);
        jspInit();
            _jspInit();
        }
        
        public String getServletInfo() {
        return Localizer.getMessage("jsp.engine.info");
        }
     
        public final void destroy() {
        jspDestroy();
        _jspDestroy();
        }
     
        /**
         * Entry point into service.
         */
        public final void service(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException 
        {
            _jspService(request, response);
        }
        
        public void jspInit() {
        }
     
        public void _jspInit() {
        }
     
        public void jspDestroy() {
        }
     
        protected void _jspDestroy() {
        }
     
        public abstract void _jspService(HttpServletRequest request, 
                         HttpServletResponse response) 
        throws ServletException, IOException;
    }

    2,_jspService方法

    问题1:Jsp页面中的html排版标签是如何被发送到客户端的?

    浏览器接收到的这些数据,都是在_jspService方法中使用如下的代码输出给浏览器的。

    问题2:Jsp页面中的java代码服务器是如何执行的?

    在jsp中编写的java代码会被翻译到_jspService方法中去,当执行_jspService方法处理请求时,就会执行在jsp编写的java代码了,所以Jsp页面中的java代码服务器是通过调用_jspService方法处理请求时执行的。

    3,jsp在服务器的执行流程

    第一次执行:

    1. 客户端通过电脑连接服务器,因为是请求是动态的,所以所有的请求交给WEB容器来处理
    2. 在容器中找到需要执行的*.jsp文件
    3. 之后*.jsp文件通过转换变为*.java文件
    4. *.java文件经过编译后,形成*.class文件
    5. 最终服务器要执行形成的*.class文件

    第二次执行:

    1. 因为已经存在了*.class文件,所以不在需要转换和编译的过程

    修改后执行:

    1. 源文件已经被修改过了,所以需要重新转换,重新编译。

    三,JSP指令

    JSP指令(directive)是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。

    1,Page指令

    page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。

    page指令的完整语法:

    <%@ page 
        [ language="java" ] 
        [ extends="package.class" ] 
        [ import="{package.class | package.*}, ..." ] 
        [ session="true | false" ] 
        [ buffer="none | 8kb | sizekb" ] 
        [ autoFlush="true | false" ] 
        [ isThreadSafe="true | false" ] 
        [ info="text" ] 
        [ errorPage="relative_url" ] 
        [ isErrorPage="true | false" ] 
        [ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ] 
        [ pageEncoding="characterSet | ISO-8859-1" ] 
        [ isELIgnored="true | false" ] 
    %>

    import属性

    可以在一条page指令的import属性中引入多个类或包,其中的每个包或类之间使用逗号(,)分隔

    <%@ page import="java.util.*,java.io.*,java.sql.*"%>

    备注:

    在Jsp页面中,Jsp引擎会自动导入下面的包

    java.lang.*

    javax.servlet.*

    javax.servlet.jsp.*

    javax.servlet.http.*

    errorPage属性

    使用errorPage属性指明出错后跳转的错误页面,errorPage属性的设置值必须使用相对路径,如果以"/"开头,表示相对于当前Web应用程序的根目录,否则,表示相对于当前页面。

    比如index.jsp页面有如下的代码:

            <%@ page language="java" errorPage="/error.jsp" contentType="text/html; charset=UTF-8"
                pageEncoding="UTF-8"%>
            <%
                String path = request.getContextPath();
                String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
            %>
            <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
            <html>
            <head>
            <base href="<%=basePath%>">
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>Insert title here</title>
            </head>
            <body>
                <%
                  //错误代码
                  int x = 1/0;
                %>
            </body>
            </html>

    在index.jsp中,page指令的errorPage属性指明了出错后跳转到"/error.jsp",error.jsp页面代码如下:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%
        String path = request.getContextPath();
        String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <base href="<%=basePath%>">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>error jsp</title>
    </head>
    <body>
            <h1>对不起,出错了,请联系网站管理员解决!</h1>
    </body>
    </html> 

    运行结果如下:

    我们也可以在在web.xml中使用<error-page>标签为整个web应用设置错误处理页面,web.xml的代码下:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>JSP</display-name>
      <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
      </welcome-file-list>
      <!-- 404错误的处理页面 -->
      <error-page>
          <error-code>404</error-code>
          <location>/error.jsp</location>
      </error-page>
    </web-app>

    error.jsp页面代码同上

    当访问一个不存在的web资源时,就会跳转到在web.xml中配置的404错误处理页面error.jsp,如下图所示:

    一个jsp页面是作为系统的错误处理页面,那么建议将page指令的isErrorPage属性(默认为false)设置为"true"来显式声明这个Jsp页面是一个错误处理页面。

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" isErrorPage="true"%>

    将error.jsp页面显式声明为错误处理页面后,Jsp引擎在将jsp页面翻译成Servlet的时候,在Servlet的 _jspService方法中会声明一个exception对象,然后将运行jsp出错的异常信息存储到exception对象中,由于Servlet的_jspService方法中声明了exception对象,那么就可以在error.jsp页面中使用exception对象。源码如下:

    2,include指令

    在JSP中对于包含有两种语句形式:

    1. @include指令

      include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。

      语法:<%@ include file="relativeURL"%>

      file属性用于指定被引入文件的路径。路径以"/"开头,表示代表当前web应用。

      注意细节:

      1. 被引入的文件必须遵循JSP语法。
      2. 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments(片段))作为静态引入文件的扩展名。
      3. 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
    2. <jsp:include>标签

      <jsp:include>标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。

      语法: <jsp:include page="relativeURL | <%=expression%>" flush="true|false" />

      page属性:用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。

      flush属性:指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。

    3. <jsp:include>标签与include指令的区别

      <jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。 而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。

  • 相关阅读:
    模拟费用流学习笔记
    爬山游记
    基数排序板子
    webim
    centos9 重启网络
    Linux虚拟机桥接模式下ping不通自己配置的网关
    win7怎样开启loopback接口(环回网卡)
    在CentOS上配置SAMBA共享目录
    linux间scp拷贝文件夹
    nginx配置http和https可同时访问方法
  • 原文地址:https://www.cnblogs.com/Zender/p/7794783.html
Copyright © 2020-2023  润新知