第三章 JSP

一. JSP
JSP是为弥补 Servlet 的缺陷而产生的
Servlet 的不足之处: 1. 在 servlet 中编写页面必须将 HTML 标签卸载 java 字符串中, Http 响应十分繁琐, 2. 所有的 HTML 都是硬编码, 任何改动都需要重新编译.
本章主演内容: 隐式对象, 三种句法元素: 指令, 脚本元素, 动作

  • JSP页面实质是一个 Servlet: 第一次请求一个 JSP 页面时, Servlet/JSP容器要做两件事
  1. 将 JSP 文件转化为实现 JspPage 接口或其子接口 HttpJspPage的 java 类. JspPage是 Servlet 的子接口
  2. 然后编译成.class类, 实例化成 java对象, 并执行声明周期方法
  • 对于同一个 JSP 页面的后续请求, Servlet/JSP容器会查看这个 jsp 页面从最后一次转换以来是否修改过, 若修改过, 重新转换, 并执行, 第一次执行 JSP的时间总是比后续请求时间长, So 可以采取以下措施:
  1. 配置应用程序, 使 JSP 在应用启动时被编译.
  2. 预编译 JSP页面, 并将它以 Servlet 的方式进行部署.
    这里写图片描述

对于 JSP API 除了 javax.servlet.jsp.tagext 包下以外, 很少用到 JSP API , 但在开发 JSP容器或者编译 JSP 时需要大量使用 JSP API
在 tomcat/work/catalina中, 会有jsp编译后的java文件和. Class 文件等,

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,
                 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(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, "JSPs only permit GET POST or HEAD");
      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");
      out.write("<html>\n");
      out.write("  <head>\n");
      out.write("    <title>$Title$</title>\n");
      out.write("  </head>\n");
      out.write("  <body>\n");
      out.write("  ");
      out.write((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${pageContext.request.session.id}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
      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);
    }
  }
}

对于这个 Servlet 的类名不用在意, 是 Servlet/JSP 解析 JSP 时自动给定的, HttpJspBase它是继承了HttpServlet 实现了HttpJspPage 的抽象类
这里写图片描述

二.隐式对象
Servlet 被访问过成功, 会被传入一个 ServletRequest, 一个 ServletResponse, 在 init()方法中获得 ServletConfig, 可以通过 ServletRequest.getSession 获得 Session 对象. 在 JSP 页面中, 可以在<%%>中使用隐式对象, 直接使用这些对象.

对象
类型
request javax.Servlet.http.HttpServletRequest
response javax.Servlet.http.HttpServletResponse
out javax.Servlet.jsp.JspWriter
session javax.Servlet.http.HttpSession
application javax.Servlet.ServletContxt
config javax.Servlet.ServletConfig
pageContext javax.Servlet.jsp.PageContext
page javax.Servlet.jsp.HttpJspPage
exception java.lang.Throwable

在 PageContext 类提供的方法中, 可以通过 getAttribute 和 setAttribute 方法, 操作 page, request, session, application 四个属性, 这是 javaweb 中及其重要的四个域对象
public abstract void setAttribute(String key, Object value, int scope);
scope 取值可以是 PageContext 中的属性: PAGE_SCOPE, REQUEST_SCOPE, SESSION_SCOPE, APPLICATION_SCOPE, 这些属性都是 static final int

<%
    pageContext.setAttribute("key", "value", PageContext.SESSION_SCOPE);
%>

<%
    session.setAttribute("key", "value");
%>

等效

<%
    Enumeration enumeration = request.getHeaderNames();
    while (enumeration.hasMoreElements()){
        String header = (String) enumeration.nextElement();
        out.println(request.getHeader(header)+"
");
    }
%>

now is2018/01/22 04:00:29 host: localhost:8080 connection: keep-alive
upgrade-insecure-requests: 1 user-agent: Mozilla/5.0 (Macintosh; Intel
Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/63.0.3239.132 Safari/537.36 accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8
referer: http://localhost:8080/jsp/ accept-encoding: gzip, deflate, br
accept-language: zh-CN,zh;q=0.9 cookie:
JSESSIONID=04B27991A562F0B38D47213D3630668D;
Webstorm-51126a97=c9c36c70-f35c-45aa-b810-b032510af931;
Idea-32792250=817d7c5c-de69-4950-8106-ff68b1a446ab;
_ga=GA1.1.185731695.1487123705

通过 request 可以获取报文头, 包含不同浏览器的信息
三. 指令

  1. page 指令
    语法: <%@ page attrubute=“value1” attribute=“value2” ……%>
    attribute 是 page 指令的的属性名
    属性列表:
  • import. 导入一种或多种 java 类型, 以供本页 java 代码使用 <%@ page import java.lang.Arrays, java.lang.List ……%>
  • session. 值为 true 时, 表示这个页面参数 session 管理, 默认为 true, 意味着, 如果之前没有 session, 那么调用 JSP页面始终会创建一个.
  • buffer. 指定 out 对象的缓冲区大小, 以千字节为单位KB, 缓冲区的默认容量大于等于8KB, 具体取决于 Servlet/JSP 容器. 这个值也可以为 none, 表示不使用缓存, 直接写到 相应的 PrintWriter.
  • autoFlush. 默认为 true, 表示当缓冲区满时自动刷新, 为 false 时, 表示只有调用 response.flush() 时才刷新缓冲区, 所以缓冲区溢出时会报异常.
  • isTheadSafe. 表示页面实现的安全级别, 建议不要轻易使用这个属性.
  • info. 指定所生成的 getServletInfo的返回值.
  • errorPage. 若页面中有异常, 但为捕获到, 指定一个页面表示产生异常.
  • currentType. 指定该页面response 的内容类型, 默认”text/html”
  • pageEncoding. 指定页面编码, 默认为 ISO-8859-1
  • isElIgnored. 是否忽略 EL表达式
  • language. 指定脚本语言, 默认为 java, 目前只支持 java,
  • extends. 指定当前页面 JSP 实现类 拓展的超类. 很少使用, 使用要特别注意
  • degerredSyntaxAllowedAsLiteral. 指明是否允许使用字符序列#{作文本页的编码字符串值, 默认为 false, #{ 在 EL表达式中是个特殊字符
  • trimDirectiveWhitespaces. 表名是否从输出内容中 删除只包含空格的模板文本, 默认为 false, 不删除空格
    page 指令可以出现在页面的任何地方, 但是 contentType 和 pageEncoding必须放在模板数据之前
    page 指定可以出现多次, 但相同属性, 必须配置值相同, 不然后面写的覆盖前面写的, 除import 不会覆盖
    2.include指令
    利用 include 指令, 可以将另一个文件的资源,放到当前 JSP 中, 一个 JSP 可以使用多个 include
    <% @include file=“url”%> 如果 url 以 ”/“ 开始, 表示 绝对路径, 否则是相对路径. url 指定文件的后缀名不限.
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
 
<%@include file="form.jsp"%>
  </body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
    <form action="welcome" method="get">
        <input type="radio" name="name" value="zcz"> zcz </br>
        <input type="radio" name="name" value="zzz"> zzz </br>
        <input type="text" name="userInfo"> </br>
        <input type="submit" name="submit"> </br>
    </form>
</body>
</html>

这里写图片描述
3.脚本元素, 方法声明, 表达式

  • 脚本元素使用<% %>, 在标签中, 可以当做代码块书写 java 代码, 一个 jsp 可以写多个<%%>, 并且, 一个<%%> 中声明的实例, 属性, 在其他<%%>中都可见.
  • 方法声明<%! %>, 可以在这个标签中声明 java 方法. 如果使用 page 指令中的 extends 属性,需要覆盖父类方法, 可以使用<%! %> 覆盖父类方法.
  • <%=%> 表达式
<%
    Enumeration enumeration = request.getHeaderNames();
    while (enumeration.hasMoreElements()){
        String header = (String) enumeration.nextElement();
        out.print(header+": "+request.getHeader(header)+"
");
    }
%>

<%!
    public String today(){
        SimpleDateFormat format = new SimpleDateFormat("YYYY/MM/dd hh:mm:ss");
        return format.format(new Date());
    }
%>
<%
    out.println("=============================</br>");
    out.println("today"+ today()+"</br>");
%>
<input type="text" value="<%=today()%>">

4.关闭脚本元素

  • 在 JSP2.0时 , 最主要的更新就是 EL 表达式, 在后端建议JSP使用 EL 表达式取代 Java 代码. 在 web.xml 中可以使用, 中定义一个 scripting-invalid 关闭 java 脚本
<jsp-config>
    <jsp-property-group>
        <url-pattern>*/welcome.jsp</url-pattern>
        <scripting-invalid>true</scripting-invalid>
    </jsp-property-group>
</jsp-config>

5.动作(方法)
创建实例, 和添加获取属性

<jsp:useBean id="people" class="com.zcz.study.jsp.People"/>
<jsp:setProperty name="people" property="name" value="zcz"/>
name: <jsp:getProperty name="people" property="name"/>

6.include
include是动态的包含一个资源, 可以包含另外一个 jsp 页面,Servlet 或静态 HTML

<jsp:include page="form.jsp">
    <jsp:param name="text" value="How are you"/>
</jsp:include>
${param.text}

include指令和 include 动作区别很重要, 使用 include 指令时, 这种包含是发生在页面转换的时候, include 动作是发生在请求的时候, 可以利用 include 动作传递参数, 上面的<jsp:param name=“text” value="How are you”/> 可以在 form.jsp里使用${param.text}获取值;
使用 include 的指令时, 包含文件的拓展名不重要, 但是 include 动作包含文件的后缀必须是. Jsp

7.forward

<jsp:forward page="form.jsp">
    <jsp:param name="tt" value="hello"/>
</jsp:forward>

将当前页年跳转到另外一个页面, 可传值过去

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值