jsp入门

Jsp入门 主要内容:

  1. JSP入门,什么是JSP?
  2. JSP一般放在哪里?
  3. JSP组成部分;
  4. JSP的语法;
  5. JSP原理;
  6. JSP注释;

Jsp入门

  1. 什么是JSP?以及JSP有什么作用? JSP即Java Server Pages, 它是JavaWeb服务器端的动态资源。(浏览器是读不懂的,必须由服务器翻译之后变成一个静态页面,相当于html)它与html页面的作用是相同的,显示数据和获取数据的。
  2. Jsp一般放在哪里? Jsp一般放在web应用的跟目录下,或者WEB-INF文件夹下面。
  3. Jsp的组成部分?
  1. JSP = html + java脚本(代码片段) + JSP动态标签。图1: 图1
  2. 如图2:新建一个项目,打开index.jsp页面,除了标红的部分,其他的都跟html一样,而标红的部分都称之为java代码片段,1是Jsp三大指令之一page,也是标签的一种,其他两大指令:taglib、include指令,其实也都是特殊的jsp标签,后面会学到。 这里的request对象,为什么可以直接使用呢?之前都是有方法,方法有形参,所以参数可以使用。JSP的强大之处是有九大内置对象,内置对象不需要创建直接可以使用!

2是java代码片段, 图2: 3) 图2中,标红部分3我们对比一下看。把day01_1项目部署运行后,访问index.jsp页面,访问结果如图3。 图3。 在图3浏览器页面点击右键,查看源码,可以看到图2上标红的代码不见了,而图2的<%=basePath%>变成了现在的http://localhost:8080/day01_1/,如图4,很明显这是一个变量,在这里直接输出这个变量。 图4 4. JSP的语法?

  1. JSP脚本 JSP脚本就是java代码片段,它分为三种: <%...%>:Java语句;内容会被原封不动的被翻译到Servlet的service方法中。 <%=…%>:Java表达式;内容会被放到out.pring()方法里面,作为out.pring()方法的参数。 <%!...%>:Java定义类成员;内容会放到_jspService()方法之外,被类直接包含,可以声明变量和成员方法。所以声明中不能使用九大内置对象。(实际使用的非常少!)  语句:所谓动态,也是在jsp页面书写程序或语句,来控制页面输出的显示效果,有顺序、选择、判断、循环等语句的出现;例如:

 表达式:内容会被放在out.print()里面输出到浏览器。

访问时输入参数,jsp的动态之处就在于可以随意修改参数;

  1. 多个<%...%>可以通用 在一个JSP中多个<%...%>是相通的。例如:

  2. 循环打印表格:

结果图:

  1. JSP基本原理? 5.1 JSP实际上就是一个Servlet,只是提供了一种比较直观的书写方式,因为写jsp就像在写html。

Web资源的运行原理: 每个web应用程序中的web.xml都会继承tomcat/conf/web.xml文件,通过请求路径,读取jsp文件,在访问Jsp时,会先访问web.xml文件中sevlet-name为jsp的JspServlet类,而JspServlet类又做了哪些操作呢?jsp页面在第一次被访问的时候,web容器(jsp引擎jspServlet)会将jsp翻译成一个Servlet,然后调用servlet的service方法。jsp翻译后的servlet文件会被放到;tomcat安装目录/work/Catalina/localhost/项目名称,最后编译.java文件生成.class文件,并执行.class文件。当jsp页面被再次访问的时候,web容器会去直接调用servlet的service方法,所以通常来讲jsp只是在第一次被访问时比较慢,如果jsp页面做了修改,此时web容器会重新翻译jsp。 (Catalina引擎+Localhost主机名+项目, JSP在运行时需要先转换成servlet,转换servlet是一个小工具,那么这个小工具就是引擎,有了引擎才可以让jsp翻译成servlet,如果不好理解的话,也可以把引擎理解为就是tomcat。比如:引擎相当于发动机,汽车有了发动机才可以行驶前进或后退,他是一个抽象的书名词。)

5.2 JSP翻译成servlet文件后的存放目录 JSP生成的servlet存放在;tomcat安装目录/work/Catalina/localhost/项目名称,我们打开看看其中的内容,你会发现在JSP中的静态信息在转换成servlet的文件中,都是使用out.write()完成打印。这些静态信息都是作为字符串输出给客户端。 JSP的整篇内容都会放到servlet的“_jspService”方法的try块中,并且是9大内置对象赋值后,所以jsp才可以直接使用9大内置对象,而不用创建。你可能会说<%@ page ……%>这里的内容不在转换后的servlet中,这个稍后会解释。 a_jsp.java的_jspServlet()方法: public void _jspService(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { //九大内置对象的创建,但是注意这里并没有实例化; PageContext pageContext = null; HttpSession session = null; ServletContext application = null; ServletConfig config = null; JspWriter out = null; Object page = this; JspWriter _jspx_out = null; PageContext _jspx_page_context = null;

try {
  response.setContentType("text/html;charset=ISO-8859-1");
  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('\r');
  out.write('\n');

String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

  out.write("\r\n");
  out.write("\r\n");
  out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
  out.write("<html>\r\n");
  out.write("  <head>\r\n");
  out.write("    <base href=\"");
  out.print(basePath);
  out.write("\">\r\n");
  out.write("    \r\n");
  out.write("    <title>My JSP 'a.jsp' starting page</title>\r\n");
  out.write("    \r\n");
  out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
  out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
  out.write("\t<meta http-equiv=\"expires\" content=\"0\">    \r\n");
  out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
  out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
  out.write("\t<!--\r\n");
  out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
  out.write("\t-->\r\n");
  out.write("\r\n");
  out.write("  </head>\r\n");
  out.write("  \r\n");
  out.write("  <body>\r\n");
  out.write("    This is my JSP page. <br>\r\n");
  out.write("  </body>\r\n");
  out.write("</html>\r\n");
} catch (Throwable t) {
  if (!(t instanceof SkipPageException)){
    out = _jspx_out;
    if (out != null && out.getBufferSize() != 0)
      try { out.clearBuffer(); } catch (java.io.IOException e) {}
    if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
    else log(t.getMessage(), t);
  }
} finally {
  _jspxFactory.releasePageContext(_jspx_page_context);

} }

  1. jsp 和 Servlet的区别
  1. Servlet 适合写java代码,因为Servlet就是一个java类; 在开发中使用Servlet对用户发送的请求进行处理并做出响应;
  2. jsp 适合做数据美化,作为数据显示模板; 因为jsp页面直接书写HTML标签;
  3. 项目中的web层通常使用mvc设计模式 Servlet+jsp+javabean 其中, Servlet做控制器,处理用户请求 jsp作为显示模板 javabean作为封装数据的实体
  4. 如何养成一种良好的编码风格 在Servlet中应避免做任何的数据输出 在jsp 中应避免去直接书写java代码, 而实际上要做到这点很难, 所以需要用到 el 和 jstl。
  1. 再论JSP脚本 现在我们已经知道了,JSP其实就是一个类,一个Servlet类。<%!...%>的作用是在类中添加方法或成员变量的,所以<%!...%>中的内容不会出现在_jspService()中。 <%! private String name; public String hello() { return "hello JSP!"; } %>
  2. JSP注释 我们已经知道JSP需要转换成.java文件,再编译成.class文件,其中<%-- --%>中的内容在JSP编译成.java时会被丢弃掉,即是JSP注释 也可以在JSP页面中使用html注释:<!-- … -->,但这个注释在JSP编译成的.java中是存在的,它不会被忽略,而且会被发送到客户端浏览器。但是在浏览器显示服务器发送过来的html时,因为<!-- … -->是html的注释,所以浏览器是不会显示它的。但是可以通过浏览器的“查看源代码”查看到html注释。 如果在注释中输出语句的话,也可以: 例如:<!-- <%= new Date() %> -->

其实就相当于是输出语句: ; 而out.write(new Date())语句最后会执行toString(),输出一个字符串。 浏览器访问是看不到的,“查看源代码”显示:

  1. JSP三大指令 9.1 JSP指令概述 在JSP2.0规范中共定义了三个指令,他们不直接产生任何可见输出,也就是不会显示在浏览器上,而只是告诉引擎如何处理JSP页面中的其余部分。 JSP中三大指令分别是:page、include、taglib最为常用,最为复杂的就是page指令了。 三大指令的格式: <%@ 指令名 属性名=“值” %>

如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。例如: <%@ page contentType=”text/html;charset=gb2312” %> <%@ page import=”java.util.Date” %> 也可以写作: <%@ page contentType=”text/html;charset=gb2312” import=”java.util.Date” %> Include指令用的不多,而page用的是100%,用的比较多的,任何一个jsp都是需要page指令,到后期也很少有jsp不使用taglib指令的,相对来说最难学就是page指令了。 9.2 page指令

  1. page指令是最为常用的指令,也是属性最多的指令。 page指令没有必须的属性,都是可选的。page指令除import属性外,其他属性不可以重复,一个jsp页面可以有多个page指令,在JSP页面中,任何指令都是可以重复出现。如下这也是可以的: <%@ page language=”java”%> <%@ page import=”java.util.*”%> <%@ page pageEncoding=”utf-8”%> 指令不是必须要放在第一行,在任何一行都行,只是平时人们习惯了放到JSP文件的最上方。 page指令的一些属性: pageEncoding: pageEncoding指定当前JSP页面的编码。这个编码是给服务器tomcat看的,因为服务器要把jsp转换成.java文件,所以服务器需要知道当前JSP页面使用的编码格式,不然服务器无法正确把JSP编译成java文件,会出现乱码问题,tomcat服务器默认以IOS-8859-1的编码形式读取。所以这个编码只需要与真实的页面编码一致即可,在MyEclipse中,JSP文件上点击右键,选择属性就可以看到当前JSP页面的编码了。

  2. contentType 与response.setContentType()方法的作用相同,它会完成两项工作,一是设置响应字符流的编码,二是设置content-type响应头。例如:<%@ contentType=”text/html;charset=utf-8”%>,它在转换成servlet时,在该servlet中会出现response.setContentType(“text/html;charset=utf-8”)。

一般在Servlet中,习惯性的会首先设置请求以及响应的内容类型以及编码方式。 Tomcat的安装目录\conf\web.xml 中就定义了大量MIME类型 ,可以参考。 (MIME (Multipurpose Internet Mail Extensions) 是描述消息内容类型的因特网标准。 MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。) response.setContentType("text/html; charset=utf-8"); html response.setContentType("text/plain; charset=utf-8"); 文本 response.setContentType("text/javascript json"); 数据 response.setContentType("application/xml "); xml数据

无论是page指令的pageEncoding还是contentType,它们的默认值都是ISO-8859-1,我们知道ISO-8859-1是无法显示中文的,所以JSP页面中存在中文的话,一定要设置这两个属性。  当设置了pageEncoding,而没设置contentType时: contentType的默认值为pageEncoding;  当设置了contentType,而没设置pageEncoding时: pageEncoding的默认值与contentType; 也就是说,当pageEncoding和contentType只出现一个时,那么另一个的值与出现的值相同。如果两个都不出现,那么两个属性的值都是ISO-8859-1。所以通过我们至少设置它们两个其中一个!

  1. page指令的import属性 import是page指令中一个很特别的属性! import属性值对应servlet中的import语句。 import属性值可以使逗号:<%@page import=”java.net.,java.util.,java.sql.*”%>

import属性是唯一可以重复出现的属性: <%@page import=”java.util.” import=”java.net.” import=”java.sql.”%> 但是,我们一般会使用多个page指令来导入多个包: <%@ page import=”java.util.”%> <%@ page import=”java.net.”%> <%@ page import=”java.text.”%>

  1. page指令的errorPage和isErrorPage 我们知道,在一个JSP页面出现错误后,tomcat会响应给用户错误信息(500、400页面等)。如果你不希望tomcat给用户输出该错误信息,那么可以使用page指令的errrorPage来指定自己设置的错误页面,也就是自定义错误页面。例如:<%@ page errorPage=”xxx.jsp” %>。这时,在当前JSP页面出现错误的时候,会请求转发到xxx.jsp页面。 index.jsp <%@ page errorPage="/hello.jsp" language="java" pageEncoding="UTF-8" %> <%@ page import="java.util.,java.io.,java.sql.* " %> <% if(true) throw new Exception("异常了~"); %> hello.jsp <%@ page pageEncoding="UTF-8"%>

<html> <body> <h1>系统正在维护,请稍后访问!</h1> </body> </html>

在上面代码中,index.jsp抛出异常后,会请求转发到hello.jsp。在浏览器的地址栏中的地址是不变的,还是index.jsp,因为是请求转发! 而且客户端浏览器收到的响应码为200,表示请求成功!如果希望客户端得到500,那么需要指定hello.jsp为错误页面。这里使用page指令的isErrorPage属性,如下脚本: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ page isErrorPage="true" %>

<html> <body> <h1>系统正在维护,请稍后访问!</h1> <!—只有isErrorPage的值为true时,该页面才可以使用JSP的内置对象exception对象,而且浏览器的状态为500,而不是200 --> <%=exception.getMessage() %> </body> </html>

  注意,当isErrorPage为true时,说明当前JSP为错误页面,即专门处理错误的页面。那么这个页面中就可以使用一个内置对象exception了。其他正常页面是不能使用这个内置对象的! 提示:IE会在状态码为500时,并且响应正文的长度小于等于512B时不给予显示!而是显示“网站无法显示该页面”字样。这时你只需要添加一些响应内容即可,例如上例中的b.jsp中我给出一些内容,IE就可以正常显示了!

  1. web.xml中配置错误页面 配置错误页面还有一种方式,就是在web.xml文件中指定错误页面。这种方式与page指令并没有什么关系,在这里只是扩展下知识。 web.xml

<error-page> <!—当出现404时,会跳转到error404.jsp页面--> <error-code>404</error-code> <location>/error404.jsp</location> </error-page> <error-page> <!—当出现500时,会跳转到error500.jsp页面--> <error-code>500</error-code> <location>/error500.jsp</location> </error-page> <error-page> <!—当出现RuntimeException异常时,会跳转到error.jsp页面--> <exception-type>java.lang.RuntimeException</exception-type> <location>/error.jsp</location> </error-page> <error-page>有两种使用方式: <error-code>和<location>子元素; <exception-type>和<location>子元素; 其中<error-code>是指定相应码;<location>指定转发的页面;<exception-type>指定抛出的一场类型。 这种方式会在控制台看到异常消息,而使用page指令时在控制台是没有打印消息的。 如果在JSP页面配置了指定错误页面,web.xml文件中也配置了,它的执行先后顺序是: 例如:500错误。如果JSP页面指定了错误页面,那么按JSP页面指定的为准;如果JSP页面没有指定错误页面,那么就看web.xml文件,看该错误是否属于异常,哪种类型的异常,在web.xml文件中<exception-type>子元素如果配置了该异常那么按照指定的跳转到错误页面,如果没有设定那么就看的<error-code>子元素是否有配置该错误的设置。 执行顺序是:1.JSP页面指令配置错误页面--2.web.xml文件中的exception-type子元素配置错误页面--3.web.xml文件中的error-code子元素配置的错误页面。

  1. page指令的autFlush和buffer(不重要) buffer表示当前JSP的输出流(out隐藏对象)的缓冲区大小,默认为8kb。 authFlush表示在out对象的缓冲区满时如果处理!当authFlush为true时,表示缓冲区满时把缓冲区数据输出到客户端;当authFlush为false时,表示缓冲区满时,抛出异常。authFlush的默认值为true。 这两个属性一般我们也不会去特意设置,都是保留默认值!

  2. page指令的isELIanored 后面我们会讲解EL表达式语言,page指令的isElIgnored属性表示当前JSP页面是否忽略EL表达式,默认值为false,表示不忽略(即支持)。

  3. page指令的其他属性(更不重要)  language:只能是Java,这个属性可以看出JSP最初设计时的野心!希望JSP可以转换成其他语言!但是,到现在JSP也只能转换成Java代码;  info:JSP说明性信息;  isThreadSafe:默认为false,为true时,JSP生成的Servlet会去实现一个过时的标记接口SingleThreadModel,这时JSP就只能处理单线程的访问;  session:默认为true,表示当前JSP页面可以使用session对象,如果为false表示当前JSP页面不能使用session对象;  extends:指定当前JSP页面生成的Servlet的父类;

  4. <jsp-config>(了解) 在web.xml文件中配置<jsp-config>也可以完成很多page指令的指定功能。 <jsp-config> <jsp-property-group> <!-- 对所有JSP进行配置 --> <url-pattern>*.jsp</url-pattern> <!-- 忽略EL表达式 --> <el-ignored>true</el-ignored> <!-- 指定页面编码为UTF-8 --> <page-encoding>UTF-8</page-encoding> <!-- 禁止用java脚本,如果在JSP页面中使用了java脚本就会抛出异常 --> <scripting-invalid>true</scripting-invalid> </jsp-property-group> </jsp-config>

9.3 include指令 include指令表示静态包含!即目的是把多个JSP合并成一个JSP文件! include指令只有一个属性:file,指定要包含的页面,例如:<%@include file=”b.jsp”%>。 静态包含:当a.jsp页面包含b.jsp页面后,在编译a.jsp页面时,首先需要把a.jsp与b.jsp页面合并成一个文件,然后再转换成servlet(.java文件)。

很明显,在ol.jsp中在使用username变量,而这个变量在hel.jsp中定义的,所以只有这两个JSP文件合并后才能使用。通过include指定完成对它们的合并!

在这里使用变量是不行的,为什么不能使用变量呢? 因为变量是在运行的时候在内存中才有值,现在JSP页面是首先要做的是合并两个JSP页面的内容,而现在的变量是没有值的,所以会报错。

9.4 taglib指令 这个指令需要在学习了自定义标签后才会使用,现在只能做为了解! 在JSP页面中使用第三方的标签库时,需要使用taglib指令来“导包”。例如: <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 其中prefix表示标签的前缀,这个名称可以随便起,但现在常用的标签人们已经养成了习惯,有常用的名字,比如jstl标签库常用的前缀名字是c,所以起名字大家也需要稍微注意下,别显得太不入流。uri是由第三方标签库定义的,所以你需要知道第三方定义的uri。 一个JSP页面可以导入多个标签库,这里标签的前缀目的是为了区分标签库,给不同的标签库起不同的名字。 在使用标签时<c:hello/>c标签库的hello标签,<a:hello/>a标签库的hello标签。

  1. JSP的九个隐式对象 10.1 在JSP中无需创建可以使用的9个对象,他们是: 对象变量名,可直接在JSP中使用 对象类型 描述 config ServletConfig 对应servlet中的ServletConfig; application ServletContext 即ServletContext类的对象; response HttpServletResponse 即HttpServletResponse类的对象; request HttpServletRequest 即HttpServletRequest类的对象;

session HttpSession 即HttpSession类的对象,不是每个JSP页面中都可以使用,如果在某个JSP页面中设置<%@page session=”false”%>,说明这个页面不能使用session; out JspWriter 等同与response.getWriter(),用来向客户端发送文本数据; page this 它就是当前JSP对象本身,即当前对象,它的引用类型是Object; exception Throwable 它是一个异常对象,只有在错误页面中可以使用这个对象; pageContext PageContext 页面上下文对象,JSP一共四个域对象,而servlet三个,多的这一个就是它,一个顶九个。

在这9个对象中有很多是极少使用的,例如:config、page、exception等基本不会使用; 在这9个对象中有两个对象不是每个JSP页面都可以使用的:exception、session; 在这9个对象中有很多对象前面已经学过了:out、request、response、application、session、config。

10.2 out对象:是一个输出流,用于向客户端输出数据。 out对象的基类是:javax.servlet.jsp.JspWriter类,是从java.io.Writer类继承而来,常用方法print()、println()、flush()、close()、clear()、clearBuffer()、getBufferSize(); JspWriter类型,是带缓冲的字符流(包装流)BufferedWriter,写入该流的数据最终会被刷新到response,调用response.getWriter().write()方法,print()方法输出数据时,不会写入一个换行符;而println()方法输出数据时,会写入一个换行符。 但是,浏览器目前不识别println()写入的换行符,如果希望浏览器显示换行,应当向浏览器写入<br>来实现换行。 clear()与clearBuffer()的区别? 如果缓冲区里的内容已经被输出,即已经调用了flush()方法,再去调用clear()方法,来清除缓冲区里的内容,则会抛出IOException。 如果缓冲区里的内容已经被输出,即已经调用了flush()方法,再去调用clearBuffer()方法,来清除缓冲区里的内容,则不会抛出IOException。

10.3 pageContext对象: pageContext是JSP中最重要的一个对象,主要功能用于获得其他8大隐式对象,范围是当前页面,出当前页面就不可使用,例如请求转发都是发不出去的。一个JSP中会有EL表达式和标签,它与页面的数据是不相通,如果EL表达式和标签想获取页面的数据,或者页面想获取EL表达式和标签里的数据时,就使用pageContext对象,它是唯一的通道。标签后面会学到,到时候就明白了。 在javaWeb中一共四个域对象,其中servlet中可以适用的适request、session、application三个域对象,而在JSP中可以使用pageContext、request、session、application四个域对象。 pageContext 对象是PageContext类型,它的主要功能有:  获取其他内置对象;  域对象功能;  代理其它域对象功能;

  1. 获取其他内置对象; 一个pageContext对象等于所有内置对象,这是因为可以使用pageContext对象获取其它8个内置对象,API常用方法:  JspWriter getOut():获取out内置对象;  ServletConfig getServletConfig():获取config内置对象;  Object getPage():获取page内置对象;  ServletRequest getRequest():获取request内置对象;  ServletResponse getResponse():获取response内置对象;  HttpSession getSession():获取session内置对象;  ServletContext getServletContext():获取application内置对象;  Exception getException():获取exception内置对象;

  2. 域对象功能; pageContext也是域对象,所谓域也就是范围的意思,它的范围是当前页面。它的范围也是四个域对象中最小的!  void setAttribute(String name, Object value);  Object getAttrbiute(String name, Object value);  void removeAttribute(String name, Object value);

  3. 代理其它域对象功能; pageContext对象还可以代理其它3个域对象的功能,也就是说可以使用pageContext向request、session、application域对象中存取数据。例如: <% pageContext.getAttribute("name", PageContext.REQUEST_SCOPE); request.getAttribute("name"); %> pageContext.getAttribute("name","ZhangSan"); pageContext.setAttribute("name", PageContext.REQUEST_SCOPE); pageContext.setAttribute("name", PageContext.APPLICATION_SCOPE); pageContext.setAttribute("name", PageContext.SESSION_SCOPE); API中pageContext有一系列,非常庞大的Attribute方法,这些方法都是在pageContext的父类JspContext类中,例如:  findAttribute(String name);全域范围查找,依次在page、request、session、application范围查找名称为name的数据,在四个域当中查找顺序是从小到大,如果找到就停止查找。这说明在这个范围内有相同名称的数据,那么page范围的优先级最高。  setAttribute(String name,Object value, int scope);在指定的范围中添加数据;  getAttribute(String name, int scope);获取指定范围的数据;  removerAttribute(String name, int scope);移除指定范围的数据;

10.4 通过Servlet来对照JSP 我们知道JSP页面的内容出现在被转换后servlet的_jspService()方法中,而在_jspService()方法开头部分已经创建了9个内置对象。 public void _jspService(HttpServletRequest request, HttpServletResponse response)// request和response两个对象 throws java.io.IOException, ServletException {

PageContext pageContext = null;// pageContext对象
HttpSession session = null;//session对象
ServletContext application = null;//application对象
ServletConfig config = null;//config对象
JspWriter out = null;//out对象
Object page = this;//page对象
JspWriter _jspx_out = null;//_jspx_out对象其实就是个引用,是java代码自动生成的,作用跟out对象一样
PageContext _jspx_page_context = null;//也是引用,作用跟pageContext对象一样;

//以后一般带下划线的对象,都是自动生成。 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; // JSP页面的内容从这里才开始,所以可以使用上面定义的变量!这就是9大内置对象为什么可以在JSP页面中无需创建就可以使用的奥秘了!     从这里开始,才是JSP页面的内容 }…

10.5 四个域对象的声明周期(重点) 生命周期就是指对象的创建到销毁的期间 page: jsp 页面被执行,生命周期开始,jsp 页面执行完毕 ,生命周期结束; request : 用户发送一个请求,开始,服务器返回响应,请求结束,生命周期结束; session : 用户打开浏览器访问,创建session(开始),session超时或被声明失效,该对象生命周期结束; application: web应用加载的时候创建(开始), web应用被移除或服务器关闭,对象销毁(结束)。

  1. JSP动作标签 11.1 JSP动作标签概述 JSP动作标签的作用是用来简化java脚本的!JSP动作标签是javaWeb内置的动作标签,不需要使用taglib指令导入标签库,他们是已经定义好的动作标签,我们可以拿来直接使用。 如果JSP动作标签不够用时,还可以使用自定义标签(详见jstl标签库、自定义标签笔记)。JavaWeb一共提供了20个JSP动作标签,但有很多基本没有用,这里只介绍一些常用的动作标签。 JSP动作标签的格式:<jsp:标签名 ……>

11.2 jsp:include jsp:include标签的作用是用来包含其他JSP页面的,咱们之前也学习了include指令,也是包含的意思。他们有什么区别呢?他们虽然都是用来包含其他JSP页面的,include指令是静态包含,include动作标签是动态包含,它们的实现级别是不同的。 include指令是,在编译级别完成的包含,它会把当前JSP和被包含的JSP合并成一个JSP,然后再编译成一个Servlet。 include动作标签是,即当前JSP和被包含的JSP都会各自生成Servlet,然后在执行前JSP的Servlet时完成包含另一个JSP 的Servlet。它与RequestDispatcher的include()方法是相同的。 d.jsp

<body> <h1>d.jsp</h1> <jsp:include page="/e.jsp"></jsp:include> </body> e.jsp <body> <% out.println("<h1>e.jsp</h1>"); %> </body> 执行时生成的.java文件:其实是把包含的那句脚本,转换成了_jspService()方法的include方法。

最终客户端访问能看到d.jsp和e.jsp两个JSP的内容:

其实jsp:include在JSP页面转换成的.java文件中就是一句方法调用,即调用另一个Servlet而已。

11.3 jsp:forward jsp:forward标签的作用是请求转发,它的作用与RequestDispatcher的forward()方法是相同的。 d.jsp

<body> <h1>d.jsp</h1> <jsp:forward page="/e.jsp"></jsp:forward> </body> e.jsp <body> <% out.println("<h1>e.jsp</h1>"); %> </body> 最终客户端访问只能看到e.jsp的内容,而看不到d.jsp的内容。<jsp:forward>的作用是“别在显示我,去显示它吧!”。

11.4 jsp:param 在Servlet中,我们可以往request域存储一些数据,然后转发或重定向到页面,页面是可以去除数据的。在这里jsp:param标签可以作为自标签在jsp:include和jsp:forward标签之间传递数据,它是用来传递参数的。下面用jsp:include来举例说明jsp:param的使用。 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html> <head> <title>a.jsp</title> </head>

<body> <h1>a.jsp</h1> <jsp:include page="/b.jsp"><!--相当于Servlet中调用RequestDispatcher.include()方法--> <jsp:param value="zhangsan" name="username"/><!--相当于request.setAttribute()--> </jsp:include> </body> </html> <%@ page language="java" pageEncoding="UTF-8" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>b.jsp</title> </head> <body> <h1>b.jsp</h1> <hr/> <% String username = request.getParameter("username"); out.print("你好:" + username); %> </body> </html> 最终客户端访问效果,在被包含的页面是可以取到:

  1. EL(表达式语言) 12.1 EL的概念 EL全名为Expression Language。是表达式,可以直接在jsp使用,不用引入标签库。 12.1.1 EL的作用 EL表达式语言是在JSP2.0版本中引入的新特性,它用于JSP文件中的数据访问。JSP2.0要把html和css分离,要把html和javascript分离,要把java脚本替换成标签。它可以简化JSP页面的代码,书写简洁。 我们知道在JSP中,表达式会被输出,所以EL表达式也会被输出,它相当于是<%=…….%>标签,也可以替代该标签。

12.1.2 EL的格式 格式:${…….} 例如:${ 1+2} 客户端访问在浏览器上会显示:3(其实这个EL表达式就相当于是<%= 1+2 %>)。

12.1.3 关闭EL 如果希望整个JSP忽略EL表达式,需要在page指令中指定isELIgnored=”true”。 如果希望忽略某个EL表达式,可以在EL表达式之前添加“\”,例如:${1 + 2}。

12.1.4 EL表达式可以进行逻辑运算 关系运算符 说明 范例 结果

  • 乘 ${17*5} 85 /或div 除 ${17/5}或${17 div 5} 3 %或mod 取余 ${17%5}或${17 mod 5} 2 ==或eq 等于 ${5==5}或${5 eq 5} true !=或ne 不等于 ${5!=5}或${5 ne 5} false <或lt 小于 ${3<5}或${3 lt 5} true

或gt 大于 ${3>5}或${3 gt 5} false <=或le 小于等于 ${3<=5}或${3 le 5} true =或ge 大于等于 ${3>=5}或${3 ge 5} false 逻辑运算符 说明 范例 结果 &&或and 并且 ${true&&false}或${true and false} false !或not 非 ${!true}或${not true} false ||或or 或者 ${true||false}或${true or false} true empty 是否为空 ${empty “”},可以判断字符串、数据、集合的长度是否为0,为0的返回true。empty还可以与not或!一起使用。${not empty “”} true

12.1.5 EL表达式中的保留关键字 and eq gt true or ne le false no lt ge null instanceof empty div mod

12.1.6 EL不显示null 当EL表达式的值为null时,会在页面上显示空白,即什么都不显示。

12.2 EL表达式格式  操作List和数组:${lisr[0]}、${arr[0]};  操作bean的属性:${person.name}、${person[‘name’]},对应person.getName()方法;  操作Map的值:${map.key}、${map[‘key’]},对应map.get(key)。 注意:把减号当成了运算符,也就是当key中有非法标识符时,必须使用下标法。

12.3 EL中的11个隐式对象 EL一共有11个隐式对象,无需创建即可使用。这11个对象中有10个是Map类型的,最后一个是pageContext对象。 隐含对象名称 描 述 pageScope 代表page域中用于保存属性的Map对象 requestScope 代表request域中用于保存属性的Map对象 sessionScope 代表session域中用于保存属性的Map对象 applicationScope 代表application域中用于保存属性的Map对象 param 表示一个保存了所有请求参数的Map对象 paramValues 表示一个保存了所有请求参数的Map对象,它对于某个请求参数,返回的是一个string[] header 表示一个保存了所有http请求头字段的Map对象 headerValues 同上,返回string[]数组。注意:如果头里面有“-” ,例Accept-Encoding,则要headerValues[“Accept-Encoding”] cookie 表示一个保存了所有cookie的Map对象 initParam 表示一个保存了所有web应用初始化参数的Map对象 pageContext 对应于JSP页面中的pageContext对象

12.3.1 域相关内置对象(重点) 域内置对象一共有四个:  pageScope:${pageScope.name}等同与pageContext.getAttribute(“name”);  requestScope:${requestScope.name}等同与request.getAttribute(“name”);  sessionScoep: ${sessionScope.name}等同与session.getAttribute(“name”);  applicationScope:${applicationScope.name}等同与application.getAttribute(“name”); 如果在域中保存的是javaBean对象,那么可以使用EL来访问javaBean属性。因为EL只能做读取操作,所以javaBean一定要提供get方法,而set方法没有要求。EL表达式写的属性名字是什么,应该由javaBean中get方法的名字决定。 Person.java Address.java public class Person { private String name; private int age; private String sex; private Address addr; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } public Address getAddr() { return addr; } public void setAddr(Address addr) { this.addr = addr; } } public class Address { private String country; private String city;

public String getCountry() {
	return country;
}
public void setCountry(String country) {
	this.country = country;
}
public String getCity() {
	return city;
}
public void setCity(String city) {
	this.city = city;
}
@Override
public String toString() {
	return "Address [country=" + country + ", city=" + city + "]";
}

} public Address(String country, String city) { super(); this.country = country; this.city = city; }

a.jsp 在JSP页面导入javaBean包; <%@ page import="cn.itcast.domain.*" %>

<body> <% Person p = new Person(); p.setName("zhangsan"); p.setAge(20); p.setSex("male"); Address address = new Address("中国","北京"); p.setAddr(address); //操作javaBean request.setAttribute("person", p); //操作数组 request.setAttribute("arr", new String[]{"one","two"}); //操作map Map<String,String> map = new HashMap<String,String>(); map.put("a","AAA");

	Map<String,Map<String,String>> mapMap = new HashMap<String,Map<String,String>>();
	mapMap.put("map", map);

	pageContext.setAttribute("mapMap", mapMap);
%>
	<h3>1.操作Map的两种方式: 1.map.key 2.map['key']</h3>
	${requestScope.person}<br/>
	${requestScope["person"]}<br/>
    
	<h3>2.操作JavaBean: bean.属性名,等同于调用get方法</h3>
	${requestScope.person.name}
	<%--相当于是:((Person)request.getAttribute(“person”)).getName(); --%>
	${requestScope['person'].name}

    <h3>3.操作数组:数组.数组角标</h3>
    ${requestScope.arr[0]}

    <h3>4.操作Map的两种方式:1.map.key 2.map['key']</h3>
	${pageScope.mapMap.map.a }<br/>
	${pageScope['mapMap']['map']['a']}<br/>

    <h3>5.如果想要得到“北京”,该如何取值呢?两种方式:</h3>
	${requestScope.person.addr.city }<br/>
	${requestScope['person']['addr']['city'] }<br/>

</body> 浏览器的显示效果:

全域查找:${person}表示依次在pageScope、requesScopet、sessionScope、appliationScope四个域中查找名字为person的属性。 案例一:

<body> <% request.setAttribute("aaa","AAA"); %> ${aaa } </body>

案例二:

<body> <% request.setAttribute("aaa","AAA"); pageContext.setAttribute("aaa","BBB"); %> ${aaa } </body>

12.3.2 请求参数相关内置对象 param和paramValues这两个内置对象是用于获取请求参数的。  param:是Map<String,String>类型,param对象可以用来获取参数,与request.getParameter()方法相同。 b.jsp

<body> ${param.username }<br/> ${param.password }<br/> <% String username = request.getParameter("username"); String password = request.getParameter("password"); out.print("用户名:" + username + ','+"密码:"+password); %><br/> </body>

注意:在使用EL表达式获取参数时,如果参数不存在,返回的是空字符串,而不是null。而在使用request.getParameter()方法时,会显示null。如下图案例:

 paramValues:是Map<String,String []>类型,当一个参数对应多个数值时可以使用paramValues。 b.jsp

<body> ${paramValues.username[0] }、${paramValues.username[1]} </body>

12.3.3 请求头相关内置对象  header:Map<String,String>类型,用来获取请求头。 b.jsp

<body> ${header.Host } </body>

举例说明: 比如要获取User-Agent的值,如下图:

b.jsp

<body> ${header.User-Agent } </body> 浏览器访问结果是显示0。 所以换成另外一种方式下标法:Map[‘key’]; b.jsp <body> ${header['User-Agent'] } </body>

把减号当成了运算符,也就是当key中有非法标识符时,必须使用下标法。  headerValues:headerValues是Map<String,String[]>类型。当一个请求头名称,对应多个值时,使用该对象,这种情况一般不多见,这里就不赘述了。

12.3.4 应用初始化参数相关内置对象 initParam:initParam是Map<String,String>类型。它对应web.xml文件中的<context-param>参数。 web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <display-name></display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <context-param> <param-name>a</param-name> <param-value>A</param-value> </context-param> <context-param> <param-name>b</param-name> <param-value>B</param-value> </context-param> </web-app> b.jsp

<body> \${initParam.a}: ${initParam.a }<br/> \${initParam['b']}: ${initParam['b'] } </body> 客户端访问显示结果:

12.3.5 Cookie相关内置对象 cookie:cookie是Map<String,Cookie>类型,其中key是Cookie的名字,而值是Cookie对象本身。要想获取名为username的Cookie的值,使用${cookie.username.value},后面的.value相当于cookie.getValue()方法。如果想要获取cookie的名字,使用${cookie.JSESSIONID.name},(这个jsessionid是session的一个标识。)相当于使用了getName()方法。 b.jsp

<body> ${cookie.JSESSIONID.name }:${cookie.JSESSIONID.value } </body> 客户端访问效果如图:

12.3.6 pageContext相关内置对象 pageContext:pageContext是pageContext类型。9大内置对象可以通过pageContext对象的一系列的get方法来获取。例如:pageContext.getRequest(),也可以${pageContext.request}。 EL表达式 说明 ${pageContext.request.queryString} pageContext.getRequest().getQueryString(); ${pageContext.request.requestURL} pageContext.getRequest().getRequestURL(); ${pageContext.request.contextPath} pageContext.getRequest().getContextPath(); ${pageContext.request.method} pageContext.getRequest().getMethod(); ${pageContext.request.protocol} pageContext.getRequest().getProtocol(); ${pageContext.request.remoteUser} pageContext.getRequest().getRemoteUser(); ${pageContext.request.remoteAddr} pageContext.getRequest().getRemoteAddr(); ${pageContext.session.new} pageContext.getSession().isNew(); ${pageContext.session.id} pageContext.getSession().getId(); ${pageContext.servletContext.serverInfo} pageContext.getServletContext().getServerInfo(); 客户端路径不准再直接打名称,可以用EL表达式,${pageContext.request.contextPath},获取项目路径:/day06_1。 例如: b.jsp

<body> ${pageContext.request.contextPath } <a href="${pageContext.request.contextPath }/a.jsp">跳转页面</a> </body> 客户端访问b.jsp:

鼠标放在客户端超链接XXX上:(浏览器状态栏会显示a.jsp真实内的路径)

点击客户端超链接XXX:(页面跳转到了a.jsp页面)

  1. EL函数库 13.1 什么是EL函数 EL函数库是由第三方对EL的扩展,我们接下来要学习的EL函数库在JSTL开发中进行描述,因此在JSP页面中使用SUN公司的EL函数库,需要导入JSTL开发包,并在页面中导入EL函数库。 EL函数库就是定义一些有返回值的静态方法。然后通过EL语言来调用它们!当然,不只是JSTL可以定义EL函数库,我们也可以自定义EL函数库。 EL函数库中包含了很多对字符串的操作方法,以及对集合对象的操作。例如:${fn:length(“abc”)}会输出3,即字符串的长度。

13.2 导入函数库 导入需要使用taglib指令!如下所示: <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> prefix是名称,值可以任意取,但是人们一般习惯用fn。

13.3 EL函数库介绍  String toUpperCase(String input):  String toLowerCase(String input):  int indexOf(String input, String substring):  boolean contains(String input, String substring):  boolean containsIgnoreCase(String input, String substring):  boolean startsWith(String input, String substring):  boolean endsWith(String input, String substring):  String substring(String input, int beginIndex, int endIndex):  String substringAfter(String input, String substring):  substringBefore(String input, String substring):  String escapeXml(String input):”、’、<、>、&  String trim(String input):  String replace(String input, String substringBefore, String substringAfter):  String[] split(String input, String delimiters):  int length(Object obj):  String join(String array[], String separator):

页面的使用格式:${前缀名称:函数名(参数) }; 例如: 例1: <% request.setAttribute(“xxx”,”AAA”); %> ${fn:toLowerCase(xxx) }<br/> <!—被转换为小写字母aaa  例2: <% request.setAttribute(“xxx”,”AAA”); %> ${fn:toLowerCase(xxx) eq "aaa"}<br/><!-- 显示结果为true --> ${fn:toLowerCase(xxx) eq "xxx"}<br/><!-- 显示结果为false --> 例3: <% request.setAttribute(“xxx”,”AAA”); %> ${fn:toLowerCase(xxx) eq "aaa" or fn:toUpperCase("xxx") eq "xxx"}<br/> <!-- 显示结果为true --> 例4: <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> … <% String[] strs = {"a", "b","c"}; List list = new ArrayList(); list.add("a"); pageContext.setAttribute("arr", strs); pageContext.setAttribute("list", list); %> ${fn:length(arr) }<br/><!-- 3,数组长度--> ${fn:length(list) }<br/><!-- 1,集合的长度--> ${fn:toLowerCase("Hello") }<br/> <!-- hello,全部转换为小写 --> ${fn:toUpperCase("Hello") }<br/> <!-- HELLO, 全部转换为大写 --> ${fn:contains("abc", "a")}<br/><!—- true,是否包含 --> ${fn:containsIgnoreCase("abc", "Ab")}<br/><!—- true,忽略大小写的是否被包含 --> ${fn:contains(arr, "a")}<br/><!—- true,数组中是否包含 --> ${fn:containsIgnoreCase(list, "A")}<br/><!—- true,集合中忽略大小写的是否被包含 --> ${fn:endsWith("Hello.java", ".java")}<br/><!-— true,是否以“小串”结尾 --> ${fn:startsWith("Hello.java", "Hell")}<br/><!-- true, 是否以“小串”开头--> ${fn:indexOf("Hello-World", "-")}<br/><!-- 5 --> ${fn:join(arr, ";")}<br/><!-- a;b;c --> ${fn:replace("Hello-World", "-", "+")}<br/><!-- Hello+World --> ${fn:join(fn:split("a;b;c;", ";"), "-")}<br/><!-- a-b-c -->

${fn:substring("0123456789", 6, 9)}<br/> <!—- 678,截取字符串,第二个参数为开始位置,第三个参数为结束位置 --> ${fn:substring("0123456789", 5, -1)}<br/> <!—- 56789,第三个参数为负数,截取的是到最后内容 --> ${fn:substringAfter("Hello-World", "-")}<br/> <!-— World,以第二个参数的位置开始截取之后的内容 --> ${fn:substringBefore("Hello-World", "-")}<br/> <!—- Hello,从第二个参数的位置开始,截取前面的内容 --> ${fn:trim(" a b c ")}<br/><!-- a b c, --> ${fn:escapeXml("<html></html>")}<br/> <!-- <html></html> --> 进行到视频17分钟;

转载于:https://my.oschina.net/robertmc/blog/760639

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值