JspServlet
JSP简介
JSP页面的构成元素
JSP的生命周期
JSP的内置对象
JSP表达式语言(EL)
JSP标准标签库(JSTL)
JSP简介
1.使用Servlet产生动态页面,需要在代码中打印出很多HTML的标签,在Servlet将静态显示的内容和动态内容代码混合在一起。
2.使用Servlet开发动态网页,程序员与美工人员无法一起工作,因为美工不了解Java语言,无法修改Servlet代码。
为了解决这些问题,SUN公司推出了JSP技术。
JSP的基本原理:
JSP的本质依然是Servlet(一个特殊的Java类),当用户向Servlet发送请求时,Servlet利用输出流动态生成HTML页面,包括每一个静态的HTML标签和所有在HTML页面中出现的内容。也就是说,JSP其实是Servlet的一种简化,使用JSP时,其实还是使用Servlet,因为在Web应用中,每个JSP页面都会由Servlet容器生成对应的Servlet。JSP必须在Web应用中才有效。
JSP仅作为表现层技术,其作用有2点:
1.收集用户的请求参数。
2.将应用程序的处理结果呈现给用户。
JSP是一种建立在Servlet规范提供的功能之上的动态网页技术,在网页文件中通过JSP页面元素嵌入Java代码。
JSP页面的构成元素
1.静态内容:HTML静态文本。
2.指令:
指令主要用于转换阶段提供整个JSP页面的相关信息,指令不会产生任何的输出到当前的输出流中。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
page指令用于设置JSP页面的属性。
<%@ include file="/WEB-INF/jsp/res.jsp"%>
include指令用于在JSP页面中静态包含一个文件,该文件可以是JSP页面,HTML页面,文本文件。使用了include指令的JSP页面在转换时,JSP容器会在其中插入所包含文件的文本或代码。
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
taglib指令可以让JSP页面使用标签。
3.声明:<%!%> 类、方法和全局变量。
4.脚本段:<% int a = 30; out.println(a);%> Java代码。
4.表达式:<%=Math.PI%> 表达式用于求值,然后其值转化为字符串,插入到当前流中。
6.动作:嵌入到JSP页面中的一个标签。在页面被转换为Servlet期间,当JSP容器遇到这个标签,就用预先定义的对应该标签的Java代码来替代它。
<jsp:useBean>寻找或者实例化一个JavaBean。
<jsp:setProperty>设置JavaBean的属性。
<jsp:getProperty>输出某个JavaBean的属性。
<jsp:useBean id="BeanId" class="example5.simpleBean" scope="application"/>
<jsp:setProperty name="BeanId" property="name" value="Andrew"/>
<jsp:setProperty name="BeanId" property="age" value="25"/>
<jsp:getProperty name="BeanId" property="name"/>
<jsp:getProperty name="BeanId" property="age"/>
<jsp:include> <jsp:include page="sample.jsp" flush="true"><jsp:param name="name" value="csp"/></jsp:include>
用于在当前页面中包含静态和动态的资源,可以传递参数。
<jsp:forward> <jsp:forward page="requestedpage.jsp"/>
和RequestDispatcher接口的forward()方法的作用一样。允许在运行时将当前的请求转发给一个静态的资源,JSP页面或者Servlet,请求被转向到的资源必须位于同JSP发送请求相同的上下文环境中。
<jsp:plugin>根据浏览器类型为Java插件生成OBJECT或EMBED标记。
7.注释:<!-- --> <%-- --%>
include指令与include动作
include指令可以在JSP页面转换成Servlet之前,将JSP代码插入其中。它的主要优点是功能强大,所包含的代码可以含有总体上影响主页面的JSP构造,比如属性、方法的定义和文档类型的设定。它的缺点是难于维护只要被包含的页面发生更改,就得更改主页面,这是因为主页面不会自动地查看被包含的页面是否发生更改。
include动作是引入执行页面或Servlet所生成的应答文本。在主页面被请求时,将次级页面的输出包含进来。被包含的页面发生改变时,无须对主页面做出修改。
ps:仅当include动作不能满足要求时,我们才应该使用include指令。
forward和redirect的区别
forward是服务器请求资源,服务器直接访问目标地址的URL,把那个URL的响应内容读取过来,然后把这些内容再发给浏览器,浏览器根本不知道服务器发送的内容是从哪儿来的,所以它的地址栏中还是原来的地址。
redirect就是服务端根据逻辑,发送一个状态码,告诉浏览器重新去请求那个地址,一般来说浏览器会用刚才请求的所有参数重新请求,所以session,request参数都可以获取。
scope作用域
1.page
表示页面作用域,即所创建的对象在当前页面有效,请求转交给其他页面处理时,对象失效。
默认值。在处理当前请求的过程中,bean对象都应该存放在PageContext对象中。让同一Servlet中的其他方法可以访问该bean。
2.request
表示请求作用域,即在当前页面创建的对象,在该请求后续访问的页面都可以访问。
处理当前请求的过程中,bean对象应存储在ServletRequest对象中,可以通过getAttribute访问到它。
3.session
表示会话作用域,即在某个客户的会话期间,创建的对象,在其会话存续期间都可以访问。
bean会被存储在与当前请求关联的HttpSession中,和普通的会话对象一样,在常规Servlet中可以使用getAttribute和setAttribute访问到它们。
4.application
表示应用程序作用域,即创建的对象在web服务器没有被关闭之前,该对象都可以访问。
bean将存储在ServletContext中(通过application变量或调用getServletContext()来访问)。ServletContext由同一Web应用中的所有Servlet共享(或服务器上的所有Servlet——在没有另外定义Web应用的情况下)。
JSP的生命周期
1.翻译和编译(转换阶段)
jspinit - JSP容器创建一个对象的时候,执行jspinit方法,该方法在JSP的生命周期中只执行一次。
2.执行阶段
jspService - JSP容器处理用户请求的时候,调用这个方法。一个请求,一个线程。
3.销毁阶段
jspDestory - 由于Servlet常驻内存,所以JSP响应速度快。当系统资源不足的时候,需要将Servlet移出内存,此时执行jspDestory方法。
JSP执行流程:
第一个用户请求JSP文件的时候,把JSP文件转换成Java文件(Servlet类文件),然后再编译成class文件,常驻内存。然后再有用户请求的时候,直接再开一个线程,而不是一个进程,无须重新编译,直接执行第一次已经编译好的class文件,速度快。如果JSP文件发生变化,那么就需要重新编译一次。
JSP的内置对象
1.JSP内置对象是Web容器加载的一组类。
2.它不像一般的Java对象那样用"new"去获取实例,而是可以直接在JSP页面使用的对象。
3.内置对象的名称是JSP的保留字。
4.JSP使用Java定义的内置对象来访问网页的动态内容。
编写test.jsp,编译之后查看test_jsp.java源代码:
public void _jspService(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
JspFactory _jspxFactory = null;
javax.servlet.jsp.PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
...
}
这些内置对象都在_jspService中定义,所以只能在脚本或表达式中使用内置对象。
1.输入/输出对象
request、response、out
2.作用域通信对象
pageContext、request、session、application
3.Servlet对象
page、config
4.异常对象
exception
request
表示客户端对网页的请求,实现javax.servlet.http.HttpServletRequest接口。使用HTTP协议处理客户端的请求。
常用方法
String getParameter(String name)
String[] getParameterValues(String name)
response
处理JSP生成的响应,将响应发送给客户端,实现javax.servlet.http.HttpServletResponse接口。
常用方法
void setContentType(String name)设置响应内容的类型和字符编码。
void sendRedirect(String name)重定向。
out
表示输出流,javax.servlet.jsp.JspWriter类的实例,以字符流的形式输出数据,通过page指令的buffer属性来制定缓冲区的大小,默认是8kb。
常用方法
write()、print()、println()
session
用户会话对象,Web服务器为单个用户发送的多个请求创建会话,实现javax.servlet.http.HttpSession接口。
常用方法
void setAttribute(String name,Object value)
void getAttribute(String name)
application
JSP页面所属的应用程序,实现javax.servlet.ServletContext接口。
常用方法
void setAttribute(String name,Object value)
void getAttribute(String name)
pageContext
页面上下文对象,继承javax.servlet.jsp.PageContext类。它的作用范围是在同一页面。
常用方法
void setAttribute(String name,Object value)
void getAttribute(String name)
page
页面对象,继承java.lang.Object类。JSP中很少使用该对象。
config
配置信息对象,实现javax.servlet.ServletConfig接口。在Servlet初始化时向其传递配置信息。
exception
异常对象,用于处理JSP页面中的异常。
JSP表达式语言
EL(Expression Language),可以简化对变量的访问。由两个组开发(JSP标准标签库专家组、JSP2.0专家组)。
语法
${EL Expression}
EL表达式的操作内容可以是常量、变量、JSP内置对像。还提供了对操作内容的运算(算述运算、关系运算、逻辑运算)。EL表达式的操作结果会自动输出到输出流对象中。
EL支持的文字常量
字符串 - 由0个或多个字符组成。
整形 - 十进制、十六进制和八进制类型的值。
浮点型 - 由两部分组成,如用'E'、'e'和f后缀类型表示的指数。
布尔型 - 指定或检查运算结果,返回结果为true或false。
Null - 表示无值,Null值可用于代码中检查方法是否返回值。
使用情形
1.静态文本。
2.标准标签和自定义标签。
3.EL不能在脚本元素中使用。
10/5=${10/5} -- 10/5=2.0
10%5=${10%5} -- 10%5=0
${true && false} -- false
${true || false} -- true
5>6=${5>6} -- 5>6=false
5==6=${5==6} -- 5==6=false
EL使用"[]"和"."操作符来访问对象属性。
${user.name}同${user["name"]}
禁用EL
<%@ page isELIgnored ="true"%>
EL表达式搜索范围
EL在对变量进行操作的时候,它默认通过pageContext.findAttribute("")的方式来查找变量,查找的范围从page、request、session到application。假如途中找到变量,就直接回传,不再继续找下去。如果这几个范围都没有找到则返回null。也可以通过以下的内容来指定范围pageScope、requestScope、sessionScope和applicationScope。${pageScope.user.name}。
EL变量类型自动转换
${param.count + 20}当param.count为10时,则结果为30。
运算符
1.算术运算符
(+、-、*、/或div、%或mod)
${param.count + param.count}
2.关系运算符
(==或eq、!=或ne、<或lt、>或gt、<=或le、>=或ge)
${param.count eq param.count}
3.逻辑运算符
(&&或and、||或or、!或not)
${param.count == 1 || param.count == 2}
4.其它运算符
empty运算符主要用来判断值是否为null或空的。
${empty param.count}
条件运算符。当A为true时,执行B,A为false时,则执行C。
${A ? B : C}
EL中的隐含对像共有11个,可以分成三类
1.与范围有关的隐含对象(pageScope、requestScope、sessionScope、applicationScope)。
它们基本上就和JSP的pageContext、request、session和application一样,不过必须注意的是,这四个隐含对象只能用来取得范围属性值,即JSP中的getAttribute(String name),却不能取得其他相关信息,没有其它相关的方法。
2.与输入有关的隐含对象(param、paramValues)。
用来取得用户请求的参数,如:
${param.name}
${paramValues.name}
以上的作用为:
request.getParameter(String name)
request.getParameterValues(String name)
3.其他隐含对象。
cookie是一个小小的文本文件,它是以key、value的方式将session tracking的内容记录在这个文本文件内。EL没有实现cookie地动作,只是可以简单的把cookie中保存的值取出,其它的工作交由后台的程序员来完成。
${cookie.userCountry}
取出cookie中保存的userCountry的信息。
header和headerValues
取出请求的关信息。用户浏览器的版本、用户计算机所设定的区域等其他相关数据。在鲜少机会下,有可能同一标头名称拥有不同的值,此时必须改为使用headerValues来取得这些值。
${header["User-Agent"]}
取得浏览器的版本信息。
initParam
取得web.xml中的配置参数,如在web.xml中有如下配置
<context-param>
<param-name>userid</param-name>
<param-value>mike</param-value>
</context-param>
${initParam.userid}同String userid = (String)application.getInitParameter("userid");
pageContext
提供对页面属性的访问
${pageContext.request.queryString}取得请求的参数字符串
${pageContext.request.requestURL}取得请求的URL,但不包括请求参数字符串。
${pageContext.request.contextPath}服务的web application的名称。
${pageContext.request.method}取得HTTP的方法(get、post)。
${pageContext.request.protocol}取得使用的协议(HTTP/1.1、HTTP/1.0)。
${pageContext.request.remoteUser}取得用户名称。
${pageContext.request.remoteAddr}取得用户IP。
${pageContext.session.new}判断session是否为新的。所谓新的session,表示刚由server产生而client尚未使用。
${pageContext.session.id}取得session的ID。
${pageContext.servletContext.serverInfo}取得主机端的服务信息。
JSP标准标签库
JSTL(JSP Standard Tag Library),由标签库和EL表达式两部分组成。功能包括迭代和条件判断、数据管理格式化、XML操作以及数据库访问。由apache的jakarta小组维护。JSTL1.0发布于2002年6月,目前最新版本为1.2。
JSTL包含5大标签库
1.核心标签库:包含Web应用的常见工作,比如:循环、表达式赋值、基本输入输出等。
2.国际化标签库:用来格式化显示数据,比如:日期、数字格式化。
3.数据库标签库:访问数据库。
4.XML标签库:访问XML。
5.函数标签库:读取已定义的函数。
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/xml" prefix="x" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
1.核心标签库
对JSP页面一般处理的封装,包含14标签,分为4类
a.多用途核心标签
<c:out>、<c:set>、<c:remove>、<c:catch>
用于显示的<c:out>标签
<c:out>标签是一个最常用的标签,用于在JSP中显示数据。如果vlaue为null时,会显示default的值。
<c:out value="${param.count}" [escapeXml="{true|false}"] [default="0"] />
用于赋值的<c:set>标签
<c:set>标签主要用来将变量存储到JSP范围中或JavaBean中的属性中。
<c:set var="number" scope="request" value="csp" />
<c:set target="user" property="name" value="csp" />
用于删除的<c:remove>标签
<c:remove>标签用于删除存在于scope中的变量。
<c:remove var="varName" [scope="{page|request|session|application}]" />
用于异常捕获的<c:catch>标签
<c:catch var="err">
${param.car[2] == 1}
</c:catch>
${err}
b.条件控制标签
<c:if>、<c:choose>、<c:when>、<c:otherwise>
用于判断的<c:if>标签
<c:if test="${param.count==1}" [var="varName"] [scope="{page|request|session|application}"]>
...
</c:if>
用于复杂判断的<c:choose>、<c:when>、<c:otherwise>标签
<c:choose>标签没有属性,可以被认为是父标签,<c:when>、<c:otherwise>将作为其子标签来使用。<c:when>标签等价于if语句,它包含一个test属性,该属性表示需要判断的条件。<c:otherwise>标签没有属性,它等价于else语句。
<c:choose>
<c:when test="${param.count == 0}">
...
</c:when>
<c:when test="${param.count == 1}">
...
</c:when>
<c:otherwise>
...
</c:otherwise>
</c:choose>
c.循环控制标签
<c:forEach>、<c:forTokens>
用于循环的<c:forEach>标签
<c:forEach [var="v"] [items="collection"] [varStatus="i"] [begin="begin"] [end="end"] [step="step"]>
...
</c:forEach>
用于分隔字符的<c:forTokens>标签
<c:forTokens items="stringOfTokens" delims="delimiters" [var="v"] [varStatus="i"] [begin="begin"] [end="end"] [step="step"]>
</c:forTokens>
<c:forTokens items="aa,bb,cc,dd" delims="," var="v">
${v}
</c:forTokens>
d.URL相关标签
<c:import>、<c:url>、<c:redirect>、<c:param>
用于包含页面的<c:import>
<c:import>标签可以把其他静态或动态文件包含到本页面来。和<jsp:include>最大的区别是<jsp:include>只能包含和自己同一个应用下的文件,<c:import>即可包含和自己同一个应用下的文件,也可以包含和自己不同的应用下的文件。
<c:import url="url" [context="context"] [var="v"] [scope=""] [charEncoding="charEncoding"]>
...
</c:import>
用于得到URL地址的<c:url>标签
<c:url value="url" [context="context"] [var="varName"] [scope=""] >
<c:param name="param" value="value"/>
</c:url>
用于页面重定向的<c:redirect>标签
<c:redirect url="url" [context="context"]>
<c:param>
</c:redirect>
用于包含传递参数的<c:param>标签
<c:param name="param" [value="value"]/>
2.国际化标签库
fmt库中的定制标记主要分成四组。第一组允许设置本地化上下文,其它标记将在其中进行操作。换句话说,这组标记允许页面作者显式地设置其它fmt标记在格式化数据时将要使用的语言环境和时区。第二组和第三组标记分别支持对日期和数字进行格式化和解析。最后一组标记侧重于对文本消息进行本地化。
用户语言环境
<fmt:setLocale value="en_US" [scope="session"] [variant="Microsoft Windows"]/>
JSP容器处理完该JSP代码段之后,将忽略用户浏览器设置中所指定的语言首选项。
用于时区
<fmt:setTimeZone value="Australia/Brisbane" [var="name"] [scope="scope"]/>
用于日期标记
<fmt:formatDate>用来格式化和显示日期和时间(数据输出)。
<fmt:parseDate>用来解析日期和时间值(数据输入)。
<fmt:formatDate value="expression" [timeZone="expression"] [type="field]" [dateStyle="style"] [timeStyle="style]" [var="name"] [pattern="expression"] [scope="scope"]/>
<fmt:formatDate value="${createTime}" pattern="yyyy/MM/dd HH:mm:ss"/>
用于数字标记
<fmt:formatNumber>标记用来以特定于语言环境的方式显示数字数据,包括货币和百分数。
<fmt:parseNumber>操作解析了一个数值,该数值是通过value属性或该操作的标记体内容以特定于语言环境的方式提供的,将结果作为java.lang.Number类的实例返回。
<fmt:formatNumber value="expression" [type="type"] [pattern="expression"] [currencyCode="expression"] [currencySymbol="expression"] [maxIntegerDigits="expression"] [minIntegerDigits="expression"] [maxFractionDigits="expression"] [minFractionDigits="expression"] [groupingUsed="expression"] [var="name"] [scope="scope"]/>
<fmt:formatNumber value="0.02" type="currency"/>
用于消息标记
<fmt:message key="expression" [bundle="expression"] [var="name"] [scope="scope"]>
<fmt:param value="expression"/>
</fmt:message>
3.函数标签
functions标签被用于EL表达式语句中。为两大类,共16个函数。长度函数:fn:length。字符串处理函数:fn:contains、fn:containsIgnoreCase、fn:endsWith、fn:escapeXml、fn:indexOf、fn:join、fn:replace、fn:split、fn:startsWith、fn:substring、fn:substringAfter、fn:substringBefore、fn:toLowerCase、fn:toUpperCase、fn:trim。
长度函数
${fn:length(arrayList)}
判断函数 fn:contains,判断源字符串是否包含子字符串。 ${fn:contains("ABC","A")}
判断函数 fn:containsIgnoreCase,忽略大小写判断源字符串是否包含子字符串。
词头判断函数 fn:startsWith。
词尾判断函数 fn:endsWith。
字符实体转换函数 fn:escapeXml,将所有特殊字符转化为字符实体码。只包含一个string参数,返回一个string类型的值。
字符匹配函数 fn:indexOf,取得子字符串与源字符串匹配的开始位置。
分隔符函数,返回string类型的值。 ${fn:join({"a","b","c"},",")}
替换函数 ${fn:replace("ABC","A","B")}
分隔符转换数组函数,返回string[]类型的值。 ${fn:split("A,B,C",",")}
字符串截取函数 ${fn:substring("ABC","1","2")} B
起始到定位截取字符串函数 ${fn:substringBefore("ABCD","BC")} A
小写转换函数 fn:toLowerCase
大写转换函数 fn:toUpperCase
空格删除函数 fn:trim
Servlet
前面已经介绍JSP本质就是Servlet,直接使用Servlet的坏处是:
1.开发效率低,所有的HTML标签都需要使用页面输出流完成。
2.不利于团队开发,美工人员无法参与Servlet开发。
3.可维护性差,修改时需要编辑Java代码并重新编译。
自MVC规范出来后,Servlet的责任开始明确下来,仅仅作为控制器使用,类似于调度员,所有用户的请求都发送到Servlet。不再需要生成页面标签,也不再作为视图层角色使用。
Servlet被称为服务器端小程序,运行在服务器端,用于处理及响应客户端的请求。
Servlet是个特殊的Java类,这个Java类必须继承HttpServlet。Servlet提供不同的方法来响应客户端请求。
doGet:用于响应客户端的GET请求。
doPost:用于响应客户端的POST请求。
大部分时候,Servlet对于所有请求的响应都是完全一样的。因此可以采用重写service方法来代替上面的所有方法。
init(ServletConfig config):创建Servlet实例时,初始化Servlet资源。
destory():销毁Servlet。
JSP与Servlet的区别:
1.Servlet中没有内置对象,需要由程序显示创建。
2.对于静态HTML标签,Servlet都必须使用页面输出流逐行输出。
从Servlet3.0开始,配置Servlet有两种方式:
1.在web.xml文件中配置。
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>com.csp.LoginAction</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
2.在Servlet类中使用注解配置。
@WebServlet(name="login",urlPatterns={"/login"})
Servlet生命周期:
1.创建Servlet实例。
2.init方法初始化Servlet对象。
3.service方法处理客户的请求。
4.destroy方法销毁Servlet。
当Servlet在容器中运行时,其实例的创建及销毁都不是由程序员决定的,而是由Web容器进行控制。
创建Servlet实例有两个时机:
1.客户端第一次请求某个Servlet时,系统创建该Servlet实例,大部分Servlet都是这种Servlet。
2.Web应用启动时立即创建Servlet实例,即load-on-startup,这种Servlet没有service方法,不能处理用户请求。
<servlet>
<servlet-name>myThread</servlet-name>
<servlet-class>com.csp.MyThread</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
Filter介绍:
Filter可以认为是Servlet的加强版,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理。创建Filter需要两个步骤:
1.创建Filter处理类,实现Javax.servlet.Filter接口。
2.web.xml文件中配置Filter。
<filter>
<filter-name>login</filter-name>
<filter-class>com.csp.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>login</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>