思维导图如下所示:
平时打开浏览器就可以浏览网页了,html、css、javascript都是运行在浏览器中的。使用html可以制作出一个网页,css可以使网页变的更美观,javascript可以动态的修改html和css从而使网页变的更加强大。在实际工作中有专门的开发者来制作这部分内容,他们被称为前端工程师。
浏览器都是安装在客户端的即用户自己的电脑或者手机中,打开后,浏览器会通过HTTP协议访问服务器,在服务器中通过容器Tomcat就可以访问特定的Servlet, Servlet会使用jdbc访问数据库将数据读取出来再返回给客户端,这样用户就可以看到网页上的信息了。 而制作这一部分内容的称为后端工程师。
这一阶段的知识对于后端工程师来说非常重要,因为以后的工作方向就是服务器端的开发。
本阶段讲解的Servlet就是服务器端的开发,后面要学习的各种服务器端的框架都是在这部分知识点上封装出来的,用来简化Servlet开发的
构建Java Web项目关键步骤如下:
进行项目开发时,首先要确立的是程序架构的类型。在明确程序架构的基础上才能开展后续开发工作,下面介绍两种常用的程序架构。
c/s架构,client/server架构,这种架构需要客户安装软件才可以使用, 比如电脑上安装qq、迅雷等等, c/s架构的优点就是可以编写出界面丰富美观的软件,缺点是升级维护成本较高, 每次更新都需要客户端部分进行更新。
b/s架构,browser/server架构,b/s架构的开发有时被称为web开发, 这种架构只需要客户的电脑上面装有浏览器就可以使用,比如淘宝、百度等, b/s架构的优点是升级维护成本低,缺点是制作出的网页不如c/s架构的美观, 不过随着技术的发展,这个缺点基本可以忽略了。
B/S架构采用浏览器请求,服务器响应的工作模式
B/S架构的工作原理如图所示:
B/S架构的工作原理,总结起来包括以下4点:
在了解URL之前,先了解一下HTTP协议
HTTP是HyperText Transfer Protocol(超文本传输协议)的简写,可以传输HTML文件、图片等文件。用于定义WEB浏览器与WEB服务器之间交换数据的过程及数据本身的格式,HTTP默认端口号是80,在网址中可以省略。
HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。
URL:全称是Uniform Resource Locator,中文是统一资源定位符,是互联网上资源的地址,即平时所说 的网址。一个完整的URL由以下几部分组成,例如:
http://www.kgc.cn/news/201609/newslist.jsp?page=6
http
是传输数据时所使用的协议www.kgc.cn
可以定位到课工场的主机,如果知道主机的IP地址,这里也可以替换成具体的IP地址来定位news/201609
是我们要访问的资源的位置或者资源的路径,而newslist.jsp
则是我们要访问的资源的名称&
符号进行连接,如page=6&size=10
URI:全称是Uniform Resource Identifier,中文是统一资源标识符,主要用于标识网络资源名称。 比如:URL是:http://www.kgc.cn/news/201609/newslist.jsp?page=6
那其中的news/201609/newslist.jsp?page=6
就是URI
注意:区分URL与URI
平时上网的时候,打开浏览器(客户端)访问网址,此时会向网址所在的Web服务器上发送请求,Web服务器获得请求后会将请求的数据响应给发送请求的浏览器(比如:html,css,javascript等)
Web服务器的主要功能就是提供网上信息浏览服务
在Web服务器中提供对外界访问的资源一般分为两种:
在服务器的机器上安装Web服务器软件后才可以工作,安装好之后,将资源部署到web服务器软件 就可以允许外界访问了。
常用的Web服务器主要有:
NIO
的非堵塞机制。Undertow 是红帽公司的开源产品,是 Wildfly 默认的 Web 服务器。Undertow 提供一个基础的架构用来构建 Web 服务器,这是一个完全为嵌入式设计的项目,提供易用的构建器 API,完全向下兼容 Java EE Servlet 3.1
和低级非堵塞的处理器。Tomcat 是Apache基金会开发的一个小型的轻量级应用服务器,技术先进,性能稳定,而且免费,占用的系统资源小,运行速度快,由Java语言编写,可以去官网下载。 官网地址:https://tomcat.apache.org/
,Tomcat9软件下载地址:https://tomcat.apache.org/download-90.cgi
。
建议使用免安装版的Tomcat,下载后直接解压即可,解压目录最好不要带有中文和空格。
提示:
在安装Tomcat之前,确认在本地已经安装了JDK,以免造成Tomcat服务器运行错误
Tomcat安装好之后,会产生一些目录,每个目录功能介绍如下表所示:
目录 | 说明 |
---|---|
/bin | 存放各种平台下用于启动和停止Tomcat的脚本文件 |
/conf | 存放Tomcat服务器的各种配置文件 |
/lib | 存放Tomcat服务器所需的各种JAR文件 |
/logs | 存放Tomcat的日志文件 |
/temp | Tomcat运行时用于存放临时文件 |
/webapps | 当发布Web应用时,默认情况下会将Web应用的文件存放于此目录中 |
/work | Tomcat把由JSP生成的Servlet放于此目录下 |
Tomcat在Windows下的启动和停止:
Tomcat在Linux下启动和停止:
切换到tomcat主目录下的bin目录
cd usr/local/tomcat/bin
启动Tomcat服务
./startup.sh
关闭Tomcat服务
./shutdown.sh
备注:
Windows 查看进程的命令:
netstat –ano windows
杀死进程的命令:
taskkill /pid (进程id号)
打开conf目录下的server.xml文件,找到下面代码:
Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"
将8080修改为别的端口号,例如可以修改为8888,启动Tomcat。
Web项目开发完毕后,必须要部署到服务器中才能被访问。
示例演示:
在D盘下新建一个名为hello的目录,在hello目中新建hello.html文件,并在文件中写入一行代码,如下:
<h1>
Hello,Tomcat!!
h1>
假设hello目录是一个简单的小项目,接下来以一个hello项目为例,演示如何在Tomcat中部署。
具体的部署方式有3种:
直接将hello项目赋值到webapps目录下,启动Tomcat,然后在浏览器中输入:localhost:8080/hello/hello.html,若项目过大时,将项目打成一个war包,再将war包放到webapps目录下,启动Tomcat,war包会自动解压。解释路径:
/hello
:项目资源所在的目录
/hello.html
:项目资源的名称
配置conf/server.xml文件 在
标签中配置:
在conf/Catalina/localhost创建任意名称的xml文件,在文件中编写:
备注:
第1种方式是在开发过程中常用的部署的方式,第2、3种是运维人员常用的部署方式(可以忽略)
1) 打开IDEA工具的主界面,选择Create New Project,如图所示:
2) 在跳出的窗口中点击Java,勾选Web Application,同时勾选web.xml,并点击Next按钮
3) 在跳出的窗口中输入项目名称,同时可以选择项目存放的目录,点击Finish按钮,完成项目的创建
1) 在IDEA的项目开发界面上点击 Add Configuration,如图所示:
2) 在跳出的窗口界面中点击“+”号按钮,如图所示:
3) 在下拉框中找到 Tomcat Server,点击它,并在出现的下拉框中点击Local按钮
4) 在右边的窗口中点击 Configure按钮,在跳出的窗口中选择Tomcat的安装路径,如图所示:
到目前为止,Tomcat服务器配置成功!
在上个案例的基础上部署刚才新创建的Web项目:
1) 在Tomcat配置成功的界面,点击Deployement按钮,切入到与部署有关的界面,如图所示:
2) 在此界面的下面点击“+”号,在下来框中选择“Artifact”,项目就会部署到Tomcat服务器中,如图所示:
3) 可以修改此项目对外显示的浏览器上的路径,比如可以将/hello_demo_war_exploded
修改为/hello-demo
,点击OK,如图所示:
4) 修改index.jsp的内容为如下内容,如图所示:
5) 点击Run Tomcat 或者使用快捷键 Shift+F10
6) 浏览上输入路径:localhost:8080/hello-demo
,浏览器界面显示如下:
至此,在IDEA中创建Web项目,配置Tomcat,以及部署并运行项目完成
1) 在IDEA的开发界面点击Project Structure或者使用快捷键Ctrl+Alt+Shift+S打开新的窗口,如图所示:
2) 在跳出的窗口中一次点击Aritifacts——>"+"——>Web Application:Arichive——>For ‘hello-demo:war exploded’,如图所示:
3) 修改war包的名称,指定导出war包的目录,然后点击OK,如图所示:
4) 回到开发页面,依次点击Build——>Build Artitacts——>hello-demo——>Build按钮,如图所示:
5) 打开war包生成的目录,如图所示:
可以看到IDEA生成了该项目的war包
6) 将hello-demo.war包复制到Tomcat的webapps目录下,如图所示:
7) 启动Tomcat,可以看到hello-demo.war包自动解压成hello-demo目录,然后再浏览器上输入路径:localhost:8080/hello-demo
,浏览器显示出了index.jsp的页面,如图所示:
关键步骤如下:
JSP 与 PHP、ASP、ASP.NET 等语言类似,运行在服务端的语言。
JSP(全称Java Server Pages)是由 Sun公司倡导和许多公司参与共同创建的一种使软件开发者可以响应客户端请求,而动态生成 HTML、XML 或其他格式文档的Web网页的技术标准。
JSP全称是Java Server Pages,是一种动态网页技术,JSP其实就是在html中插入了java代码和JSP标签之后形成的文件,文件名以.jsp结尾。 相比html而言,html只能为用户提供静态数据即静态页面,而Jsp技术允许在页面中嵌套java 代码,为用户提供动态数据,从而形成动态页面。
需要注意的是最好只在JSP中编写动态输出的java代码
JSP开发的WEB应用可以跨平台使用,既可以运行在 Linux 上也能运行在 Windows 上。
JSP运行在服务器端,当用户通过浏览器请求访问某个JSP资源时,Web服务器会使用JSP引擎对请求的JSP进行编译和执行,然后将生成的页面返回给客户端浏览器进行显示,整个工作原理如下图所示:
当JSP请求提交到服务器时,简单来说,Web容器会通过三个阶段实现处理:
Web容器处理JSP文件请求的三个阶段如下图所示:
一旦Web容器把JSP文件翻译和编译完,Web容器会将编译好的字节码文件保存到内存中,如果客户端再次访问相同的JSP文件,就可以重用这个编译好的字节码文件,没有必要再把同一个JSP文件进行翻译和编译了,这就大大提高了Web系统的性能。
与之相反的情况是,如果对JSP进行了修改,Web容器就会及时发现改变,此时Web容器就会重新进行翻译和编译。所以,在第一次请求JSP时会比较慢,后续访问时速度就会很快,当然如果JSP文件发生了变化,同样需要重新进行编译。
Web容器对同一个JSP文件的二次请求的处理过程如下图所示:
JSP在HTML中嵌入Java脚本语言来响应页面动态请求的,除了HTML标记和Java代码,还可以包含一些其他的元素。比如:JSP指令、JSP脚本元素、表达式…
JSP指令元素:是对当前页面做一些基本的属性设置,为页面的运行提供基本的环境。
这些指令的使用的语法格式均为如下形式:
<%@ 指令名称 属性名=属性值 ... %>
在JSP中包含三类指令:page(页面指令)、 include(包含指令)、 taglib(标签库指令)
用于设置当前JSP页面的相关信息,通过属性定义了JSP的特性,实现与JSP容器的通信
每个JSP都有各自的page指令,如果没有对某些属性进行设置,JSP容器将使用默认的属性设置。page指令的语法如下:
<%@ page language="属性值" import="属性值" contentType="属性值"
pageEncoding="属性值" errorPage="属性值" %>
解释指令中常用的属性如下表所示:
属性 | 描述 |
---|---|
language | 指定JSP页面使用的脚本语言,JSP中默认是“java” |
import | 主要用于在JSP中导入java包, 如: <%@ page import="java.util.*" %> 在java源码中被翻译为:import java.util.*; 若要导入多个类,则在 import 属性值中可使用逗号将这些类分隔。 |
contentType | 用来指定页面的MIME类型,通常为text/html类型,其中还可以使用charSet指定字符编码方式。若在JSP页面中设置如下: <%@ page contentType="text/html" %> 该属性被翻译到java源码里面的_jspService()方法中的 response.setContentType(“text/html")。 当内容类型为”text/html”时,使用 pageEncoding 属性与 contentType 属性效果是相同的。 只有当内容类型不为”text/html”时,才专门使用contentType 属性指定。在指定字符编码时,这两个属 性一般不同时使用。 |
pageEncoding | 用于设置当前JSP页面的字符编码格式。 如: <%@ page pageEncoding="UTF-8" %> 该属性被翻译到java源码里面的_jspService()方法中的 response.setContentType(“text/html;charset=UTF-8”) |
errorPage | 主要用于指定当前页面运行过程中发生异常时所要跳转到的页面。(不常用) |
page指令是JSP非常重要的指令之一,常见的page指令设置如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
包含指令,用于将某个文件包含到当前的 JSP 文件中。
该指令只有一个属性 file, 用于指定要包含的文件。被包含的文件可以是 JSP 文件,也可以是 HTML文件
语法格式为:
<%@ include file = "应用文件的路径" %>
使用include指令:
例如:现在有一个loginControl.jsp文件,里面有关于用户Session判断的代码,将该JSP页面中的代码引入到admin.jsp中。
示例如下:
创建loginControl.jsp 文件,编写关于用户Session判断的代码。loginControl.jsp文件代码如下:
<%
String login = (String) session.getAttribute("login");
if (login == null){
response.sendRedirect("index.jsp");
return;
}
%>
在admin.jsp文件中使用 <%@ include file=“loginControl.jsp” %> 引入即可
关于include原理解析:
找到服务器运行jsp文件生成java文件的目录,里面只生成了一个 admin_jsp.java 的文件,并没有生成 loginControl_jsp.java 文件。
那是因为容器在翻译jsp时,会将 include 指令所指定的文件内容直接翻译到当前 JSP 的java源码中, 形成一个.java 文件。这个包含操作是在编译之前由容器翻译完成的,不是在程序运行期完成的。
由于在编译期就将这些文件合并为了一个 java文件,所以,整个过程就一个_jspService()方法。
也就是说,这些文件之间是可以相互访问局部变量的,只要满足变量声明与使用的先后顺序即可。
taglib指令是用来在当前jsp页面中导入第三方的标签库
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
解释属性如下:
备注:
使用taglib命令导入第三方标签库的时候,需要先把第三方标签库所需jar包放到类路径中。
JSP中的注释:可以使用下面两种注释:
<%-- --%>
两者之间的区别是html注释可以在客户端浏览器中查看源代码的方式下看到,而JSP注释则不会被看到。
JSP中脚本元素:小脚本、表达式、声明
小脚本:可以包含Java片段,形式比较灵活,通过在JSP页面中编写小脚本可以执行复杂的操作和业务处理。
编写方法是是将Java程序片段插入
<% %>
标记中
在一个JSP中可以有多个<% %>
并且可以出现JSP文件中的任意位置。
需要注意的是:在<% %>
中只能出现以分号结尾的Java语句,不能出现下面内容:
原因是:JSP引擎会将这部分Java代码按照从上到下的顺序放到_jspService方法中
例如:
<%
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年 MM 月 dd日");
String time = sdf.format(new Date());
%>
表达式语法:<%= %>
该标签中的内容可以直接在JSP中输出变量、常量等,里面的内容是不用分号结尾的会被JSP引擎直接翻译到_jspService方法中的out.write()方法中输出
例如:
<% int a = 1024;%>
<%= a %>
<%= "jsp表达式" %>
JSP声明:为Java脚本定义成员变量和方法。
声明的语法:<%! %>
例如:
<%!
String formateDate(Date d){
return new SimpleDateFormat("yyyy年 MM 月 dd日").format(d);
}
%>
//调用
<%=formateDate(new Date())%>
为了便于开发者的使用,在JSP引擎将JSP翻译为.java文件时,会提供9个与web开发相关的对象,这些对象被称为JSP中内置对象。
JSP的内置对象一共有9个。开发者在JSP中可以直接使用这些对象并调用其方法,因为在service方法已经对这个九个隐含对象进行声明及赋值,所以可以在JSP中直接使用。
9个内置对象的引用名分别是:request,、response、session、application、config、out、page、exception、pageContext
out对象是JSP提供的一个内置对象,该对象所对应的类是: javax.servlet.jsp.JspWriter,该类继承了IO流中的Writer。所以out是一个输出流对象,用来向客户端输出数据。常用的方法如下:
方法 | 说明 |
---|---|
print() | 输出各种类型数据。 |
println() | 输出各种类型数据后自动加上换行符 |
out对象演示示例如下:
创建新闻显示页面(newsDetail.jsp),使用out对象正确显示新闻标题“谈北京精神”。
关键代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" pageEncoding="utf-8" %>
第一个Web项目
<%
/*新闻标题*/
out.println("谈北京精神");
out.print("再谈北京精神");
%>
如果希望在页面中输出一些特殊的符号,如输出单引号或者双引号,必须要使用转义符进行输出,否则输出显示将会出现异常。在JSP中使用转义符输出的语法非常简单,使用"\"
符号添加到需要输出的特殊字符即可
Web程序常见错误:
404错误—找不到访问的页面或资源
500错误----JSP页面代码有误
页面无法显示
关键步骤如下:
在HTML中,表单用于填写数据,并通过提交实现数据的请求。提交表单时有两种常见的方式,分别是POST方式和GET方式,这两种提交方式的区别如下:
比较项 | GET | POST |
---|---|---|
是否在URL中显示参数 | 是 | 否 |
数据传递是否有长度限制 | 有 | 无 |
数据安全性 | 低 | 高 |
URL是否可以传播 | 是 | 否 |
request对象也是JSP提供的一个内置对象,该对象所对应的类是:javax.servlet.http.HttpServletRequest。代表了客户端的请求信息,主要用于接受通过HTTP协议传送到服务器的数据,包括头信息、系统信息、请求方式以及请求参数等。
request对象的作用域为一次请求。
request对象常用的方法:
方法名称 | 说明 |
---|---|
String getParameter(String name) | 主要用于获取表单中控件的数据。 其中参数名一定要与客户端表单中的控件name属性相一致。 所以在构建表单各元素时,name属性一定要有。 而name属性和id属性的区别就在于, id属性一般是作为客户端区分控件的标识,name属性是服务器端区分各控件的标识。 如果参数名写错,则该方法会返回null |
String[] getParameterValues(String name) | 获取表单组件对应多个值时的请求数据 |
void setCharacterEncoding(String charset) | 指定每个请求的编码 |
RequestDispatcher getRequestDispatcher(String path) | 返回一个RequestDispatcher对象,该对象的forward( )方法用于转发请求 |
Object getAttribute(Stringname) | 返回指定属性的属性值 |
String getCharacterEncoding() | 返回字符编码方式 |
int getContentLength() | 返回请求体的长度(以字节数) |
String getContentType() | 返回得到请求体的MIME类型 |
String getProtocol() | 返回请求用的协议类型及版本号 |
int getServerPort() | 返回服务器接受此请求所用的端口号 |
void setAttribute(String key,Object obj) | 设置属性的属性值 |
String getContextPath() | 可以返回当前页面所在的应用的名字 |
String getSchema() | 可以返回当前页面使用的协议,http 或是 https |
String getServerName() | 可以返回当前页面所在的服务器的名字 |
String getServerPort() | 可以返回当前页面所在的服务器使用的端口号 |
示例:
获取用户在注册页面中输入的数据,并在JSP中显示
实现步骤如下:
关键代码如下:
创建注册页面( reginput.jsp),表单包含字段:用户名和密码,关键代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
演示request对象的用法
学员注册
请输入注册信息
提交表单到reginfo.jsp页面,并在该页面中显示提交的用户名和密码,示例代码如下:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
演示request对象的用法
<%
request.setCharacterEncoding("UTF-8");
String username = request.getParameter("name");
String pwd = request.getParameter("password");
%>
用户名:<%=username %>
密码:<%=pwd %>
使用request对象可以获取表单提交的数据,进而可以实现页面输出显示。但是当用户在表单提交中文信息时,有时候会在页面中显示中文乱码。这是JSP页面默认的编码格式为”ISO-8859-1",这个编码方式不支持中文。支持中文编码的如下表所示:
编码方式 | 收录的字符 |
---|---|
gb2312 | 常用简体汉字 |
gbk | 简体和繁体汉字 |
utf-8 | 所有国家需要的字符,是国际编码,通用性强 |
因此在进行JSP开发时,建议将编码格式修改为通用性强的"utf-8“。
当页面的编码格式使用的是UTF-8,那么表单提交的数据就会以UTF-8的方式进行编码后传输,但是也会出现乱码,这是因为Web服务器在默认情况下对提交的表单数据会使用ISO8859-1的字符集来解码, 编码与解码的方式不一致就产生了表单提交时的中文乱码问题。
当表单提交时,浏览器会对表单中的中文参数值进行编码,而使用的编码是打开页面时所使用的字符集, 如当前页面使用的UTF-8的字符集进行显示的,那么表单提交的数据就会以UTF-8的方式进行编码后传输, 而Web服务器在默认情况下对提交的表单数据会使用ISO8859-1的字符集来解码, 编码与解码的方式不一致就产生了表单提交时的中文乱码问题。
在JSP中解决中文乱码问题时,依据请求的方式不同,解决的方式也有所不同。
通过设置配置文件解决GET方式中的中文乱码问题。设置配置文件如下:
配置tomcat\conf\server.xml文件:
<Connector URIEncoding="UTF-8" connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
在服务器端需要在调用request对象的getParameter方法读取参数之前,告诉浏览器如何解码。
设置==响应==的编码格式如下:
response.setCharacterEncoding("utf-8");
若设置了JSP页面的编码格式为utf-8,这一步可以忽略
设置==请求==的编码格式如下:
request.setCharacterEncoding("utf-8");
这一步必须设置,且一定要在所有调用request对象的getParameter()方法之前设置。
在JSP中为了方便数据的使用,有时候需要将数据通过request对象的属性进行保存和读取,这就需要使用到request对象的另外两个方法,分别是setAttribute()和getAttribute()方法。
setAttribute()方法的语法如下:
该方法没有返回值,参数name表示属性名称,参数o表示属性的值,为Object类型
当需要保存数据时,使用request对象直接调用该方法即可。例如:
request.setAttribute("mess","注册失败");
getAttribute()方法的预防如下:
该方法有一个String类型的参数,返回值是Object类型。获取属性的时候,可以使用String类型的属性名,从请求中取出对应的Object类型的属性值
在读取属性中保存的数据时,必须将数据转换为成其最初的类型。例如:
String mess = (String)request.getAttribute("mess");
如果mess不等于null,表示获取到实际数据,可以进行使用。
注意:
在使用的时候需要注意如下两点:
重定向是指当客户端浏览器提交请求到服务器的JSP处理时,JSP的处理结果是要客户端重新向服务器请求一个新的地址,这种行为就称为重定向。
由于服务器重新定向了URL,因而在浏览器中显示的是一个新的URL地址。由于是从客户端发送新的请求,因而上次请求中的数据就会随之丢失。
重定向是基于response对象实现的,response对象也是JSP的内置对象之一,它的作用是对用户的请求给予响应并向客户端输出信息。而response对象的sendRedirect()方法就可以将用户请求重新定位到一个新的URL上。
重定向的语法如下:
response.sendRedirect("URL");
该方法的参数值URL即Location消息头中的重定向地址。
注意,该段代码后面如果还有其他代码的话也会被继续执行的。
重定向的特点:
由于重定向动作的执行者为浏览器,所以请求的地址可以是任意地址,哪怕是当前应用以外的应用; 浏览器发出请求时一定会保持地址栏与目标地址的一致,所以发生重定向时可以从地址栏中看到地址的改变; 由于整个跳转过程是在浏览器收到响应后重新发起请求,所以涉及到的Web组件并不会共享同一个request和 response。
重定向的使用场景:
使用转发可以实现同一个请求的信息在多个页面中共享。
转发定义:
在Web服务器端处理用户请求的时候,有时候需要多个Web组件(Servlet/JSP)配合才能完成认为。 一个Web组件(Servlet/JSP)将未完成的处理通过Web服务器转交给另外一个Web组件继续完成。这个转交的过程叫做转发。
在转发之后,客户端浏览器可以看到服务器处理完成后的结果页面,但URL地址并未发生变化,所以浏览器也并未察觉是服务端是经过多个组件的处理后,才产生本次请求的结果。
转发的语法如下:
request.getRequestDispatcher("URI").forward(request,response);
参数URI表示将要转发的页面名称或者路径
注意:在forward之后的其他语句还是会继续执行完的,只要不报异常。
转发的特点:
转发过程发生在服务器端,客户端只发送了一个请求,虽然请求到达服务器的指定位置后,被容器控制着传到了第二个组件继续完成工作, 但浏览器并不知道这个过程,所以转发之后地址栏地址不会发生变化。
转发的目的地必须是同一个应用内部的某个地址,决不能跳出应用。毕竟这个转交过程由容器实现,容器只有访问本应用的权限, 而不能控制请求到达应用以外的位置。 转发过程中涉及到的所有Web组件共享同一个request对象和response对象,数据的传递和共享就依赖 request对象。
转发的经典使用场景:
常见情况是Servlet负责获取数据,然后将控制权转发给JSP页面,由JSP进行数据的展现。
转发的特点是:
重定向的特点:
关键步骤如下:
Web应用程序使用HTTP协议作为传输数据的标准协议,而HTTP协议是无状态协议,即一次请求对应一次响应, 响应结束后连接即断开,状态管理能够做到不同客户端的身份识别。
将客户端与服务器之间多次交互当做一个整体来看待,并且将多次交互中涉及的数据保存下来, 提供给后续的交互进行数据的管理即状态管理。 这里的状态指的是当前的数据,管理指的是在这个多次交互的过程中对数据的存储、修改、删除。
状态管理的过程中重要的是数据的保存,只有存下来的数据才能在多次交互中起到记录的作用,所以可以按照管理的数据的存储方式和位置的不同来区分状态管理的模式。
状态管理之会话:
会话就是用户通过浏览器与服务器之间进行的一次通话,它可以包含浏览器与服务器之间的多次请求、响应过程。简单来说就是在一段时间内,单个客户端与Web服务器的一连串相关的交互过程。
当用户通过浏览器向服务器发出第一次请求时,服务器会为该用户创建唯一的会话,会话将一直延续到用户访问结束(浏览器关闭也可以结束会话)
JSP提供了一个可以在多个请求之间持续有效的会话对象session,session对象允许用户存储和提取会话状态信息。
session一词的原意是指有始有终的一系列动作,在实际应用中通常翻译为会话。例如:打电话时,甲方拿起电话拨通乙方这一系列的过程就可以称为一个会话,电话挂断时会话结束
session机制是一种服务器端的机制,在服务器端保存信息。
当程序接收到客户端的请求时,服务器首先会检查是否已经为这个客户单创建了session。判断session是否创建是通过一个唯一的标识“sessionid“实现的。
如果客户端在请求中包含了一个sessionid,则说明在此前已经为客户端创建了session,服务器就会根据这个sessionid将对应的session读取出来。否则,就会重新创建一个新的session,并生成一个与此session对应的sessionid,然后将sessionid在首次响应过程中返回到客户端保存。
使用session对象保存数据时,需要调用相应的方法。常用的方法如下:
方法 | 返回值类型 | 说明 |
---|---|---|
setAtrribute(String key,Object value) | void | 以key-value的形式保存对象值 |
getAttribute(String key) | Object | 通过key获取对象值 |
getId() | String | 获取sessionid |
invalidate() | void | 设置session对象失效 |
setMaxInactiveInterval(int interval) | void | 设置session的有效期 |
removeAttribute(String key) | void | 移除session的属性 |
使用session保存数据,代码如下:
session.setAttribute(String key,Object value);
从session中读取数据,代码如下:
Object value = session.getAttribute(String key);
session的数据是在服务器端的,随着页面访问量的增大,服务器保存的会话数据量也会越来越大,若没有清理session机制,会导致服务器的性能开销问题,严重者可能出现服务器崩溃。为此,设置session的有效期,及时清理不使用的session以实现资源的释放就变得特别的有意义。
在JSP中清除或者设置session过期的方式有两种:一种是程序主动清除session;一种是服务器主动清除长时间没有发出请求的session。
第一种也分为两种:一种是调用session.invalidate()使得session失效;另一种是如果仅仅希望清除session中的某个属性,可以使用session.removeAttribute(“userName”)方法将指定名称的属性清除
第二种也可以通过两种方式实现:一种是通过设置session的过期时间,调用setMaxInactiveInterval(int interval)方法设置session的最大活动时间,以秒为单位,如果在这个时间内客户端没有再次发送请求,那么服务器将清除这个session;另一种是通过在配置文件中设置过期时间来实现,即在Tomcat服务器的web.xml文件中
和之间添加如下代码:
<session-config>
<session-timeout>10session-timeout>
session-config>
注意:
里设置的数值是分为单位,而不是以秒为单位
一小段文本信息随着请求和响应,在客户端与服务器端之间来回传递。根据设定的时间来决定该文本在客户端保存时长的这种工作模式叫做Cookie。最初服务器将信息发给客户端时,是通过响应数据的Set-Cookie头信息来完成的。
创建Cookie:
当用户第一次浏览某个使用Cookie的网站时,该网站的服务器就进行如下工作:
1)该用户生成一个唯一的识别码(Cookie id),创建一个Cookie对象;
2) 默认情况下它是一个会话级别的cookie,存储在浏览器的内存中,用户退出浏览器之后被删除。 如果网站希望浏览器将该Cookie存储在磁盘上,则需要设置最大时效(maxAge),并给出一个以秒为单位的时间(将最大时效设为0则是命令浏览器删除该Cookie);
3)将Cookie插入到一个 Set-Cookie HTTP请求报头中。
4)发送该HTTP响应报文。
设置存储Cookie 浏览器收到该响应报文之后,根据报文头里的Set-Cookied特殊的指示,生成相应的Cookie,保存在客户 端。 该Cookie里面记录着用户当前的信息。
发送Cookie 当用户再次访问该网站时,浏览器首先检查所有存储的Cookies,如果某个存在该网站的Cookie (即该Cookie所声明的作用范围大于等于将要请求的资源),则把该Cookie附在请求资源的HTTP请求头上 发送给服务器。
取Cookie 服务器接收到用户的HTTP请求报文之后,从报文头获取到该用户的Cookie,从里面找到所需要的东西。
在JSP中使用Cookie需要经过一下三个步骤:
Servlet API提供了javax.servlet.http.Cookie这种类型来解释Cookie。其中存储的文本以key-value对的形式进行区分, 所以创建Cookie时指定key-value对即可。
创建Cookie的语法如下所示:
Cookie c = new Cookie(String key,String value);
Cookie创建后,需要将其添加到响应中发送回浏览器保存,在响应中写入Cookie对象的语法如下:
response.addCookie(c);
该方法执行的效果就是在响应数据包中追加一个Set-Cookie的消息头。如果发送了相同key的 Cookie数据,那么之前的数据会被覆盖。能够创建多少个Cookie存放在客户端与当前浏览器的种类相关。
当客户端向服务器发出请求时,服务器端可以尝试着从请求数据包的消息头中获取是否携带了Cookie信息。
实现这一功能的代码如下:
Cookie[] cookies = request.getCookies();
由于客户端是可以存放多个Cookie的,所以request提供的获取Cookie的方法的返回值是Cookie数组, 如果想进一步获取某一个Cookie信息可以通过遍历数组,分别获取每一个Cookie的key和value。代码如 下:
Cookie[] cookies = request.getCookies();
if(cookies!=null){
for(Cookie c : cookies){
String cookieName = c.getName();
String cookieValue = c.getValue();
}
}
Cookie创建之后,可以通过调用其自身的方法来对Cookie进行设置。Cookie对象常用的方法如下表所示:
方法名称 | 说 明 |
---|---|
void setMaxAge(int expiry) | 设置cookie的有效期,以秒为单位 通常情况下expiry参数应为大于0的整数,表示Cookie的有效时间。 如果设置expiry参数为0,表示删除Cookie。 如果设置expiry参数为-1或者不设置,表是Cookie会在当前窗口关闭后失效。 |
void setValue(String value) | 在cookie创建后,对cookie进行赋值 |
String getName() | 获取cookie的名称 |
String getValue() | 获取cookie的值 |
int getMaxAge() | 获取cookie的有效时间,以秒为单位 |
Cookie的根本作用就是在客户端存储用户访问网站的一些信息。
典型的应用有:
application对象类似于系统的“全局变量“,每个Web项目都会有一个application对象,可以在整个Web项目中共享使用数据。application对象常用的方法如下表所示:
方法名称 | 说 明 |
---|---|
void setAttribute(String key, Object value) | 以key/value的形式保存对象值 |
Object getAttribute(String key) | 通过key获取对象值 |
String getRealPath(String path) | 返回相对路径的真实路径 |
补充知识:
在JSP中的对象,包括用户创建的对象,都有一个范围属性,这个范围也称为“作用域”。作用域定义了在什么时间内,在哪一个JSP中可以访问这些对象。
在JSP中有四种作用域,分别是:page、request、session和application。
所谓的page作用域指单一JSP的范围,page作用域内数据只能在本页面中访问。
在page作用域内可以使用pageContext对象的setAttribute()和getAttribute()方法访问具有这种作用域类型的数据
page作用域内的对象在客户端每次请求JSP时创建,在服务器发送回响应或请求转发到其他的页面或资源后失效。
提示
pageContext对象本身也属于page范围。具有page范围的对象都被绑定到pageContext对象中
到目前为止,我们已经掌握了对象的四种作用域范围。它们彼此之间的区别如下表所示:
名称 | 说 明 |
---|---|
page作用域 | 在一个页面范围内有效,通过pageContext对象访问 |
request作用域 | 在一个服务器请求范围内有效 |
session作用域 | 在一次会话范围内容有效 |
application作用域 | 在一个应用服务器范围内有效 |