Maison  >  Article  >  Java  >  Comment implémenter la fonction de traitement unifié SpringBoot

Comment implémenter la fonction de traitement unifié SpringBoot

WBOY
WBOYavant
2023-05-11 16:04:061184parcourir

Lors du traitement des requêtes réseau, certaines fonctions doivent être extraites et traitées de manière uniforme, séparées de l'entreprise.

Vérification de connexion

Vous pouvez utiliser l'intercepteur Interceptor de spring mvc pour implémenter l'interface HandlerInterceptor. Après implémentation de cette interface, la requête sera interceptée avant d'être envoyée au Contrôleur.

L'implémentation de l'intercepteur est divisée en deux étapes suivantes :

  • Créer un intercepteur personnalisé et implémenter la méthode preHandle (prétraitement avant d'exécuter la méthode spécifique) de l'interface HandlerInterceptor.

  • Ajoutez des intercepteurs personnalisés à la méthode addInterceptors de WebMvcConfigurer.

Nous utilisons la session comme exemple de vérification de connexion. L'implémentation est la suivante :

package com.demo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
 * 登录拦截器
 */
@Component
@Slf4j
public class LoginInterceptor implements HandlerInterceptor {
    /**
     * 为 false 则不能继续往下执行;为 true 则可以。
     */ 
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 判断session的信息是否合法
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("userinfo") != null) {
            return true;
        }
        log.error("当前用户没有访问权限");
        response.setStatus(401);
        return false;
    }
}

Enregistrez l'intercepteur de définition ⾃écrit dans le conteneur via WebMvcConfigurer pour rendre l'intercepteur efficace. Le code d'implémentation spécifique est le suivant :

package com.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyConfig implements WebMvcConfigurer {
    @Autowired
    private LoginInterceptor loginInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor)
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/user/login"); // 排除不拦截的 url
    }
}
.

Si aucun objet n'est injecté, les paramètres de addInterceptor() peuvent également créer directement un nouvel objet :

@Configuration // 一定不要忘记
public class MyConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**") // 拦截所有请求
                .excludePathPatterns("/user/login"); // 排除不拦截的 url
    }
}

Principe

Toutes les exécutions du contrôleur seront implémentées via le planificateur Spring MVC DispatcherServlet, et toutes les méthodes exécuteront la planification doDispatch dans Méthode DispatcherServlet, le code source de doDispatch est le suivant :

protected void doDispatch(HttpServletRequest request, HttpServletResponse
        response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    try {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;
            try {
                // ...  忽略不重要的代码
                // 调⽤预处理
                if (!mappedHandler.applyPreHandle(processedRequest, respon
                        se)) {
                    return;
                }
                // 执⾏ Controller 中的业务
                mv = ha.handle(processedRequest, response, mappedHandler.g
                        etHandler());
               // ...  忽略不重要的代码
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler di
                        spatch failed", var21);
            }
            this.processDispatchResult(processedRequest, response, mappedH
                    andler, mv, (Exception)dispatchException);
        } catch (Exception var22) {
            this.triggerAfterCompletion(processedRequest, response, mapped
                    Handler, var22);
        } catch (Throwable var23) {
            this.triggerAfterCompletion(processedRequest, response, mapped
                    Handler, new NestedServletException("Handler processing failed", var23));
        }
    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processe
                        dRequest, response);
            }
        } else if (multipartRequestParsed) {
            this.cleanupMultipart(processedRequest);
        }
    }
}

À partir du code source ci-dessus, nous pouvons voir qu'avant de commencer à exécuter le Controller, la méthode de prétraitement applyPreHandle sera appelée en premier. Le code source d'implémentation de la méthode applyPreHandle est le suivant. suit :

boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex
            = i++) {
        // 获取项⽬中使⽤的拦截器 HandlerInterceptor
        HandlerInterceptor interceptor = (HandlerInterceptor)this.intercep
        torList.get(i);
        if (!interceptor.preHandle(request, response, this.handler)) {
            this.triggerAfterCompletion(request, response, (Exception)null
            );
            return false;
        }
    }
    return true;
}

Gestion des exceptions

Request La gestion des exceptions basée sur le temps est également un objet courant du traitement unifié.

La gestion unifiée des exceptions est implémentée à l'aide de @ControllerAdvice + @ExceptionHandler. @ControllerAdvice représente la classe de notification du contrôleur, et @ExceptionHandler est le gestionnaire d'exceptions. La combinaison des deux signifie qu'une certaine notification est exécutée lorsqu'une exception se produit, et c'est le cas. pour exécuter un certain événement de méthode. Le code d'implémentation spécifique est le suivant :

package com.demo;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.HashMap;
/**
 * 统一处理异常
 * 一般都需要自定义一个异常对象,这里为了简单说明只用一个map对象来说明
 */
@ControllerAdvice
public class ErrorAdive {
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public HashMap<String, Object> exceptionAdvie(Exception e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", "-1");
        result.put("msg", e.getMessage());
        return result;
    }
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public HashMap<String, Object> arithmeticAdvie(ArithmeticException e) {
        HashMap<String, Object> result = new HashMap<>();
        result.put("code", "-2");
        result.put("msg", e.getMessage());
        return result;
    }
}

Si une exception se produit à ce moment, aucune erreur ne sera signalée, mais les informations d'exception personnalisées seront renvoyées au premier plan. fin!

Principe

@ControllerAdvice est l'aop de Spring qui supprime tous les attributs du contrôleur, y compris les points d'entrée et la logique des facettes qui doivent être intégrées. Il fonctionne avec @ExceptionHandler pour capturer le type d'exception spécifié lancé dans le contrôleur, donc afin d'atteindre différents types de Le but de la gestion des exceptions.

Structure des données de retour

La structure de données de retour unifiée peut être implémentée à l'aide de l'interface @ControllerAdvice + ResponseBodyAdvice. Le code d'implémentation spécifique est le suivant :

package com.demo;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyA
dvice;
import java.util.HashMap;
/**
 * 统一返回数据的处理
 */
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    /**
     * 内容是否需要重写(通过此⽅法可以选择性部分控制器和⽅法进⾏重写)
     * 返回 true 表示重写
     */
    @Override
    public boolean supports(MethodParameter returnType, Class converterTyp
e) {
        return true;
    }
    /**
     * ⽅法返回之前调⽤此⽅法
     */
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType,
                                  Class selectedConverterType, ServerHttpR
                                          equest request,
                                  ServerHttpResponse response) {
        // 构造统⼀返回对象
        HashMap<String, Object> result = new HashMap<>();
        result.put("state", 1);
        result.put("msg", "");
        result.put("data", body);
        return result;
    }
}
.

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer