一、相关知识介绍
1.JSP内置对象的实质
JSP脚本中有九个内置对象,都是Servlet API接口的实例(由JSP页面对应Servlet的_jspService()方法来创建),可以直接使用。
再到这个
D:\java\save\apache-tomcat-8.0.24\work\Catalina\localhost\20170710_webDemo\org\apache\jsp目录下,看下Servlet代码
public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
......
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,
"", true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
......
}
几乎所有的JSP页面编译后Servlet类都有上述结构的代码,从这里可以看出JSP内置对象的实质,要么是_jspService()方法的形参,要么是局部变量,所以我们不必创建它们,可以直接使用。
2.Web服务器原理
基于Web的应用采用B/S(Browser/Server)架构,其实也是C/S(Client/Server)结构,只不过它的服务端是Web服务器,而客户端是浏览器。
大部分浏览器一般要完成三件事情,
(1)向远程服务器发送请求;
(2)读取远程服务器返回的字符串数据;
(3)负责根据字符串数据渲染出一个丰富多彩的页面。
Tips:
浏览器是一个非常复杂的网络通信程序,除了可以向服务器发送请求,读取网络数据以外,最大的技术难点在于将HTML文本渲染成页面,建立HTML页面的DOM模型,支持JavaScript脚本程序等。
Web服务器则负责接收客户端请求,每当接收到客户端连接请求之后,Web服务器应该使用单独的线程为该客户端提供服务:接收请求数据、送回响应数据。
如图,客户端发送请求,服务器接收到请求后送回响应的数据,这是“请求/响应”架构。
每次客户端请求,Web服务器需要完成的步骤:
(1)启动单独的线程;
(2)使用I/O流读取用户的请求数据;
(3)从请求数据中解析参数;
(4)处理用户请求;
(5)生成响应数据;
(6)使用I/O流向客户端发送请求数据。
Web应用里的JSP页面、Servlet等程序都将由Web服务器来调用,他们相互之间通常不会彼此调用,那JSP跟Servlet之间是如何交换数据的呢?
为了解决这个问题,Web服务器会提供4个类似Map的结构,分别是application、session、request、page,允许JSP、Servlet将数据放入这四个类似Map的结构中,并允许从这4个Map结构中取出数据,这四个结构的区别是范围不同。
这就类似于两个人的钱需要交换,但是不能直接接触,就通过银行来实现,这四个结构就起到一个银行的作用。把数据放在这四个结构中扩大了数据的作用范围。
(1)application
对整个Web应用有效,其中的数据可以被该应用下所有JSP及Servlet访问。
(2)session
仅对一次会话有效,其中的数据可以被该次会话的其他所有JSP及Servlet访问。
(3)request
仅对本次请求有效,其中的数据可以被该次请求的其他所有JSP及Servlet访问。
(4)page
仅对当前页面有效,其中的数据只可以被当前页面的JSP脚本、声明部分访问。
Tips:会话跟请求有什么区别
**会话(Session)是指在一段时间内,一个客户与Web服务器的一系列交互过程,在一次会话中,客户可能多次访问同一个页面,也可能访问多个不同服务器资源。**
**而每访问一次服务器就是一次请求,就是每访问一个servlet是一个请求。**
二、概括说明
三、详细说明
(一)application对象
前面已经提到,放入application对象的数据是对整个Web应用有效的。
1.让多个JSP、Servlet共享数据
来一个小栗子
放数据
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<html>
<head>
<title>application测试</title>
</head>
<body>
<%!
int i;
%>
<%
application.setAttribute("counter", String.valueOf(++i));%>
<%=i%>
</body>
</html>
输出结果一直在增长,强制刷新都会,放在另一个浏览器里也会在原来的基础上增长。
取数据
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<html>
<head>
<title>application测试</title>
</head>
<body>
<%=application.getAttribute("counter")%>
</body>
</html>
取数据的jsp跟放数据的jsp没有直接关联,但是可以通过counter变量共享数据。
2.获得Web应用配置参数
比如把数据库参数写在web.xml里,连接数据库时从web.xml中获取。这里不举栗子啦
(二)config对象
代表当前JSP配置信息,但是JSP页面通常无需配置,所以在JSP中用的少,在Servlet中用处比较大,暂时就先不说它啦。
(三)exception对象
这个是异常处理机制,Servlet文件的_jspService()这个方法里就有try/catch,如果该页面的page指令指定了errorPage属性,就可以访问exception内置对象,不指定的话,系统就直接把错误信息打印在页面上。
(四)out对象
之前输出是这么写的
<%
while(rs.next()){
%>
<tr>
<td><%=rs.getString(1)%></td>
<td><%=rs.getString(2)%></td>
<td><%=rs.getString(3)%></td>
</tr>
<%}%>
out对象就这么写
<%
//遍历结果集
while(rs.next())
{
//输出表格行
out.println("<tr>");
//输出表格列
out.println("<td>");
//输出结果集的第二列的值
out.println(rs.getString(1));
//关闭表格列
out.println("</td>");
//开始表格列
out.println("<td>");
//输出结果集的第三列的值
out.println(rs.getString(2));
//关闭表格列
out.println("</td>");
//关闭表格行
out.println("</tr>");
}
%>
这样代码太长了,所有使用out的地方,都可以用输出表达式<%=…%>来代替,这样更为简洁。
(五)pageContext对象
这个对象代表页面上下文,主要用于访问JSP之间的共享数据,可以访问page、request、session、application范围的变量。感觉平时也用的少,先不写它啦。
(六)request对象
哎呀重点来啦,request对象是获取请求参数的重要途径,每个request对象封装着一次用户请求,并且所有的请求参数都被封装在request对象中。
1.获取请求头/请求参数
Web应用是请求/响应架构,浏览器发送请求给服务端,附带一些请求头/请求参数,服务器端JSP/Servlet通过request获取请求头/请求参数并解析。
request是HttpServletRequest接口的实例。
请求头通常由浏览器自动添加,请求参数需要开发人员自行添加。
发送请求参数的方式有两种:
(1)GET方式:
请求参数附加在原url后,格式是这样的
url?param=value1¶m=value2
传送数据量小,不超过2kb
地址栏可以看到请求参数的值。
(2)POST方式:
通常用form表单提交实现,method要设置成post,默认是get方式。
传送数据量大。
地址栏不可以看到请求参数的值,比较安全。
因此使用POST方式比较好。
Tips:
表单中每个name属性对应一个请求参数名,每个value属性对应一个请求参数值,多个相同的name是一个请求参数,但是有多个值。
举一个小栗子
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<html>
<head>
<title>request测试</title>
</head>
<body>
<form id="testForm" method="post" action="20170807jspRequestRes.jsp">
姓名:<br/>
<input type="text" name="name" value="Anna"><hr/>
性别:<br/>
男:<input type="radio" name="gender" value="男">
女:<input type="radio" name="gender" value="女" checked="true"><hr/>
爱好:<br/>
听音乐:<input type="checkbox" name="hobby" value="听音乐" checked="true"><br/>
羽毛球:<input type="checkbox" name="hobby" value="羽毛球"><br/>
Hip-Hop:<input type="checkbox" name="hobby" value="Hip-Hop"><br/>
瑜伽:<input type="checkbox" name="hobby" value="瑜伽" checked="true"><hr/>
星座:<br/>
<select name="constellation">
<option value="天蝎座">天蝎座</option>
<option value="双鱼座">双鱼座</option>
<option value="白羊座">白羊座</option>
</select><hr/>
<input type="submit" value="提交">
<input type="reset" value="重置">
</form>
</body>
</html>
读取结果
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title>request获取请求参数</title>
</head>
<body>
<%
request.setCharacterEncoding("UTF-8");
String name = request.getParameter("name");
String gender = request.getParameter("gender");
// 注意这里取出多个值的方法
String[] hobby = request.getParameterValues("hobby");
String constellation = request.getParameter("constellation");
%>
您的姓名:<%=name%><br/>
您的性别:<%=gender%><br/>
您的爱好:<%for(String h:hobby){
out.println(h);
}%><br/>
您的星座:<%=constellation%>
</body>
</html>
跳转页面后
看请求头可以写代码看,我就直接用浏览器看啦
以上是post方式的获取请求参数,get方式也是一样的。
(七)response对象
response代表服务器对客户端的响应。
1.响应输出
一般可以用更简单的响应对象out来代替,作为页面输出流,但是out是
JspWriter的实例,JSPWriter是Writer的子类,Writer是字符流,无法输出非字符例如动态生成图片或pdf文档这样的内容。
举一个简单的小栗子~~~
<%-- 通过contentType属性指定响应数据是图片 --%>
<%@ page contentType="image/jpeg" language="java"%>
<%@ page import="java.awt.image.*,javax.imageio.*,java.io.*,java.awt.*"%>
<%
//创建BufferedImage对象
BufferedImage image = new BufferedImage(340 ,
160, BufferedImage.TYPE_INT_RGB);
//以Image对象获取Graphics对象
Graphics g = image.getGraphics();
//使用Graphics画图,所画的图像将会出现在image对象中
g.fillRect(0,0,400,400);
//将图像输出到页面的响应
ImageIO.write(image , "jpg" , response.getOutputStream());
%>
随便画个空白的画布,不是很喜欢这样的效果,随便画画~~~
记得以前在Java类里面写过下载pdf的用法
http://blog.csdn.net/yolanda_nuonuo/article/details/50372611
2.重定向
举个小栗子~~~
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title>request获取请求参数</title>
</head>
<body>
<%
response.sendRedirect("20170807jspRequestForm.jsp");
%>
</body>
</html>
然后地址栏就会变成重定向后的地址,有关重定向、转发和超链接等的区别请见下一篇博文
3.增加cookie
cookie是服务器放在浏览器的一些数据,通常是用来记录用户信息。
Tips:cookie跟session的区别
在于周期,session是一次会话,浏览器关闭就失效了,但是cookie不同,会一直存放在客户端机器上,除非被清除或者超过生命周期。
增加cookie分为三步:
第一步,创建cookie的实例;
第二步,设置生命周期;
第三步,把cookie写入客户端
又要来举一个小栗子了~
设置cookie
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title>request增加cookie</title>
</head>
<body>
<%
// url请求用get方式
String name = request.getParameter("name");
Cookie c = new Cookie("username", name);
// 设置生存期限
c.setMaxAge(24 * 3600);
response.addCookie(c);
%>
</body>
</html>
http://localhost:8080/20170710_webDemo/20170808jspResponseCookieAdd.jsp?name=Anna
获取cookie
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@ page import="java.util.*" %>
<html>
<head>
<title>request获取cookie</title>
</head>
<body>
<%
// 获取客户端上所有的cookie
Cookie[] cookies = request.getCookies();
for(Cookie c:cookies){
if(c.getName().equals("username")){
out.println(c.getName() + ":" + c.getValue());
}
}
%>
</body>
</html>
然后输出结果啦:
username:Anna
(八)session对象
session对象代表一次用户会话,表示从客户端浏览器连接服务器开始,到客户端浏览器与服务器断开为止。通常用于跟踪用户的会话信息,可以在多个页面内共享数据,一旦关闭浏览器,属性丢失。
不举小栗子啦~
主要的方法就是两个
setAttribute(String attName, Object attValue);
getAttribute(String attName);
Tips:
通常应该只把与用户会话状态相关的信息放入session范围内,如果仅仅只是两个页面之间交换信息,可以放到request范围内,然后forward请求。
(九)page对象
指页面本身,没太大用处,不写啦。