过几天要回家去笔试了,真紧张,这几天不知道是复习java ee还是好好在牛客网上刷一下面试题。还是要赶紧做出打算了。
day08主要讲了jsp的应用,jsp全称为java server page,也是一种开发动态web资源的工具,从某种角度来说它也是servlet,但是这种技术主要用来展示数据,操作数据还是得用servlet。
一.入门
视频课上写了一个显示当前日期时间的jsp页面作为入门程序。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP '1.jsp' starting page</title>
</head>
<body>
<%
Date date = new Date();
out.write(date.toLocaleString());
%>
</body>
</html>
上方代码表现了jsp中内嵌java代码的格式,即<%%>中添加代码,细心的朋友可能发现不像在servlet中那样,需要response去获取writer,在jsp中直接调用了,这个问题我们等等再解答。
二.jsp脚本片段与脚本表达式
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<%
int i=1;
%>
<%=i%>
<!-- JSP引擎在翻译脚本表达式时,会将程序数据转成字符串,然后在相应位置用out.print(…) 将数据输给客户端 -->
<br/><br/><br/>
<%
for(int j=0;j<5;j++){
%>
<%=j %>
<%} %>
<%-- jsp内必须为完整java代码 --%>
</body>
</html>
注意以下几点:
1.JSP脚本片段中只能有java代码,不能出现其他模板元素
2.一个JSP中可以有多个脚本片段,多个脚本片段的代码可以互相访问
3.单个脚本片段中的代码可以是不完整的,但是所有脚本块组合起来必须>是完整的
4. JSP页面中编写的所有代码,默认会翻译到servlet的service方法中, 而Jsp声明中的java代码被翻译到_jspService方法的外面。语法:
<%!
java代码
%>
5.JSP中有两种注释,第一种是html中的注释<!--注释内容-->,第二种是JSP的注释<%--注释内容--%>,前者会被翻译到servlet中去,后者直接被无视。
三.JSP指令
JSP指令是为JSP引擎而设计的,它们并不直接产生任何可见输出,而只是告诉引擎如何处理JSP页面中的其余部分。
JSP指令的基本语法格式:
<%@ 指令 属性名="值" %>
举例:<%@ page contentType="text/html;charset=gb2312"%>
JSP有三大指令page,include,taglib.
1.page
page指令用于定义JSP页面的各种属性,无论page指令出现在JSP页面中的什么地方,它作用的都是整个JSP页面,为了保持程序的可读性和遵循良好的编程习惯,page指令最好是放在整个JSP页面的起始位置。
其中黑体是比较重要的。
例1:通过errorPage与isErrorPage来弹出友好错误界面
1.比如出现运行时错误
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" session="false" errorPage="/errors.jsp"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<%
int x = 1 / 0;
%>
</body>
</html>
在page指令中写这个 errorPage="/errors.jsp,即可在发生错误时,转到错误界面。
2.如果出现某种特定错误,可在web.xml中设置(这里以算数错误为例)
<error-page>
<exception-type>java.lang.ArithmeticException</exception-type>
<location>/errors.jsp</location>
</error-page>
在errors.jsp的page中要声明isErrorPage="true"
如果是应对错误码应该这样设置:
<error-page>
<error-code>404</error-code>
<location>/errors/404.jsp</location>
</error-page>
解决中文乱码问题:
设置:
pageEncoding="UTF-8"或
contentType="text/html; charset=UTF-8"
2.include
include指令用于引入其它JSP页面,如果使用include指令引入了其它JSP页面,那么JSP引擎将把这两个JSP翻译成一个servlet。所以include指令引入通常也称之为静态引入。
语法:
<%@ include file="relativeURL"%>
细节:
被引入的文件必须遵循JSP语法。
被引入的文件可以使用任意的扩展名,即使其扩展名是html,JSP引擎也会按照处理jsp页面的方式处理它里面的内容,为了见明知意,JSP规范建议使用.jspf(JSP fragments)作为静态引入文件的扩展名。
由于使用include指令将会涉及到2个JSP页面,并会把2个JSP翻译成一个servlet,所以这2个JSP页面的指令不能冲突(除了pageEncoding和导包除外)。
例:
<body>
<%@include file="/public/head.jsp" %>
<br>当前页面内容. <br>
<%@include file="/public/foot.jsp" %>
3.taglib
过几天更新自定义标签的时候补上。
四.JSP九大隐式对象
分别为response,request,application,config,session,page,exception,out,pageContext
其中,out和pageContext比较特殊。
1.out
out隐式对象用于向客户端发送文本数据。
out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。
JSP页面中的out隐式对象的类型为JspWriter,JspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。
只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象
将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:
设置page指令的buffer属性关闭了out对象的缓存功能
out对象的缓冲区已满
整个JSP页面结束
当同时使用response.getWriter()和out时,out所输出的在前面。原因如图:
使用jsp进行下载
<%@page import="java.io.OutputStream"%><%@page import="java.io.FileInputStream"%><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%
String path = application.getRealPath("/1.jpg");
String fileName = path.substring(path.lastIndexOf("\\")+1);
response.setHeader("content-disposition", "attachment;filename="+fileName);
FileInputStream in = new FileInputStream(path);
int len = 0;
byte buffer[] = new byte[1024];
OutputStream sout = response.getOutputStream();
while((len=in.read(buffer))>0){
sout.write(buffer, 0, len);
}
在这里有一个问题,java.lang.IllegalStateException: getOutputStream() has already been called for this response这个错误会在out隐式对象生成时发生,如果想不生成out隐式对象,可以把空格全部删掉。
2.pageContext
pageContext对象是JSP技术中最重要的一个对象,它代表JSP页面的运行环境,这个对象不仅封装了对其它8大隐式对象的引用,它自身还是一个域对象,可以用来保存数据。并且,这个对象还封装了web开发中经常涉及到的一些常用操作,例如引入和跳转其它资源、检索其它域对象中的属性等。
(1)getException方法返回exception隐式对象
(2)getPage方法返回page隐式对象
(3)getRequest方法返回request隐式对象
(4)getResponse方法返回response隐式对象
(5)getServletConfig方法返回config隐式对象
(6)getServletContext方法返回application隐式对象
(7)getSession方法返回session隐式对象
(8)getOut方法返回out隐式对象
例:在其他域设置属性,取属性
<body>
<%
pageContext.setAttribute("data","xxx2",PageContext.SESSION_SCOPE);
//String data = (String)session.getAttribute("data");
//String data = (String)pageContext.getAttribute("data",PageContext.SESSION_SCOPE);
String data = (String)pageContext.findAttribute("data"); //pageContext request session servletContext
%>
<%=data %>
</body>
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
跳转到其他界面:
pageContext.forward(url)
五.标签
JSP标签也称之为Jsp Action(JSP动作)元素,它用于在Jsp页面中提供业务逻辑功能,避免在JSP页面中直接编写java代码,造成jsp页面难以维护。
<jsp:include>标签用于把另外一个资源的输出内容插入进当前JSP页面的输出内容之中,这种在JSP页面执行时的引入方式称之为动态引入。
语法:
<jsp:include page="relativeURL | <%=expression%>" flush="true|false" />
page属性用于指定被引入资源的相对路径,它也可以通过执行一个表达式来获得。
flush属性指定在插入其他资源的输出内容时,是否先将当前JSP页面的已输出的内容刷新到客户端。
<jsp:include>与include指令的比较
<jsp:include>标签是动态引入, <jsp:include>标签涉及到的2个JSP页面会被翻译成2个servlet,这2个servlet的内容在执行时进行合并。
而include指令是静态引入,涉及到的2个JSP页面会被翻译成一个servlet,其内容是在源文件级别进行合并。
不管是<jsp:include>标签,还是include指令,它们都会把两个JSP页面内容合并输出,所以这两个页面不要出现重复的HTML全局架构标签,否则输出给客户端的内容将会是一个格式混乱的HTML文档。
<jsp:forward>标签用于把请求转发给另外一个资源。
语法:
<jsp:forward page="relativeURL | <%=expression%>" />
page属性用于指定请求转发到的资源的相对路径,它也可以通过执行一个表达式来获得。
当使用<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>标签来传递多个参数。
例
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>My JSP '7.jsp' starting page</title>
</head>
<body>
<jsp:include page="/public/head.jsp"/>
<br/> 这是页面内容 <br/>
<jsp:include page="/public/foot.jsp"/>
<%
String url = "/public/head.jsp";
%>
<jsp:include page="<%=url %>"/>
<jsp:forward page="/1.jsp">
<jsp:param name="xxx" value="yyyy"/>
</jsp:forward>
</body>
</html>
六.几种域的差别
1、request:如果客户向服务器发请求,产生的数据,用户看完就没用了,像这样的数据就存在request域,像新闻数据,属于用户看完就没用的
2、session:如果客户向服务器发请求,产生的数据,用户用完了等一会儿还有用,像这样的数据就存在session域中,像购物数据,用户需要看到自己购物信息,并且等一会儿,还要用这个购物数据结帐
3、servletContext:如果客户向服务器发请求,产生的数据,用户用完了,还要给其它用户用,像这样的数据就存在servletContext域中,像聊天数据