JavaWeb
一、Servlet
- Servlet 是 JavaEE 规范之一。规范就是接口。
- Servlet 是 JavaWeb三大组件之一。三大组件分别是:Servlet程序、Filter过滤器、Listener监听器。
- Servlet 是 运行在服务器上的一个 java程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
1.1、Servlet 概述
1.1.1、Servlet类的继承体系:
一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现Servlet程序
- 编写一个类去继承 HttpServlet 类
- 根据业务需要重写 doGet 或 doPost 等分发处理方法
- 到web.xml 中配置 自定义Servlet 程序的访问地址
1.1.2、Servlet接口 五种方法介绍 以及生命周期
- 执行 Servlet 构造器方法
- 执行 init 初始化方法. (第一、二步,是在第一次访问的时候创建Servlet程序会调用)
- 执行 service 方法 (第三步每次访问都会调用)
- 执行 destroy() 销毁方法(第四步、在web工程停止的时候调用)
1.1.3、web.xml 中的配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--servlet 标签给 Tomcat 配置 Servlet程序-->
<servlet>
<!--servlet-name 标签 Servlet程序起一个别名(一般是类名)-->
<servlet-name>HelloServlet</servlet-name>
<!--servlet-class 是 Servlet 程序的全类名-->
<servlet-class>com.hgw.javaweb.HelloServlet</servlet-class>
<!--init-param 是初始化参数-->
<init-param>
<!--参数名-->
<param-name>username</param-name>
<!--参数值 -->
<param-value>hgw</param-value>
</init-param>
</servlet>
<!--servlet-mapping 标签给 Servlet 程序配置访问地址-->
<servlet-mapping>
<!--servlet-name 标签的作用是告诉服务器,我们当前配置的地址给哪个 Servlet 程序使用-->
<servlet-name>HelloServlet</servlet-name>
<!--url-pattern 标签访问地址
/ 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径
/hello 表示地址为:http://ip:port/工程路径/hello
-->
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!--context-param 是上下文参数(它属于整个web工程)-->
<context-param>
<param-name>username</param-name>
<param-value>context</param-value>
</context-param>
</web-app>
1.2、ServletConfig 接口
1.3、ServletContext 接口
1.4、HttpServletRequest 接口
1.5、HttpServletResponse 接口
二、Filter
2.1、简介
Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
它主要用于对用户请求进行预处理,也可以对HttpServletResponse 进行后处理。使用Filter 的完整流程:Filter 对用户请求进行预处理,接着将请求交给Servlet 进行处理并生成响应,最后Filter 再对服务器响应进行后处理。
Filter功能:
- 在HttpServletRequest 到达 Servlet 之前,拦截客户的 HttpServletRequest 。 根据需要检查 HttpServletRequest ,也可以修改HttpServletRequest 头和数据。
- 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse 。 根据需要检查 HttpServletResponse ,也可以修改HttpServletResponse头和数据。
大概流程图如下
2.2、如何实现拦截
Filter 接口中有一个 doFilter 方法,当开发人员编写好Filter,并配置对哪个Web资源进行拦截后,WEB服务器每次在调用web资源的service方法之前,都会先调用一下filter的doFilter方法,因此,在该方法内编写代码可达到如下的目的:
- 调用目标资源之前,让一段代码执行
- 是否调用目标资源(即是否让用户访问Web资源)
web服务器在调用doFilter方法时,会传递一个 filterChain 对象进来,filterChain对象是 filter 接口中最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需要决定死否调用此方法,调用该方法,则web服务器就会调用web资源的service方法,即web资源就会被访问,否则web资源不会被访问。
2.3、Filter 开发两步走
- 编写java类实现Filter接口,并实现其doFilter方法。
- 在 web.xml 文件中使用
<filter>
和<filter-mapping>
元素对编写的filter类进行注册,并设置它所能拦截的资源。
web.xml配置各节点介绍:
<!--filter标签用于配置一个Filter过滤器-->
<filter>
<!--用于为过滤器指定一个名字,该元素的内容不能为空。 -->
<filter-name>AdminFilter</filter-name>
<!--元素用于指定过滤器的完整的限定类名。 -->
<filter-class>com.atguigu.filter.AdminFilter</filter-class>
<!--元素用于为过滤器指定初始化参数,它的子元素 -->
<init-param>
<!--指定参数的名字-->
<param-name>username</param-name>
<!--指定参数的值-->
<param-value>root</param-value>
</init-param>
</filter>
<!--元素用于设置一个 Filter 所负责拦截的资源。一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径 -->
<filter-mapping>
<!--子元素用于设置filter的注册名称。该值必须是在<filter>元素中声明过的过滤器的名字 -->
<filter-name>AdminFilter</filter-name>
<!--设置 filter 所拦截的请求路径(过滤器关联的URL样式)
/ 表示请求地址为:http://ip:port/工程路径/ 映射到Idea 的 web目录
/admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
2.4、Filter链
在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。
web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给改方法。在doFilter方法中,开发人员如果调用了 FilterChain 对象的 doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
2.5、Filter的生命周期
public void init(FilterConfig filterConfig) throws ServletException; // 初始化
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作**(filter对象只会创建一次,init方法也只会执行一次)**。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws IOException, ServletException
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain 参数用于访问后续过滤器。
public void destroy(); // 销毁
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。
2.6、FilterConfig接口
用户在配置filter时,可以使用为filter配置一些初始化参数,当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法,就可获得以下内容:
String getFilterName();//得到filter的名称。
String getInitParameter(String name);//返回在部署描述中指定名称的初始化参数的值。如果不存在返回null.
Enumeration getInitParameterNames();//返回过滤器的所有初始化参数的名字的枚举集合。
public ServletContext getServletContext();//返回Servlet上下文对象的引用。
2.7、Filter使用案例
2.7.1、使用Filter验证用户是否登录
package com.atguigu.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class AdminFilter implements Filter {
public AdminFilter() {
System.out.println("1 Filter构造方法AdminFilter()");
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("2 Filter的init()初始化");
System.out.println("filter-name的值是: " + filterConfig.getFilterName());
System.out.println("初始化参数username的值是: " + filterConfig.getInitParameter("username"));
System.out.println("初始化参数url的值是: " + filterConfig.getInitParameter("url"));
System.out.println(filterConfig.getServletContext());
}
/**
* doFilter方法,专门用于拦截请求。可以做权限检查
* @param servletRequest
* @param servletResponse
* @param filterChain
* @throws IOException
* @throws ServletException
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws IOException, ServletException {
System.out.println("3 Filter的doFilter()方法");
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
HttpSession session = httpServletRequest.getSession();
Object user = session.getAttribute("user");
// 如果等于null,说明还没有登录
if (user == null) {
servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
return;
}else {
// 让程序继续往下访问用户的目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
System.out.println("4 Filter的destroy()销毁方法");
}
}
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<!--filter标签用于配置一个Filter过滤器-->
<filter>
<!--给filter起一个别名-->
<filter-name>AdminFilter</filter-name>
<!--配置filter的全类名-->
<filter-class>com.atguigu.filter.AdminFilter</filter-class>
<init-param>
<param-name>username</param-name>
<param-value>root</param-value>
</init-param>
<init-param>
<param-name>url</param-name>
<param-value>jdbc:mysql://localhost3306/test</param-value>
</init-param>
</filter>
<!--filter-mapping配置Filter过滤器的拦截路径-->
<filter-mapping>
<!--filter-name表示当前的拦截路径给哪个filters使用-->
<filter-name>AdminFilter</filter-name>
<!--url-pattern配置拦截路径
/ 表示请求地址为:http://ip:port/工程路径/ 映射到Idea 的 web目录
/admin/* 表示请求地址为:http://ip:port/工程路径/admin/*
-->
<url-pattern>/admin/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.atguigu.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/loginServlet</url-pattern>
</servlet-mapping>
</web-app>
三、Listener
3.1、Listener 的定义与作用
监听器Listener 就是在 application、session、request 三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。
Listener 是 Servlet 的监听器,可以监听客户端的请求,服务端的操作等。
3.2、Listener 的分类与使用
主要有以下三类:
3.2.1、ServletContext 监听
- ServletContextListener:用于对Servlet整个上下文进行监听(创建、销毁)。
public void contextInitialized(ServletContextEvent sce);//上下文初始化
public void contextDestroyed(ServletContextEvent sce);//上下文销毁
public ServletContext getServletContext();//ServletContextEvent事件:取得一个ServletContext(application)对象
- ServletContextAttributeListener:对Servlet上下文属性的监听(增删改属性)。
public void attributeAdded(ServletContextAttributeEvent scab);//增加属性
public void attributeRemoved(ServletContextAttributeEvent scab);//属性删除
public void attributeRepalced(ServletContextAttributeEvent scab);//属性替换(第二次设置同一属性)
//ServletContextAttributeEvent事件:能取得设置属性的名称与内容
public String getName();//得到属性名称
public Object getValue();//取得属性的值
3.2.2、Session监听
Session属于http协议下的内容,接口位于javax.servlet.http.*包下。
- **HttpSessionListener**接口:对Session的整体状态的监听。
public void sessionCreated(HttpSessionEvent se);//session创建
public void sessionDestroyed(HttpSessionEvent se);//session销毁
//HttpSessionEvent事件:
public HttpSession getSession();//取得当前操作的session
- **HttpSessionAttributeListener**接口:对session的属性监听。
public void attributeAdded(HttpSessionBindingEvent se);//增加属性
public void attributeRemoved(HttpSessionBindingEvent se);//删除属性
public void attributeReplaced(HttpSessionBindingEvent se);//替换属性
//HttpSessionBindingEvent事件:
public String getName();//取得属性的名称
public Object getValue();//取得属性的值
public HttpSession getSession();//取得当前的session
session的销毁有两种情况:
- session超时,web.xml配置:
<session-config>
<session-timeout>120</session-timeout><!--session120分钟后超时销毁-->
</session-config>
- 手工使session失效
public void invalidate();//使session失效方法。session.invalidate();
3.2.3、Request监听
- ServletRequestListener:用于对Request请求进行监听(创建、销毁)。
public void requestInitialized(ServletRequestEvent sre);//request初始化
public void requestDestroyed(ServletRequestEvent sre);//request销毁
//ServletRequestEvent事件:
public ServletRequest getServletRequest();//取得一个ServletRequest对象
public ServletContext getServletContext();//取得一个ServletContext(application)对象
- ServletRequestAttributeListener:对Request属性的监听(增删改属性)。
public void attributeAdded(ServletRequestAttributeEvent srae);//增加属性
public void attributeRemoved(ServletRequestAttributeEvent srae);//属性删除
public void attributeReplaced(ServletRequestAttributeEvent srae);//属性替换(第二次设置同一属性)
//ServletRequestAttributeEvent事件:能取得设置属性的名称与内容
public String getName();//得到属性名称
public Object getValue();//取得属性的值
3.2.4、在web.xml中配置
Listener配置信息必须在Filter和Servlet配置之前,Listener的初始化(ServletContentListener初始化)比Servlet和Filter都优先,而销毁比Servlet和Filter都慢。
<listener>
<listener-class>com.listener.class</listener-class>
</listener>
3.3、Listener 应用实例
1、利用HttpSessionListener统计最多在线用户人数
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class HttpSessionListenerImpl implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent event) {
ServletContext app = event.getSession().getServletContext();
int count = Integer.parseInt(app.getAttribute("onLineCount").toString());
count++;
app.setAttribute("onLineCount", count);
int maxOnLineCount = Integer.parseInt(app.getAttribute("maxOnLineCount").toString());
if (count > maxOnLineCount) {
//记录最多人数是多少
app.setAttribute("maxOnLineCount", count);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//记录在那个时刻达到上限
app.setAttribute("date", df.format(new Date()));
}
}
//session注销、超时时候调用,停止tomcat不会调用
public void sessionDestroyed(HttpSessionEvent event) {
ServletContext app = event.getSession().getServletContext();
int count = Integer.parseInt(app.getAttribute("onLineCount").toString());
count--;
app.setAttribute("onLineCount", count);
}
}