Java教程

JavaWeb的学习(上)

本文主要是介绍JavaWeb的学习(上),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

JavaWeb的学习(上)

尚硅谷JavaWEB基础教程,哔哩哔哩链接:https://www.bilibili.com/video/BV1jW411u7PZ

一、JavaWeb应用概述

• 在SunJava Servlet规范中,对Java Web应用作了这样定义:Java Web应用由一组Servlet、HTML页、类、以及其它可以被绑定的资源构成。它可以在各种供应商提供的实现Servlet规范的Servlet容器中运行。

Java Web应用中可以包含如下内容:

​ – Servlet

​ – JSP

​ – 实用类

​ – 静态文档如HTML、图片等

​ – 描述Web应用的信息(web.xml

Web 程序结构

​ – 一个 web 应用程序是由一组 Servlet,HTML 页面,类,以及其它的资源组成的运行在 web 服务器上的完整的应用程序,以一种结构化的有层次的目录形式存在

​ – 组成 web 应用程序的这些文件要部署在相应的目录层次中,根目录代表整个 web 应用程序的

​ – 通常将 web 应用程序的目录放在Tomcatwebapps 目录下,在 webapps 目录下的每一个子目录都是一个独立的 web 应用程序,子目录的名字就是 web 应用程序的名字,也就是 web 应用程序的。用户通过 web 应用程序的来访问 web 应用程序中的资源

Web 应用程序的目录解析

image-20200221165024651

• 说明:

​ – WEB-INF目录下的classeslib目录都可以存放Java的类文件,在Servlet容器运行时,Web应用程序的类加载器将首先加载classes目录下的,其次才是lib目录下的类。如果这两个目录下存在同名的类,起作用的将是classes目录下的类

​ –WEB-INF 是一个特殊的目录(所有字母都要大写)。这个目录并不属于Web应用程序可以访问的上下文路径的一部分,对客户端来说,这个目录是不可见的。但该目录下的内容对于Servlet代码是可见的

配置任意目录下的Web应用1

• 在Web服务器中可以配置虚拟目录,而虚拟目录所对应的真实目录可以在任何路径下。

• 在Tomcat服务器中,主要在XML配置文件中通过<Context>元素的设置来完成的。一个元素就表示一个Web应用程序,运行在特定的虚拟主机中。

<Context>元素是<Host>元素的子元素,可以在conf\server.xml文件中设置Context元素。

image-20200221165247192

Context元素的常用属性

image-20200221165205385

• 使用docBase属性指定Web应用程序的真实路径。将属性reloadable设置为true,Tomcat在运行时会自动监测Servlet类的改动,如果发现有类被更新,Tomcat服务器将自动重新加载该Web应用程序。这样,在开发时,就不需要频繁重启Tomcat了

配置任意目录下的Web应用2

image-20200408222441581

image-20200221165434689

二、Servlet容器和Servlet

1.Servlet容器的概念

​ – Servlet容器为JavaWeb应用提供运行时环境,它负责管理Servlet和JSP的生命周期,以及管理它们的共享数据。

​ – Servlet容器也称为JavaWeb应用容器,或者Servlet/JSP容器

Servlet容器响应客户请求的过程

image-20200221165608124

Servlet 容器

image-20200221164616613

目前最流行的Servlet容器软件包括:

​ – Tomcat

​ – Resin

​ – J2EE服务器(如Weblogic)中也提供了内置的Servlet容器

Tomcat 简介

​ – Tomcat 是一个免费的开放源代码的 Servlet 容器,它是 Apache 软件基金会的一个顶级项目,由 Apache,Sun和其他一些公司及个人共同开发而成。由于有了 Sun 的参与与支持,最新的 Servlet 和 JSP 规范总是能在 Tomcat 中得到体现。

Tomcat 的目录结构

image-20200221164734176

运行 Tomcat

​ – 1. 配置java_homejre_home

​ – 2. 双击 bin 目录下的 startup.bat 文件,或cmd窗口输入startup run(在已配置环境变量的情况下)

​ – 3. 在地址栏中输入 http://localhost:8080/

当出现如下标识即为成功:

image-20200408221420815

关闭 Tomcat & 配置 Tomcat 的端口号

• 1.双击 bin 目录下的shutdown.bat 文件关闭 Tomcat 服务器

• 2. 修改 Tomcat 默认的端口号:

​ – 打开 conf 目录下的 server.xml 文件

​ – 修改端口号

image-20200221164819109

Tomcat 启动分析1

image-20200221164842359

Tomcat 启动分析2

• 若想在任意目录下都能启动 Tomcat,则需设置 CATALINA_HOME 环境变量

• 直接执行 catalina.bat 时需要带上命令行参数,常用的参数是start,run 和 stop

image-20200408221636254

Tomcat启动时乱码解决

image-20200512190418013

Tomcat 的管理程序:manager

​ – Tomcat 提供了一个管理程序:manager,用于管理部署到 Tomcat 服务器中的 web 应用程序

​ – 要访问 manager web 应用程序,需要添加具有管理员权限的账号,编辑 conf 目录下的 tomcat-users.xml 文件,添加 manager 角色,设置用户名和密码

image-20200221164941155

2.Servlet 简介

• Java Servlet是和平台无关的服务器端组件,它运行在Servlet容器中。Servlet容器负责Servlet和客户的通信以及调用Servlet的方法,

Servlet和客户的通信采用“请求/响应”的模式。

• Servlet可完成如下功能:

​ – 创建并返回基于客户请求的动态HTML页面。

​ – 创建可嵌入到现有HTML 页面中的部分HTML 页面(HTML 片段)。

​ – 与其它服务器资源(如数据库或基于Java的应用程序)进行通信。

ServletAPI

image-20200221165729471

Servlet容器响应客户请求的过程

​ ①Servlet引擎检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。

​ ②装载并创建该Servlet的一个实例对象:调用该 Servlet 的构造器

​ ③调用Servlet实例对象的init()方法。

​ ④创建一个用于封装请求的ServletRequest对象和一个代表响应消息的ServletResponse对象,然后调用Servlet的service()方法并将请求和响应对象作为参数传递进去。

​ ⑤WEB应用程序被停止或重新启动之前,Servlet引擎将卸载Servlet,并在卸载之前调用Servlet的destroy()方法。

Servlet的注册与运行

• Servlet程序必须通过Servlet容器来启动运行并且储存目录有特殊要求,通常需要存储在<WEB应用程序目录>\WEB-INF\classes\目录中

• Servlet程序必须在WEB应用程序的web.xml文件中进行注册和映射其访问路径,才可以被Servlet引擎加载和被外界访问。

• 一个<servlet>元素用于注册一个Servlet,它包含有两个主要的子元素:<servlet-name><servlet-class>,分别用于设置Servlet的注册名称Servlet的完整类名

• 一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name><url-pattern>,分别用于指定Servlet的注册名称Servlet的对外访问路径

Servlet映射的细节

• 同一个Servlet可以被映射到多个URL上,即多个<servlet-mapping>元素的<servlet-name>子元素的设置值可以是同一个Servlet的注册名。

• 在Servlet映射到的URL中也可以使用 * 通配符,但是只能有两种固定的格式:一种格式是.扩展名,另一种格式是以正斜杠(/)开头并以/*结尾。

<servlet-mapping>
	<servlet-name>AnyName</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

<servlet-mapping>
	<servlet-name>AnyName</servlet-name>
	<url-pattern>/action/*</url-pattern>
</servlet-mapping>

image-20200221165751696

ServletConfig 接口

• Servlet在有些情况下可能需要访问Servlet容器或借助Servlet容器访问外部的资源,所以,Serlvet引擎需要将表示Servlet容器的对象传递给Servlet。另外,在web.xml文件中为某个Servlet设置的友好名称初始化参数等信息也需要传递给该Servlet

• Servlet引擎将代表Servlet容器的对象(ServletContext)和Servlet的配置参数信息一并封装到一个称为ServletConfig的对象中,并在初始化Servlet实例对象时传递给该Servlet。ServletConfig接口则用于定义ServletConfig对象需要对外提供的方法,以便在Servlet程序中可以调用这些方法来获取有关信息。

• Servlet引擎调用Servlet的实例对象的init(ServletConfig config)方法将ServletConfig对象传递给Servlet。Servlet.getServletConfig()方法必须返回init(ServletConfig config)方法传递进来的这个ServletConfig对象的引用

ServletConfig接口的方法

  • getInitParameterNames
  • getInitParameter
  • getServletName
  • getServletContext

ServletContext接口(application 对象或Web应用程序对象)

• Servlet引擎为每个WEB应用程序都创建一个对应的ServletContext对象,ServletContext对象被包含在ServletConfig对象中,调用ServletConfig.getServletContext方法可以返回ServletContext对象的引用。

• **由于一个WEB应用程序中的所有Servlet都共享同一个ServletContext对象,**所以,ServletContext对象被称之为 application 对象(Web应用程序对象)

• 功能:

  • 获取WEB应用程序的初始化参数
  • 记录日志
  • application域范围的属性
  • 访问资源文件
  • 获取虚拟路径所映射的本地路径
  • WEB应用程序之间的访问
  • ServletContext的其他方法

获取WEB应用程序的初始化参数

• 为WEB应用程序设置初始化参数的好处在于不需要修改Servlet源程序,就可以改变一些参数信息

ServletContext.getInitParameterNames方法用于返回一个包含WEB应用程序的所有初始化参数名称的Enumeration集合对象,ServletContext.getInitParameter方法用于返回某个指定名称的初始化参数值。

• 在web.xml文件的根元素<web-app>中增加<context-param>子元素,如下所示:

<context-param>
     <param-name>companyName</param-name>
     <param-value>lampbrother</param-value>
 </context-param>

获取虚拟路径所映射的本地路径

getRealPath(String path) 方法: 用于返回某个虚拟路径所映射的本地文件系统路径

Servlet登录验证示例

编写继承httpServlet的自定义servlet类UserServlet,重写doGet或者doPost方法。

package com.gxuwz.attends.servlet;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import javax.servlet.ServletException;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 定义用户登录验证Servlet
 * @author x240
 *
 */
public class UserServlet extends HttpServlet{

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		this.doPost(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("C");
		String userid=req.getParameter("userid");
		String pwd=req.getParameter("pwd");
		if("admin".equals(userid)&&"123".equals(pwd)){
			resp.sendRedirect(req.getContextPath()+"/index.jsp");
		}else{
			resp.sendRedirect(req.getContextPath()+"/login.jsp");
		}
	}

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("B");
		super.service(req, resp);
	}

	@Override
	public void init() throws ServletException {
		System.out.println("A");
		super.init();
	}
    
常用的发起请求的方式:get请求和post请求

 1.get请求的发起方式
   通常采用超链接标签发起一个get请求,语法格式如下:
   <a href="api/app/helloworldServlet">发起get请求</a>
       
 2.post请求的发起方式
   通常采用表单标签,显式设置表单标签中method的值为post来发起一个post请求,注意表单标签默认的请求方式为get,语法格式是:

   <form action="api/app/helloworldServlet" method="post">
     <!--表单标签之间可以使用其他的html标签(包括布局标签或者表单元素标签。表单元素标签用于发送请求参数)-->
     <input type="text" name="stuNo" value="20180101003"/>
   </form>    

重写doGet或者doPost方法的目的。

​ 具体业务逻辑的处理,重写doGet或者doPost方法中一般的编码步骤为:

​ (1)接收参数

​ (2)具体业务逻辑的实现(这一部分通常由实现逻辑处理的java程序片段构成)

​ (3)跳转页面。

	//1:接收参数,注意不是使用jsp内置对象request来接收参数,
    //用doGet||doPost方法的方法参数 HttpServletRquest类型的请求对象名称[x]。
      String  userid=x.getParameter("userid");//用户名
      String  password=x.getParameter("pwd"); //密码
     //2:登录验证处理
      boolean flag="admin".equals(userid)&&"123".equals(password);
      if(flag){
          //3:跳转(重定向)
          resp.sendRedirect("index.jsp");
      }else{
          //3:跳转(转发)
            //获得指定路径的转发对象
          RequestDispatcher rd=x.getRequestDispatcher("login.jsp");
            //调用转发对象的xx方法跳转
             rd.forward(x,resp);
       }

配置Servlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>attends_javabean_56</display-name>
  <!-- 配置servlet名称,等价于对象变量 -->
  <servlet>
    <!-- 这里的名字取名随意,建议与类名一致 -->
    <servlet-name>userServlet</servlet-name>
    <!--这里要写servlet的具体路径 -->
    <servlet-class>com.gxuwz.attends.servlet.UserServlet</servlet-class>
  </servlet>
  <servlet-mapping>
     <!--这里的name要设置与上面的name一致-->
    <servlet-name>userServlet</servlet-name>
    <!--映射的URL路径元素,是一个虚拟的请求路径元素,与web目录下的子文件夹没有任何关系
        /表示以及根目录,可以写多级表示具体的作用,取的名字随意-->
    <url-pattern>/system/userServlet</url-pattern>
  </servlet-mapping>
  <welcome-file-list>
    <welcome-file>login.jsp</welcome-file>
  </welcome-file-list>
</web-app>

注意:
在web.xml配置userServlet,由web容器加载并实例化对应的对象,该对象是单例的。
web容器实例化userServlet对象的过程,等价于UserServlet userServlet=new UserServlet()。    

三、HTTP协议简介

• WEB浏览器与WEB服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议

• HTTP是 hypertext transfer protocol(超文本传输协议)的简写,它是 TCP/IP 协议集中的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程以及数据本身的格式。

• HTTP协议的版本 HTTP/1.0、HTTP/1.1、HTTP-NG

1.HTTP 的会话方式

• 四个步骤:

image-20200221171151061

​ – 浏览器与WEB服务器的连接过程是短暂的,每次连接只处理一个请求和响应。对每一个页面的访问,浏览器与WEB服务器都要建立一次单独的连接。

​ – 浏览器到WEB服务器之间的所有通讯都是完全独立分开的请求和响应对。

2.浏览器访问多图网页的过程

image-20200221171234129

3.HTTP请求消息

请求消息的结构:

一个请求行、若干消息头、以及实体内容,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开

image-20200221171329391

4.HTTP响应消息

响应消息的结构:

一个状态行、若干消息头、以及实体内容 ,其中的一些消息头和实体内容都是可选的,消息头和实体内容之间要用空行隔开

image-20200221171417339

5.HTTP消息—>其他细节

• 响应消息的实体内容就是网页文件的内容,也就是在浏览器中使用查看源文件的方式所看到的内容。

• 一个使用GET方式的请求消息中不能包含实体内容,只有使用POST、PUT和DELETE方式的请求消息中才可以包含实体内容。

使用GET和POST方式传递参数

• 在URL地址后面可以附加一些参数

​ 举例:http://www.it315.org/servlet/ParamsServlet?param1=abc&param2=xyz

• GET方式

​ 举例:GET /servlet/ParamsServlet?param1=abc&param2=xyz HTTP/1.1

​ 特点:传送的数据量是有限制的,一般限制在1KB以下。

• POST方式

举例:

POST /servlet/ParamsServlet HTTP/1.1
Host:
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
//空一行
param1=abc&param2=xyz

特点:传送的数据量要比GET方式传送的数据量大得多 。

使用GET方式传递参数

• 在浏览器地址栏中输入某个URL地址或单击网页上的一个超链接时,浏览器发出的HTTP请求消息的请求方式为GET

• 如果网页中的<form>表单元素的method属性被设置为了GET,浏览器提交这个FORM表单时生成的HTTP请求消息的请求方式也为GET

• 使用GET请求方式给WEB服务器传递参数的格式:

http://www.lampbrother.net/counter.jsp?name=lc&password=123

• 使用GET方式传送的数据量一般限制在1KB以下。

使用POST方式传递参数

• POST请求方式主要用于向WEB服务器端程序提交FORM表单中的数据。

• POST方式将各个表单字段元素及其数据作为HTTP消息的实体内容发送给WEB服务器,传送的数据量要比使用GET方式传送的数据量大得多。

//POST请求消息的格式: 
POST /counter.jsp HTTP/1.1
referer: http://localhost:8080/Register.html
content-type: application/x-www-form-urlencoded
host: localhost:8080
content-length: 43
//空一行
name=zhangsan&password=123

image-20200221172311141

6.HttpServletRequest 简介

• Servlet API 中定义的 ServletRequest 接口类用于封装请求消息。

HttpServletRequest 是专用于HTTP协议ServletRequest 子接口,它用于封装 HTTP 请求消息。

• 在 service() 方法内部调用 HttpServletRequest 对象的各种方法来获取请求消息。

获取请求行的相关信息

  • HTTP请求消息的请求行包括请求方式、资源路径和HTTP协议版本:

GET /lampbrother/servlet/RequestURI?param1=a&param2=b HTTP/1.1

  • getMethod:返回HTTP请求消息中的请求方式。
  • getRequestURI:返回请求行中的资源名部分。
  • getQueryString :返回请求行中的参数部分。
  • getProtocol:返回请求行中的协议名和版本。
  • getContextPath:返回请求资源所属于的WEB应用程序的路径。
  • getPathInfo:返回请求URL中的额外路径信息。额外路径信息是请求URL中的位于Servlet的路径之后和查询参数之前的内容,它以/开头。
  • getPathTranslated:返回URL中的额外路径信息所对应的资源的真实路径。
  • getServletPath方法:Servlet的名称或Servlet所映射的路径。

获取网络连接信息

  • getRemoteAddr方法返回发出请求的客户机的IP地址,其格式为192.168.0.3这种形式的字符文本。
  • getRemoteHost方法返回发出请求的客户机的完整主机名,即pc1.atguigu.com这种格式。
  • getRemotePort方法返回发出请求的客户机所使用的网络接口的端口号。
  • getLocalAddr方法返回WEB服务器上接收当前请求的网络接口的IP地址。
  • getLocalName方法返回WEB服务器上接收当前请求的网络接口的IP地址所对应的主机名。
  • getLocalPort方法返回WEB服务器上接收当前请求的网络接口的端口号。
  • getServerName方法返回当前请求所指向的主机名。
  • getServerPort方法返回当前请求所连接的服务器端口号。
  • getScheme方法返回请求的协议名,例如http、https或ftp
  • getRequestURL方法返回客户端发出请求时的完整URL。

获取请求头信息

  • getHeader方法

  • getHeaders方法

  • getHeaderNames方法

  • getIntHeader方法

  • getDateHeader方法

  • getContentType方法

  • getContentLength方法

  • getCharacterEncoding方法

获取请求参数

  • getParameter方法
  • getParameterValues方法
  • getParameterNames方法
  • getParameterMap方法
获取请求参数实例
Enumeration paramNames = request.getParameterNames();
while(paramNames.hasMoreElements())
{
	String paramName = (String)paramNames.nextElement();
	out.print(paramName + " : " + request.getParameter(paramName) + "<br>");
	<%-- 如果要考虑同一个请求头名可能出现多次,那么应该用下面的代码段代替上面一行程序代码 
	String [] paramValues = request.getParameterValues(paramName);
	--%>
    <%--良好的编程习惯,在使用对象和数组之前先判断其是否为null--%>
	if(paramValues != null)
	{
		for(int i=0;i<paramValues.length;i++)
		{
			out.print(paramName + " : " + (String)paramValues[i] + "<br>");
		}
	}
}

请求域属性

• 存储在ServletRequest对象中的对象称之为请求域属性,属于同一个请求的多个处理模块之间可以通过请求域属性来传递对象数据。

与请求域属性相关的方法:

  • setAttribute方法
  • getAttribute方法
  • removeAttribute方法
  • getAttributeNames方法

7.HttpServletResponse简介

• Servlet API中定义的ServletResponse接口类用于创建响应消息。

HttpServletResponse是专用于HTTP协议的ServletResponse子接口,它用于封装HTTP响应消息。

请求重定向与请求转发

RequestDispatcher接口

• 用forward方法实现请求转发

• 请求转发的运行流程

• 用sendRedirect方法实现请求重定向

• 请求重定向的运行流程

• 请求重定向与请求转发的比较

RequestDispatcher接口

RequestDispatcher实例对象是由Servlet引擎创建的,它用于包装一个要被其他资源调用的资源(例如,Servlet、HTML文件、JSP文件等),并可以通过其中的方法将客户端的请求转发给所包装的资源。

RequestDispatcher接口中定义了两个方法:forward方法和include方法。

forwardinclude方法接收的两个参数必须是传递给当前Servletservice方法的那两个ServletRequestServletResponse对象,或者是对它们进行了包装的ServletRequestWrapperServletResponseWrapper对象。

获取RequestDispatcher对象的方法:

  • ServletContext.getRequestDispatcher (参数只能是以“/”开头的路径)
  • ServletContext.getNamedDispatcher
  • ServletRequest.getRequestDispatcher (参数可以是不以“/”开头的路径)

用sendRedirect方法实现请求重定向

sendRedirect 方法不仅可以重定向到当前应用程序中的其他资源,它还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。

• 传递给sendRedirect方法的相对URL以/开头,则是相对于整个WEB站点的根目录,而不是相对于当前WEB应用程序的根目录。

请求转发与请求重定向的比较

  1. RequestDispatcher.forward方法只能将请求转发给同一个WEB应用中的组件;而HttpServletResponse.sendRedirect方法还可以重定向到同一个站点上的其他应用程序中的资源,甚至是使用绝对URL重定向到其他站点的资源。

  2. 创建RequestDispatcher对象时指定的相对URL以/开头,它是相对于当前WEB应用程序的根目录。传递给HttpServletResponse.sendRedirect 方法的相对URL以/开头,它是相对于整个WEB站点的根目录;

  3. 调用RequestDispatcher.forward 方法的请求转发过程结束后,浏览器地址栏保持初始的URL地址不变。调用HttpServletResponse.sendRedirect方法重定向的访问过程结束后,浏览器地址栏中显示的URL会发生改变,由初始的URL地址变成重定向的目标URL;

  4. RequestDispatcher.forward方法在服务器端内部将请求转发给另外一个资源,浏览器只知道发出了请求并得到了响应结果,并不知道在服务器程序内部发生了转发行为。HttpServletResponse.sendRedirect方法对浏览器的请求直接作出响应,响应的结果就是告诉浏览器去重新发出对另外一个URL的访问请求;

  5. RequestDispatcher.forward方法的调用者与被调用者之间共享相同的request对象和response对象,它们属于同一个访问请求和响应过程;而HttpServletResponse.sendRedirect方法调用者与被调用者使用各自的request对象和response对象,它们属于两个独立的访问请求和响应过程。

application域范围的属性

application 对象(ServletContext对象)内部有一个哈希表集合对象,存储进application对象内的哈希表集合对象中的每对关键字/值被称为application对象的属性。

• 存储在application对象中的属性也被称之为application域范围的属性,application域范围的属性可以被当作该WEB应用程序范围内的全局变量使用。

ServletContext接口中定义了4个分别用于增加、删除、访问application域范围的属性的方法:

  • getAttributeNames方法
  • getAttribute方法
  • removeAttribute方法
  • setAttribute方法

四、JSP

1.JSP起源

• 在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变。

• 如果使用Servlet程序来输出只有局部内容需要动态改变的网页,其中所有的静态内容也需要程序员用Java程序代码产生,整个Servlet程序的代码将非常臃肿,编写和维护都将非常困难。

• 对大量静态内容的美工设计和相关HTML语句的编写,并不是程序员所要做的工作,程序员对此也不一定在行。网页美工设计和制作人员不懂Java编程,更是无法来完成这样的工作。

• 为了弥补 Servlet 的缺陷,SUN公司在Servlet的基础上推出了JSP(Java Server Pages)技术作为解决方案。

• JSP是简化Servlet编写的一种技术,它将Java代码和HTML语句混合在同一个文件中编写,只对网页中的要动态产生的内容采用Java代码来编写,而对固定不变的静态内容采用普通静态HTML页面的方式编写。

2.建立对JSP的直观认识

  • JSP页面是由HTML语句和嵌套在其中的Java代码组成的一个普通文本文件,JSP 页面的文件扩展名必须为.jsp
  • 在JSP页面中编写的Java代码需要嵌套在<%%>中,嵌套在<%%>之间的Java代码被称之为脚本片段(Scriptlets),没有嵌套在<%%>之间的内容被称之为JSP的模版元素。
  • JSP中的Java代码可以使用out.println语句将其他Java程序代码产生的结果字符串输出给客户端,也可以使用System.out.println语句将它们打印到命令行窗口。
  • JSP文件就像普通的HTML文件一样,它们可以放置在WEB应用程序中的除了WEB-INF及其子目录外的其他任何目录中,JSP页面的访问路径与普通HTML页面的访问路径形式也完全一样。
  • 在JSP页面中也可以使用一种称之为JSP表达式的元素,只需将要输出的变量或表达式直接封装在<%=%>之中,就可以向客户端输出这个变量或表达式的运算结果。在JSP表达式中嵌套的变量或表达式后面不能有分号

3.JSP的运行原理

• WEB容器(Servlet引擎)接收到以.jsp为扩展名的URL的访问请求时,它将把该访问请求交给JSP引擎去处理。

• 每个JSP 页面在第一次被访问时,JSP引擎将它翻译成一个Servlet源程序,接着再把这个Servlet源程序编译成Servlet的class类文件,然后再由**WEB容器(Servlet引擎)**像调用普通Servlet程序一样的方式来装载和解释执行这个由JSP页面翻译成的Servlet程序。

• JSP规范也没有明确要求JSP中的脚本程序代码必须采用Java语言,JSP中的脚本程序代码可以采用Java语言之外的其他脚本语言来编写,但是,JSP页面最终必须转换成Java Servlet程序。

• 可以在WEB应用程序正式发布之前,将其中的所有JSP页面预先编译成Servlet程序。

4.注册与配置JSP页面的访问路径

<servlet>
	<servlet-name>SimpleJspServlet</servlet-name>
	<jsp-file>/jsp/simple.jsp</jsp-file>
	<load-on-startup>1</load-on-startup >
</servlet>
	……
<servlet-mapping>
	<servlet-name>SimpleJspServlet</servlet-name>
	<url-pattern>/xxx/yyy.html</url-pattern>
</servlet-mapping>

5.JSP与Servlet的应用比较

  1. JSP是一种以产生网页显示内容为中心的WEB开发技术,它可以直接使用模版元素来产生网页文档的内容。
  2. JSP页面的源文件要比Servlet源文件简单,并且JSP页面的开发过程要比Servlet的开发过程简单得多。
  3. JSP引擎可以对JSP页面的修改进行检测,并自动重新翻译和编译修改过的JSP文件。
  4. JSP技术是建立在Servlet技术基础之上的,所有的JSP页面最终都要被转换成Servlet来运行。
  5. 在大型WEB应用程序的开发中,Servlet与JSP经常要混合使用,各司其职,Servlet通常用作控制组件,并处理一些复杂的后台业务,JSP则作为显示组件。
  6. 一次响应过程可以划分成几个功能模块来协同完成,首先Servlet完成流程控制和业务处理,并将结果数据存储在requestsession域中,然后将请求转发(forward)到JSP页面,再由JSP页面从requestsession域中取出结果数据并完成响应内容的输出。通过这种方式实现业务逻辑与显示内容的分离,从而将应用程序开发者和网页作者的工作分离。

6.JSP基本语法

JSP模版元素

JSP页面中的静态HTML内容称之为JSP模版元素,在静态的HTML内容之中可以嵌套JSP的其他各种元素来产生动态内容和执行业务逻辑。

• JSP模版元素定义了网页的基本骨架,即定义了页面的结构和外观。

JSP表达式<%= %>

• JSP表达式(expression)提供了将一个java变量或表达式的计算结果输出到客户端的简化方式,它将要输出的变量或表达式直接封装在<%=%>之中。

举例:Current time: <%= new java.util.Date() %>

• JSP表达式中的变量或表达式的计算结果将被转换成一个字符串,然后被插入进整个JSP页面输出结果的相应位置处。

• JSP表达式中的变量或表达式后面不能有分号(;),JSP表达式被翻译成Servlet程序中的一条out.print(…)语句。

JSP脚本片断 (1)<% %>

• JSP脚本片断(scriptlet)是指嵌套在<%%>之中的一条或多条Java程序代码。

• 在JSP脚本片断中,可以定义变量、执行基本的程序运算、调用其他Java类、访问数据库、访问文件系统等普通Java程序所能实现的功能。

• 在JSP脚本片断可以直接使用JSP提供的隐式对象来完成WEB应用程序特有的功能。

• JSP脚本片断中的Java代码将被原封不动地搬移进由JSP页面所翻译成的Servlet的jspService方法中,所以,JSP脚本片断之中只能是符合Java语法要求的程序代码,除此之外的任何文本、HTML标记、其他JSP元素都必须在脚本片断之外编写。

• JSP脚本片断中的Java代码必须严格遵循Java语法,例如,每条命令执行语句后面必须用分号(;)结束。

• 在一个JSP页面中可以有多个脚本片断(每个脚本片断代码嵌套在各自独立的一对<%%>之间),在两个或多个脚本片断之间可以嵌入文本、HTML标记和其他JSP元素。

JSP脚本片断 (2)<% %>

image-20200408230623677

JSP脚本片断 (3)<% %>

• **单个脚本片断中的Java语句可以是不完整的,但是,多个脚本片断组合后的结果必须是完整的Java语句,**例如,涉及条件和循环处理时,多个脚本片断及其他元素组合的结果必须能形成完整的条件和循环控制语句。

• 由于脚本片断中的Java代码将被原封不动地搬移进由JSP页面所翻译成的Servlet的jspService方法中,脚本片断之外的任何文本、HTML标记以及其他JSP元素也都会被转换成相应的Java程序代码插入进jspService方法中,且脚本片断和其他JSP元素的插入位置与它们在JSP页面中的原始位置相对应。

• 在脚本片断中可以使用条件、循环、选择等流程控制语句来创建其周围的其他元素的执行逻辑,因此,在编写JSP页面时应考虑各个元素之间的先后顺序和相互关系,特别是将循环、条件判断等语句分布在若干个脚本片断中编写时对其邻近的其他JSP元素产生的影响。

image-20200221175556052

JSP声明<%! %>

• JSP声明将Java代码封装在<%!%>之中,它里面的代码将被插入进Servlet的jspService方法的外面,所以,JSP声明可用于定义JSP页面转换成的Servlet程序的静态代码块、成员变量和方法

• 多个静态代码块、变量和函数可以定义在一个JSP声明中,也可以分别单独定义在多个JSP声明中。

JSP隐式对象的作用范围仅限于Servlet的_jspService方法,所以在JSP声明中不能使用这些隐式对象。

JSP声明实例

<%!
    static { System.out.println("loading Servlet!"); }
    private int globalVar = 0;
    public void jspInit(){
            System.out.println("initializing jsp!");
    }
%>
<%!
    public void jspDestroy(){
        System.out.println("destroying jsp!");
    }
%>
<%
	int localVar = 0;
%>
globalVar:<%= ++globalVar %><br> 
localVar:<%= ++localVar %>

JSP注释 <%-- 注释信息 --%>

• JSP注释的格式:

<%-- 注释信息 --%>

• JSP引擎在将JSP页面翻译成Servlet程序时,忽略JSP页面中被注释的内容。

7.如何查找JSP页面中的错误

• JSP页面中的JSP语法格式有问题,导致其不能被翻译成Servlet源文件,JSP引擎将提示这类错误发生在JSP页面中的位置(行和列)以及相关信息。

• JSP页面中的JSP语法格式没有问题,但被翻译成的Servlet源文件中出现了Java语法问题,导致JSP页面翻译成的Servlet源文件不能通过编译,JSP引擎也将提示这类错误发生在JSP页面中的位置(行和列)以及相关信息。

• JSP页面**翻译成的Servlet程序在运行时出现异常,**这与普通Java程序的运行时错误完全一样,Java虚拟机将提示错误发生在Servlet源文件中的位置(行和列)以及相关信息。

8.out隐式对象

在JSP页面中应使用out隐式对象来向客户端发送文本形式的实体内容。

out对象是通过调用pageContext对象的getOut方法返回的,其作用和用法与ServletResponse.getWriter方法返回的PrintWriter对象非常相似。

• JSP页面中的out隐式对象的类型为JspWriterJspWriter相当于一种带缓存功能的PrintWriter,设置JSP页面的page指令的buffer属性可以调整它的缓存大小,甚至关闭它的缓存。

• JSP页面中的out隐式对象相当于插入到ServletResponse.getWriter方法返回的PrintWriter对象前面的缓冲包装类对象。

• 只有向out对象中写入了内容,且满足如下任何一个条件时,out对象才去调用ServletResponse.getWriter方法,并通过该方法返回的PrintWriter对象将out对象的缓冲区中的内容真正写入到Servlet引擎提供的缓冲区中:

​ 设置page指令的buffer属性关闭了out对象的缓存功能

​ 写入到out对象中的内容充满了out对象的缓冲区

​ 整个JSP页面结束

out隐式对象的工作原理图

image-20200221180344560

9.pageContext对象

pageContext对象简介

pageContext对象封装了当前JSP页面的运行信息,它提供了返回JSP页面的其他隐式对象的方法。

PageContext类中定义了一个setAttribute方法来将对象存储进pageContext对象内部的一个HashMap对象中,同时也定义了一个getAttribute方法来检索存储在该HashMap对象中的对象。

PageContext类除了可以存储和检索自身中的属性对象外,还定义了可以存储和检索其他域范围内的属性对象的方法。

获得其他隐式对象

getException方法返回exception隐式对象

getPage方法返回page隐式对象

getRequest方法返回request隐式对象

getResponse方法返回response隐式对象

getServletConfig方法返回config隐式对象

getServletContext方法返回application隐式对象

getSession方法返回session隐式对象

getOut方法返回out隐式对象

引入和跳转到其他资源

PageContext类中定义了一个forward方法和两个include方法来分别简化和替代RequestDispatcher.forward方法和RequestDispatcher.include方法的调用:

image-20200408231819383

• 传递给这些方法的资源路径都只能是相对路径,如果路径以/开头,表示相对于当前WEB应用程序的根目录,否则,表示相对于当前JSP所映射到的访问路径。

访问各个域范围中的属性

• 在application、session、request、pageContext对象中都可以调用setAttribute方法和getAttribute方法来设置和检索各自域范围内的属性。

• 存储在application对象中的属性可以被同一个WEB应用程序中的所有Servlet和JSP页面访问

存储在session对象中的属性可以被属于同一个会话的所有Servlet和JSP页面访问。

• 存储在request对象中的属性可以被属于同一个请求的所有Servlet和JSP页面访问,例如使用PageContext.forwardPageContext.include方法连接起来的多个Servlet和JSP页面。

• 存储在pageContext对象中的属性仅可以被当前JSP页面的当前响应过程中调用的各个组件访问,例如,正在响应当前请求的JSP页面和它调用的各个自定义标签类。

PageContext类中还提供了对各个域范围的属性进行统一管理的方法,以简化对各个域范围内的属性的访问。

•  setAttribute方法 
  	public void setAttribute(java.lang.String name,java.lang.Object value)
  	public void setAttribute(java.lang.String name,	java.lang.Object value,int scope) 
							 					
•  常量
      PageContext.APPLICATION_SCOPE
      PageContext.SESSION_SCOPE
      PageContext.REQUEST_SCOPE
      PageContext.PAGE_SCOPE

•  getAttribute方法
      public java.lang.Object getAttribute(java.lang.String name)
      public java.lang.Object getAttribute(java.lang.String name,int scope)

•  removeAttribute方法 
      public void removeAttribute(java.lang.String name)
      public void removeAttribute(java.lang.String name,int scope)

•  getAttributeNamesInScope方法 

•  findAttribute方法    

10.JSP指令<%@ %>

1.JSP指令简介

image-20200221181459090

2.page指令

image-20200221181524604

3.include指令

image-20200221181555559

image-20200221181626986

image-20200221181654050

11.JSP标签概念

• JSP还提供了一种称之为Action的元素,在JSP页面中使用Action元素可以完成各种通用的JSP页面功能,也可以实现一些处理复杂业务逻辑的专用功能。

• Action元素采用XML元素的语法格式,即每个Action元素在JSP页面中都以XML标签的形式出现。

• JSP规范中定义了一些标准的Action元素,这些元素的标签名都以jsp作为前缀,并且全部采用小写,例如,<jsp:include><jsp:forward>等等。

12.JSP标签内容

<jsp:include>标签

image-20200221182016656

image-20200221182221961

<jsp:include>标签与include指令的比较

•  <jsp:include>标签是在当前JSP页面的执行期间插入被引入资源的输出内容,
    当前JSP页面与被动态引入的资源是两个彼此独立的执行实体,
    被动态引入的资源必须是一个能独立被WEB容器调用和执行的资源。
    
    include指令只能引入遵循JSP格式的文件,被引入文件与当前JSP文件共同合被翻译成一个Servlet的源文件。 

•  使用<jsp:include>标签和include指令都可以把一个页面的内容分成多个组件来生成,
    开发者不必再把页眉和页脚部分的相同HTML代码复制到每个JSP文件中,从而可以更轻松地完成维护工作,
    但是都应注意最终的输出结果内容应遵循HTML语法结构,
    例如,如果当前页面产生了<html>、</html>、<body>、</body>等标记,
    那么在被引入文件中就不能再输出<html>、</html>、<body>、</body>等标记。 

•  <jsp:include>标签对JSP引擎翻译JSP页面的过程不起作用,它是在JSP页面的执行期间才被调用,
    因此不会影响两个页面的编译。由于include指令是在JSP引擎翻译JSP页面的过程中被解释处理的,
    所以它对JSP引擎翻译JSP页面的过程起作用,如果多个JSP页面中都要用到一些相同的声明,
    那么就可以把这些声明语句放在一个单独的文件中编写,然后在每个JSP页面中使用include指令将那个文件包含进来。 

<jsp:forward>标签

image-20200221182306555

<jsp:param>标签

image-20200221182330722

13.JSP中文乱码

image-20200221182406565

image-20200221182432211

五、MVC 设计模式

1.组件开发

image-20200409122439937

JavaEE 开发中常见的组件

image-20200409122519193

2.JavaEE 开发流程

image-20200221191554261

image-20200221191649679

3.MVC处理过程

image-20200221191629601

4.MVC的概念

• MVC是Model-View-Controller的简称,即模型-视图-控制器

• MVC是一种设计模式,它把应用程序分成三个核心模块:模型、视图、控制器,它们各自处理自己的任务。

模型(model)

• 模型是应用程序的主体部分,模型表示业务数据和业务逻辑。

• 一个模型能为多个视图提供数据。

• 由于应用于模型的代码只需写一次就可以被多个视图重用,所以提高了代码的可重用性。

视图

• 视图是用户看到并与之交互的界面,作用如下:

​ – 视图向用户显示相关的数据。

​ – 接受用户的输入。

​ – 不进行任何实际的业务处理。

控制器

• 控制器接受用户的输入并调用模型和视图去完成用户的需求。

• 控制器接收请求并决定调用哪个模型组件去处理请求,然后决定调用哪个视图来显示模型处理返回的数据。

image-20200221192029161

image-20200221192050862

六、会话与状态管理(HttpSession)

提出问题

• **HTTP协议是一种无状态的协议,**WEB服务器本身不能识别出哪些请求是同一个浏览器发出的 ,浏览器的每一次请求都是完全孤立的

• 即使HTTP1.1支持持续连接,但当用户有一段时间没有提交请求,连接也会关闭。

• 怎么才能实现网上商店中的购物车呢:某个用户从网站的登录页面登入后,再进入购物页面购物时,负责处理购物请求的服务器程序必须知道处理上一次请求的程序所得到的用户信息。

作为 web 服务器,必须能够采用一种机制来唯一地标识一个用户,同时记录该用户的状态

会话和会话状态

• WEB应用中的会话是指一个客户端浏览器与WEB服务器之间连续发生的一系列请求和响应过程。

• WEB应用的会话状态是指WEB服务器与浏览器在会话过程中产生的状态信息,借助会话状态,WEB服务器能够把属于同一会话中的一系列的请求和响应过程关联起来。

1.如何实现有状态的会话

• WEB服务器端程序要能从大量的请求消息中区分出哪些请求消息属于同一个会话,即能识别出来自同一个浏览器的访问请求,这需要浏览器对其发出的每个请求消息都进行标识:属于同一个会话中的请求消息都附带同样的标识号,而属于不同会话的请求消息总是附带不同的标识号,这个标识号就称之为会话IDSessionID)。

在 Servlet 规范中,常用以下两种机制完成会话跟踪

​ – Cookie

​ – Session

Cookie机制

• cookie机制采用的是在客户端保持 HTTP 状态信息的方案

• Cookie是在浏览器访问WEB服务器的某个资源时,由WEB服务器在HTTP响应消息头中附带传送给浏览器的一个小文本文件。

• 一旦WEB浏览器保存了某个Cookie,那么它在以后每次访问该WEB服务器时,都会在HTTP请求头中将这个Cookie回传给WEB服务器。

• 底层的实现原理: WEB服务器通过在HTTP响应消息中增加Set-Cookie响应头字段将Cookie信息发送给浏览器,浏览器则通过在HTTP请求消息中增加Cookie请求头字段将Cookie回传给WEB服务器。

• 一个Cookie只能标识一种信息,它至少含有一个标识该信息的名称(NAME)和设置值(VALUE)。

• 一个WEB站点可以给一个WEB浏览器发送多个Cookie,一个WEB浏览器也可以存储多个WEB站点提供的Cookie。

• 浏览器一般只允许存放300个Cookie,每个站点最多存放20个Cookie,每个Cookie的大小限制为4KB

Cookie的传送过程示意图

image-20200221193712966

在Servlet程序中使用Cookie

Servlet API中提供了一个javax.servlet.http.Cookie类来封装Cookie信息,它包含有生成Cookie信息提取Cookie信息的各个属性的方法。

• Cookie类的方法:

​ 构造方法: public Cookie(String name,String value)

getName方法

setValue与getValue方法

setMaxAge与getMaxAge方法

setPath与getPath方法

HttpServletResponse接口中定义了一个addCookie方法,它用于在发送给浏览器的HTTP响应消息中增加一个Set-Cookie响应头字段。

HttpServletRequest接口中定义了一个getCookies方法,它用于从HTTP请求消息的Cookie请求头字段中读取所有的Cookie项。

Cookie的发送

• 1.创建Cookie对象

• 2.设置最大时效

• 3.将Cookie放入到HTTP响应报头

​ – 如果创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie; 存储在浏览器的内存中,用户退出浏览器之后被删除。若希望浏览器将该cookie存储在磁盘上,则需要使用maxAge,并给出一个以为单位的时间。将最大时效设为0则是命令浏览器删除该cookie

​ – 发送cookie需要使用HttpServletResponseaddCookie方法,将cookie插入到一个 Set-Cookie HTTP响应报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创建新的报头,因此将这个方法称为是addCookie,而非setCookie

会话cookie和持久cookie的区别

• 如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览器会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。

• 如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。

• 存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。

Cookie的读取

• 1.调用request.getCookies

​ 要获取浏览器发送来的cookie,需要调用HttpServletRequestgetCookies方法,这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。

• 2.对数组进行循环,调用每个cookiegetName方法,直到找到感兴趣的cookie为止

自动登录

不需要填写用户名和密码等信息,可以自动登录到系统

image-20200221193943834

显示最近浏览的 5 本书的 title

image-20200221194011263

跟踪用户上次访问站点的时间

功能:

​ 帮助网站实现提示客户端计算机上次访问网站的时间

实现原理:

​ 将每一个会话作为一次访问过程,将每次会话的开始时间作为每次访问网站的时间,然后将这个时间以Cookie的形式存储到客户端的计算机中,客户端进行下次访问时通过该Cookie回传上次访问站点的时间值。

​ 为了让Cookie信息在客户端浏览器或计算机关闭后仍然保持存在,Cookie的保存时间被设置为了一年。

2.session在不同环境下的不同含义

session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session

session在Web开发环境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。

3.Session机制

session机制采用的是在服务器端保持 HTTP 状态信息的方案 。

• 服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。

• 当程序需要为某个客户端的请求创建一个session时,服务器首先检查这个客户端的请求里是否包含了一个session标识(即sessionId),如果已经包含一个sessionId则说明以前已经为此客户创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。

• 如果客户请求不包含sessionId,则为此客户创建一个session并且生成一个与此session相关联的sessionId,这个session id将在本次响应中返回给客户端保存。

image-20200221194219187

保存session id的几种方式

• 保存session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。

• 由于cookie可以被人为的禁用,必须有其它的机制以便在cookie被禁用时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id

Session cookie

session通过SessionID来区分不同的客户,session是以cookieURL重写为基础的,默认使用cookie来实现,系统会创造一个名为JSESSIONID的输出cookie,这称之为session cookie,以区别persistent cookies(也就是我们通常所说的cookie)

session cookie是存储于浏览器内存中的,并不是写到硬盘上的,通常看不到JSESSIONID,但是当把浏览器的cookie禁止后,web服务器会采用URL重写的方式传递Sessionid,这时地址栏看到

session cookie针对某一次会话而言,会话结束session cookie也就随着消失了,而persistent cookie只是存在于客户端硬盘上的一段文本。

• 关闭浏览器,只会使浏览器端内存里的session cookie消失,但不会使保存在服务器端的session对象消失,同样也不会使已经保存到硬盘上的持久化cookie消失。

Session的创建与删除

• 一个常见的错误是以为session在有客户端访问时就被创建,然而事实是直到某server端程序(如Servlet)调用HttpServletRequest.getSession(true)或者 HttpServletRequest.getSession()这样的语句时才会被创建。

• session在下列情况下被删除:

​ – A.程序调用HttpSession.invalidate()

​ – B.距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间

​ – C.服务器进程被停止

注意:关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象失效。

两个浏览器窗口访问应用程序会使用同一个session

• 通常session cookie是不能跨窗口使用的(IE 8 版本以前),当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的session id,这样信息共享的目的就达不到了。

• 此时可以先把session id保存在persistent cookie中(通过设置cookie的最大有效时间),然后在新窗口中读出来,就可以得到上一个窗口的session id了,这样通过session cookiepersistent cookie的结合就可以实现了跨窗口的会话跟踪。

Session的超时管理

• WEB服务器无法判断当前的客户端浏览器是否还会继续访问,也无法检测客户端浏览器是否关闭,所以,即使客户已经离开或关闭了浏览器,WEB服务器还要保留与之对应的HttpSession对象。

• 随着时间的推移而不断增加新的访问客户端,WEB服务器内存中将会因此积累起大量的不再被使用的HttpSession对象,并将最终导致服务器内存耗尽。

WEB服务器采用“超时限制”的办法来判断客户端是否还在继续访问,如果某个客户端在一定的时间之内没有发出后续请求,WEB服务器则认为客户端已经停止了活动,结束与该客户端的会话并将与之对应的HttpSession对象变成垃圾。

• 如果客户端浏览器超时后再次发出访问请求,WEB服务器则认为这是一个新的会话的开始,将为之创建新的HttpSession对象和分配新的会话标识号。

会话的超时间隔可以在web.xml文件中设置,其默认值由Servlet容器定义。

<session-config>
    <!-- 表示30分钟 -->
	<session-timeout>30</session-timeout>
</session-config>

HttpSession接口中的方法

image-20200221194727409

HttpServletRequest接口中的Session方法

getSession方法

public HttpSession getSession(boolean create)

public HttpSession getSession()

isRequestedSessionIdValid方法

isRequestedSessionIdFromCookie方法

isRequestedSessionIdFromURL方法

image-20200409132129830

image-20200409132145100

利用URL重写实现Session跟踪

Servlet规范中引入了一种补充的会话管理机制,**它允许不支持Cookie的浏览器也可以与WEB服务器保持连续的会话。**这种补充机制要求在响应消息的实体内容中必须包含下一次请求的超链接,并将会话标识号作为超链接的URL地址的一个特殊参数。

• **将会话标识号以参数形式附加在超链接的URL地址后面的技术称为URL重写。**如果在浏览器不支持Cookie或者关闭了Cookie功能的情况下,WEB服务器还要能够与浏览器实现有状态的会话,就必须对所有可能被客户端访问的请求路径(包括超链接、form表单的action属性设置和重定向的URL)进行URL重写

• HttpServletResponse接口中定义了两个用于完成URL重写方法:

encodeURL方法

encodeRedirectURL方法

application域范围的属性

image-20200221195037348

Session域范围的属性

image-20200221195057915

什么时候会创建HttpSession对象

1.是否浏览器访问服务端的任何一个 JSPServlet,服务器都会立即创建一个 HttpSession 对象呢?

​ 不一定。若当前的 JSP(或 Servlet) 是客户端访问的当前 WEB 应用的第一个资源,且 JSP 的 page 指定的 session 属性值为 false, 则服务器就不会为 JSP 创建一个 HttpSession 对象;若当前 JSP 不是客户端访问的当前 WEB 应用的第一个资源,且其他页面已经创建一个 HttpSession 对象,则当前 JSP 页面会返回一个会话的 HttpSession 对象,而不会创建一个新的 HttpSession对象

​ 对于 Serlvet 而言,若 Serlvet 是客户端访问的第一个 WEB 应用的资源,则只有调用了 request.getSession()request.getSession(true) 才会创建 HttpSession 对象

2.session="false" 到底表示什么意思?

​ 当前 JSP 页面禁用 session 隐含变量!但可以使用其他的显式的 HttpSession 对象

4.避免表单的重复提交

• 调用 RequestDispatcher.forward() 方法,浏览器所保留的URL 是先前的表单提交的 URL,此时点击”刷新”, 浏览器将再次提交用户先前输入的数据,引起重复提交

• 如果采用 HttpServletResponse.sendRedirct()方法将客户端重定向到成功页面,将不会出现重复一条问题

JS 客户端避免表单重复提交

image-20200221195346598

不足:当用户单击”刷新”,或单击”后退”再次提交表单,将导致表单重复提交

利用Session防止表单重复提交

• 包含有FORM表单的页面必须通过一个服务器程序动态产生,服务器程序为每次产生的页面中的FORM表单都分配一个唯一的随机标识号,并在FORM表单的一个隐藏字段中设置这个标识号,同时在当前用户的Session域中保存这个标识号。

• 当用户提交FORM表单时,负责接收这一请求的服务器程序比较FORM表单隐藏字段中的标识号与存储在当前用户的Session域中的标识号是否相同,如果相同则处理表单数据,处理完后清除当前用户的Session域中存储的标识号。在下列情况下,服务器程序将忽略提交的表单请求:

​ 当前用户的Session中不存在表单标识号

​ 用户提交的表单数据中没有标识号字段

​ 存储在当前用户的Session域中的表单标识号与表单数据中的标识号不同

• 浏览器只有重新向WEB服务器请求包含FORM表单的页面时,服务器程序才又产生另外一个随机标识号,并将这个标识号保存在Session域中和作为新返回的FORM表单中的隐藏字段值。

• 问题:

同一个用户打开同一个浏览器进程的多个窗口来并发访问同一个WEB站点的多个FORM表单页面时,将会出现表单无法正常提交的情况。

• 解决方案:

​ 1. 将FORM表单的标识号作为表单隐藏字段的名称,如下所示:

<input type='hidden' name='4b15c6b2f573831b4b5107d849fcafb8' value=''>
     2. 将所有的表单标识号存储进一个`Vector`集合对象中,并将`Vector`集合对象存储进`Session`域中。当表单提交时,先从`Session`域中取出`Vector`集合对象,然后再从`Vector`集合对象中逐一取出每个表单标识号作为参数调用`HttpServletRequest.getParameter`方法,如果其中有一次调用的返回值不为`null`,则接受并处理该表单数据,处理完后将该表单标识号从`Vector`集合对象中删除。

利用Session实现一次性验证码

image-20200409132707469

• 一次性验证码的主要目的就是为了限制人们利用工具软件来暴力猜测密码,其原理与利用Session防止表单重复提交的原理基本一样,只是将表单标识号变成了验证码的形式,并且要求用户将提示的验证码手工填写进一个表单字段中,而不是通过表单的隐藏字段自动回传给服务器。

• 服务器程序接收到表单数据后,首先判断用户是否填写了正确的验证码,只有该验证码与服务器端保存的验证码匹配时,服务器程序才开始正常的表单处理流程。

• 密码猜测工具要逐一尝试每个密码的前题条件是先输入正确的验证码,而验证码是一次性有效的,这样基本上就阻断了密码猜测工具的自动地处理过程。

源码获取

至此,我们的JavaWeb的学习(上)就讲解完成了。下篇我们将介绍JavaBean、自定义标签、过滤器Filter、监听器、文件的上传下载、国际化,源码素材可以通过关注我的微信公众号 我爱学习呀嘻嘻 ,回复关键字JavaWeb源码素材进行获取哦。

JavaWeb的学习(下):JavaBean、自定义标签、过滤器Filter、监听器、文件的上传下载、国际化

image-20211108230322493

这篇关于JavaWeb的学习(上)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!