使用Servlet产生动态网页,需要在代码中打印输出很多的HTML标签,将静态显示的内容和动态产生的内容的代码混合在一起。
res.setContentType("text/html;charset=UTF-8");
PrintWriter out=res.getWriter();
//静态内容与动态内容混合在一起
out.println("<html><head><title>");
out.println("登录页面");
out.println("</title></head><body>");
String name=req.getParameter("name");
String pass=req.getParameter("password");
JSP是一种建立在Servlet规范功能之上的动态网页技术。在通常的网页文件中嵌入脚本代码,用于产生动态内容。
JSP文件在用户第一次请求时,会被编译成Servlet,然后再由这个Servlet处理用户的请求,所以JSP也可以看成是运行时的Servlet。
JSP容器(WEB容器)管理JSP页面生命周期的两个阶段:
1、转换阶段:当有一个对JSP页面的请求到来时,JSP容器检验JSP页面的语法是否正确,将JSP页面转换成Servlet源文件,然后调用javac工具类编译servlet源文件生成字节码文件。
2、执行阶段:Servlet容器加载转换后的servlet类,实例化一个对象处理客户端的请求,在请求处理完成后,响应对象被JSP容器接收,容器将HTML格式的响应信息发送到客户端。
当第一次加载JSP页面时,因为要将JSP文件转换成Servlet类,所以响应速度比较慢。当再次请求时,JSP容器就会直接执行第一次请求时产生的Servlet,而不再重新转换JSP文件。在JSP执行期间,JSP容器会检查JSP文件是否更新或修改。如果有更新或修改,JSP容器会再次编译JSP或Servlet。
JSP页面转换为Servlet是在后台由JSP容器自动进行的,查看转换后的文件位置:Tomcat安装路径–>work–>Catalina–>localhost文件夹下的应用程序。以下是输出Hollo World内容的index.jsp页面的转换后的index_jsp.java部分源程序:
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method) && !javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) {
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs only permit GET POST or HEAD");
return;
}
//8大内置对象,
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;
try {
response.setContentType("text/html");
//对8大内置对象进行初始化,是由JSP容器自动产生的,可以直接使用这些内置对象
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("<html>\r\n");
out.write("<body>\r\n");
out.write("<h2>Hello World!</h2>\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
JSP语法
一个JSP页面由元素和模板数据组成。元素是必须由JSP容器处理的部分,而模板数据是JSP容器不处理的部分,这些模板数据会直接发送到客户端(HTML)。
元素有三种类型:指令元素、脚本元素和动作元素。
1、指令元素
指令元素主要用于为转换阶段提供整个JSP页面的相关信息,指令不会产生任何的输出到当前的输出流中。语法形式:
<%@ 指令 属性 %>
指令元素有三种指令:
1.1 page指令
page指令作用于整个JSP页面,定义许多与页面相关的属性,这些属性将被用于和JSP容器进行通信。语法形式:
<%@ page attr1="value1" attr2="value2" %>
无论将page指令放在JSP文件的哪个位置,它的作用范围都是整个JSP页面。最好将page指令放在JSP文件的顶部。
page指令有15个属性,常见属性如下:
1.1.1、language=”scriptingLanguage”
该属性用于指定在脚本元素中使用的脚本语言,默认是Java。
1.1.2、extends=”className”
该属性用于指定JSP页面转换后的servlet类从哪一个类继承,属性的值是完整的限定类名。通常不需要使用这个属性,JSP容器会提供转换后的Servlet类的父类。
1.1.3、import=”importList”
指定在脚本环境中可以使用的Java类。属性值和java程序中的import声明类似,该属性值是以逗号分隔的导入列表,:
<%@ page import="java.util.Vector,java.io.*"%>
也可以重复设置import属性:
<%@ page import="java.util.Vector"%>
<%@ page import="java.io.*"%>
注意,page指令中只有import属性可以重复设置。import默认导入的列表是:java.lang.*, javax.servlet.* ,javax.servlet.jsp.*,和javax.servlet.http.*。
1.1.4、session=”true|false”
该属性用于指定JSP页面是否参与到HTTP会话中,如果是true,则在JSP页面中可以使用隐含的session对象。默认是true。
1.1.5、buffer=”none|sizekb”
该属性用于指定out对象使用的缓冲区大小,如果设置为none,将不使用缓冲区,所有的对象通过PrintWriter对象写出。只能是kb为单位,默认是8kb。
1.1.6、errorPage=”error_url”
该属性用于指定当JSP页面发生异常时,将转向哪一个错误处理页面。注意,如果一个页面通过使用该属性定义了错误页面,那么在web.xml中定义的任何错误页面将不会被使用。
1.1.7、contentType=”ctinfo”
该属性指定用于响应的JSP页面的MIME类型和字符编码,例如:
<%@ page contentType="text/html;charset=utf-8" %>
1.1.8、pageEncoding=”peinfo”
改属性指定JSP页面使用的字符编码。
如果设置了这个属性,则JSP页面的字符编码使用该属性指定的字符集;如果没有设置这个属性,则JSP页面使用contentType属性指定的字符集,都没指定,那使用字符集“ISO-8859-1”。
1.2、include指令
include指令用于在JSP页面中静态包含一个文件(将文件作为静态对象,将页面的内容(文本或代码)在include指令的位置处包含进来,并不会进行处理,只是单纯的替代到指令的位置,该过程发生在JSP的转换阶段)。因此该文件可以是JSP页面、HTML网页、文本文件或java代码。语法如下:
<%@ include file="relativeURL"%>
file属性的值为相对于当前JSP文件的URL。
//test.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
time:<%@include file="date.jsp"%>
</body>
</html>
//date.jsp
<%
out.println(new java.util.Date());
%>
注意:在被包含文件中最好不要使用<\html><\/html><\body><\/body>等标签,因为会影响到原JSP文件中同样的标签。
因为原文件和被包含的文件可以互相访问彼此定义的变量和方法,所以在包含文件时,避免在被包含文件中定义了同名的变量和方法。
2、脚本元素
脚本元素包括三个部分:声明、脚本段和表达式。
2.1、声明
声明脚本元素用于声明在其他脚本元素中可以使用的变量和方法。声明必须是完整的声明语句,遵照java语言的语法。声明不会在当前的输出流中产生任何输出。语法形式:
<%! 声明语句 %>
例如:
<%! a=0;%>
<%! public int fun(int i){return i;}%>
可以在一个声明语句中声明多个变量和方法,也可以使用多个声明语句。声明只在当前的jsp页面中有效。
利用<%%>声明的变量,在JSP容器转换JSP页面为Servlet类时,将作为该类的实例变量或者类变量(声明时使用了static关键字)。在多用户并发访问时,将导致线程安全问题。
2.2、脚本段
脚本段是在请求处理期间要执行的java代码段。脚本段可以产生输出,并将输出发送到客户端。语法形式:
<% 脚本段 %>
例如:
<%! i=99;%>
<% if(i>100){ %>
<!--模板元素直接显示-->
<h2>hello</h2>
<%
}else{
%>
<h2>worl</h2>
<% } %>
在脚本段中也可以声明本地变量,可以在后面的脚本段中使用。在JSP容器转换JSP页面为Servlet类时,页面中的代码会按照出现的次序,一次被转换为_jspService()方法中的代码。在脚本段中声明的变量,将成为_jspService()方法中的本地变量,因此,脚本段中变量是线程安全的。
2.3、表达式
表达式脚本元素是java语言中完整的表达式,在请求处理时计算这些表达式,计算的结果将被转换为字符串,插入到当前的输出流中。语法形式:
<%= 表达式%>
例如:
<%=(new java.util.Date()).toString()%>
在书写表示时,一定不要在表达式后面添加任何标点符号。
3、动作元素
首先了解一个JavaBean组件的特性:
1、它是一个公开类(public)。
2、它有一个默认无参的构造方法。
3、它提供setXXX()方法和getXXX()方法来设置和获取属性。
4、支持序列化,实现Serializable。
在页面被转换为servlet期间,当JSP容器遇到这个标签,就用预定义的对应于该标签的Java代码来代替它。
3.1、<\jsp:useBean>
该动作元素用于实例化JavaBean或者定位一个已经存在的JavaBean实例,并把实例的引用赋给一个变量。语法形式:
<jsp:useBean id="name" scope="page|request|session|application"
typeSpec/>
其中:typeSpec可以定义为:
class="className"|
class="className" type="typeName"|
type="typeName" class="className"|
beanName="beanName" type="typeName"|
type="typeName" beanName="beanName"|
type="typeName"
含义如下:
id:用于标识JavaBean实例的名字,被初始化为JavaBean实例的引用。指定的名字是区分大小写,遵照java语言变量命名规范。
scope:指定范围,在该范围内,JavaBean实例的引用是可用的,实际指定JavaBean实例的生命周期。默认是page 。
class:指定JavaBean对象的完整的限定类名。
beanName:指定Bean的名字,该名字被提供给Bean类的instantiate()方法来实例化一个JavaBean。
type:指定定义的脚本变量(也就是id值)的类型,这个类型可以是Bean类本身,它的父类,或者由Bean类实现的接口。默认值和class值一样。
例如:
<jsp:useBean id="user" scope="session" class="org.wdz.test.bean.User">
3.2、<\jsp:setProperty>
该动作和<\jsp:useBean>一起使用,用来设置JavaBean的简单属性和索引属性。<\jsp:setProperty>动作使用Bean中的setXXX()方法,在Bean中设置一个或多个属性值。语法形式:
<jsp:setProperty name="beanName" prop_expr/>
其中:prop_expr定义为:
property="*"|
property="propertyName"|
property="propertyName" param="parameterName"|
peoperty="propertyName" value="propertyValue"
含义如下:
name:表示Bean实例的名字,它必须是已经在<\jsp:useBean>元素中通过id属性定义的名字。Bean的实例中必须包含可写(setXXX()方法)的属性。
property:被设置的属性的名字。如果属性的值是”*”,标签就会在请求对象中查找所有的请求参数,看是否有参数的名字和Bean属性的名字相同,如果找到匹配的参数和属性,就会按照正确的类型将参数的值设置为属性的值。如果一个参数的值为空(”“),对应的属性值不会被修改。
param:指定请求对象中参数的名字。在设置Bean的属性时,如果请求参数的名字和Bean属性的名字不同,可以用param来指定参数的名字。如果没有使用param,那么认为请求参数的名字和Bean属性的名字相同。在<\jsp:setProperty>元素中,不能同时出现param和value属性。
value:指定要赋给Bean属性的值。可以用一个请求时属性表达式作为value属性的值。
3.3、<\jsp:getProperty>
该动作用来访问一个Bean属性,并把属性的值转化成一个String 。然后发送到输出流中。如果属性是一个对象,将调用该对象的toString()方法。语法形式:
<jsp:getProperty name="name" property="propertyName" />
含义:
name:Bean实例的名字,也就是id的值
property:要得到的属性的名字。Bean实例必须包含可读(具有getXXX()方法)的属性。
实例:
// log.html 登录页面
<form action="reg.jsp" method="post">
<table>
<tr>
<td>姓名:</td>
<td><input type="text" name="name"></td>
</tr>
</table>
</form>
// reg.jsp 保存属性值
<!--将客户端form中提交的数据保存到JavaBean的属性中-->
<jsp:useBean id="user"scope="session" class="org.wdz.test.bean.User"/>
<jsp:setProperty name="user" property="*"/>
<jsp:setProperty name="user" property="name" param="userName"/>
//info.jsp 获取属性值
<jsp:useBean id="user" scope="session" class="org.wdz.test.bean.User"/>
姓名:<jsp:getProperty name="user" property="name"/>
3.4、<\jsp:param>
该动作用来以名值对的形式为其他标签提供附加信息。语法形式:
<jsp:param name="name" value="value"/>