[SpringMVC] Démarrage rapide avec JSR 303 et intercepteur intercepteur

Table des matières

1.JSR303

1. Qu'est-ce que la JSR 303 ?

2. Pourquoi utiliser JSR 303 ?

3. Annotations communes JSR 303

3.1. Annotations JSR 303 couramment utilisées

3.2. La différence entre @Validated et @Valid

3.2.1、@Validé

3.2.2、@Valid

3.2.3. Différences

4. Cas d'utilisation

4.1. Importer les dépendances

4.2. Configurer les règles de vérification

4.3. Méthode de vérification d'écriture

4.4. Code frontal

4.5. Tests

2. intercepteur intercepteur

1. Qu'est-ce qu'un intercepteur ?

2. Pourquoi utiliser des intercepteurs ?

3. Intercepteurs et filtres

 3.1. Qu'est-ce qu'un filtre ?

3.2. La différence entre les intercepteurs et les filtres

3.2.1. Filtrer

3.2.2. Intercepteur

3.2.3. Résumé

4. Scénarios d'application des intercepteurs

5. Cas d'utilisation

5.1. Créer un intercepteur

5.2. Configurer l'intercepteur

5.3. Exécutez le test

5.4. Principe de fonctionnement de l'intercepteur

5.5. Chaîne d'intercepteur

5.6. Exemple d'interception de connexion

5.6.1. Créer un intercepteur

5.6.2. Configurer l'intercepteur

5.6.3. Écriture de la couche de contrôle

5.6.4. Page d'accueil

5.6.5. Tests

se connecter

se déconnecter


1.JSR303

1. Qu'est-ce que la JSR 303 ?

JSR 303 est l'abréviation de Java Spécification Request , qui signifie proposition de spécification Java. Il s'agit d'une demande formelle adressée à JCP (Java Community Process) pour ajouter une spécification technique standardisée. N'importe qui peut soumettre un JSR pour ajouter de nouvelles API et services à la plateforme Java. JSR est devenu un standard important dans le monde Java. JSR-303 est une sous-spécification de JAVA EE 6 appelée Bean Validation . Hibernate Validator est l'implémentation de référence de Bean Validation . Hibernate Validator fournit l'implémentation de toutes les contraintes intégrées dans la spécification JSR 303 , en plus de certaines contraintes supplémentaires.

Il définit un ensemble de normes pour la validation Java Bean. JSR 303 utilise des annotations, qui sont largement utilisées dans Spring MVC pour la vérification et la vérification des données.

La validation des données est une tâche courante qui se produit dans toutes les couches d'application, de la couche de présentation à la couche de persistance. Souvent, la même logique de validation est mise en œuvre à chaque couche, ce qui prend du temps et est sujette aux erreurs. Pour éviter de dupliquer ces validations, les développeurs regroupent souvent la logique de validation directement dans le modèle de domaine, en mélangeant les classes de domaine avec un code de validation qui est en réalité des métadonnées sur les classes elles-mêmes.

2. Pourquoi utiliser JSR 303 ?

        Nous avons effectué la vérification des données sur le front-end, mais pourquoi avons-nous besoin de faire un autre article ? Parce qu'à cause d'une petite erreur, notre vérification frontale n'a pas été bien écrite, mais certaines personnes contournent toujours les requêtes envoyées par le front-end (via des tests comme Postman Tools font des requêtes de données extraordinaires) et transmettent des paramètres erronés, ce qui mettra notre code back-end en grand danger, nous utilisons donc généralement un ensemble de vérifications sur le front-end et un ensemble de vérifications sur le back-end, donc que la sécurité est Elle peut être grandement améliorée.

J'ai donc résumé ci-dessous les avantages du JSR 303 :

  1. Améliorer la maintenabilité du code : en ajoutant des annotations à la classe d'entité, les champs et les règles qui doivent être vérifiés peuvent être clairement identifiés, ce qui rend le code plus facile à comprendre et à maintenir.
  2. Améliorer l'intégrité des données : selon des règles définies, la légalité des données saisies peut être automatiquement vérifiée pour empêcher les données erronées d'entrer dans le système et garantir l'intégrité et l'exactitude des données.
  3. Réduisez le code en double : grâce aux annotations, les mêmes règles de vérification peuvent être réutilisées dans différents scénarios, réduisant ainsi la charge de travail liée à l'écriture de code en double.

3. Annotations communes JSR 303

3.1. Annotations JSR 303 couramment utilisées

Description de l'annotation @Null est utilisé pour vérifier que l'objet est nul . @NotNull est utilisé lorsque l'objet ne peut pas être null et qu'une chaîne d'une longueur de 0 ne peut pas être vérifiée. @NotBlank est uniquement utilisé pour le type String , il ne peut pas être null et le size after trim() is > 0 @NotEmpty Utilisé pour les classes de collection, les classes String ne peuvent pas être null et size>0 . Mais les chaînes avec des espaces ne peuvent pas être vérifiées. @Size est utilisé pour les objets ( Array, Collection, Map, String ) si la longueur est dans la plage donnée. @Length est utilisé pour les objets String . La taille doit être dans la plage spécifiée. @ Modèle Utilisé pour savoir si l'objet String est conforme aux règles de l'expression régulière @Email Utilisé pour si l'objet String est conforme au format email @Min Utilisé pour si les objets Number et String sont supérieurs ou égaux à la valeur spécifiée @Max Utilisé pour savoir si les objets Number et String sont inférieurs ou égaux à la valeur spécifiée @ AssertTrue est utilisé pour déterminer si l' objet booléen esttrue @AssertFalse pour savoir si l' objet booléen est faux

3.2. La différence entre @Validated et @Valid

@Validated et @Valid sont des annotations utilisées pour la vérification des données, mais elles présentent quelques différences et scénarios d'application.

3.2.1、@Validé
  • Annotations fournies par le framework Spring
  • Vérification du groupe de soutien
  • Peut être utilisé sur les types, les méthodes et les paramètres de méthode . Mais il ne peut pas être utilisé sur les attributs des membres (champs)
  • Puisqu'elle ne peut pas être ajoutée aux attributs (champs) des membres, la vérification en cascade ne peut pas être effectuée seule et doit être coordonnée avec @Valid.
  • Le validateur fourni par Spring utilise Hibernate Validator par défaut (implémente la spécification JSR-303), mais il prend en charge des scénarios de validation plus riches, tels que la validation de groupe.
3.2.2、@Valid
  • Annotations de la spécification JSR-303 ( Bean Validation ) fournies par le JDK
  • La vérification de groupe n'est pas prise en charge
  • Peut être utilisé sur les méthodes, les constructeurs, les paramètres de méthode et les propriétés des membres (champs)
  • Peut être ajouté aux attributs des membres (champs) pour effectuer la vérification en cascade de manière indépendante
  • Lors de l'utilisation de l'annotation @Valid, JSR-303 ou d'autres frameworks de validation pris en charge seront déclenchés pour valider l'objet annoté.
3.2.3. Différences
  1. Champ d'application : @Valid peut être appliqué aux paramètres de méthode, aux valeurs de retour, aux champs et aux méthodes, tandis que @Validated ne peut être appliqué qu'aux classes, interfaces et méthodes.
  2. Framework de validation : @Validated utilise Hibernate Validator (implémente JSR-303), Spring Validator ou un validateur personnalisé par défaut, tandis que @Valid utilise JSR-303 ou d'autres frameworks de validation pris en charge.
  3. Vérification de groupe : @Validated prend en charge la vérification de groupe, permettant d'utiliser différentes règles de vérification dans différents scénarios, tandis que @Valid ne prend pas directement en charge la vérification de groupe.

@Validated est une annotation étendue fournie par le framework Spring et n'appartient pas à la spécification standard Java. Lors de son utilisation, vous pouvez sélectionner les annotations appropriées pour la vérification des données en fonction de besoins spécifiques.

4. Cas d'utilisation

4.1. Importer les dépendances

<!-- JSR303 -->
<hibernate.validator.version>6.0.7.Final</hibernate.validator.version>

<!-- JSR303 -->
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>${hibernate.validator.version}</version>
</dependency>

4.2. Configurer les règles de vérification

Ajouter une vérification de configuration dans la classe d'entité

package com.tgq.model;

import lombok.ToString;
import org.hibernate.validator.constraints.NotBlank;

import javax.validation.constraints.NotNull;

@ToString
public class MyStudent {

    @NotNull(message = "学生编号不能为空")
    private String sid;

    @NotBlank(message = "学生名不能为空")
    private String sname;

    @NotBlank(message = "学生年龄不能为空")
    private String sage;

    @NotBlank(message = "学生性别不能为空")
    private String ssex;

    public MyStudent(String sid, String sname, String sage, String ssex) {
        this.sid = sid;
        this.sname = sname;
        this.sage = sage;
        this.ssex = ssex;
    }

    public MyStudent() {
        super();
    }

    public String getSid() {
        return sid;
    }

    public void setSid(String sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSage() {
        return sage;
    }

    public void setSage(String sage) {
        this.sage = sage;
    }

    public String getSsex() {
        return ssex;
    }

    public void setSsex(String ssex) {
        this.ssex = ssex;
    }
}

4.3. Méthode de vérification d'écriture

   Utilisez @Validateddes annotations pour effectuer une vérification côté serveur sur notre MyStudent.

    //    给数据添加服务端校验
    @RequestMapping("/valiAdd")
    public String valiAdd(@Validated MyStudent myStudent, BindingResult result, HttpServletRequest req) {
//        如果服务端验证不通过,有错误
        if (result.hasErrors()) {
//            服务端验证了实体类的多个属性,多个属性都没有验证通过
            List<FieldError> fieldErrors = result.getFieldErrors();
            Map<String, Object> map = new HashMap<>();
            for (FieldError fieldError : fieldErrors) {
//                将多个属性的验证失败信息输送到控制台
                System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
                map.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
            req.setAttribute("errorMap", map);
        } else {
            this.myStudentBiz.insertSelective(myStudent);
            return "redirect:stu/list";
        }
        return "stu/edit";
    }

4.4. Code frontal

Soumettre via le formulaire

<%--
  Created by IntelliJ IDEA.
  User: tgq
  Date: 12/9/2023
  Time: 下午8:05
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>edit</title>
</head>
<body>

<form action="${pageContext.request.contextPath }/stu/valiAdd" method="post">
    用户id:<input type="text" name="sid"><span style="color: red">${errorMap.sid}</span><br>
    用户名:<input type="text" name="sname"><span style="color: red">${errorMap.sname}</span><br>
    用户年龄:<input type="text" name="sage"><span
        style="color: red">${errorMap.sage}</span><br>
    用户性别:<input type="text" name="ssex"><span style="color: red">${errorMap.ssex}</span><br>
    <input type="submit" value="提交">
</form>
</body>
</html>

4.5. Tests

Cliquez sur Soumettre. S'il est vide, vous serez invité.

2. intercepteur intercepteur

1. Qu'est-ce qu'un intercepteur ?

        Les intercepteurs sont des composants qui exécutent une logique spécifique avant ou après qu'une requête entre dans un gestionnaire backend. Ils sont capables d'intercepter le flux d'exécution par le gestionnaire, permettant ainsi d'insérer des fonctionnalités supplémentaires dans le processus de traitement des demandes.

        L'intercepteur de processeur de SpringMVC est similaire au filtre du développement de servlets et est utilisé pour pré-traiter et post-traiter le processeur. Il s'appuie sur le framework Web et est basé sur le mécanisme de réflexion de Java en implémentation, qui est une application de programmation orientée aspect (AOP) . Étant donné que l'intercepteur est basé sur l'appel du framework Web, l'injection de dépendance (DI) de Spring peut être utilisée pour effectuer certaines opérations commerciales. Dans le même temps, une instance d'intercepteur peut être appelée plusieurs fois au cours d'un cycle de vie du contrôleur .

2. Pourquoi utiliser des intercepteurs ?

  1. Expansion horizontale des fonctions : grâce aux intercepteurs, des fonctions supplémentaires peuvent être ajoutées sans modifier la logique métier d'origine, telles que la journalisation, la vérification des autorisations, les statistiques de performances, etc.
  2. Réutilisation du code : plusieurs requêtes peuvent nécessiter la même logique de traitement. Cette partie de la logique peut être extraite via des intercepteurs pour réduire l'écriture répétée du code.
  3. Découplage : grâce aux intercepteurs, les préoccupations peuvent être séparées et la logique commune est traitée dans les intercepteurs, permettant au processeur métier de se concentrer davantage sur l'activité elle-même.

3. Intercepteurs et filtres

 3.1. Qu'est-ce qu'un filtre ?

Dépend du conteneur de servlet . Sur la base des rappels de fonction lors de l'implémentation, presque toutes les requêtes peuvent être filtrées , mais l'inconvénient est qu'une instance de filtre ne peut être appelée qu'une seule fois lors de l'initialisation du conteneur . Le but de l'utilisation de filtres est d'effectuer certaines opérations de filtrage, telles que : modifier l'encodage des caractères dans le filtre ; modifier certains paramètres de HttpServletRequest dans le filtre , notamment : filtrer le texte vulgaire, les caractères dangereux, etc.

3.2. La différence entre les intercepteurs et les filtres

3.2.1. Filtrer
  1.   Filter appartient à la technologie Servlet et peut être utilisé dans n’importe quel projet Web.
  2.   le filtre est principalement dû au filtrage de toutes les demandes
  3.   Le temps d'exécution du filtre est antérieur à celui de l'intercepteur
3.2.2. Intercepteur
  1.   Interceptor appartient à la technologie SpringMVC et doit disposer d'un environnement SpringMVC avant de pouvoir être utilisé.
  2.   l'intercepteur intercepte généralement le contrôleur du processeur
  3.   l'intercepteur ne peut intercepter que les requêtes traitées par dispatcherServlet
3.2.3. Résumé
  • Les intercepteurs sont exécutés à l'intérieur du gestionnaire d'application , tandis que les filtres sont exécutés avant ou après l'application .
  • Les filtres sont basés sur la spécification Servlet et les intercepteurs sont basés sur le framework d'application.
  • Les filtres peuvent traiter les requêtes avant qu'elles n'atteignent le conteneur de servlet, tandis que les intercepteurs ne peuvent traiter les requêtes qu'après avoir atteint l'application.

4. Scénarios d'application des intercepteurs

  1. Vérification des autorisations : L'intercepteur peut vérifier si l'utilisateur a l'autorisation d'opérer. Dans le cas contraire, il peut intercepter la demande et renvoyer le message d'erreur correspondant. Sinon, revenez directement à la page de connexion.
  2. Journalisation : l'intercepteur peut enregistrer les informations détaillées de la demande, telles que l'heure de la demande, les informations, les paramètres de la demande, etc., pour faciliter l'analyse ultérieure des journaux et le dépannage. Afin d'effectuer un suivi des informations, des statistiques d'informations, le calcul de PV (Page View), etc.
  3. Statistiques de performances : L'intercepteur peut compter le temps d'exécution des requêtes pour faciliter l'analyse et l'optimisation des performances du système. (S'il existe un proxy inverse, tel qu'Apache, il peut être automatiquement enregistré) ;
  4. Comportement général : lire le cookie pour obtenir des informations sur l'utilisateur et insérer l'objet utilisateur dans la requête, afin de faciliter l'utilisation ultérieure du processus, ainsi que pour extraire les informations de localisation et de thème, etc., à condition que les méthodes de traitement dans plusieurs contrôleurs si nous en avons besoin, nous pouvons utiliser un outil d'interception.

Une chaîne d'intercepteurs est une structure de chaîne composée de plusieurs intercepteurs , chacun pouvant effectuer des opérations spécifiques avant ou après l'exécution du gestionnaire de requêtes. Les intercepteurs de la chaîne d'intercepteurs sont exécutés dans un ordre prédéfini et chaque intercepteur a la possibilité de traiter la demande et la réponse. La chaîne d'intercepteurs peut assurer l'exécution ordonnée de chaque intercepteur pour réaliser la logique de traitement attendue.

5. Cas d'utilisation

5.1. Créer un intercepteur

Créez un package d'intercepteur et créez l'intercepteur sous le package

package com.tgq.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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


public class OneInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【OneInterceptor】:preHandle...");

        return true;//返回true / false
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("【OneInterceptor】:postHandle...");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("【OneInterceptor】:afterCompletion...");
    }
}

5.2. Configurer l'intercepteur

Configurez notre intercepteur dans notre propre configuration spring-mvc.xml

<mvc:interceptors>
        <bean class="com.tgq.interceptor.OneInterceptor"></bean>
    </mvc:interceptors>

5.3. Exécutez le test

Démarrez le projet, ouvrez le navigateur pour accéder à l'adresse de la demande et testez l'effet d'interception de l'intercepteur.

Leur ordre d'exécution est : preHandle --> postHandle --> afterCompletion

http://localhost:8080/sc/list

5.4. Principe de fonctionnement de l'intercepteur

  • preHandle : permet de prétraiter les requêtes interceptées. La méthode reçoit une valeur de retour de type booléen (true, false). Renvoie true : libérée, false : non libérée.

Synchronisation d'exécution : exécuté avant l'exécution de la méthode du processeur

paramètres de méthode
paramètre illustrer
demande       objet de demande    
réponse     objet de réponse    
gestionnaire       Méthode du gestionnaire intercepté  
ModèleEtVue Objets modèle et vue renvoyés par la méthode du gestionnaire, le modèle et la vue peuvent être modifiés dans la méthode
  • afterCompletion : utilisé pour le traitement final une fois l'ensemble du processus terminé. S'il y a une exception dans le processus de demande, l'objet peut être obtenu dans la méthode

  Calendrier d'exécution : une fois le rendu de la vue terminé (après la fin de l'ensemble du processus)

paramètres de méthode
paramètre illustrer
demande   Paramètres de la demande
réponse objet de réponse  
gestionnaire   Méthode du gestionnaire intercepté
ex objet d'exception

5.5. Chaîne d'intercepteur

Si plusieurs intercepteurs peuvent intercepter la même demande, plusieurs intercepteurs formeront une chaîne d'intercepteurs.L'objectif principal est de comprendre l'ordre d'exécution de chaque intercepteur dans la chaîne d'intercepteurs. L'ordre d'exécution de plusieurs intercepteurs dans la chaîne d'intercepteurs est lié à l'ordre de configuration de l'intercepteur racine. Celui configuré en premier est exécuté en premier.

package com.tgq.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class TwoInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【TwoInterceptor】:preHandle...");

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("【TwoInterceptor】:postHandle...");

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("【TwoInterceptor】:afterCompletion...");
    }
}

Configurer spring-mvc.xml

<mvc:interceptors>
        <!--2) 多拦截器(拦截器链)-->
        <mvc:interceptor>
            <mvc:mapping path="/**"/>
            <bean class="com.tgq.interceptor.OneInterceptor"/>
        </mvc:interceptor>
        <mvc:interceptor>
            <mvc:mapping path="/sc/**"/>
            <bean class="com.tgq.interceptor.TwoInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>

Utilisez un intercepteur : éditez icon-default.png?t=N7T8http://localhost:8080/stu/save

Prenez deux intercepteurs : listez icon-default.png?t=N7T8http://localhost:8080/sc/list

5.6. Exemple d'interception de connexion

5.6.1. Créer un intercepteur
package com.tgq.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("【implements】:preHandle...");
        StringBuffer url = request.getRequestURL();
        if (url.indexOf("/login") > 0 || url.indexOf("/logout") > 0) {
            //        如果是 登录、退出 中的一种
            return true;
        }
//            代表不是登录,也不是退出
//            除了登录、退出,其他操作都需要判断是否 session 登录成功过
        String sname = (String) request.getSession().getAttribute("sname");
        if (sname == null || "".equals(sname)) {
            response.sendRedirect("/page/stu/login");
            return false;
        }
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
5.6.2. Configurer l'intercepteur
    <!--登录拦截器实例-->
    <mvc:interceptors>
        <bean class="com.tgq.interceptor.LoginInterceptor"></bean>
    </mvc:interceptors>

5.6.3. Écriture de la couche de contrôle
package com.tgq.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

@Controller
public class LoginController {
    @RequestMapping("/login")
    public String login(HttpServletRequest req) {
        String sname = req.getParameter("sname");
        HttpSession session = req.getSession();
        if ("tgq".equals(sname)) {
            session.setAttribute("sname", sname);
        }
        return "redirect:/sc/list";
    }

    @RequestMapping("/logout")
    public String logout(HttpServletRequest req) {
        req.getSession().invalidate();
        return "redirect:/sc/list";
    }
}
5.6.4. Page d'accueil
<%--
  Created by IntelliJ IDEA.
  User: tgq
  Date: 12/9/2023
  Time: 下午10:03
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>用户登录</title>
</head>
<body>

<form action="/login" method="post">
    账号:<input name="sname">
    <input type="submit">
</form>
</body>
</html>
5.6.5. Tests
se connecter

http://localhost:8080/logout icon-default.png?t=N7T8http://localhost:8080/login

se déconnecter

http://localhost:8080/logout icon-default.png?t=N7T8http://localhost:8080/logout

Je suppose que tu aimes

Origine blog.csdn.net/weixin_74383330/article/details/132837017
conseillé
Classement