Web基础-JSP

1.JSP基础概念

1.1 什么是JSP?
  • Java Server Pages,即Java 的服务器页面。主要作用是代替 Servlet 程序回传 html 页面的数据(Servlet 程序回传 html 页面数据很繁锁并且开发成本和维护成本都极高)

    • Servlet 回传 html 页面数据的代码:
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 通过响应的回传流回传 html 页面数据
        resp.setContentType("text/html; charset=UTF-8");
        PrintWriter writer = resp.getWriter();
        writer.write("<!DOCTYPE html>\r\n");
        writer.write(" <html lang=\"en\">\r\n");
        writer.write(" <head>\r\n");
        writer.write(" <meta charset=\"UTF-8\">\r\n");
        writer.write(" <title>Title</title>\r\n");
        writer.write(" </head>\r\n");
        writer.write(" <body>\r\n");
        writer.write(" 这是 html 页面数据 \r\n");
        writer.write(" </body>\r\n");
        writer.write("</html>\r\n");
        writer.write("\r\n");
    }
    
    • jsp 回传一个简单 html 页面的代码:
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
    	<title>Title</title>
    </head>
    <body>
    	这是 html 页面数据
    </body>
    </html>
    

tips:

  • jsp页面和html页面一样,都是存放在 web 目录下。访问也跟访问 html 页面一样
1.2 JSP的本质
  • jsp 页面本质上是一个 Servlet 程序:当第一次访问 jsp 页面的时候,Tomcat 服务器会把 jsp 页面翻译成为一个 java 源文件,并且将它编译成为.class 字节码程序
// 将test.jsp翻译为源文件test_jsp.java后的代码
// 因为HttpJspBase继承了HttpServlet类,即test_jsp.java是一个Servlet
public final class test_jsp extends org.apache.jasper.runtime.HttpJspBase...{
    public void _jspService(){
        // 也是通过输出流把htmly页面数据回传给客户端
    	out.write("\r\n");
      	out.write("\r\n");
      	out.write("<html>\r\n");
        ...
    }

}
1.3 JSP的三种语法
1.3.1 jsp 头部的 page 指令
  • jsp 的 page 指令可以修改 jsp 页面中一些重要的属性,或者行为:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
i. language属性:表示 jsp 翻译后是什么语言文件。暂时只支持 java。
ii. contentType属性:表示 jsp 返回的数据类型是什么。也是源码中response.setContentType()参数值
iii. pageEncoding属性:表示当前 jsp 页面文件本身的字符集。
iv. import属性:跟 java 源代码中一样。用于导包,导类
v. autoFlush属性:设置当 out 输出流缓冲区满了之后,是否自动刷新冲级区。默认值是 true。
vi. buffer属性:设置 out 缓冲区的大小。默认是 8kb
vii. errorPage属性:设置当 jsp 页面运行时出错,自动跳转去的错误页面路径
viii. isErrorPage属性:设置当前 jsp 页面是否是错误信息页面。默认是 false。如果是 true 可以获取异常信息
ix. session属性:设置访问当前 jsp 页面,是否会创建 HttpSession 对象。默认是 true。
x. extends属性:设置 jsp 翻译出来的 java 类默认继承谁。
1.3.2 jsp 中的常用脚本
  • 声明脚本:

    • 格式:<%! 声明 java 代码 %>
    • 作用:可以给 jsp 翻译出来的 java 类定义属性和方法甚至是静态代码块、内部类等
    <%!
        private Integer id;
        private String name;
        private static Map<String,Object> map;
    %>
    
  • 表达式脚本:

    • 格式:<%=表达式%>
    • 作用:用于向页面输出内容。表达式脚本翻译到 Servlet 程序的 service 方法中 以 out.print() 打印输出
    <body>
        <%=12%>
    	<%="psj"%>
    </body>
    
  • 代码脚本*:

    • 格式:<% java 代码 %>
    • 作用:代码脚本里可以书写任意的 java 语句,其内容都会被翻译到 service 方法中。service 方法中可以写的 java 代码,都可以书写到代码脚本中
    <%
        int a = 0;
        if (a == 0){
            System.out.println("a=0");
        }else {
            System.out.println("a!=0");
        }
    %>
    

tips:

  • 表达式脚本中不能以分号结束
  • 单行注释和多行注释能在翻译后的 java 源代码中看见,jsp注释释在翻译的时候会直接被忽略掉,html 的注释会被翻译到 java 代码中输出到 html 页面中查看:
// 单行 java 注释
/* 多行 java 代码注释
*/
<%-- jsp 注释 --%>
<!-- html 注释 -->
  • 表达式脚本可以和代码脚本结合使用:
<%
    for (int i = 0; i < 10; i++) {
%>
    <h1>第<%=i+1%>行</h1>
<%
    }
%>

// 翻译后的java代码:
for (int i = 0; i < 10; i++) {    
      out.write("\r\n");
      out.write("        <h1>第");
      out.print(i+1);
      out.write("行</h1>\r\n");
      out.write("    ");
}

2.JSP九大内置对象

2.1 什么是内置对象
  • 指Tomcat在翻译jsp页面成为Servlet源代码后,内部提高的九大对象,称为内置对象:

在这里插入图片描述

2.2 九大对象
  • request对象:请求对象,可以获取请求信息
  • response对象:响应对象,可以设置响应信息
  • pageContext 对象:当前页面上下文对象。可以在当前上下文保存属性信息
  • session对象:会话对象。可以获取会话信息。
  • exception对象:异常对象只有在 jsp 页面的 page 指令中设置 isErrorPage="true" 的时候才会存在
  • application对象:ServletContext 对象实例,可以获取整个工程的一些信息
  • config对象:ServletConfig 对象实例,可以获取 Servlet 的配置信息
  • out对象 输出流
  • page对象:表示当前 Servlet 对象实例(用它不如使用 this 对象)

tips:

  • 九大内置对象都是我们可以在【代码脚本】中或【表达式脚本】中直接使用的对象
2.2.1 四大域对象
  • 经常用来保存数据信息:

    • pageContext 可以保存数据在同一个 jsp 页面中使用(当前jsp页面范围内有效)
    • request 可以保存数据在同一个 request 对象中使用。经常用于在转发的时候传递数据(一次请求内有效)
    • session 可以保存在一个会话中使用(一个会话范围内有效)
    • application就是 ServletContext 对象(整个web工程范围内有效,只要web工程不停止数据都在)
    // test1.jsp
    <%
        //设置 page 域的数据
        pageContext.setAttribute("key", "pageContext-value");
        //设置 request 域的数据
        request.setAttribute("key", "request-value");
        //设置 session 域的数据
        session.setAttribute("key", "session-value");
        //设置 application 域的数据
        application.setAttribute("key", "application-value");
    %>
    <%-- 测试当前页面作用域 --%>
    <%=pageContext.getAttribute("key") %><br/> 
    <%=request.getAttribute("key") %><br/>
    <%=session.getAttribute("key") %><br/>  
    <%=application.getAttribute("key") %><br/> 
    <%
        request.getRequestDispatcher("/test2.jsp").forward(request, response);
    %>
    
    // test2.jsp
    <%=pageContext.getAttribute("key") %><br/>
    <%=request.getAttribute("key") %><br/>
    <%=session.getAttribute("key") %><br/>
    <%=application.getAttribute("key") %><br/>
    
    // 没加上转发后,页面输出:
        pageContext-value
        request-value
        session-value
        application-value
    // 加上转发后,页面输出:
        null
        request-value
        session-value
        application-value
    // 把浏览器关闭再输打开输入网址访问test2.jsp后session-value=null
    // 把服务器关闭/重新部署后输入网址访问test2.jsp后application-value=null
    

tips:

  • 域对象是可以像Map一样存取数据的对象,上述四个域对象功能一致,但是对数据的存储范围不一样
  • 会话范围就是打开浏览器访问服务器到关闭浏览器这个阶段
  • 四个域对象在使用时的优先顺序按从小到大的范围查找:pageContext->request->session->application
2.2.2 out vs response.getwriter()
  • 情景:为什么out的输出代码在前面最终输出却在response后?
<%
    out.write("这是 out 的第一次输出<br/>");
    out.flush();
    // 最后一次的输出,由于没有手动flush,会在整个页面输出到客户端的时候,自动写入到writer缓冲区
    out.write("这是 out 的第二次输出<br/>");
    response.getWriter().write("这是 writer 的第一次输出<br/>");
    response.getWriter().write("这是 writer 的第二次输出<br/>");
%>
// 结果输出:
这是 out 的第一次输出
这是 writer 的第一次输出
这是 writer 的第二次输出
这是 out 的第二次输出
  • 原因:执行out和response输出时都有自己的缓冲区,但是当jsp页面中所有代码执行完毕后会进行以下两个操作:

    • 执行out.flush(),将out缓冲区的数据追加到response缓冲区末尾
    • 执行response的刷新操作,把所有数据写入客户端

    因为第二行代码手动执行了out.flush(),所以在最前面输出,但是第二个out的输出内容被追加到末尾,所以输出在response输出后

tips:

  • out.print(11)方法输出任意数据都会把数据11转换为字符串“11”,然后调用out.witer(“11”)方法输出。但是直接调用out.writer(11)会出现乱码,因为底层是执行了(char)11,即将数字11强转为字符(所以在jsp页面中,可以统一使用out.print()进行输出)

3.jsp 的常用标签

3.1 静态包含
  • 格式:<%@ include file="" %>(路径中的第一个斜杠表示http://ip:port/工程路径/)
  • 作用:把包含的页面内容原封装不动的输出到包含的位置

tips:

  • 静态包含不会翻译被包含的jsp页面,即将被包含的jsp页面代码拷贝到包含的位置执行输出。所以将jsp翻译为java代码后目录下还是只有一个java文件
  • 静态包含不能传递参数
  • 静态包含适用于包含纯静态内容(CSS,HTML,JS)或没有非常耗时操作或大量 java 代码的 jsp
  • jsp 页面中基本上只有html,css,js还有一些简单的 EL,表达式脚本等输出语句(jsp 在开发过程中被定位为专门用来展示页面的技术),所以基本都使用静态包含。
3.2 动态包含
  • 格式:<jsp:include page=""></jsp:include>
  • 作用:把包含的 jsp 页面单独翻译成 servlet 文件,然后在执行到时候再调用翻译的 servlet 程序,并把计算的结果返回(在执行的时候,才会加载)

tips:

  • 由于动态包含把包含的jsp页面也翻译为java代码,所以在目录下会出现多个java文件(假设使用包含的jsp页面为test.jsp,被包含的为test2.jsp),然后在test.java中的service方法会调用以下代码:
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "test2.jsp", out, false);
  • 为什么动态包含的输出内容顺序和静态包含一样?本质就是在执行方法时将out对象通过方法传递给了被包含的页面

在这里插入图片描述

  • 动态包含可以传递参数:
// test.jsp
<body>
<jsp:include page="test2.jsp">
    <jsp:param name="username" value="psj"/>
</jsp:include>
</body>
// test2.jsp
<body>
<%=request.getParameter("username")%>
</body>
// 最后输入网址访问test.jsp会显示psj,在test.java中执行了:
org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "test2.jsp" + "?" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("username", request.getCharacterEncoding())+ "=" + org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("psj", request.getCharacterEncoding()), out, false);
3.3 页面转发
  • 格式:<jsp:forward page=""></jsp:forward>
  • 作用:相当于request.getRequestDispatcher("/xxxx.jsp").forward(request, response)

在这里插入图片描述


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值