集合多天关于JavaWeb开发的学习笔记。利用Servlet开发web应用程序很高效。接下来将学习使用Spring MVC开发web应用程序。
基本概念
- web开发
- web就是网页的意思,如www.baidu.com
- 静态web
- html,css
- 提供给所有人看的数据始终不会发生变化
- 动态web
- 淘宝,几乎是所有网站
- 提供给所有人看的数据始终会发生变化,每个人在不同时间,不同地点看到的网页信息各不相同
- 技术栈:Servlet/JSP,ASP,PHP
- 在Java中,动态web资源开发的技术统称为JavaWeb
- web应用程序:可以提供浏览器访问的程序
- xxx.html…多个web资源,这些资源可以被外界访问,对外界提供服务
- 我们能访问到的任何一个页面或者资源,都存在于这个世界上某一台计算机上
- 统一的web资源会被放在同一个文件夹下,web应用程序–>Tomcat服务器
- 一个web应用由多个部分组成(静态web,动态web)
- html,css,js
- jsp,servlet
- Java程序
- jar包
- 配置文件(properties)
- web应用程序编写完毕后,若想提供给外界访问,需要一个服务器来统一管理
- 静态web
- *.htm,*.html
- 静态web缺点
- web页面无法动态更新,所有用户看到的都是同一个页面
- 轮播图,点击特效:伪动态
- JavaScript:实际开发使用最多
- VBScript
- 无法和数据库交互(数据无法持久化,用户无法交互)
- web页面无法动态更新,所有用户看到的都是同一个页面
- 动态web
- 页面会动态展示,web页面的展示效果因人而异
- 优点
- web页面可以动态更新,提供多样化服务
- 可以于数据库交互(数据持久化:注册,商品信息,用户信息…)
- 缺点
- 若服务器的动态web资源发生错误,需要重新编写后台程序,停机维护,重新发布
web服务器
分类
-
ASP
- 微软:国内最早流行的服务器
- 在HTML嵌入VB脚本,ASP+COM
- 在ASP开发中,基本一个页面都有几千行业务代码,页面及其混乱
- 维护成本高
- C#
-
PHP
- PHP开发速度很快,功能很强大,跨平台,代码简单
- 无法承担大访问量
-
JSP/Servlet
- sun公司主推的B/S架构
- 基于Java语言(所有大公司,或者一些开源组件,都是用Java写的)
- 可以承载三高问题带来的影响
- 语法像ASP
-
IIS
- 微软windows自带
-
Tomcat
- 实际上运行JSP页面和Servlet
- 免费开源web服务器,属于轻量级应用服务器
- 在中小型系统和并发用户不多的场合下被普遍使用
- 开发和调试JSP程序的首选
- JavaWeb初学者最佳选择
网站结构
- JavaWeb网站结构
|--RootDir :Tomcat服务器的web目录
|--webapp:网站目录名
|--WEB-INF
|--classes:Java程序
|--lib:web应用所依赖的jar包
|--web.xml:网站配置文件
|--index.html:默认首页
|--static
|--css
|--style.css
|--js
|--img
|--......
Servlet
Servlet简介
- Servlet(Server Applet)是 Java Servlet 的简称,是使用 Java 语言编写的运行在服务器端的程序。具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容
- 通常来说,Servlet 是指所有实现了 Servlet 接口的类
- Servlet 主要用于处理客户端传来的 HTTP 请求,并返回一个响应,它能够处理的请求有 doGet() 和 doPost() 等
- Servlet 由 Servlet 容器提供,Servlet 容器是指提供了 Servlet 功能的服务器(如 Tomcat)
- Servlet 容器会将 Servlet 动态加载到服务器上,然后通过 HTTP 请求和 HTTP 应与客户端进行交互
- Servlet 应用程序的体系结构如下图所示
- Servlet 的请求首先会被 HTTP 服务器(如 Apache)接收,HTTP 服务器只负责静态 HTML 页面的解析,而 Servlet 的请求会转交给 Servlet 容器,Servlet 容器会根据 web.xml 文件中的映射关系,调用相应的 Servlet,Servlet 再将处理的结果返回给 Servlet 容器,并通过 HTTP 服务器将响应传输给客户端
- Servlet技术特点
- 方便
- Servlet 提供了大量的实用工具例程,如处理很难完成的 HTML 表单数据、读取和设置 HTTP 头,以及处理 Cookie 和跟踪会话等
- 跨平台
- Servlet 使用 Java 类编写,可以在不同的操作系统平台和不同的应用服务器平台运行
- 灵活性和可扩展性强
- 采用 Servlet 开发的 Web 应用程序,由于 Java 类的继承性及构造函数等特点,使得应用灵活,可随意扩展
- 除了上述几点以外,Servlet 还具有功能强大、能够在各个程序之间共享数据、安全性强等特点
- 方便
Servlet相关接口和类
-
在 Servlet 接口中定义了 5 个抽象方法
其中 init()、service() 和 destroy() 方法可以表现 Servlet 的生命周期,它们会在某个特定的时刻被调用 -
Servlet 的接口有两个默认的接口实现类:GenericServlet 和 HttpServlet
- GenericServlet 是一个抽象类,该类为 Servlet 接口提供了部分实现,它并没有实现 HTTP 请求处理
- HttpServlet 是 GenericServlet 的子类,它继承了 GenericServlet 的所有方法,并且为 HTTP 请求中的 GET 和 POST 等类型提供了具体的操作方法。通常情况下,编写的 Servlet 类都继承自 HttpServlet,在开发中使用的也是 HttpServlet 对象
-
HttpServlet 类中包含两个常用方法
-
HttpServlet 主要有两大功能,具体如下
- 根据用户请求方式的不同,定义相应的 doXxx() 方法处理用户请求。例如,与 GET 请求方式对应的 doGet() 方法,与 POST 方式对应的 doPost() 方法
- 通过 service() 方法将 HTTP 请求和响应分别强转为 HttpServletRequest 和 HttpServletResponse 类型的对象
-
需要注意的是,由于 HttpServlet 类在重写的 service() 方法中,为每一种 HTTP 请求方式都定义了对应的 doXxx() 方法,因此,当定义的类继承 HttpServlet 后,只需要根据请求方式重写对应的 doXxx() 方法即可,而不需要重写 service() 方法
Servlet生命周期
-
Servlet声明周期如下图
-
按照功能的不同,大致可以将 Servlet 的生命周期分为三个阶段,分别是初始化阶段、运行阶段和销毁阶段
-
初始化阶段
- 当客户端向 Servlet 容器发出 HTTP 请求要求访问 Servlet 时,Servlet 容器首先会解析请求,检查内存中是否已经有了该 Servlet 对象,如果有,则直接使用该 Servlet 对象,如果没有,则创建 Servlet 实例对象,然后通过调用 init() 方法实现 Servlet 的初始化工作。需要注意的是,在 Servlet 的整个生命周期内,它的 init() 方法只能被调用一次
-
运行阶段
- 这是 Servlet 生命周期中最重要的阶段,在这个阶段中,Servlet 容器会为这个请求创建代表 HTTP 请求的 ServletRequest 对象和代表 HTTP 响应的 ServletResponse 对象,然后将它们作为参数传递给 Servlet 的 service() 方法
- service() 方法从 ServletRequest 对象中获得客户请求信息并处理该请求,通过 ServletResponse 对象生成响应结果
- 在 Servlet 的整个生命周期内,对于 Servlet 的每一次访问请求,Servlet 容器都会调用一次 Servlet 的 service() 方法,并且创建新的 ServletRequest 和 ServletResponse 对象,也就是说,service() 方法在 Servlet 的整个生命周期中会被调用多次
-
销毁阶段
- 当服务器关闭或 Web 应用被移除出容器时,Servlet 随着 Web 应用的关闭而销毁。在销毁 Servlet 之前,Servlet 容器会调用 Servlet 的 destroy() 方法,以便让 Servlet 对象释放它所占用的资源。在 Servlet 的整个生命周期中,destroy() 方法也只能被调用一次
-
-
需要注意的是,Servlet 对象一旦创建就会驻留在内存中等待客户端的访问,直到服务器关闭或 Web 应用被移除出容器时,Servlet 对象才会销毁
Servlet配置虚拟路径映射
- 在 web.xml 文件中,一个 <servlert-mapping> 元素用于映射一个 Servlet 的对外访问路径,该路径也称为虚拟路径
- 创建好的 Servlet 只有映射成虚拟路径,客户端才能对其进行访问
Servlet多重映射
- Servlet 的多重映射指同一个 Servlet 可以被映射成多条虚拟路径。也就是说,客户端可以通过多条路径实现对同一个 Servlet 的访问。Servlet 实现多重映射的两种方式:
- 配置多个 <servlet-mapping> 元素
可以通过浏览器输入地址http://localhost:8080/dmeo/Test01和http://localhost:8080/dmeo/TestServlet01访问同一个servlet对象<servlet-mapping> <!-- 映射为Test01 --> <servlet-name>TestServlet01</servlet-name> <url-pattern>/Test01</url-pattern> </servlet-mapping> <servlet-mapping> <!-- 映射为TestServlet01--> <servlet-name>TestServlet01</servlet-name> <url-pattern>/TestServlet01</url-pattern> </servlet-mapping>
- 配置多个 <url-pattern> 子元素
<servlet-mapping> <!-- 映射为TestServlet01和Test01 --> <servlet-name>TestServlet01</servlet-name> <url-pattern>/TestServlet01</url-pattern> <url-pattern>/Test01</url-pattern> </servlet-mapping>
- 配置多个 <servlet-mapping> 元素
Servlet映射路径中使用通配符
- 在实际开发过程中,开发者有时会希望某个目录下的所有路径都可以访问同一个 Servlet,这时,可以在 Servlet 映射的路径中使用通配符*。通配符的格式有两种,具体如下。
- 格式为“*.扩展名”,例如 *.do 匹配以 .do 结尾的所有 URL 地址
- 格式为 /*,例如 /abc/* 匹配以 /abc 开始的所有 URL 地址
- 以上两种通配符的格式不能混合使用。例如,/abc/*.do 是不合法的映射路径
- 另外,当客户端访问一个 Servlet 时,如果请求的 URL 地址能够匹配多条虚拟路径,那么 Tomcat 将采取最具体匹配原则查找与请求 URL 最接近的虚拟映射路径
默认Servlet
- 如果某个 Servlet 的映射路径仅仅是一个正斜线(/),那么这个 Servlet 就是当前 Web 应用的默认 Servlet
- Servlet 服务器在接收到访问请求时,如果在 web.xml 文件中找不到匹配的 <servlet-mapping> 元素的 URL,则会将访问请求交给默认 Servlet 处理,也就是说,默认 Servlet 用于处理其他 Servlet 都不处理的访问请求
- 配置默认Servlet
<servlet> <servlet-name>DefaultServlet</servlet-name> <servlet-class>com.xxx.servlet.DefaultServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DefaultServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
Servlet Config接口
-
在运行 Servlet 程序时,可能需要一些辅助信息,例如,文件使用的编码、使用 Servlet 程序的共享信息等,这些信息可以在 web.xml 文件中使用一个或多个 <init-param> 元素进行配置
-
当 Tomcat 初始化一个 Servlet 时,会将该 Servlet 的配置信息封装到 ServletConfig 对象中,此时可以通过调用 init(ServletConfig config)方法将 ServletConfig 对象传递给 Servlet
-
ServletConfig接口的常用方法
-
参数信息配置代码
<servlet> <servlet-name>ServletDemo</servlet-name> <servlet-class>com.demo.servlet.ServletDemo</servlet-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>ServletDemo</servlet-name> <url-pattern>/ServletDemo</url-pattern> </servlet-mapping>
Servlet Context接口
- 当 Tomcat 启动时,Tomcat 会为每个 Web 应用创建一个唯一的 ServletContext 对象代表当前的 Web 应用,该对象封装了当前 Web 应用的所有信息。可以利用该对象获取 Web 应用程序的初始化信息、数据共享、读取资源文件等
获取 Web 应用程序的初始化参数
- 在 web.xml 文件中,配置整个 Web 应用的初始化信息
<context-param> 元素位于根元素 <web-app> 中,它的子元素 <param-name> 和 <param-value> 分别用于指定参数的名字和参数值。要想获取这些参数名和参数值的信息,可以使用 ServletContext 接口中定义的<context-param> <param-name>XXX</param-name> <param-value>xxx</param-value> </context-param> <context-param> <param-name>yyy</param-name> <param-value>yyy</param-value> </context-param>
getInitParameterNames()
和getInitParameter(String name)
方法分别获取
在不同Servlet中进行数据通信
- 可以在一个Servlet中通过
getServletContext
方法获得web应用中唯一的context对象 - Servlet可以通过context对象的
setAttribute
方法,设定参数名和参数值,并保存在context中 - 另一个Servlet同样可以通过
getServletContext
方法获得context对象,并通过context对象的getAttribute
方法获得另一个Servlet设定的参数值
读取 Web 应用下的资源文件
- 在实际开发中,有时会需要读取 Web 应用中的一些资源文件,如配置文件和日志文件等。为此,在 ServletContext 接口中定义了一些读取 Web 资源的方法,这些方法是依靠 Servlet 容器实现的
- Servlet 容器根据资源文件相对于 Web 应用的路径,返回关联资源文件的 I/O 流或资源文件在系统的绝对路径等
- ServletContext 接口中用于获取资源路径的相关方法
Servlet处理用户请求的完整流程
- 针对 Servlet 的每次请求,Web 服务器在调用 service() 方法之前,都会创建 HttpServletRequest 和 HttpServletResponse 对象
- HttpServletRequest 对象用于封装 HTTP 请求消息,简称 request 对象
- HttpServletResponse 对象用于封装 HTTP 响应消息,简称 response 对象
- 浏览器访问Servlet过程
- 首先浏览器向 Web 服务器发送了一个 HTTP 请求,Web 服务器根据收到的请求,会先创建一个 HttpServletRequest 和 HttpServletResponse 对象,然后再调用相应的 Servlet 程序
- 在 Servlet 程序运行时,它首先会从 HttpServletRequest 对象中读取数据信息,然后通过 service() 方法处理请求消息,并将处理后的响应数据写入到 HttpServletResponse 对象中。最后,Web 服务器会从 HttpServletResponse 对象中读取到响应数据,并发送给浏览器
- 在 Web 服务器运行阶段,每个 Servlet 都只会创建一个实例对象,针对每次 HTTP 请求,Web 服务器都会调用所请求 Servlet 实例的 service(HttpServletRequest request,HttpServletResponse response)方法,并重新创建一个 request 对象和一个 response 对象
HttpServlerRequest
HttpServlerResponse
请求转发
-
当一个 Web 资源收到客户端的请求后,如果希望服务器通知另外一个资源处理请求,那么这时可以通过 RequestDispatcher 接口的实例对象实现。ServletRequest 接口中定义了一个获取 RequestDispatcher 对象的方法
方法 功能 RequestDispatcher getRequestDispatcher(String path) 返回封装了某条路径所指定资源的 RequestDispatcher 对象。其中,参数 path 必须以“/”开头,用于表示当前 Web 应用的根目录。需要注意的是,WEB-INF 目录中的内容对 RequestDispatcher 对象也是可见的。因此,传递给 getRequestDispatcher(String path) 方法的资源可以是 WEB-INF 目录中的文件 -
获取到 RequestDispatcher 对象后,最重要的工作就是通知其他 Web 资源处理当前的 Servlet 请求,为此,RequestDispatcher 接口定义了两个相关方法
方法 功能 forward(ServletRequest request,ServletResponse response) 该方法用于将请求从一个 Servlet 传递给另一个 Web 资源。在 Servlet 中,可以对请求做一个初步处理,然后通过调用这个方法,将请求传递给其他资源进行响应。需要注意的是,该方法必须在响应提交给客户端之前被调用,否则将抛出 IllegalStateException 异常 include(ServletRequest request,ServletResponse response) 该方法用于将其他的资源作为当前响应内容包含进来 -
在 Servlet 中,如果当前 Web 资源不想处理请求,则可以通过 forward() 方法将当前请求传递给其他的 Web 资源进行处理,这种方式称为请求转发
-
当客户端访问 Servlet1 时,可以通过 forward() 方法将请求转发给其他 Web 资源,其他 Web 资源处理完请求后,直接将响应结果返回到客户端
-
浏览器地址栏中显示的仍然是访问Servlet1的请求路径,但是浏览器却显示出了Servlet2中要输出的内容。这是因为请求转发是发生在服务器内部的行为,从 Servlet1到 Servlet2属于一次请求,在一次请求中是可以使用 request 属性(set,getAttribute)进行数据共享的
重定向
-
在某些情况下,针对客户端的请求,一个 Servlet 类可能无法完成全部工作。这时,可以使用请求重定向完成这一工作
-
请求重定向指 Web 服务器接收到客户端的请求后,可能由于某些条件的限制,不能访问当前请求 URL 所指向的 Web 资源,而是指定了一个新的资源路径,让客户端重新发送请求
-
为了实现请求重定向,HttpServletResponse 接口定义了一个
sendRedirect()
方法,该方法用于生成 302 响应码和 Location 响应头,从而通知客户端重新访问 Location 响应头中指定的 URL
-
重定向方法
public void sendRedirect(java.lang.String location) throws java.io.IOException
参数 location 可以使用相对 URL,Web 服务器会自动将相对 URL 翻译成绝对 URL,再生成 Location 头字段
-
重定向与请求转发的区别
- 请求转发是服务器内部行为,url地址不会发生变化,浏览器只对服务器进行一次访问
- 重定向url地址会发生变化,浏览器对服务器进行两次访问
中文乱码问题解决方法
-
由于计算机中的数据都是以二进制形式存储的,因此,当传输文本数据时,会发生字符和字节之间的转换。字符与字节之间的转换是通过查码表完成的,将字符转换成字节的过程称为编码,将字节转换成字符的过程称为解码,如果编码和解码使用的码表不一致,则会导致乱码问题
-
Request中文乱码问题以及解决方案
- 在 HttpServletRequest 接口中提供了一个 setCharacterEncoding() 方法,该方法用于设置 request 对象的解码方式
request.setCharacterEncoding("utf-8"); //设置request对象的解码方式
- 需要注意的是,这种解决乱码的方式只对 POST 方式有效,而对 GET 方式无效
- 为了解决 GET 方式提交表单时出现的中文乱码问题,可以先使用错误码表 ISO-8859-1 将用户名重新编码,然后使用码表 UTF-8 进行解码
name = new String(name.getBytes("iso8859-1"),"utf-8");
- 在 HttpServletRequest 接口中提供了一个 setCharacterEncoding() 方法,该方法用于设置 request 对象的解码方式
-
Response中文乱码问题以及解决方案
- 方式一
response.setCharacterEncoding("utf-8"); //设置 HttpServletResponse使用utf-8编码 response.setHeader("Content-Type", "text/html;charset=utf-8"); //通知浏览器使用utf-8解码
- 方式二
response.setContentType("text/html;charset=utf-8"); //包含第一种方式的两个功能
- 方式一
-
使用URL编码解码方式
URLEncoder.encode("中文", "utf-8") URLDecoder.decode(stringName, "utf-8")
Cookie
-
Cookie常用方法
Cookie[] cookies = req.getCookies(); // 返回cookie数组,cookie可能有多个 cookie.getName() // 获得cookie的名字 cookie.getValue() // 获得cookie的值 Cookie ck = new Cookie("cookieName", "cookieValue") // 新建一个cookie ck.setMaxAge(24*60*60); // 设置cookie有效期,单位为秒 resp.addCookie(ck); // 添加cookie,响应给客户端
-
cookie细节
- cookie一般保存在客户端本地
- 一个cookie只能保存一个信息(键值对)
- 一个web站点可以给浏览器发送多个cookie,最多存放20个cookie
- cookie大小有限制,限制为4kb
- 浏览器cookie上限为300个
-
删除cookie的方式
- 不设置cookie有效期,关闭浏览器,自动失效
- 设置maxAge为0
Session
-
session概念
- 服务器会给每个用户(浏览器)创建一个session对象
- 一个session对象独占一个浏览器,只要浏览器没有关闭,这个session就存在
- 用户登录之后,整个网站它都可以以登录状态访问
- 用途有保存用户信息,保存购物车信息和记录登录状态等
-
注销session设置
- 手动注销
session.invalidate() // 手动注销session
- web.xml设置
<session-config> <!--1分钟后session自动失效,以分钟为单位--> <session-timeout>1</session-timeout> </session-config>
- 手动注销
-
session和cookie区别
- cookie把用户数据写给用户的浏览器,在浏览器中保存(可以保存多个)
- session把用户数据写到用户独占的session中,在服务端保存(保存重要信息,减少服务器资源浪费)
JSP
- JSP全称Java Server Pages,即Java服务端页面,用于动态web技术
- JSP与HTML很相似,它们之间的区别:
- HTML只能给用户提供静态数据
- JSP页面中可以嵌入Java代码,为用户提供动态数据
JSP原理
-
JSP文件最终会在Tomcat的work工作目录中变成Java程序
-
并从其变成的Java程序中分析出,JSP最终会被转换成一个继承HttpServlet的Java类,该类实现的功能就是将JSP文件中的内容传输给客户端
-
所以本质上,浏览器向服务器发送请求,不管访问什么资源,都是在访问Servlet
-
源码剖析
-
判断请求方法
if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { final java.lang.String _jspx_method = request.getMethod(); if ("OPTIONS".equals(_jspx_method)) { response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); return; } if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) { response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP 只允许 GET、POST 或 HEAD。Jasper 还允许 OPTIONS"); return; } }
-
输出jsp页面前添加的代码,定义一些对象。这些对象都可以在jsp文件中以
${}
的形式直接使用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;
-
最后给上面定义的对象赋值,并输出页面
response.setContentType("text/html"); 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("<html>\n"); out.write("<body>\n"); out.write("<h2>Hello World!</h2>\n"); out.write("</body>\n"); out.write("</html>\n");
-
-
所以,在JSP页面中只要是Java代码,就是原封不动的输出,如果是html代码,则会被转换为文本通过
out.write
输出给客户端 -
Java代码以<%%>的形式内嵌
-
原理流程图
MVC三层架构模型
-
Model
- 业务处理:业务逻辑(Service层)
- 数据持久化:CRUD(Dao层)
-
View
- 展示数据
- 给用户提供链接发起Servlet请求
-
Controller(Servlet)
- 接收用户请求(req:请求参数、session信息等)
- 交给业务层处理相应业务
- 控制试图跳转
-
典型例子
用户点击登录-->控制层接收用户的登录请求-->控制层处理用户请求(获得用户登录的参数,如账号密码等)-->将参数交给业务层处理登录业务(账号、密码是否正确,还有可能涉及数据库事务处理)-->交给Dao层查询用户名和密码是否正确-->数据库
过滤器(Filter)
-
Filter是Servlet的过滤器,主要用于完成一些通用的操作,如编码的过滤、判断用户的登录状态、过滤垃圾请求等
-
Filter 被称为过滤器,其主要作用是对 Servlet 容器调用 Servlet 的过程进行拦截,从而在 Servlet 进行响应处理的前后实现一些特殊功能
-
Filter拦截过程图示
当用户通过浏览器访问服务器中的目标资源时,首先会被 Filter 拦截,在 Filter 中进行预处理操作,然后再将请求转发给目标资源。当服务器接收到这个请求后会对其进行响应,在服务器处理响应的过程中,也需要将响应结果经过滤器处理后,才发送给客户端 -
本质上,Filter 过滤器就是一个实现了 javax.servlet.Filter 接口的类,在 javax.servlet.Filter 接口中定义了三个方法
方法声明 方法描述 init(FilterConfig filterConfig) init() 方法用于初始化过滤器,开发人员可以在 init() 方法中完成与构造方法类似的初始化功能,如果初始化代码中要使用到 FillerConfig 对象,那么,这些初始化代码就只能在 Filler 的 init() 方法中编写,而不能在构造方法中编写。在 Web 应用程序加载时会被调用,只被调用一次 doFilter(ServletRequest request,SeivletResponse response, FilterChain chain) doFilter() 方法有多个参数,其中,参数 request 和 response 为 Web 服务器或 Filter 链中的上一个 Filter 传递过来的请求和响应对象;参数 chain 代表当前 Filter 链的对象,只有在当前 Filter 对象中的 doFilter() 方法内部需要调用 FilterChain 对象的 doFilter() 方法,才能把请求交付给 Filter 链中的下一个 Filter 或者目标程序处理。会被调用多次(只要客户端有请求时就会被调用),Filter 所有的工作集中在 doFilter() 方法中 destroy() destroy() 方法在 Web 服务器卸载 Filter 对象之前被调用,该方法用于释放被 Filter 对象打开的资源,例如关闭数据库和 I/O 流。在 Web 应用程序卸载(或关闭)时被调用,只被调用一次
过滤器映射方式
- 在web.xml配置文件中,使用Filter 的\ <filter-mapping> 元素用于配置过滤器拦截的资源信息,如果想让过滤器拦截所有的请求,那么可以使用通配符*实现
<filter> <filter-name>FilterName</filter-name> <filter-class>com.demo.filter.FilterName</filter-class> </filter> <filter-mapping> <filter-name>FilterName</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 拦截不同方式的访问请求
- 在 web.xml 文件中,每一个 <filter-mapping> 元素都可以配置一个 Filter 所负责拦截的资源。在\ <filter-mapping> 元素中有一个特殊的子元素 <dispatcher>,该元素用于指定过滤器所拦截的资源被 Servlet 容器调用的方式。<dispatcher> 元素的值共有四个
- 以FORWARD为例,xml配置如下
该过滤器会拦截所有以请求转发(forward)的方式访问/first.jsp的所有请求<filter> <filter-name>ForwardFilter</filter-name> <filter-class>com.demo.filter.ForwardFilter</filter-class> </filter> <filter-mapping> <filter-name>ForwardFilter</filter-name> <url-pattern>/first.jsp</url-pattern> <dispatcher>FORWARD</dispatcher> </filter-mapping>
- 在 web.xml 文件中,每一个 <filter-mapping> 元素都可以配置一个 Filter 所负责拦截的资源。在\ <filter-mapping> 元素中有一个特殊的子元素 <dispatcher>,该元素用于指定过滤器所拦截的资源被 Servlet 容器调用的方式。<dispatcher> 元素的值共有四个
过滤器链
- 在一个 Web 应用程序中可以注册多个 Filter 程序,每个 Filter 程序都可以针对某一个 URL 进行拦截。如果多个 Filter 程序都对同一个 URL 进行拦截,那么这些 Filter 就会组成一个Filter 链
- Filter 链用 FilterChain 对象表示,FilterChain 对象中有一个 doFilter() 方法,该方法的作用是让 Filter 链上的当前过滤器放行,使请求进入下一个 Filter
- 因为Filter的拦截作用,可以使用Filter进行权限访问控制,对某些访问没有权限的页面的请求进行拦截,不调用doFilter方法传递给下一个Filter,而将其重定向到权限不足的出错页面
- 拦截过程如下图
- 当浏览器访问 Web 服务器中的资源时,需要经过两个过滤器 Filter1 和 Filter2。首先 Filter1 会对这个请求进行拦截,在 Filter1 中处理完请求后,通过调用 Filter1 的 doFilter() 方法将请求传递给 Filter2,Filter2 处理用户请求后同样调用 doFilter() 方法,最终将请求发送给目标资源。当 Web 服务器对这个请求做出响应时,也会被过滤器拦截,但这个拦截顺序与之前相反,最终将响应结果发送给客户端浏览器
- 需要注意的是,Filter 链中各个 Filter 的拦截顺序与它们在 web.xml 文件中 <filter-mapping> 元素的映射顺序一致
编码过滤器示例
- 编写编码过滤器类
package com.demo.filter; import javax.servlet.*; import java.io.IOException; public class CharacterEncodingFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { Filter.super.init(filterConfig); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { request.setCharacterEncoding("utf-8"); response.setCharacterEncoding("utf-8"); response.setContentType("text/html;charset=utf-8"); chain.doFilter(request, response); // 过滤器有多个,传递给下一个过滤器,不执行传递则被拦截 } @Override public void destroy() { Filter.super.destroy(); } }
- web.xml配置filter,与servlet配置一致
<filter> <filter-name>CharacterEncodingFilter</filter-name> <filter-class>com.demo.filter.CharacterEncodingFilter</filter-class> </filter> <filter-mapping> <filter-name>CharacterEncodingFilter</filter-name> <!--要执行过滤的访问指定url路径的所有请求--> <url-pattern>/servlet/*</url-pattern> </filter-mapping>
Servlet事件监听器
-
Servlet 事件监听器是一个实现了特定接口的 Java 程序,这个程序专门用于监听 Web 应用中 ServletContext、HttpSession 和 ServletRequest 等域对象的创建和销毁过程、监听这些域对象属性的修改以及感知绑定到 HttpSession 域中的某个对象的状态
-
Servlet 规范中定义了八种监听器,这八种监听器的类型及作用如下表所示
-
根据监听事件的不同,可以将表中的监听器分为如下三类
- 用于监听域对象创建和销毁的事件监听器(ServletContextListener 接口、HttpSessionListener 接口、ServletRequestListener 接口)
- 用于监听域对象属性增加和删除的事件监听器(ServletContextAttributeListener 接口、HttpSessionAttributeListener 接口、ServletRequestAttributeListener 接口)
- 用于监听绑定到 HttpSession 域中某个对象状态的事件监听器(HttpSessionBindingListener 接口、HttpSessionActivationListener 接口)
-
在 Servlet 规范中,这三类事件监听器都定义了相应的接口,在编写事件监听器程序时只需实现对应的接口即可。在使用监听程序时,Web 服务器会根据监听器所实现的接口,把它注册到被监听的对象上,当触发了某个对象的监听事件时,Web 容器将会调用 Servlet 监听器与之相关的方法对事件进行处理