JavaWeb -- Jsp

1. Jsp原理

work/Catalina/localhost/WebTest4/org/apache/jsp# 看到源码, JSp就是Servlet

    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;

不管是JSP还是Servlet,虽然都可以用于开发动态web资源。但由于这2门技术各自的特点,在长期的软件实践中,人们逐渐把servlet作为web应用中的控制器组件来使用,而把JSP技术作为数据显示模板来使用。

其原因为,程序的数据通常要美化后再输出:
jsp既用java代码产生动态数据,又做美化会导致页面难以维护。
servlet既产生数据,又在里面嵌套html代码美化数据,同样也会导致程序可读性差,难以维护。
因此最好的办法就是根据这两门技术的特点,让它们各自负责各的,servlet只负责响应请求产生数据,并把数据通过转发技术带给jsp,数据的显示jsp来做。

2. Jsp 语法 

JSP模版元素

JSP页面中的HTML内容称之为JSP模版元素。
JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。
JSP脚本表达式
JSP脚本表达式(expression)用于将程序数据输出到客户端

  语法:<%= 变量或表达式%>

  举例:当前时间:<%= new java.util.Date() %>

JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.print(…)将数据输给客户端。
JSP脚本表达式中的变量或表达式后面不能有分号(;
JSP脚本片断
lJSP脚本片断(scriptlet)用于在JSP页面中编写多行Java代码。语法:

<%

  多行java代码

%>

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

  举例:

<%

  int x = 10;

  out.println(x);

%>

<p>这是JSP页面文本</p>

<%

  int y = 20;

  out.println(y);

  %>

多个脚本片断中的代码可以相互访问,犹如将所有的代码放在一对<%%>之中的情况。如:out.println(x);
单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,例如:

<%

  for (int i=1; i<5; i++)

  {

%>

  <H1>www.it315.org</H1>

<%

  }

%>

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

<%

  java代码

%>

所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法
多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。
JSP隐式对象的作用范围仅限于Servlet_jspService方法,所以在JSP声明中不能使用这些隐式对象
JSP注释
JSP注释的格式:

    <%--注释信息--%>

JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容。
JSP指令简介
lJSP指令的基本语法格式:

  <%@ 指令 属性名="" %>

  举例:<%@ page contentType="text/html;charset=gb2312"%>

l如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。

  例如:

  <%@ page contentType="text/html;charset=gb2312"%>

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

  也可以写作:

  <%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%>

page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
lJSP 2.0规范中定义的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"  //指定错误处理页面, 必须为相对路径“/”代表当前Web应用

  [ isErrorPage="true | false" ]   //翻译为Servlet的时候 会传递异常对象

  [ contentType="mimeType [ ;charset=characterSet ]" | "text/html ; charset=ISO-8859-1" ]  //翻译到的Servlet 控制浏览器以什么码表来显示

  [ pageEncoding="characterSet | ISO-8859-1" ]   //通知服务器以什么码表来翻译Jsp

  [ isELIgnored="true | false" ]

%>

errorPage属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前页面。
可以在web.xml文件中使用<error-page>元素为整个WEB应用程序设置错误处理页面,其中的<exception-type>子元素指定异常类的完全限定名<location>元素指定以“/”开头的错误处理页面的路径。
如果设置了某个JSP页面的errorPage属性,那么在web.xml文件中设置的错误处理将不对该页面起作用。
  <error-page>
  	<exception-type>java.lang.NullPointerException</exception-type>  //可以配置异常统一处理
  	<location>/errors/error_null.jsp</location>  	
  </error-page>
  
  <error-page>
  	<error-code>404</error-code>      //可以配置错误代码统一处理
  	<location>/errors/error_404.jsp</location>
  </error-page>


include指令

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

  <%@ include file="relativeURL"%>

  其中的file属性用于指定被引入文件的相对路径。 file属性的设置值必须使用相对路径,如果以“/”开头,表示相对于当前WEB应用程序的根目录(注意不是站点根目录),否则,表示相对于当前文件。

细节:
被引入的文件必须遵循JSP语法。
被引入的文件可以使用任意的扩展名,即使其扩展名是htmlJSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspfJSP fragments)作为静态引入文件的扩展名。
由于使用include指令将会涉及到2JSP页面,并会把2JSP翻译成一个servlet(静态包含)所以这2JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
<body>
<font size="8">
	<%
		String str = "";
		out.write(str);
	%>	  
	<%@include file="/public/head.jsp" %>
		中间内容!! <br/>    //head.jsp foot.jsp 编译时也会合成一个,所以里面不需要其他标签,直接写内容即可!! 
	<%@include file="/public/foot.jsp" %>
</font>
</body>

静态包含和动态包含的区别:

静态包含用: <%@include file="/public/head.jsp" %> 编译时包含,全被编译为一个Servlet文件

动态包含用: 转发 request.getRequestDispatcher("/public/head.jsp").include(request, response)运行时包含,每个Jsp都会有单独的Servlet,性能较差。


3. JSP运行原理和九大隐式对象

 每个JSP 页面在第一次被访问时,WEB容器都会把请求交给JSP引擎(即一个Java程序)去处理。JSP引擎先将JSP翻译成一个_jspServlet(实质上也是一个servlet),然后按照servlet的调用方式进行调用。

由于JSP第一次访问时会翻译成servlet,所以第一次访问通常会比较慢,但第二次访问,JSP引擎如果发现JSP没有变化,就不再翻译,而是直接调用,所以程序的执行效率不会受到影响。

JSP引擎在调用JSP对应的_jspServlet时,会传递或创建9个与web开发相关的对象供_jspServlet使用。JSP技术的设计者为便于开发人员在编写JSP页面时获得这些web对象的引用,特意定义了9个相应的变量,开发人员在JSP页面中通过这些变量就可以快速获得这9大对象的引用。

-----------------------------------------------------------------

request HttpServletRequest
response HttpServletResponse
session HttpSession
application servletContext
config   servletConfig
out      JspWriter  ----->  PrintWriter
exception
page    this
pageContext
-----------------------------------------------------------------
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out隐式对象的类型为JspWriterJspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
(1)设置page指令的buffer属性关闭了out对象的缓存功能
(2)out对象的缓冲区已满
(3)整个JSP页面结束
 
pageContext对象JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
getException方法返回exception隐式对象
getPage方法返回page隐式对象
getRequest方法返回request隐式对象
getResponse方法返回response隐式对象
getServletConfig方法返回config隐式对象
getServletContext方法返回application隐式对象
getSession方法返回session隐式对象
getOut方法返回out隐式对象
pageContext对象的方法
public void setAttribute(java.lang.String name,java.lang.Object value)
public java.lang.Object getAttribute(java.lang.String name)
public void removeAttribute(java.lang.String name)
pageContext对象中还封装了访问其它域的方法
public java.lang.Object getAttribute(java.lang.String name,int scope)
public void setAttribute(java.lang.String name, java.lang.Object value,int scope)
public void removeAttribute(java.lang.String name,int scope)
代表各个域的常量
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
findAttribute方法   *重点,查找各个域中的属性page->request->session->application
PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和include方法

传递给这些方法的资源路径都只能是相对路径,如果路径以“/”开头,表示相对于当前WEB应用程序的根目录,否则,表示相对于当前JSP所映射到的访问路径

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

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

page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。 
 
<jsp:forward>标签用于把请求转发给另外一个资源。
语法:

  <jsp:forward page="relativeURL | <%=expression%>" />

page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得
设置首页的时候 web.xml 不能设置Servlet,只能先设置成一个Jsp,然后在用这个标签跳转到一个Servlet.
 
<jsp:param>标签:当使用<jsp:include><jsp:forward>标签引入或将请求转发给其它资源时,可以使用<jsp:param>标签向这个资源传递参数
语法1

  <jsp:include page="relativeURL | <%=expression%>">

  <jsp:param name="parameterName" value="parameterValue|<%= expression %>" />

  </jsp:include>

语法2

  <jsp:forward page="relativeURL | <%=expression%>">

  <jsp:param name="parameterName" value="parameterValue|<%= expression %>" />

  </jsp:include>

<jsp:param>标签的name属性用于指定参数名,value属性用于指定参数值。在<jsp:include><jsp:forward>标签中可以使用多个<jsp:param>标签来传递多个参数。
转发到的Servlet可以通过String data = request.getParameter("data"); 获得传入的参数值。
 
映射JSP

<servlet>

  <servlet-name>SimpleJspServlet</servlet-name>

  <jsp-file>/jsp/simple.jsp</jsp-file>

  <load-on-startup>1</load-on-startup >

</servlet>

<servlet-mapping>

  <servlet-name>SimpleJspServlet</servlet-name>

  <url-pattern>/xxx/yyy.html</url-pattern>

</servlet-mapping>

 
原文地址:https://www.cnblogs.com/xj626852095/p/3648068.html