2017-04 from--https://github.com/FatliTalk/blog/issues/38

重点: request 对象 、 response 对象 、 session 对象和 cookie 、 application 对象

  • 任务:掌握实现用户注册功能
    • 掌握 request 对象和 response 对象的使用
    • 掌握转发和重定向的区别
  • 任务:保存用户状态、登录时自动填写用户名、统计页面访问次数

JSP 九大内置对象

JSP 已经准备好的,可以直接使用的对象

参考:
http://www.importnew.com/19128.html
https://www.tutorialspoint.com/jsp/jsp_implicit_objects.htm
http://www.blogjava.net/ourday/archive/2008/09/20/230107.html

对象目的 对象名称 对象描述 对象类型 作用域
请求对象 request 每次客户端请求页面时, JSP 引擎(例如 Tomcat )都会创建一个新对象来表示该请求。 javax.servlet.ServletRequest Request
输出对象 out 用于在响应中发送内容。 javax.servlet.jsp.JspWriter Page
响应对象 response 正如服务器创建请求对象一样,它也创建一个对象来表示对客户端的响应。 javax.servlet.SrvletResponse Page
会话对象 session 它的行为与会话对象在 Java Servlet 下的行为完全相同。会话对象用于跟踪客户端请求之间的客户端会话。 javax.servlet.http.HttpSession Session
应用程序对象 application 通过向应用程序添加属性,可以确保组成 Web 应用程序的所有 JSP 文件都可以访问它。 javax.servlet.ServletContext Application
页面上下文对象 pageContext 此对象存储对每个请求的请求和响应对象的引用。应用程序,配置,会话和输出对象是通过访问此对象的属性导出的。使用它可以访问到本页面中所有其他对象。 javax.servlet.jsp.PageContext Page
页面对象 page 类似于 Java 中的 this 指针,用于调用翻译后的 servlet 类定义的方法。 javax.lang.Object Page
配置对象 config 在 Servlet 初始化的时候,JSP 引擎(如 Tomcat )通过 config 向它传递信息。这种信息可以是 属性名/值 匹配的参数,也可以是通过 ServletContext 对象传递的服务器的有关信息。一般在 JSP 开发过程很少使用到 config 内置对象,只有在编写 Servlet 时,需要重载 Servlet的init() 方式时才用到。此对象允许 JSP 程序员访问 Servlet 或 JSP 引擎初始化参数,如路径或文件位置等。 javax.servlet.ServletConfig Page
异常对象 exception 异常对象允许指定的 JSP 访问异常数据。用来处理页面出现的异常错误。 java.lang.Throwable page

JSP 引擎是用来管理和运行 Web 应用程序的软件,而安装了 JSP 引擎的计算机就是 Web 服务器。严格意义上, Web 服务器指的是 安装了 JSP 引擎(如 Tomcat )的计算机。

JSP中的四大作用域

作用范围由小到大:Page 作用域 → Request 作用域 → Session 作用域 → Application 作用域

  1. Page
    Page 作用域表示只在当前页面有效。当程序运行跑出了当前的页面,就无法在其它的页面访问当前页面设置的属性值。
    我们都知道,JSP 最终会被编译成 Servlet 文件。在 Servlet 容器(如 Tomcat )中,每个 Servlet 都只存在一个实例。但是对于 Page 作用域的属性来说,在当前页面设置的属性只在本次访问该页面有效,再次访问该页面时,又会重新初始化页面的属性。
  2. Request
    Request 表示一次客户端的请求。一次请求的生命周期从客户端发起到服务器接收并响应该请求,或者将该请求 forward 到另一个页面或者 Servlet 进行处理而结束。在此期间,本次请求的参数,属性都是有效的;一旦客户端刷新浏览器,重新发起请求,则之前的请求参数和属性都将失效。
    特别需要注意的是,当我们使用 <jsp:forward .../> 动作将当前请求转向另一个页面或者 Servlet 的时候,该请求的参数和属性也一并转过去,并不会因为 <jsp:forward .../> 动作而丢失 request 的参数和属性。
  3. Session
    当我们向服务器发送第一个请求开始,只要页面不关闭,或者会话未过期(默认30分钟),或者未调用 HttpSession 的 invalidate() 方法,接下来的操作都属于同一次会话的范畴。
    在 JSP 中,每当向服务器发送一个请求,服务器响应这个请求的时候,会在客户端的 Cookie 中写一个 session id 值。每次发送请求的时候,会将该 session id 值一起发送到服务器端,服务器端根据该 session id 值来判断每次请求是否属于同一个 session 的范畴之内。
  4. Application
    Application的作用域是最广的,它代表着整个Web应用的全局变量,对每一个页面,每一个 Servlet 都是有效的。当我们在 application 中设置属性时,这个属性在任意的一个页面都是可以访问的。
    在application作用域中设置的属性如果不手动调用 removeAttribute 函数进行删除的话,那么 application 中的属性将永远不会删除,如果 Web 容器发生重启,此时 application 范围内的所有属性都将丢失。

get 和 post 提交表单的区别

参考:http://www.w3school.com.cn/tags/html_ref_httpmethods.asp

在客户机和服务器之间进行请求-响应时,两种最常用的 HTTP 方法是:GET 和 POST。

  • GET :从指定的资源请求数据。
  • POST :向指定的资源提交要被处理的数据

什么是 HTTP?
超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信。
HTTP 的工作方式是客户机与服务器之间的请求-应答协议。
web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。
举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。

比较项 method=”get” method=”post”
参数出现在 URL 中
长度限制 2k
安全性 低,因为所发送的数据是 URL 的一部分 高,因为参数不会被保存在浏览器历史或 web 服务器日志中
URL 可传播
传参方式 将参数以 参数1=参数值1&参数2=参数值2 这种形式拼接在 URL 后面进行传递 将参数作为 http 请求的内容,发送到指定的 URL 中去
能否被缓存 不能
后退按钮/刷新 无害 数据会被重新提交(浏览器应该告知用户数据会被重新提交)
对数据类型的限制 只允许 ASCII 字符 没有限制,也允许二进制数据

 


request 对象

  • 请求对象: request
    • public String getParameter (String name)
  • 示例:
    • HTML 代码
      • <input type="text" name="userName">
    • JSP代码
      • String userName=request.getParameter("userName");

 

request 对象常用方法

方法名称 说明
String getParameter(String name) 根据表单组件名称获取提交数据
String[] getParameterValues(String name) 获取表单组件对应多个值时的请求数据
void setCharacterEncoding(String charset) 指定每个请求的编码
RequestDispatcher getRequestDispatcher(String path) 返回一个RequestDispatcher(请求转发)对象,该对象的forward()方法用于转发请求

 

request 对象常用方法一:获取表单提交的数据

语法: String getParameter(String name)

在网页的表单中填入数据,提交表单后,数据被提交到 JSP

实例:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>用户注册</title>
</head>
<body>
	<form action="doUserCreate.jsp" method="get">
	<table class="tb" border="0" cellspacing="5" cellpadding="0" align="center">
		<tr>  <td class="text_tabledetail2">用户名</td> <td><input type="text" name="username" value=""/></td>  </tr>
		<tr>  <td class="text_tabledetail2">密码</td> <td><input type="password" name="password" value=""/></td>  </tr>
		<tr>  <td class="text_tabledetail2">确认密码</td> <td><input type="password" name="con_password" value=""/></td>  </tr>
		<tr>  <td class="text_tabledetail2">电子邮件</td> <td><input type="text" name="email" value=""/></td>  </tr>
		<tr>  <td style="text-align:center;" colspan="2"> <button type="submit" name="save">注册</button> <button type="reset" name="return">返回</button> </td>  </tr>
	</table>
	</form>
</body>
</html>

上面的 userCreate.jsp 注册表单的数据提交到下面的 doUserCreate.jsp :

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
	String username=request.getParameter("username");
	out.println(username+"<br />");						 //法一:声明_使用变量 和 out 对象
	out.println(request.getParameter("password")+"<br />"); //法二:使用 out 对象直接输出
	String email=request.getParameter("email"); 			//法三:JSP 中声明和使用变量,<%= %\> 实现页面输出
 %>														  
 <%=request.getParameter("con_password")+"<br />" %>	  <%//法四:<%=request.getParameter("表单组件名")” %\> 直接输出  %>
 <%=email %>
</body>
</html>

doUserCreate.jsp 中的 %\>转义字符

 

request 对象常用方法二:获取同名的多个参数

语法: String[] getParameterValues(String name)

实例:批量删除邮件

删除 标题 对应 checkbox
GitHub 交流分享会 <input type="checkbox" name="mailId" value="1001" />
21届互联网大会邀请函 <input type="checkbox" name="mailId" value="1002" />
Fatli 公司内部交流会 <input type="checkbox" name="mailId" value="1003" />
FatliTalk 访谈 <input type="checkbox" name="mailId" value="1004" />
ILTAF 公司技术加盟邀请 <input type="checkbox" name="mailId" value="1005" />

语法:

<%
String[] mailIds=request.getParameterValues("mailId"); 
if(mailIds!=null&&mailIds.length!=0){ 
	//循环mailIds访问提交的数据 
}else{ 
	//未提交与参数mailId相关的数据 
}
%>

 

request 对象常用方法三: 指定每个请求的编码

语法: void setCharacterEncoding(String charset)

实例: 解决 JSP 中文乱码

  • 设置请求和响应的编码方式(method="post"):
    • request.setCharacterEncoding(“UTF-8”);
    • <%@page language=”java” contentType=”text/html”;charset=”utf-8″%>
      • response.setCharacterEncoding(“UTF-8”); (等同上面的 charset="utf-8"
  • method="get"(通过 url 传参)提交表单出现乱码,copy 上面的 method="post" 的代码后:
    • 治标的方法:new String(s.getBytes(“iso-8859″),”utf-8”);
      eg : String username = request.getParameter("username");
      String un = new String(username.getBytes("iso-8859-1"),"utf-8");
    • 治本的方法:配置 tomcat\conf\server.xml 文件
      • ①URIEncoding=”UTF-8″
      • ②useBodyEncodingForURI=”true”(使用响应页面中设置的 request.setCharacterEncoding(""); 请求的编码格式,比①灵活):
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" useBodyEncodingForURI="true"/>

 

request 对象常用方法四:在请求中存取属性

语法:

在请求中保存属性:

  • public void setAttribute(String name,Object o) 其中,String name为「属性名」,Object o为「属性值」
  • request.setAttributes("mess","注册失败");
    在请求中获取属性:
    public Object getAttribute(String name)

实例:见下

注意:

  1. 在使用属性值的时候要做非空判断,否则可能出现空指针异常;
  2. 它的返回值类型是 Object 类型,需要做数据类型的转换。
/*错误示范:*/
String mess=request.getAttribute("mess"); 
mess. length();
/*正确写法:*/
String mess=(String)request.getAttribute("mess"); 
if(mess!=null){ 
	//在请求中取到 “mess” 属性对应的属性值,正常使用 “mess” 数据 
}else{ 
	//在请求中没有取到 “mess” 属性对应的属性值,使用备选方案 
}

 

request 对象常用方法五:请求转发和重定向

语法:

请求转发:

  • RequestDispatcher 对象
  • forward() 方法
    request.getRequestDispatcher(URL).forward(request,response)

重定向:

  • 将用户请求重新定位到一个新的 URL
    response.sendRedirect(URL)

实例:request 作用域(省略具体例子)

转发和重定向的区别

比较项 转发 重定向
URL 变化
重新发出请求 不会
是否携带请求
目标 URL 要求 仅本 Web 应用 任意 URL

请求转发(RequestDispatcher)是服务器行为,重定向(response_sendRedirect)是客户端行为

转发(RequestDispatcher)的工作方式:
requestdispatcher

重定向(sendRedirect)的工作方式:
response_sendredirect

 


session 对象

Session 对象用于存储特定的用户会话所需的信息 。 Session 对象的引入是为了弥补 HTTP 协议的不足。 HTTP 是无状态协议,这意味着每次客户端检索网页时,都要单独打开一个服务器连接,因此服务器不会记录下先前客户端请求的任何信息。
JSP 利用 servlet 提供的 HttpSession 接口来识别一个用户,存储这个用户的所有访问信息。

使用 session 保存用户名

问题:注册成功后自动登录。登录后记住用户状态,并在多个页面显示用户名,如何实现?

  • 使用会话对象 session 实现
    • 一个会话就是浏览器与服务器之间的一次通话
  • 会话可以在多次请求中保存和使用数据
  • 语法: public void setAttribute(String name, Object value);
    • 用法: session.setAttribute("userName", "张三丰");
  • 语法: public Object getAttribute(String name);
    • 用法: String userName=(String)session.getAttribute("userName");

session 的工作方式:

  • 每个 session 都有一个唯一的 sessionid
    • session.getId();
    • public String getId ();

sessionworking

 

session 会话的清除和过期

session 的数据是在服务器端的,服务器保存的会话数据量会越来越大,从而导致性能问题。
若没有清理机制,会导致性能问题或服务器崩溃。

  • 程序主动清除 session 数据
    • 设置会话失效:
      • session.invalidate();
    • 移除会话的一个属性:
      • 语法: public void removeAttribute(String name);
      • 用法: session.removeAttribute("userName");
  • 服务器主动清除长时间没有再次发出请求的 session
    • 设置会话过期时间:
      • 方法一(单位:秒) : public void setMaxInactiveInterval(int interval);
      • 方法二(单位:分钟):
       <session-config>
       	<session-timeout>30</session-timeout> 
       </session-config>

小结:

  • 用浏览器访问服务器——产生会话
  • 通过浏览器在网站登录——在会话中保存数据
  • 登录成功后用个人身份进行访问——会话有效期内
  • 关闭了浏览器——结束会话
  • 服务器主动结束会话——会话到期
  • 使会话失效、删除属性——及时释放会话资源
  • 程序主动结束会话、会话到期——会话中的数据丢失

 


附:使用 cookie 自动填写用户名

问题:

  1. 浏览器关闭,会话结束,但为什么有些论坛在用户再次进入的时候却可以识别用户身份,并且用户状态为:已登录?
  2. 用户每次访问邮箱的时候,页面上会自动显示该用户名?

cookie 以文件方式保存数据:

  • 添加数据
    • public void addCookie(Cookie cookie)
  • 获取数据
    • public Cookie[] getCookies()
  • 设置有效期
    • public void setMaxAge(int expiry)
  • 用户可以禁用 cookie

 


application 对象

application 是 javax.servlet.ServletContext 类对象的一个实例,用于实现用户之间的数据共享(多使用于网络聊天系统)。
它的作用有点类似于 session 内置对象。但是它们之间还是有区别的,一般来说,一个用户对应着一个 session,并且随着用户的离开 session 中的信息也会消失,所以不同客户之间的会话必须要确保某一时刻至少有一个客户没有终止会话;而 application 则不同,它会一直存在,类似于系统的“全局变量”,而且只有一个实例。

问题:如何统计页面的访问次数?
实例:网站计数器实例

分析:

  • 每个用户都需要使用访问次数
  • application 可在整个项目中共享使用数据
  • 使用 application 实现计数器
  • 每次访问该页面,计数器加 1

解决方法:

  • public void setAttribute(String name, Object object)
  • public Object getAttribute (String name)

 


request、session、application 三个对象对比

  • 相同点
    • 都可以存储属性
  • 不同点
    • request 中存储的数据仅在一个请求中可用
    • session 中存储的数据在一个会话的有效期内可用
    • application 中存储的数据在整个Web项目中可用

 


总结:

  • 实现用户注册
  • 解决中文乱码
  • 转发和重定向
  • 使用 session 在多页面显示用户名
  • 使用 cookie 实现自动填写用户名
  • 使用 application 统计页面访问次数