devstory

Le Tutoriel de Java Servlet Filter

  1. Introduction
  2.  Pourquoi avoir besoin de Server-Filter?
  3. Que peut faire Servlet-Filter?
  4. Créer un Projet pour commence avec Servlet-Filter
  5. La configuration de l'environnement d'exécution
  6. Le premier exemple de Servlet-Filter
  7. Les modèles d'organisation de Filter
  8. Les paramètres initiaux de Servlet-Filter
  9. Servlet-Filter url-pattern
  10. Servlet-Filter utilise Annotation
  11. L'établissement de la connexion JDBC dans Filter
  12. Le tutoriel JSP

1. Introduction

Ce document est basé sur:
  • Eclipse 4.6 NEON

  • Tomcat 8.x

Il vous convient d'avoir des connaissances en Servlet avant de lire le document de Servlet-Filter, si vous êtes débutant, vous pouvez voir Java Servlet à:

2.  Pourquoi avoir besoin de Server-Filter?

Situation 1:
En général, lors que l'utilisateur demande une page Internet, une requête est envoyé au serveur. Elle doit passer du filtrage de Servlet (Filter) avant d'arriver à la page demandée, comme l'illustration suivante.
Situation 2:
Mais il y a des situation où les demandes de l'utilisateur ne passent pas aux tous les filtrages Filter.
Situation 3:
Au cas où l'utilisateur demande à une page (page1), Cette demande doit passer les Filter, dans un certain filtre, la requête est redirigée vers une autre page (page2).
Exemple des situations:
  1. Des utilisateurs soumettent une requête pour voir les informations personnelles.
  2. La requête va être envoyée au serveur.
  3. Elle passe le filtre et qui enregistre l'information de log.
  4. Elle traverse le filtre pour vérifier l'utilisateur a inscrit ou pas encore, ce filtre trouve que l'utilisateur n'est pas inscrit et il va réorienter la requête de l'utilisateur vers la page de connexion.
  5. http://blog.paumard.org/cours/servlet/chap04-filtre.html
  6. https://www.jmdoudoux.fr/java/dej/chap-servlets.htm#servlets-4

3. Que peut faire Servlet-Filter?

Parfois, vous avez cru que Filter n'avez qu'utilisé pour réorienter la requête de l'utilisateur vers une autre page, ou empêcher l'accès d'une page particulière si l'utilisateur n'a pas de droit. Ou il est utilisé pour écrire des information de Log.
En réalité, Filter peut être utilisé pour codifier (encoding) la page de web. Par exemple, l'établissement la codification pour la page UTF-8. L'ouverture et la fermeture la connection à la base de données et la prépation la transaction JDBC (JDBC Transaction).

4. Créer un Projet pour commence avec Servlet-Filter

D'abord nous créez un projet WebApp en vue de travailler avec Servlet-Filter.
  • File/New/Other...
Saisissez:
  • Project Name: ServletFilterTutorial
Le projet est créé:
Créez le fichier index.html:
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>

  <h2>Servlet-Filter Tutorial</h2>

</body>
</html>

5. La configuration de l'environnement d'exécution

Cliauez sur le bouton droit du Projet et sélectionnez Propriétés:
Cliquez sur le bouton droit et sélectionnez:
  • Run As/Run on Server
OK!, tout est prêt de commencer à apprendre Servlet-Filter.

6. Le premier exemple de Servlet-Filter

Servlet Filter est une classe qui met en oeuvre l'interface javax.servlet.Filter. La classe LogFilter suivant enregistre le temps et le lien de requête envoyé à l'application web.
LogFilter.java
package org.o7planning.tutorial.servletfilter;

import java.io.IOException;
import java.util.Date;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class LogFilter implements Filter {

	public LogFilter() {
	}

	@Override
	public void init(FilterConfig fConfig) throws ServletException {
		System.out.println("LogFilter init!");
	}

	@Override
	public void destroy() {
		System.out.println("LogFilter destroy!");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest req = (HttpServletRequest) request;

		String servletPath = req.getServletPath();

		System.out.println("#INFO " + new Date() + " - ServletPath :" + servletPath //
				+ ", URL =" + req.getRequestURL());

		// Passez à l'élément suivant (filtre ou cible) en chaîne.
		chain.doFilter(request, response);
	}

}
Configure filter in web.xml:
Ajoutez la configuration web.xml:
<!--
  Declaring a filter named logFilter
-->
<filter>
  <filter-name>logFilter</filter-name>
  <filter-class>org.o7planning.tutorial.servletfilter.LogFilter</filter-class>
</filter>

<!--
  Declare the path (of the page) will have the effect of logFilter
 /* for all paths
-->
<filter-mapping>
  <filter-name>logFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                               http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">

<display-name>ServletFilterTutorial</display-name>

<filter>
 <filter-name>logFilter</filter-name>
 <filter-class>org.o7planning.tutorial.servletfilter.LogFilter</filter-class>
</filter>

<filter-mapping>
 <filter-name>logFilter</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>



<welcome-file-list>
 <welcome-file>index.html</welcome-file>
 <welcome-file>index.htm</welcome-file>
 <welcome-file>index.jsp</welcome-file>
 <welcome-file>default.html</welcome-file>
 <welcome-file>default.htm</welcome-file>
 <welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
Réexécutez votre application web
Vous pouvez exécuter le lien suivant sur votre navigateur, il y a quelques liens qui mènent aux sources qui n'existent pas sur votre application web,mais ils sont encore sous l'effet de LogFilter.
Des informations de Log sont enregistrées sur l'écran de Console:
Le code suivant permet la requête de passer le filtre (Filter) pour continuer aller vers la page requêtée.
// Autoriser la demande à aller en avant.
// Il peut aller au filtre suivant ou à la cible.
chain.doFilter(request, response);

7. Les modèles d'organisation de Filter

Quand l'utilisateur envoie unhe requête, l'objectif (target) peut être une ressource (resource) ou une servlet. La requête doit être passée les filtre (Filter) et finalement atteint l'objectif. Les filtres et l'objectif sont enchaînés (chained) ensemble comme l'illustration suivante:
Utilisez chain.doFilter(request,response) pour déplacer la requête à la prochaine étape. Si le filtre chain.doFilter(request, response) n'est pas appelé , la requête de l'utilíateur ne va pas atteindre son objectif, elle va être arrêtée à ledit filtre.

8. Les paramètres initiaux de Servlet-Filter

Comme avec Servlet, vous pouvez initialiser les paramètres de Filter. Dans l'exemple ci- dessous, un Filter est responsable d'écrire le log dans un fichier, vous pouvez configurer dans le fichier nommé web.xml pour écrire.
Log2Filter.java
package org.o7planning.tutorial.servletfilter;

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;

public class Log2Filter implements Filter {

	private String logFile;

	public Log2Filter() {
	}

	@Override
	public void init(FilterConfig fConfig) throws ServletException {
		this.logFile = fConfig.getInitParameter("logFile");

		System.out.println("Log File " + logFile);
	}

	@Override
	public void destroy() {
		System.out.println("Log2Filter destroy!");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		if (this.logFile != null) {
			// Enregistrez les informtions de Log dans le fichier.
			this.logToFile(this.logFile);
		}

		// Autorisez la demande de passer à l'élément suivant (filtre ou cible) en chaîne.
		chain.doFilter(request, response);
	}

	private void logToFile(String fileName) {
		// Enregistrez le log au fichier.
		System.out.println("Write log to file " + fileName);
	}

}
Ajoutez la configuration dans web.xml:
<filter>
   <filter-name>log2Filter</filter-name>
   <filter-class>org.o7planning.tutorial.servletfilter.Log2Filter</filter-class>
   <init-param>
       <param-name>logFile</param-name>
       <param-value>AppLog.log</param-value>
   </init-param>
</filter>

<filter-mapping>
   <filter-name>log2Filter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>ServletFilterTutorial</display-name>

<filter>
  <filter-name>logFilter</filter-name>
  <filter-class>org.o7planning.tutorial.servletfilter.LogFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>logFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>


<filter>
  <filter-name>log2Filter</filter-name>
  <filter-class>org.o7planning.tutorial.servletfilter.Log2Filter</filter-class>
  <init-param>
      <param-name>logFile</param-name>
      <param-value>AppLog.log</param-value>
  </init-param>
</filter>

<filter-mapping>
  <filter-name>log2Filter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
 


<welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>default.html</welcome-file>
  <welcome-file>default.htm</welcome-file>
  <welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>

9. Servlet-Filter url-pattern

Il y a 3 façons de configurer url-pattern pour Filter:
URL Pattern
Example
/*
http://example.com/contextPath
/*
http://example.com/contextPath/status/abc
/status/abc/*
http://example.com/contextPath/status/abc
/status/abc/*
http://example.com/contextPath/status/abc/mnp
/status/abc/*
http://example.com/contextPath/status/abc/mnp?date=today
/status/abc/*
http://example.com/contextPath/test/abc/mnp
*.map
http://example.com/contextPath/status/abc.map
*.map
http://example.com/contextPath/status.map?date=today
*.map
http://example.com/contextPath/status/abc.MAP

10. Servlet-Filter utilise Annotation

Dans l'exemple supérieur, la configuration du Filter dans web.xml, mais avec la version 3 ou version plus haute de l'application web (WebApp) vous pouvez utiliser l'annotation afin de configurer le filtre.

Cet exemple illustre alors que des utilisateurs utilisent la requête pour voir un fichier d'image ( jpg, png ou gif), le filtre va vérifier ledit fichier existe ou pas. Au cas il n'existe pas, le filtre va réorienter la requête vers le fichier d'image par défaut.
D'abord, vous copiez 2 fichiers flower.png & image-not-found.png dans le dossier d'image sur votre application web (WebApp).
ImageFilter.java
package org.o7planning.tutorial.servletfilter;

import java.io.File;
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;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebFilter(urlPatterns = { "*.png", "*.jpg", "*.gif" }, initParams = {
		@WebInitParam(name = "notFoundImage", value = "/images/image-not-found.png") })
public class ImageFilter implements Filter {

	private String notFoundImage;

	public ImageFilter() {
	}

	@Override
	public void init(FilterConfig fConfig) throws ServletException {

		// ==> /images/image-not-found.png
		notFoundImage = fConfig.getInitParameter("notFoundImage");
	}

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest req = (HttpServletRequest) request;

		// ==> /images/path/my-image.png
		// ==> /path1/path2/image.pngs
		String servletPath = req.getServletPath();

		// Le chemin d'accès absolu du répertoire racine WebApp (WebContent).
		String realRootPath = request.getServletContext().getRealPath("");

		// Le chemin absolu de l'image.
		String imageRealPath = realRootPath + servletPath;

		System.out.println("imageRealPath = " + imageRealPath);

		File file = new File(imageRealPath);

		// Vérifiez l'existence de l'image.
		if (file.exists()) {

			// Permettez la demande de passer à l'élément suivant (filtre ou servlet) dans la chaîne
			// (Allez vers le fichier de l'image demandé).
			chain.doFilter(request, response);

		} else if (!servletPath.equals(this.notFoundImage)) {

			// Redirect (Réorienter) vers le fichier d'image 'image not found'.
			HttpServletResponse resp = (HttpServletResponse) response;

			// ==> /ServletFilterTutorial + /images/image-not-found.png
			resp.sendRedirect(req.getContextPath() + this.notFoundImage);

		}

	}

}
Réexécurez votre application et essayez URL suivant:
Avec des liens qui sollicitent le fichier d'image mais ledit fichier n'existe pas, il va être réorienté vers l'image par défaut.
Dans l'exemple précédent, vous pouvez également utiliser la requête Transmettre (Forward) au lieu d'utiliser la requête Réorienter (Redirect) au fichier d'image au cas où le fichier d'image n'existe pas.
// Redirect:

// ==> /ServletFilterTutorial + /images/image-not-found.png
response.sendRedirect(request.getContextPath()+ this.notFoundImage);

// Forward:

request.getServletContext().getRequestDispatcher(this.notFoundImage).forward(request, response);

11. L'établissement de la connexion JDBC dans Filter

Vous pouvez créer l'objet Connection qui connecte JDBC dans Servlet pour traiter des activités dans la base de données. Mais vous pouvez également créer l'objet Connection qui connecte JDBC dans le filtre (Filter), et il va prendre effet aux plusieurs Servlet. Et vous pouvez utiliser ce Connection partout sur le chemin de la requête. Vous pouvez observer l'illustration ci-dessous pour comprendre mieux:
ConnectionUtils est une classe qui crée l'objet Connection connecté à la base de données, dans ce document, je n'introduit pas en détail comment obtenir l'objet Connection.
Vous pouvez découvrir le document sur JDBC à:
ConnectionUtils.java
package org.o7planning.tutorial.servletfilter.conn;

import java.sql.Connection;

public class ConnectionUtils {

	public static Connection getConnection() {

		// Créez une Connection (Connexion) vers la base de données.
		Connection conn = null;

		// .....
		return conn;
	}

	public static void closeQuietly(Connection conn) {
		try {
			conn.close();
		} catch (Exception e) {
		}
	}

	public static void rollbackQuietly(Connection conn) {
		try {
			conn.rollback();
		} catch (Exception e) {
		}
	}
}
MyUtils.java
package org.o7planning.tutorial.servletfilter.conn;

import java.sql.Connection;

import javax.servlet.ServletRequest;

public class MyUtils {

	public static final String ATT_NAME = "MY_CONNECTION_ATTRIBUTE";

	// Stockez l'objet Connection dans un attribut (attribute) de la demande.
	// Des informations stockées existent uniquement dans le temps de l'exécution de la demande (request)
	// jusuq'à que des données seront envoyées vers le navigateur de l'utilisateur.
	public static void storeConnection(ServletRequest request, Connection conn) {
		request.setAttribute(ATT_NAME, conn);
	}

	// Obtenez l'objet Connection qui a été stocké dans un attribut de la demande.
	public static Connection getStoredConnection(ServletRequest request) {
		Connection conn = (Connection) request.getAttribute(ATT_NAME);
		return conn;
	}
}
Je déclare url-pattern pour JDBCFilter est /*, ce filtre va traiter toutes les requêtes des utilisateurs.
JDBCFilter.java
package org.o7planning.tutorial.servletfilter.conn;

import java.io.IOException;
import java.sql.Connection;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

@WebFilter(urlPatterns = { "/*" })
public class JDBCFilter implements Filter {

	public JDBCFilter() {
	}

	@Override
	public void init(FilterConfig fConfig) throws ServletException {

	}

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest req = (HttpServletRequest) request;

		// 
		String servletPath = req.getServletPath();

		// Ouvrez uniquement Connection (Connexion) pour des demandes ayant le chemin particulier
		// (Par exemple: des chemins vont envers servlet, jsp, ..)
		// Évitez le cas d'ouverture Connection pour des demandes normales
		// (Par exemple: image, css, javascript,... )
		if (servletPath.contains("/specialPath1") || servletPath.contains("/specialPath2")) {
			Connection conn = null;
			try {
				// Créez l'objet Connection pour se connecter à la base de données.
				conn = ConnectionUtils.getConnection();
				// Définissez automatiquement commit = false.
				conn.setAutoCommit(false);

				// Enregistrez la connexion dans un attribut (attribute) de demande.
				MyUtils.storeConnection(request, conn);

				// Permettez la demande de passer à l'élément suivant (filtre ou cible) dans la chaîne.
				chain.doFilter(request, response);

				// Appelez commit() pour terminer la transaction (transaction) avec DB.
				conn.commit();
			} catch (Exception e) {
				ConnectionUtils.rollbackQuietly(conn);
				throw new ServletException();
			} finally {
				ConnectionUtils.closeQuietly(conn);
			}
		}
		// Pour des demandes normales.
		else {
			// Autorisez de la demande de passer à l'élément suivant (Passer ce filtre).
			chain.doFilter(request, response);
		}

	}

}
Au prochain filtre ou dans l'objectif (servlet ou JSP), vous pouvez obtenir un objet Connection qui est stocké dans l'attribut (attribute) de la requête:
Connection conn = (Connection) request.getAttribute(ATT_NAME);

// Ou
Connection conn = MyUtils.getStoredConnection();

12. Le tutoriel JSP

Ensuite, vous pouvez apprendre JSP à: