JSP

当客户端访问jsp页面的时候,服务器会先把jsp翻译成一个servlet,翻译成的servlet位于tomcat根目录下的work文件夹下 。可以查看源码看看。

jsp是HTTPServlet的孙子。

 

JSP模板更改

找到myeclipse的安装目录,搜索servlet,然后在查看servlet的具体路径

在该路径下有个jsp文件夹,修改里面的jsp.vt1

同时要把pageEncoding改为UTF-8

 

JSP指令:是为JSP引擎使用的,也就是给tomcat服务器使用的,是告诉服务器如何将jsp翻译成servlet,他们并直接的产生任何的可见输出,

JSP2.0规范中定义了三个指令:

  1.page指令

  2.include指令

  3.taglib指令

 

JSP指令的基本语法格式:
  <%@ 指令 属性名="值" %>
例如:<%@ page contentType="text/html;charset=gb2312"%>

如果一个指令有多个属性,这多个属性可以写在一个指令中,也可以分开写。
  例如:
  <%@ page contentType="text/html;charset=gb2312"%>
  <%@ page import="java.util.Date"%>
  也可以写作:
  <%@ page contentType="text/html;charset=gb2312" import="java.util.Date"%>

详情请参看jsp指令的完整语法。

jsp指令中可以把session设为false,这样jsp翻译成的servlet中就没有session对象了,在该jsp页面中就不能再使用session了。

因为session的声明周期相对较长,所以让开发者可以关闭session。

 

jsp解决中文乱码:jsp 中page指令的pageEncoding=“UTF-8”

 

include指令:主要用来做包含

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

其中的file属性用于指定被引入文件的路径。路径以“/”开头,表示代表当前web应用。(/ 是给服务器用的,所以代表当前web应用)

 

include指令细节:
  1. 被引入的文件必须遵循JSP语法。
  2. 被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。
  3. 由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。

 

静态包含。

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>include指令(静态包含(编译时包含),它包含的所有jsp会编译成一个servlet)</title>
  </head>
  
  <body>
    
    <%@include file="/public/head.jsp" %>
    
    aaaaaaaaaaaaaaaa<br/>
    
    <%@include file="/public/foot.jsp" %>
    
    
  </body>
</html>

 

动态包含:服务器会把这三个jsp翻译成三个servlet,执行的时候再包含进来

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>动态包含(这种情况是运行时包含)</title>
  </head>
  
  <body>
    
    <% 
        request.getRequestDispatcher("/public/head.jsp").include(request,response);
    %>
    
    <% 
        response.getWriter().write("aaaaaaaaaaaaa<br/>");
    
    %>
    
      <% 
        request.getRequestDispatcher("/public/foot.jsp").include(request,response);
    %>
    
  </body>
</html>

 

开发中推荐使用静态包含。

 

 

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

Response

Session

application ----servletContext

config ----servletConfig

Page ----this

Exception

Out jspWriter:相对于一个带缓冲功能的printWriter

pageContext

 

out隐式对象:

  1. out隐式对象用于向客户端发送文本数据。
  2. out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
  3. JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
  a. 设置page指令的buffer属性关闭了out对象的缓存功能
  b. out对象的缓冲区已满
  c. 整个JSP页面结束

 

 

同时使用out和response.getwriter()输出数据的问题:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>out隐式对象注意的问题</title>
  </head>
  
  <body><% 
        out.write("hahhahahahah");
        response.getWriter().write("wowowowo");
    %>
    
  </body>
</html>

程序会先输出wowowow,在输出hahahahah,因为out隐式对象有缓冲功能。

 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>out隐式对象注意的问题</title>
  </head>
  
  <body>
    aaaaaaaaaaa   ----这个会调用隐式对象out输出
    <% 
        response.getWriter().write("wowowowo");
    %>
    
  </body>
</html>

输出的结果还是先输出wowowow,在输出aaaaaa

 

所以在jsp中建议只使用隐式对象输出,最好不要两个混用。

 

用JSP实现文件下载:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@page import="java.io.FileInputStream"%><% 
        String path = application.getRealPath("/download/1.jpg");  //c:\\
        String filename = path.substring(path.lastIndexOf("\\")+1);
        response.setHeader("content-disposition","attachment;filename=" + filename);
        
        FileInputStream in = new FileInputStream(path);
        byte buffer[] = new byte[1024];
        int len = 0;
        while((len=in.read(buffer))>0){
            response.getOutputStream().write(buffer,0,len);
        }
        in.close();
    %>

注意:一定要保证jsp中不能有其他的代码,包括空格,因为jsp页面中的文本数据在翻译成的servlet会用out输出,out是一个字符流,getOutputStream是字节流,输出图片只能用字节流,在一个servlet中不允许同时用字节流和字符流输出,会抛异常。

 

pageContext对象 

pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境

  1. 这个对象不仅封装了对其它8大隐式对象的引用。

  2. 它自身还是一个域对象,可以用来保存数据。

  3. 并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。

 

通过pageContext获得其他对象 

JSP

pageContext获取八大隐式对象的方法一般用在自定义标签中,在jsp中可以直接获取八大隐式对象,不需要通过pageContext来获取。

自定义标签用来移除jsp中的java代码的。把pageContext传递过去,就可以在java类中获取八大隐式对象,这就是为什么pageContext中封装八大隐式对象的意义。

 

pageContext作为域对象 :

 JSP

pageContext封装了访问其他域的方法,可以指定往哪个域中存数据,

<% 
   pageContext.setAttribute("data","abc",PageContext.SESSION_SCOPE);
%>
      
<%=pageContext.getAttribute("data",PageContext.SESSION_SCOPE) %>

 

<% 
   pageContext.findAttribute("data");    //page  request  session application   范围由小变大
%>

 

findAttribute("data"); 会先从page域中找,再从request域中找,还是找不到,会从session域中找,还找不到就从application域中找。
${data}  作用就是依次从四个域中找数据data,功能等效下面一句java代码。
<% pageContext.findAttribute("data");
%>

 

引入和跳转到其他资源 :

  PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和include方法。

  方法接收的资源如果以“/”开头, “/”代表当前web应用。

 

<% 
    request.getRequestDispatcher("/index.jsp").forward(request,response);
    pageContext.forward("/index.jsp");    这两个等效
          
    pageContext.include("/public/head.jsp");动态包含

%>

 

 

JSP标签:避免在jsp中出现java代码

  <jsp:include>标签
  <jsp:forward>标签
  <jsp:param>标签

 

映射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>

 

这时可以使用/jsp/simple.jsp访问,也可以使用/xxx/yyy.html访问,是一样的。

 

四个域对象:

  pageContext(称之为page域) 页面范围
  request(称之为request域)请求范围
  session(称之为session域)会话范围
  servletContext(称之为application域)应用程序范围,只要web程序不停,都有效