Maison  >  Article  >  Java  >  Une introduction détaillée au filtre, au servlet et à l'écouteur en Java

Une introduction détaillée au filtre, au servlet et à l'écouteur en Java

黄舟
黄舟original
2017-07-30 13:18:361406parcourir

Cet article présente principalement en détail le matériel d'apprentissage de Filter, Servlet et Listener. Il a une certaine valeur de référence. Les amis intéressés peuvent se référer à

Matériel d'apprentissage de Filter, Servlet et Listener, j'espère que vous. j'aime

1. Fonction de filtre

La fonction de filtre permet aux utilisateurs de modifier une requête et de modifier une réponse. Le filtre n'est pas un servlet, il ne peut pas générer. une réponse, il peut prétraiter une requête avant qu'elle n'atteigne le servlet, et il peut également traiter la réponse en quittant le servlet. En d'autres termes, le filtre est en fait un "chaînage de servlets" (chaîne de servlets).

Un filtre comprend :

1), intercepter avant l'appel du servlet
2), vérifier la demande du servlet avant l'appel du servlet
3), en fonction du besoin ; pour modifier l'en-tête de la requête et les données de la requête ;
4), modifier l'en-tête de la réponse et les données de la réponse si nécessaire
5), intercepter le servlet après son appel

Le serveur. appelle uniquement à chaque fois La méthode setFilterConfig prépare le filtre pour le traitement une fois ; la méthode doFilter est appelée plusieurs fois pour gérer différentes requêtes. L'interface FilterConfig dispose de méthodes pour trouver le nom du filtre et les informations sur les paramètres d'initialisation. Le serveur peut définir FilterConfig sur vide pour l'indiquer. que le filtre est terminé.
Chaque filtre obtient la requête et la réponse actuelles de la méthode doFilter(). Dans cette méthode, toute opération sur la requête et la réponse peut être effectuée (y compris la collecte de données, l'empaquetage des données, etc.). () donne le contrôle au filtre suivant. Un filtre se termine par la méthode doFilter(). Si un filtre veut arrêter le traitement de la requête et prendre le contrôle complet de la réponse, il n'a pas besoin d'appeler le filtre suivant
Exemple :
Créez d'abord un nouveau filtre


/** 
 * 
 */ 
package com.ee.filter; 
 
import java.io.IOException; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class LogFilter implements Filter { 
 private FilterConfig filterConfig; 
 
 public FilterConfig getFilterConfig() { 
  System.err.println("...getFilterConfig..."); 
  return filterConfig; 
 } 
 
 public void setFilterConfig(FilterConfig filterConfig) { 
  System.err.println("...setFilterConfig..."); 
  this.filterConfig = filterConfig; 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#destroy() 
  */ 
 @Override 
 public void destroy() { 
  System.err.println("...filter destroy..."); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) 
  */ 
 @Override 
 public void doFilter(ServletRequest request, ServletResponse response, 
   FilterChain chain) throws IOException, ServletException { 
  System.err.println("...doFilter..."); 
  chain.doFilter(request, response);//看到这没,这只要是传递下一个Filter 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 
  */ 
 @Override 
 public void init(FilterConfig filterConfig) throws ServletException { 
  System.err.println("...init Filter..."); 
  this.filterConfig = filterConfig; 
 } 
 
}

Configurez-le dans web.xml


<filter> 
 <filter-name>LogFilter</filter-name> 
 <filter-class>com.ee.filter.LogFilter</filter-class> 
</filter> 
 
<filter-mapping> 
 <filter-name>LogFilter</filter-name> 
 <url-pattern>/*</url-pattern> 
</filter-mapping>

Démarrer et exécuter
Vous pouvez voir...init Filter... est imprimé pour la première fois au démarrage de TOMCAT, puis vous pouvez voir...doFilter... .is imprimé.

2. Fonction servlet

1). Qu'est-ce qu'une servlet ?

Servlet est un programme Java qui utilise l'interface de programmation d'application (API) Java Servlet et les classes et méthodes associées. En plus de l'API Java Servlet, les servlets peuvent également utiliser des packages de classes Java qui étendent et complètent l'API. Les servlets s'exécutent sur un serveur Web ou un serveur d'applications compatible Java et étendent les capacités de ce serveur. Les servlets Java sont aux serveurs Web ce que les applets Java sont aux navigateurs Web. Les servlets sont chargés dans le serveur Web et exécutés dans le serveur Web, tandis que les applets sont chargés dans le navigateur Web et exécutés dans le navigateur Web. L'API Java Servlet définit une interface standard entre un servlet et un serveur compatible Java, ce qui fait des servlets une plate-forme multi-serveurs.

Les servlets étendent les capacités d'un serveur en créant un cadre pour fournir des services de requête et de réponse sur le Web. Lorsqu'un client envoie une requête au serveur, le serveur peut envoyer les informations de requête au servlet et laisser le servlet créer la réponse que le serveur renvoie au client. Les servlets peuvent être chargés automatiquement au démarrage d'un serveur Web ou lorsqu'un client demande un service pour la première fois. Après le chargement, le servlet continue de s'exécuter jusqu'à ce que d'autres clients fassent des demandes. Les servlets ont un large éventail de fonctions. Par exemple, Servlet peut remplir les fonctions suivantes :

  (1) Créer et renvoyer une page HTML complète contenant du contenu dynamique en fonction de la nature de la demande du client.
 (2) Créez une partie d'une page HTML (fragment HTML) qui peut être intégrée dans une page HTML existante.
 (3) Communiquez avec d'autres ressources du serveur (y compris les bases de données et les applications basées sur Java).
 (4) Utilisez plusieurs clients pour gérer les connexions, recevoir les entrées de plusieurs clients et diffuser les résultats à plusieurs clients. Par exemple, une servlet pourrait être un serveur de jeu multi-participant.
 (5) Lorsque la transmission de données en mode connexion unique est autorisée, ouvrez une nouvelle connexion du serveur vers l'applet du navigateur et maintenez la connexion
ouverte. Les applets peuvent également initier des connexions entre le navigateur du client et le serveur, permettant au client et au serveur d'effectuer des sessions de manière simple et efficace. La communication peut se faire via des protocoles personnalisés ou des normes telles que IIOP.
 (6) Utilisez les données de filtrage de type MIME pour des traitements spéciaux, tels que la conversion d'images et les inclusions côté serveur (SSI).
 (7) Une routine standard qui fournit un traitement personnalisé à tous les serveurs. Par exemple, une servlet peut modifier la manière dont les utilisateurs sont authentifiés.

2). Le cycle de vie d'un Servlet
Le cycle de vie d'un Servlet commence lorsqu'il est chargé dans la mémoire du serveur Web et se termine lorsque le Servlet est terminé ou rechargé.

(1) Initialisation
Chargez le Servlet aux moments suivants :
Si l'option de chargement automatique a été configurée, elle sera automatiquement chargée au démarrage du serveur
Après le serveur démarre, lorsque le client fait une requête au servlet pour la première fois
Lors du rechargement du servlet Après avoir chargé le servlet, le serveur crée une instance du servlet et appelle la méthode init() du servlet. Pendant la phase d'initialisation, les paramètres d'initialisation du servlet sont transmis à l'objet de configuration du servlet.

(2) Traitement des requêtes
Pour une requête client arrivant au serveur, le serveur crée un objet "requête" et un objet "réponse" spécifique à la requête. Le serveur appelle la méthode service() du servlet, qui permet de transmettre les objets « requête » et « réponse ». La méthode service() obtient les informations de demande de l'objet "request", traite la demande et utilise les méthodes de l'objet "response" pour renvoyer la réponse au client. La méthode service() peut appeler d'autres méthodes pour gérer la requête, telles que doGet(), doPost() ou d'autres méthodes.

(3) Résiliation
Lorsque le serveur n'a plus besoin du Servlet, ou recharge une nouvelle instance du Servlet, le serveur appellera la méthode destroy() du Servlet.

3) API Java Servlet
L'outil de développement de servlets Java (JSDK) fournit plusieurs packages logiciels nécessaires lors de l'écriture de servlets. Ceux-ci incluent deux packages de base pour tous les servlets : javax.servlet et javax.servlet.http. Les outils de développement Java Servlet peuvent être téléchargés à partir du site Web de Sun. Ce qui suit présente principalement l'interface de programmation d'application HTTP Servlet fournie par javax.servlet.http.
HTTP Servlet utilise un formulaire HTML pour envoyer et recevoir des données. Pour créer un servlet HTTP, étendez la classe HttpServlet, qui est une sous-classe de GenericServlet qui utilise des méthodes spécialisées pour gérer les tableaux HTML. Les formulaires HTML sont définis par les balises 632555444b46edf0af44e58213a0ac8c Les formulaires contiennent généralement des champs de saisie (tels que des champs de saisie de texte, des cases à cocher, des boutons radio et des listes de sélection) et des boutons pour soumettre des données. Lors de la soumission des informations, ils précisent également quel servlet (ou autre programme) le serveur doit exécuter. La classe HttpServlet comprend init(), destroy(), service() et d'autres méthodes. Les méthodes init() et destroy() sont héritées.

(1) méthode init()

 Dans le cycle de vie du Servlet, la méthode init() n'est exécutée qu'une seule fois. Il est exécuté lorsque le serveur charge le servlet. Vous pouvez configurer le serveur pour qu'il charge un servlet lors de son démarrage ou lorsqu'un client accède au servlet pour la première fois. Quel que soit le nombre de clients accédant au servlet, init() n'est jamais exécuté de manière répétée.
La méthode init() par défaut est généralement adéquate, mais elle peut être remplacée par une méthode init() personnalisée, généralement pour gérer les ressources côté serveur. Par exemple, vous pouvez écrire un init() personnalisé pour charger une image GIF une seule fois, améliorant ainsi les performances d'un servlet renvoyant une image GIF et contenant plusieurs requêtes client. Un autre exemple est l'initialisation d'une connexion à une base de données. La méthode init() par défaut définit les paramètres d'initialisation du servlet et utilise ses paramètres d'objet ServletConfig pour démarrer la configuration, donc toutes les servlets qui remplacent la méthode init() doivent appeler super.init() pour garantir que ces tâches sont toujours effectuées. Avant d'appeler la méthode service(), vous devez vous assurer que la méthode init() est terminée.

(2) méthode service()
 La méthode service() est le cœur de Servlet. Chaque fois qu'un client demande un objet HttpServlet, la méthode service() de l'objet est appelée et un objet « requête » (ServletRequest) et un objet « réponse » (ServletResponse) sont transmis à cette méthode en tant que paramètres. La méthode service() existe déjà dans HttpServlet. La fonction de service par défaut consiste à appeler la fonction do correspondant à la méthode de la requête HTTP. Par exemple, si la méthode de requête HTTP est GET, doGet() est appelée par défaut. Les servlets doivent remplacer la fonctionnalité do pour les méthodes HTTP prises en charge par le servlet. Étant donné que la méthode HttpServlet.service() vérifie si la méthode de requête appelle le gestionnaire approprié, il n'est pas nécessaire de remplacer la méthode service(). Remplacez simplement la méthode do correspondante et vous avez terminé.
Lorsqu'un client fait une requête HTTP POST via un formulaire HTML, la méthode doPost() est appelée. Les paramètres associés à la requête POST sont envoyés du navigateur au serveur sous la forme d'une requête HTTP distincte. Lorsque vous devez modifier des données côté serveur, vous devez utiliser la méthode doPost().
Lorsqu'un client effectue une requête HTTP GET via un formulaire HTML ou demande directement une URL, la méthode doGet() est appelée. Les paramètres liés à la requête GET sont ajoutés à la fin de l'URL et envoyés avec cette requête. La méthode doGet() doit être utilisée lorsque les données côté serveur ne seront pas modifiées.
La réponse du servlet peut être des types suivants :
Un flux de sortie, que le navigateur interprète en fonction de son type de contenu (tel que texte/HTML).
Une réponse d'erreur HTTP, redirection vers une autre URL, servlet, JSP.

(3) destroy() 方法
  destroy() 方法仅执行一次,即在服务器停止且卸装Servlet 时执行该方法。典型的,将 Servlet 作为服务器进程的一部分来关闭。缺省的 destroy() 方法通常是符合要求的,但也可以覆盖它,典型的是管理服务器端资源。例如,如果 Servlet 在运行时会累计统计数据,则可以编写一个 destroy() 方法,该方法用于在未装入 Servlet 时将统计数字保存在文件中。另一个示例是关闭数据库连接。
当服务器卸装 Servlet 时,将在所有 service() 方法调用完成后,或在指定的时间间隔过后调用 destroy() 方法。一个Servlet 在运行service() 方法时可能会产生其它的线程,因此请确认在调用 destroy() 方法时,这些线程已终止或完成。

(4) GetServletConfig()方法
  GetServletConfig()方法返回一个 ServletConfig 对象,该对象用来返回初始化参数和  ServletContext。ServletContext 接口提供有关servlet 的环境信息。

(5) GetServletInfo()方法
  GetServletInfo()方法是一个可选的方法,它提供有关servlet 的信息,如作者、版本、版权。
  当服务器调用sevlet 的Service()、doGet()和doPost()这三个方法时,均需要 “请求”和“响应”对象作为参数。“请求”对象提供有关请求的信息,而“响应”对象提供了一个将响应信息返回给浏览器的一个通信途径。javax.servlet 软件包中的相关类为ServletResponse和ServletRequest,而javax.servlet.http 软件包中的相关类为HttpServletRequest 和 HttpServletResponse。Servlet 通过这些对象与服务器通信并最终与客户机通信。Servlet 能通过调用“请求”对象的方法获知客户机环境,服务器环境的信息和所有由客户机提供的信息。Servlet 可以调用“响应”对象的方法发送响应,该响应是准备发回客户机的。 

例子:
创建一个servlet


/** 
 * 
 */ 
package com.ee.servlet; 
 
import java.io.IOException; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class LogServlet extends HttpServlet { 
 
 /** 
  * 
  */ 
 private static final long serialVersionUID = 1L; 
 
 @Override 
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
   throws ServletException, IOException { 
  doPost(req, resp); 
 } 
  
 @Override 
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
   throws ServletException, IOException { 
  System.err.println("...doPost(req, resp)..."); 
 } 
}

在web.xml中的配置:


<servlet> 
 <servlet-name>LogServlet</servlet-name> 
 <servlet-class>com.ee.servlet.LogServlet</servlet-class> 
</servlet> 
 
<servlet-mapping> 
 <servlet-name>LogServlet</servlet-name> 
 <url-pattern>/*</url-pattern><!-- 看到此没有,这个拦截所有路径 --> 
</servlet-mapping>

它的拦截规则:

当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了(filter不同,后文会提到)。其匹配规则和顺序如下:
1.精确路径匹配。例子:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先 进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了。
2.最长路径匹配。例子:servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。
3.扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:*.action
4.如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。如果应用定义了一个default servlet,则容器会将请求丢给default servlet 

3、Listener功能

它是基于观察者模式设计的,Listener 的设计对开发 Servlet 应用程序提供了一种快捷的手段,能够方便的从另一个纵向维度控制程序和数据。目前 Servlet 中提供了 5 种两类事件的观察者接口,它们分别是:4 个 EventListeners 类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。如下图所示: 

Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEvent se)方法,这样就可以给在线人数加1。常用的监听接口有以下几个:

ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。
ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。
HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发session Created(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。
HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。

下面我们开发一个具体的例子,这个监听器能够统计在线的人数。在ServletContext初始化和销毁时,在服务器控制台打印对应的信息。当ServletContext里的属性增加、改变、删除时,在服务器控制台打印对应的信息。
要获得以上的功能,监听器必须实现以下3个接口:

HttpSessionListener
ServletContextListener
ServletContextAttributeListener 

例子:


/** 
 * 
 */ 
package com.ee.listener; 
 
import javax.servlet.ServletContextAttributeEvent; 
import javax.servlet.ServletContextAttributeListener; 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
import javax.servlet.http.HttpSessionEvent; 
import javax.servlet.http.HttpSessionListener; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class OnlineUserListener implements HttpSessionListener, 
  ServletContextListener, ServletContextAttributeListener { 
 private long onlineUserCount = 0; 
 
 public long getOnlineUserCount() { 
  return onlineUserCount; 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeAdded(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeAdded(ServletContextAttributeEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeRemoved(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeRemoved(ServletContextAttributeEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeReplaced(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeReplaced(ServletContextAttributeEvent attributeEvent) { 
  System.err.println("...attributeReplaced..."); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) 
  */ 
 @Override 
 public void contextDestroyed(ServletContextEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) 
  */ 
 @Override 
 public void contextInitialized(ServletContextEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent) 
  */ 
 @Override 
 public void sessionCreated(HttpSessionEvent httpSessionEvent) { 
  onlineUserCount ++; 
  toUpdateCount(httpSessionEvent); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent) 
  */ 
 @Override 
 public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { 
  onlineUserCount --; 
  toUpdateCount(httpSessionEvent); 
 } 
 
 private void toUpdateCount(HttpSessionEvent httpSessionEvent){ 
  httpSessionEvent.getSession().setAttribute("onlineUserCount", onlineUserCount); 
 } 
}

 Web.xml


<listener> 
 <listener-class>com.ee.listener.OnlineUserListener</listener-class> 
</listener>

 JSP页面:


<%@ page language="java" contentType="text/html; charset=UTF-8" 
 pageEncoding="UTF-8"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>主页</title> 
</head> 
<body> 
 <h4>你好!</h4> 
 在线人数:<h1><%=request.getSession().getAttribute("onlineUserCount") %></h1> 
</body> 
</html>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn