IT老王:JavaWeb04_ JSP

IT老王:WEB04_ JSP

一、Jsp基础语法

1.1. JSP模板元素

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

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

1.2. JSP脚本片段

JSP脚本片断用于在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、多个脚本片断中的代码可以相互访问

1.3. JSP表达式

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

例如:

<%="123" %>

1.4. JSP声明

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

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

例如

<%!

static{

System.out.println("静态代码块");

}

private String name = "xinzhi";

public void TestFun(){

System.out.println("成员方法");

}

%>

<%

TestFun();

out.println("name:" + name);

%>

1.5. JSP注释

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

区别:

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

二、Jsp原理

2.1. Jsp本质上是什么

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

所以jsp的本质其实就是个html模板,编译器会根据模板生成对应的servlet。

例如下面的代码:

<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="UTF-8" %>
<%
    String path = request.getContextPath();
    String basePath =
      request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/"+path;
%>
<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 = "IT老王";
​
        public void TestFun(){
            System.out.println("成员方法!");
        }
    %>
    <%
        TestFun();
        out.println("name:" + name);
    %>
</body>
</html>

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

package org.apache.jsp.web;
​
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,
                 org.apache.jasper.runtime.JspSourceImports {
​
​
    static {
      System.out.println("静态代码块");
    }
​
    private String name = "IT老王";
​
    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 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(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 java.lang.String _jspx_method = request.getMethod();
    if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
      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('\n');
      out.write('\n');
​
  String path = request.getContextPath();
  String basePath =
          request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
​
      out.write("\n");
      out.write("<html>\n");
      out.write("<head>\n");
      out.write("  <base href=\"");
      out.print(basePath);
      out.write("\">\n");
      out.write("  <meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">\n");
      out.write("  <title>Insert Title here</title>\n");
      out.write("</head>\n");
      out.write("<body>\n");
      out.write("  ");
      out.write('\n');
      out.write(' ');
      out.write(' ');
​
    TestFun();
    out.println("name:" + name);
  
      out.write("\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);
    }
  }
}

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源码如下:

packageorg.apache.jasper.runtime;
​
import java.io.IOException;//IO异常
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 org.apache.jasper.compiler.Localizer;//定位器
​
/*
 *HttpJspBase本身是个抽象类,继承了httpservlet实现了httpJspPage接口
​
 *httpJspPage接口实现了servlet(),JspPage接口(两抽象方法jspDestroy,jspInit)而本身创建jspservice(request,response)方法,
 用于JSP页面工作,同时继承了jsppage两个抽象方法又从继承的servlet接口中实现了destroy,getservletconfig,getservletinfo,init,service(五个),
 所以httpJsppage共实现了七个父类接口的抽象方法(jsppage两个,servlet五个)
 */
 */
 */
 *五个),本身创建一个jspservice方法用于jsp页面工作
 *---------------------------------------------------------------------------------------------------------------
 *HttpServlet类继承了servlet接口(5个方法)和servletconfig接口(三个方法)
​
 */
public abstractclass HttpJspBase extends HttpServlet implements HttpJspPage{
  protected HttpJspBase(){
        }
​
  public final void init(ServletConfig config)
        throws ServletException{
            super.init(config);
​
        jspInit();
          _jspInit();
        }
        
  public String getServletInfo(){
        returnLocalizer.getMessage("jsp.engine.info");
        }
​
  public final void destroy(){
        jspDestroy();
​
        _jspDestroy();
​
        }
  public final void service(HttpServletRequestrequest, 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 paramHttpServletRequest, HttpServletResponseparamHttpServletResponse)
        throws ServletException, IOException;
}

2.2. _jspService方法

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

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

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

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

2.3. jsp在服务器的执行流程

第一次执行:

1. 客户端通过电脑连接服务器,因为是请求是动态的,所以所有的请求交给WEB容器来处理。

2. 在容器中找到需要执行的*.jsp文件

3. 之后*.jsp文件通过转换变为 *.java文件

4. *.java文件经过编译后,形成 *.class文件

5. 最终服务器要执行形成的*.class文件

第二次执行:

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

修改后执行:

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

三、 JSP指令

3.1. JSP指令标识的语法格式

<%@ 指令名    属性1 = "属性1的值"    属性2 = "属性2的值"    ....%>

  • 指令名:用于指定指令名称 在JSP中包含 page、 include、 taglib 这3种指令

  • 属性: 用于指定指令属性名称 不同的指令包含不同的属性 在同一个指令中可以设置多个属性 各个属性之间用逗号或者空格隔开

  • 属性值:用于指定属性的值

注意点:

指令标识<%@%>是一个完整的指令,不能够添加空格,但是便签中定义的属性与指令名之间是有空格的

3.2. Page指令

page指令是JSP页面中最常见的指令,用于定义整个JSP页面的相关属性

语法格式

<%@ page 属性1 = “属性1的值” 属性2 = “属性2的值” ......%>

page指令的相关属性

language属性

用于设置整个JSP页面的使用的语言,目前只支持JAVA语言,改属性默认值是java

<%@ page language="java" %>

import属性

设置JSP导入的包

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

contentType属性

这种JSP页面的编码格式,也就是指定文件编码

设置JSP页面的MIME类型和字符编码

<%@ page contentType="text/html;charset=UTF-8" %>

session属性

设置页面是否使用HTTP的session会话对象。Boolean类型,默认值是true

<%@ page session="false" %>

  • session是JSP的内置对象之一

autoFlush属性

设置JSP页面缓存满时,是否自动刷新缓存,默认值是:true,如果这种为false,则当页面缓存满时就会抛出异常

<%@ page autoFlush="false" %>

isErrorPage属性

可以把当前页面设置成错误处理页面来处理另外jsp页面的错误

<%@ page isErrorPage="true" %>

errorPage属性

指定当前jsp页面异常错误的另一个Jsp页面,指定的jsp页面的isErrorPage属性必须为true,属性值是一个url字符串

<%@ page errorPage="errorPage.jsp" %>

3.3. 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和导包除外)。

3.4.taglib指令

导入资源,通常用于导入标签库(prefix:前缀,可自定义)

eg:

<%@ taglib prefix="s" uri="/struts-tags"%>(导入struts标签库)

<%@ taglib prefix="c" uri="Oracle Java Technologies | Oracle"%>(导入jstl标签库)

四、 JSP标签

4.1. Jsp标签分类

1)内置标签(动作标签): 不需要在jsp页面导入标签

2)jstl标签: 需要在jsp页面中导入标签

3)自定义标签 : 开发者自行定义,需要在jsp页面导入标签

JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。

常用内置标签有以下三个:

  • 标签一< jsp:include >

< jsp:include >标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面

执行时的引入方式称之为动态引入。

语法:

<jsp:include page="header.jsp/header.html" flush="true"></jsp:include >

标签与include指令的区别:

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

  • 标签二< jsp:forward>

    < jsp:forward>标签用于把给另外一个资源(服务器跳转,地址不变)

  • 标签三< jsp:param>

    <%--使用jsp:forward标签进行请求转发--% >

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

    <jsp:param value="10086" name="num"/>

    <jsp:param value="10010" name="num2"/>

    </jsp:forward >

五、九大内置对象

5.1.request 对象

代表的是来自客户端的请求 , 客户端发送的请求封装在 request 对象中 , 通过它才能了解到用户的请求信息 , 然后作出响应 , 它是 HTTPServletRequest 的实例

作用域为 request ( 响应生成之前 )

5.2. response 对象

对象代表的是对客户端的响应 , 也就是说可以通过 response 对象来组织发送到客户端的数据 ; 但是由于组织方式比较底层 , 所以不建议初学者使用 , 需要向客户端发送文字时直接使用 ; 它是HttpServletResponse 的实例 ;

作用域为 page ( 页面执行期 )

常用方法

5.3. session 对象

指的是客户端与服务器的一次会话 , 从客户连接到服务器的一个 WebApplication 开始 , 直到客户端与服务器断开连接为止 ; 它是 HTTPSession 类的实例

作用域为 session ( 会话期 )

5.4. out 对象

out 对象是 JspWriter 类的实例,是向客户端输出内容常用的对象 ;

作用域为 page ( 页面执行期 )

5.5. page 对象

page 对象就是指向当前 JSP 页面本身 , 有点象类中的 this 指针 , 它是 Object 类的实例 ; page 对象代表了正在运行的由 JSP 文件产生的类对象 , 不建议初学者使用 ;

作用域为 page ( 页面执行期 )

常用方法:

5.6. application 对象

实现了用户间数据的共享 , 可存放全局变量 ; 它开始于服务器的启动 , 直到服务器的关闭 , 在此期间 , 此对象将一直存在 ; 这样在用户的前后连接或不同用户之间的连接中 , 可以对此对象的同一属性进行操作 ;在任何地方对此对象属性的操作 , 都将影响到其他用户对此的访问 ; 服务器的启动和关闭决定了application 对象的生命 ; 它是 ServletContext 类的实例 ;

作用域为 application

5.7. pageContext 对象

提供了对 JSP 页面内所有的对象及名字空间的访问 , 也就是说他可以访问到本页所在的 session , 也可以取本页面所在的 application 的某一属性值 , 他相当于页面中所有功能的集大成者 , 它的本类名也叫pageContext ;

作用域为 Pageconfig 对象

5.8. config 对象

config 对象是在一个 Servlet 初始化时 , JSP 引擎向它传递信息用的 , 此信息包括 Servlet 初始化时所要用到的参数 ( 通过属性名和属性值构成 ) 以及服务器的有关信息 ( 通过传递一个 ServletContext 对象 ) ;

作用域为 page

5.9. exception 对象

这是一个例外对象 , 当一个页面在运行过程中发生了例外 , 就产生这个对象 ; 如果一个JSP页面要应用此对象 , 就必须把 isErrorPage 设为true , 否则无法编译 ; 他实际上是 Throwable 的对象 ;

作用域为 page

5.10. 总结

六、JSP属性作用域

JSP中提供了四种属性范围(四大域对象),如下:

  1. 当前页(pageContext):一个属性只能在一个页面中取得,跳转到其他页面无法取得

  2. 一次服务器请求(request):一个页面中设置的属性,只要经过了请求重定向之后的页面可以继续取得。

  3. 一次会话(session):一个用户设置的内容,只要是与此用户相关的页面都可以访问(一个会话表示一个人,这个人设置的东西只要这个人不走,就依然有效),关了浏览器就不见了。

  4. 上下文中(application):在整个服务器上设置的属性,所有人都可以访问

七、静态资源的路径问题

在Jsp中调用图片、JS脚本等,针对取得的路径有两种调用方式:

1、放入Body中生成绝对路径(不建议)

<%
  String path = request.getContextPath();
  String basePath =
          request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
​
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <title>image调用</title>
</head>
<body>
  <h1>图片访问</h1>
  <div>
    <img alt="图片" src="<%=basePath/image/a.png%>">
  </div>
</body>
</html>

2、在Head中指定,Body中使用相对路径(建议)

<%
  String path = request.getContextPath();
  String basePath =
          request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
​
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
  <title>image调用</title>
  <base href="<%=basePath%>">
</head>
<body>
  <h1>图片访问</h1>
  <div>
    <img alt="图片" src="image/a.png">
  </div>
</body>
</html>

八、错误页面和404页面

<error-page>
    <error-code>404</error-code>
    <location>/pages/404.jsp</location>
</error-page>
<error-page>
    <exception-type>java.lang.Exception</exception-type>
    <location>/pages/err.jsp</location>
</error-page>
<welcome-file-list>
    <welcome-file>/pages/home.jsp</welcome-file>
</welcome-file-list>

图片居中的方式:

可以绝对定位、浮动等手段都可以,这里使用一下弹性容器flex

<div style="display: flex;justify-content: center;align-content: center;width: 100%;height: 100%">
  <img src="images/404.png">
</div>

[老王讲IT 性感有魅力]  

  • 16
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT老王Hua_TZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值