JSP全名为Java Server Pages,其根本是一个简化的Servlet设计,实现了在Java当中使用HTML标签。
JSP指令
- page指令,通常位于jsp页面的顶端,同一个页面可以有多个page指定。
- include指令,将一个外部文件嵌套到当前JSP文件中,同时解析这个页面中的JSP语句。
- taglib指令,使用标签库定义新的自定义标签,在JSP页面中启动定制行为。
page指令:
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
属性 | 描述 | 默认值 |
---|---|---|
language | 指定jsp页面使用的脚本语言 | java |
import | 通过该属性来引用脚本语言中使用到的类文件 | 无 |
contentType | 用来指定JSP页面所采用的编码方式 | text/html,utf-8 |
Jsp脚本
在JSP页面中执行的java代码。
语法:<% Java代码%>
就是在<% %>里嵌入Java代码,这里的Java代码和我们一般的Java代码没有什么区别,所以每一条语句同样要以”;”结束,这和表达式是不相同的 语法:<% code %> 脚本的本质:就是将代码插入到Servlet的service方法中。
Jsp声明
在JSP页面中定义变量或者方法。
语法:<%! Java代码%>
就是允许用户定义Servlet中的变量、方法 语法:<%! code %> 例如:
Jsp表达式
在JSP页面中执行的表达式。
语法:<%=表达式> 表达式不以分号结束。
Jsp表达式可以调用Jsp声明中声明的变量或方法。
Jsp表达式是对数据的表示,系统将其作为一个值进行计算。 语法:<%= expression %> 例如:<%= user.getName()%> 表达式的本质:在将JSP页面转换成Servlet后,使用out.print()将表达式的值输出。这样如果user.getName()的返回值是”liky”, 那么实际上在servlet中就将转换成out.print(“liky”); 因此这里要注意以下两点:
- 如果表达式是调用一个方法,那么这个方法必须要有返回值,而不应是void,也就是说void getName()这样的方法是不能被调用的。
- 在方法的后面不能有分号;例如<%=getName();%>这是不允许的。
Jsp页面生命周期
jspService()方法被调用来处理客户端的请求。对每一个请求,JSP引擎创建一个新的线程来处理该请求。如果有多个客户端同时请求该JSP文件,则JSP引擎会创建多个线程。每个客户端请求对应一个线程。以多线程方式执行可以大大降低对系统的资源需求,提高系统的并发量及响应时间。但也要注意多线程的编程带来的同步问题,由于该Servlet始终驻于内存,所以响应是非常快的。
测试了一下,在index.jsp页面中,写了Jsp脚本,Jsp声明,Jsp表达式。
执行程序,访问index.jsp后,在 D:\program Files\apache-tomcat-8.5.11\work\Catalina\localhost\JspDemo\org\apache\jsp 路径下确实生成了index_jsp.java文件。
<body>
<h1>JSP生命周期</h1>
<hr>
<%
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
String s = sdf.format(new Date());
%>
<%!
String rain="今天下雨了";
String dalei() {
String lei ="好响的雷";
return lei;
}
%>
今天是:<%=s %>;
</body>
Jsp脚本的内容写在了_jspService()方法中了。Jsp声明的内容写在了类的最前面。Jsp表达式变成了_jspService()方法中一句out.print(s );
index_jsp.java
/*
* Generated by the Jasper component of Apache Tomcat
* Version: Apache Tomcat/8.5.11
* Generated at: 2017-08-25 22:03:48 UTC
* Note: The last modified time of this file was set to
* the last modified time of the source file after
* generation to assist with modification tracking.
*/
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import java.text.SimpleDateFormat;
import java.util.*;
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent,
org.apache.jasper.runtime.JspSourceImports {
String rain="今天下雨了";
String dalei() {
String lei ="好响的雷";
return lei;
}
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants;
private static final java.util.Set<java.lang.String> _jspx_imports_packages;
private static final java.util.Set<java.lang.String> _jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("java.util");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = new java.util.HashSet<>();
_jspx_imports_classes.add("java.text.SimpleDateFormat");
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
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;
}
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; charset=UTF-8");
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("\r\n");
out.write("\r\n");
out.write("\r\n");
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
out.write("\r\n");
out.write("\r\n");
out.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\r\n");
out.write("<html>\r\n");
out.write(" <head>\r\n");
out.write(" <base href=\"");
out.print(basePath);
out.write("\">\r\n");
out.write(" \r\n");
out.write(" <title>My JSP 'index.jsp' starting page</title>\r\n");
out.write("\t<meta http-equiv=\"pragma\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"cache-control\" content=\"no-cache\">\r\n");
out.write("\t<meta http-equiv=\"expires\" content=\"0\"> \r\n");
out.write("\t<meta http-equiv=\"keywords\" content=\"keyword1,keyword2,keyword3\">\r\n");
out.write("\t<meta http-equiv=\"description\" content=\"This is my page\">\r\n");
out.write("\t<!--\r\n");
out.write("\t<link rel=\"stylesheet\" type=\"text/css\" href=\"styles.css\">\r\n");
out.write("\t-->\r\n");
out.write(" </head>\r\n");
out.write(" \r\n");
out.write(" <body>\r\n");
out.write(" \t<h1>JSP生命周期</h1>\r\n");
out.write(" \t<hr>\r\n");
out.write(" ");
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
String s = sdf.format(new Date());
out.write("\r\n");
out.write(" ");
out.write("\r\n");
out.write(" 今天是:");
out.print(s );
out.write("\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);
}
}
}
使用表达式和脚本的方式实现九九乘法表
<%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'exercise.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<%!
//返回九九乘法表对应的HTML代码,通过表达式来调用,在页面上显示
String printMultiTable1()
{
String s = "";
for(int i=1;i<=9;i++)
{
for(int j=1;j<=i;j++)
{
s+=i+"*"+j+"="+(i*j)+" ";
}
s+="<br>"; //追加换行标签
}
return s;
}
//JSP内置out对象,使用脚本方式调用,打印九九乘法表
void printMultiTable2(JspWriter out) throws Exception
{
for(int i=1;i<=9;i++)
{
for(int j=1;j<=i;j++)
{
out.println(i+"*"+j+"="+(i*j)+" ");
}
out.println("<br>"); //追加换行标签
}
}
%>
<h1>九九乘法表</h1>
<hr>
<%=printMultiTable1()%>
<br>
<% printMultiTable2(out);%>
<br>
</body>
</html>
get与post区别
<form name="regForm" action="动作" method="提交方式"></form>
表单有两种提交方式:get与post。
- get:以明文的方式通过URL提交数据,数据在URL中可以看到。提交的数据不超过2KB。安全性较低但效率比post方式高。适合提交数据量不大,安全性不高的数据。比如:搜索、查询等功能。
- post:将用户提交的信息封装在HTML HEADER内。适合提交数据量大,安全性高的用户信息。比如:注册、修改、上传等功能。
Jsp内置对象
JSP内置对象是Web容器创建的一组对象,不使用new关键字就可以使用的内置对象。
JSP九大内置对象为:out request response session application page pagecontext exception config
out对象
out对象是JspWriter类的实例,是向客户端输出内容常用的对象。
常用方法如下:
- void println() 向客户端打印字符串
- void clear() 清除缓冲区的内容,如果在flush之后调用会抛出异常。
- void clearBuffer() 清除缓冲区的内容,如果在flush之后调用不会抛出异常。
- void flush() 将缓冲区的内容输出到客户端
- int getBufferSize() 返回缓冲区以字节数的大小,如不设缓冲区则为0
- int getRemaining() 返回缓冲区还剩余多少可用
- boolean isAutoFlush() 返回缓冲区满时,是自动清空还是抛出异常
- void close() 关闭输出流
<body>
<h1>out内置对象</h1>
<%
out.println("<h2>静夜思</h2>");
out.println("床前明月光<br>");
out.println("疑是地上霜<br>");
out.flush();
//out.clear();//这里会抛出异常。
out.clearBuffer();//这里不会抛出异常。
out.println("举头望明月<br>");
out.println("低头思故乡<br>");
%>
缓冲区大小:<%=out.getBufferSize() %>byte<br>
缓冲区剩余大小:<%=out.getRemaining() %>byte<br>
是否自动清空缓冲区:<%=out.isAutoFlush() %><BR>
</body>
request对象
request对象,客户端的请求信息被封装在request对象中,通过它才能了解到客户的需求,然后做出响应。它是HttpServletRequest类的实例。request对象具有请求域,即完成客户端的请求之前,该对象一直有效。常用方法如下:
- String getParameter(String name) 返回name指定参数的参数值
- String[] getParameterValues(String name) 返回包含参数name的所有值的数组
- void setAttribute(String,Object) 存储此请求中的属性
- Object getAttribute(String name) 返回指定属性的属性值
- String getContentType() 得到请求体的MIME类型
- String getProtocol() 返回请求用的协议类型及版本号
- String getServerName() 返回接受请求的服务器主机名
测试getParameter和getParameterValues方法
reg.jsp,建立一个form表单,input文本框输入用户名,checkbox选择爱好。在request.jsp文件中接收参数
<form name="regForm" action="request.jsp" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>爱好:</td>
<td>
<input type="checkbox" name="favorite" value="read">读书
<input type="checkbox" name="favorite" value="music">音乐
<input type="checkbox" name="favorite" value="movie">电影
<input type="checkbox" name="favorite" value="internet">上网
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"/></td>
</tr>
</table>
</form>
request.jsp页面接收参数,注意方法中的名字与reg.jsp表单中的名字对应。
用户名:<%=request.getParameter("username") %><br>
爱好 :<%
String[] favorites = request.getParameterValues("favorite");
for(int i=0;i<favorites.length;i++)
{
out.println(favorites[i]+" ");
}
%> <br>
这时如果用户名输入中文的用户名,在request.jsp页面得到的用户名出现乱码。
Tomcat在提交表单的时候,默认使用ISO-8859-1这个字符集,要想更正中文乱码问题,可以在接收参数之前,使用request.setCharacterEncoding(“”)。设置的值应于提交表单上页面设置的字符集编码要一致。
解决方案:
<%
request.setCharacterEncoding("utf-8"); //解决中文乱码问题,
%>
前面request.getParameter()是使用post方式获取的,当然也可以接收get方式提交过来的参数。
下面演示一个通过URL地址来传递用户名。在reg页面下添加以下代码。
<a href="request.jsp?username=lisi">测试URL传参数</a>
此时,点击这个a标签,想要跳转到request.jsp页面。然而,HTTP Status 500。
原来request.jsp页面还在接收favorite。
request.getParameterValues("favorite")
但通过URL传参数的时候,只传了用户名的信息,没有传爱好的信息。
所以这里可以加上判空的语句。在传值的时候加上判空语句是很重要的。
if(request.getParameterValues("favorite")!=null)
{
String[] favorites = request.getParameterValues("favorite");
for(int i=0;i<favorites.length;i++)
{
out.println(favorites[i]+" ");
}
}
接下来,测试在URL传参时,传递中文
<a href="request.jsp?username=李四">测试URL传参数</a>
发现又出现了乱码。这种情况下,req.setCharacterEncoding无法解决。
对于这种中文乱码,可以通过设置Tomcat服务器中的server.xml,找到Connector标签,加上URIEncoding=”utf-8”
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" URIEncoding="utf-8"/>
重启后生效。
request其他方法
<%
request.setAttribute("password", "123456");//设置请求中的password属性
%>
密码:<%=request.getAttribute("password") %><br>
请求体的MIME类型:<%=request.getContentType() %><br>
协议类型及版本号: <%=request.getProtocol() %><br>
服务器主机名 :<%=request.getServerName() %><br>
服务器端口号:<%=request.getServerPort() %><BR>
请求文件的长度 :<%=request.getContentLength() %><BR>
请求客户端的IP地址:<%=request.getRemoteAddr() %><BR>
请求的真实路径:<%=request.getRealPath("request.jsp") %><br>
请求的上下文路径:<%=request.getContextPath() %><BR>
结果:
用户名:李四
爱好 :read
密码:123456
请求体的MIME类型:application/x-www-form-urlencoded
协议类型及版本号: HTTP/1.1
服务器主机名 :localhost
服务器端口号:8080
请求文件的长度 :41
请求客户端的IP地址:0:0:0:0:0:0:0:1
请求的真实路径:D:\program Files\apache-tomcat-8.5.11\webapps\JspDemo\request.jsp
请求的上下文路径:/JspDemo
response对象
response对象包含了响应客户请求的有关信息,但在JSP中很少直接用到它。它是HttpServletResponse类的实例。response对象具有页面作用域,即访问一个页面时,该页面内的response对象只能对这次访问有效,其他页面的response对象对当前页面无效。常用方法如下:
- String getCharacterEncoding() 返回响应的是何种字符编码
- void setContentType(String type) 设置响应的MIME类型
- PrintWriter getWriter() 返回可以向客户端输出字符的一个对象(注意比较:PrintWriter与内置对象out对象的区别。getWriter()的输出总是在out的前面。)
- sendRedirect(java.lang.String location) 重定向客户端的请求
<%@ page language="java" import="java.util.*,java.io.*" contentType="text/html; charset=utf-8"%>
<%
response.setContentType("text/html;charset=utf-8"); //设置响应的MIMI类型
out.println("<h1>response内置对象</h1>");
out.println("<hr>");
//out.flush();
PrintWriter outer = response.getWriter(); //获得输出流对象
outer.println("大家好,我是response对象生成的输出流outer对象");
//这时,outer输出的内容在上面。如果想按正常顺序输出,可以在out输出后,加上flush方法。清空缓冲区,并把前面缓冲区的内容写在浏览器上。
response.sendRedirect("reg.jsp");//请求重定向
%>
请求重定向与请求转发的区别
- 请求重定向:客户端行为,response.sendRedirect(),从本质上讲等同于两次请求,前一次请求对象不会保存,地址栏的URL地址会改变。
- 请求转发:服务器行为,request.getRequestDispatcher().forward(req,resp);是一次请求,转发后请求对象会保存,地址栏的URL地址不会改变。
例子,在reg.jsp的表单提交到response.jsp页面,response.jsp页面分别做请求重定向和请求转发。都跳转到request.jsp页面中。观察reg.jsp中的username和favorite数据能否被request.jsp页面接收。
<form name="regForm" action="response.jsp" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username"/></td>
</tr>
<tr>
<td>爱好:</td>
<td>
<input type="checkbox" name="favorite" value="read">读书
<input type="checkbox" name="favorite" value="music">音乐
<input type="checkbox" name="favorite" value="movie">电影
<input type="checkbox" name="favorite" value="internet">上网
</td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="提交"/></td>
</tr>
</table>
</form>
response.jsp
<%@ page language="java" import="java.util.*,java.io.*" contentType="text/html; charset=utf-8"%>
<%
response.setContentType("text/html;charset=utf-8"); //设置响应的MIMI类型
//请求重定向
response.sendRedirect("request.jsp");
//请求转发
/* request.getRequestDispatcher("request.jsp").forward(request, response); */
%>
request.jsp
<body>
<h1>request内置对象</h1>
<%
request.setCharacterEncoding("utf-8"); //解决中文乱码问题,无法解决URL传递中文出现的乱码问题。
%>
用户名:<%=request.getParameter("username") %><br>
爱好 :<%
if(request.getParameterValues("favorite")!=null)
{
String[] favorites = request.getParameterValues("favorite");
for(int i=0;i<favorites.length;i++)
{
out.println(favorites[i]+" ");
}
}
%> <br>
</body>
请求重定向结果:
请求转发结果:
session对象
什么是session
- session表示客户端与服务器的一次会话
- Web中的session指的是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间
- 从上述定义中可以看到,session实际上是一个特定的时间概念。
- 在服务器的内存中保存着不同用户的session。
session对象
- session对象是一个JSP内置对象
- session对象在第一个JSP页面被装载时自动创建,完成一次客户端与服务器会话管理。
- 从一个客户打开浏览器并连接到服务器开始,到客户关闭浏览器离开这个服务器结束,被称为一个会话。
- 当一个客户访问一个浏览器时,可能会在服务器的几个页面之间切换,服务器应当通过某种办法知道这是一个客户,就需要session对象。
- session对象是HttpSession类的实例。
session对象常用方法如下:
- long getCreationTime():返回SESSION创建时间
- public String getId():返回SESSION创建时JSP引擎为它设的唯一ID
- public Object setAttribute(String name, Object value):使用指定名称将对象绑定到此会话
- public Object getAttribute(String name):返回与此会话中的指定名称绑定在一起的对象,如果没有对象绑定在该名称下,则返回null
- String[] getValueNames():返回一个包含此SESSION中所有可用属性的数组
- int getMaxInactiveInterval():返回两次请求间隔多长时间此SESSION被取消(单位为秒)
例子:
session_page1.jsp
<h1>session内置对象</h1>
<hr>
<%
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
Date d = new Date(session.getCreationTime());//session创建时间
session.setAttribute("username", "admin"); //设置属性
session.setAttribute("password", "123456");
session.setAttribute("age", 20);
//设置当前session最大生成期限单位是秒
session.setMaxInactiveInterval(10);//10秒钟
%>
Session创建时间:<%=sdf.format(d)%><br>
Session的ID编号:<%=session.getId()%><BR>
从Session中获取用户名:<%=session.getAttribute("username") %><br>
<a href="session_page2.jsp" target="_blank">跳转到Session_page2.jsp</a>
<!-- 用于测试在session_page2.jsp可以得到session_page1.jsp中设置的username等属性 -->
session_page2.jsp
<h1>session内置对象</h1>
<h1>session内置对象</h1>
<hr>
Session的ID编号:<%=session.getId()%><BR>
从Session中获取用户名:<%=session.getAttribute("username") %><br>
Session中保存的属性有:<%
String[] names =session.getValueNames();
for(int i=0;i<names.length;i++)
{
out.println(names[i]+" ");
}
%> <br>
session的生命周期
- 创建:当客户端第一次访问某个jsp或者Servlet时,服务器会为当前会话创建一个SessionId,每次客户端向服务器发送请求时,都会将此SessionId携带过去,服务端会对此SessionId进行校验。
- 活动:某次会话当中通过超链接打开的新页面属于同一次会话。
- 只要当前会话页面没有全部关闭,重新打开新的浏览器窗口访问同一项目资源时属于同一次会话。
- 除非本次会话的所有页面都关闭后再重新访问某个Jsp或者Servlet将会创建新的会话。
- 注意原有会话还存在,只是这个旧的SessionId仍然存在于服务端,只不过再也没有客户端会携带它然后交予服务端校验。除非原有会话超时,原有会话才会结束。
- 销毁:
- 调用session.invlidate()方法
- Session过期(超时)
- 服务器重启
Tomcat默认session超时时间为30分钟。
设置session超时有两种方式:
1. session.setMaxInactiveInterval(时间); 单位是秒
2. 在web.xml配置,单位是分钟
<session-config>
<session-timeout>10</session-timeout>
</session-config>
application对象
- application对象实现了用户间数据的共享,可存放全局变量。
- application开始于服务器的启动,终止于服务器的关闭
- 在用户的前后连接或不同用户之间的连接中,可以对application对象的同一属性进行操作。
- 在任何地方对application对象属性的操作,都将影响到其他用户对此的访问。
- 服务器的启动和关闭决定了application对象的生命。
- application对象是ServletContext类的实例。
常用方法:
- getAttribute/setAttribute
- Enumeration getAttributeNames() 返回所有可用属性名的枚举
- String getServerInfo() 返回JSP引擎名及版本号
<h1>application内置对象</h1>
<%
application.setAttribute("city", "北京");
application.setAttribute("postcode", "10000");
application.setAttribute("email", "lisi@126.com");
%>
所在城市是:<%=application.getAttribute("city") %><br>
application中的属性有:<%
Enumeration attributes = application.getAttributeNames();
while(attributes.hasMoreElements())
{
out.println(attributes.nextElement()+" ");
}
%><br>
JSP(SERVLET)引擎名及版本号:<%=application.getServerInfo() %><br>
运行结果:
page对象
page对象就是指当前JSP页面本身,有点像类中的this指针,它是java.lang.Object类的实例。
常用方法如下,与Object类的方法一致:
- class getClass()
- int hashCode()
- boolean equals(Object obj)
- void copy(Object obj)
- Object clone()
- String toString()
- void notify() 唤醒一个等待的线程
- void notifyAll() 唤醒所有等待的线程
- void wait(int timeout) 使一个线程处于等待直到timeout结束或被唤醒
- void wait() 使一个线程处于等待直到被唤醒
<h1>page内置对象</h1>
当前page页面对象的字符串描述:<%=page.toString() %><br>
输出结果:
当前page页面对象的字符串描述:org.apache.jsp.page_jsp@540bfa68
输出了类的全名+hashcode
page.jsp被解析成了page_jsp.java,在Tomcat的work目录下。
pageContext对象
- pageContext对象提供了对JSP页面内所有的对象及名字空间的访问
- pageContext对象可以访问到本页所在的session,也可以取本页面所在的application的某一属性值
- pageContext对象相当于页面所有功能的集大成者
- pageContext对象的本类名也叫pageContext
常用方法:
- JspWriter getOut() 返回当前客户端响应被使用的JspWrite流(out)
- HttpSession getSession()
- Object getPage()
- ServletRequest getRequest()
- ServletResponse getResponse()
- void setAttribute(String name,Object attribute)
- Object getAttribute(String name,int scope)
- int getAttributeScope(String name) 返回某属性的作用范围
- void forward(String relativeUrlPath) 使当前页面重导到另一页面
- void include(String relativeUrlPath) 在当前位置包含另一文件
例子,先访问session_page1页面,在访问当前页面。可以访问到session_page1中session的属性值
<h1>pageContext内置对象</h1>
<hr>
用户名是:<%=pageContext.getSession().getAttribute("username") %><br>
<%
//pageContext.forward("reg.jsp");//跳转到注册页面
pageContext.include("include.jsp");
%>
config对象
config是在一个Servlet初始化时,JSP引擎向它传递信息的,此信息包括Servlet初始化时所要用到的参数以及服务器有关信息
exception对象
exception对象是一个异常对象,当一个页面在运行过程中发生了异常,就产生这个对象。如果一个JSP页面要应用此对象,就必须把isErrorPage设为true,否则无法编译。他实际上是java.lang.Throwable的对象。
方法:
- String getMessage() 返回描述异常的消息
- String toString() 返回关于异常的简短描述消息
JSP状态管理
http协议的无状态性
无状态是指,当浏览器发送请求给服务器的时候,服务器响应客户端请求。但是当同一个浏览器再次发送请求给服务器的时候,服务器并不知道它就是刚才那个浏览器。服务器不会去记住你。
cookie概述
保存用户状态的两种机制:
- Session
- Cookie
Cookie是web服务器保存在客户端的一系列文本信息。
Cookie的典型应用场景:
- 判定注册用户是否已经登录网站。是否在下次登录时保留登录信息
- 购物车的处理。用户可能在一段时间内访问同一家网站,在不同页面间选择不同的商品,可以把这些信息保存到客户端的Cookie中。以便最后结账时把这些信息提取出来。
Cookie的作用:
- 对特定对象的跟踪
- 保存用户网页浏览记录与习惯
- 简化登录
安全风险:容易泄露用户信息
Jsp中创建与使用Cookie:
- 创建Cookie对象,Cookie newCookie = new Cookie(String key,Object value);
- 写入Cookie对象,response.addCookie(newCookie);
- 读取Cookie对象,Cookie[] cookies = request.getCookies();
常用方法:
方法名称 | 说明 |
---|---|
void setMaxAge(int expiry) | 设置cookie的有效期,以秒为单位 |
void setValue(String value) | 在cookie创建后,对cookie进行赋值 |
String getName() | 获取cookie的名称 |
String getValue() | 获取cookie的值 |
int getMaxAge() | 获取cookie的有效时间,以秒为单位 |
例子,实现登录的用户名密码保存到cookie
login.jsp页面。要实现读取cookie,如果cookie数组中有用户名、密码的cookie信息,则要在访问这个页面时,把信息写入到输入框中。
考虑用户名为中文问题。存入用户名的cookie需要进行编码;读取用户名的cookie需要解码
<%@ page language="java" import="java.util.*,java.net.*" contentType="text/html; charset=utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h1>用户登录</h1>
<hr>
<%
request.setCharacterEncoding("utf-8");
String username="";
String password = "";
Cookie[] cookies = request.getCookies();
if(cookies!=null&&cookies.length>0)
{
for(Cookie c:cookies)
{
if(c.getName().equals("username"))
{
username = URLDecoder.decode(c.getValue(),"utf-8");//解码
}
if(c.getName().equals("password"))
{
password = URLDecoder.decode(c.getValue(),"utf-8");
}
}
}
%>
<form name="loginForm" action="dologin.jsp" method="post">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="username" value="<%=username %>"/></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password" value="<%=password %>" /></td>
</tr>
<tr>
<td colspan="2"><input type="checkbox" name="isUseCookie" checked="checked"/>十天内记住我的登录状态</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value="登录"/><input type="reset" value="取消"/></td>
</tr>
</table>
</form>
</body>
</html>
dologin.jsp页面。这里显示登录成功。此页面需要,判断点击登录时是否勾选了记住登录状态复选框。如果勾选了,就要创建用户名、密码的cookie,并写入;没勾选,则要设置用户名、密码的cookie信息失效,并写入cookie。
<%@ page language="java" import="java.util.*,java.net.*" contentType="text/html; charset=utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'dologin.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h1>登录成功</h1>
<hr>
<br>
<br>
<br>
<%
request.setCharacterEncoding("utf-8");
//首先判断用户是否选择了记住登录状态
String[] isUseCookies = request.getParameterValues("isUseCookie");
if(isUseCookies!=null&&isUseCookies.length>0)
{
//把用户名和密码保存在Cookie对象里面
String username = URLEncoder.encode(request.getParameter("username"),"utf-8");
//使用URLEncoder解决无法在Cookie当中保存中文字符串问题
String password = URLEncoder.encode(request.getParameter("password"),"utf-8");
Cookie usernameCookie = new Cookie("username",username);
Cookie passwordCookie = new Cookie("password",password);
usernameCookie.setMaxAge(864000);
passwordCookie.setMaxAge(864000);//设置最大生存期限为10天
response.addCookie(usernameCookie);
response.addCookie(passwordCookie);
}
else
{
Cookie[] cookies = request.getCookies();
if(cookies!=null&&cookies.length>0)
{
for(Cookie c:cookies)
{
if(c.getName().equals("username")||c.getName().equals("password"))
{
c.setMaxAge(0); //设置Cookie失效
response.addCookie(c); //重新保存。
}
}
}
}
%>
<a href="users.jsp" target="_blank">查看用户信息</a>
</body>
</html>
users.jsp,显示用户信息。读取用户名、密码的cookie,并显示
<%@ page language="java" import="java.util.*,java.net.*" contentType="text/html; charset=utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'users.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h1>用户信息</h1>
<hr>
<%
request.setCharacterEncoding("utf-8");
String username="";
String password = "";
Cookie[] cookies = request.getCookies();
if(cookies!=null&&cookies.length>0)
{
for(Cookie c:cookies)
{
if(c.getName().equals("username"))
{
username = URLDecoder.decode(c.getValue(),"utf-8");
}
if(c.getName().equals("password"))
{
password = URLDecoder.decode(c.getValue(),"utf-8");
}
}
}
%>
<BR>
<BR>
<BR>
用户名:<%=username %><br>
密码:<%=password %><br>
</body>
</html>
session与cookie对比
共同点:
- 都是用来保存用户状态的机制。
- 都会过期,都有生存期限。
区别:
- session保存在服务器端内存中;cookie以文本文件的形式保存在客户端
- session保存的是Object类型;cookie保存的是字符串类型
- session随着会话的结束而将其存储的数据销毁;cookie可以长期的保存在客户端。
- session用于保存安全性高的信息;cookie相对保存不重要的信息,如浏览记录等。
JSP指令与动作元素
include指令,包含一个页面
<%@ include file="xxx.jsp" %>
include动作
<jsp:include page="URL" flush="true|false"/>
flush:表示被包含的页面是否从缓冲区读取,true使用缓冲。
include指令与include动作比较
forward动作
<jsp:forward page="URL" />
等同于 request.getRequestDispatcher(“/url”).forword(req,resp);
param动作
<jsp:param name="参数名" value="参数值" />
常常与forward动作一起使用,作为其子标签。可以添加新的参数,也可以改变前面传过来的参数。
<jsp:forward page="user.jsp">
<jsp:param name="email" value="jiaxing747@163.com" />
</jsp:forward>
到user.jsp页面的时候,不但可以获取前一个页面的属性,还可以获取email参数的值。