Home  >  Article  >  Java  >  How to implement SpringBoot unified processing function

How to implement SpringBoot unified processing function

WBOY
WBOYforward
2023-05-11 16:04:061097browse

When processing network requests, some functions need to be extracted and processed uniformly, separated from the business.

Login verification

You can use the interceptor Interceptor of spring mvc to implement the HandlerInterceptor interface. After implementing this interface, the request will be intercepted before being sent to the Controller.

The implementation of the interceptor is divided into the following two steps:

  • Create a custom interceptor and implement the preHandle of the HandlerInterceptor interface (pre-Handle before executing the specific method) processing) method.

  • Add the custom interceptor to the addInterceptors method of WebMvcConfigurer.

We use session as an example of login verification. The implementation is as follows:

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;
    }
}

Register the written custom interceptor into the container through WebMvcConfigurer to enable interception The specific implementation code is as follows:

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
    }
}

If no object is injected, the parameters of addInterceptor() can also directly create a new object:

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

Principle

All Controllers The execution will be implemented through the spring mvc scheduler DispatcherServlet. All methods will execute the doDispatch scheduling method in DispatcherServlet. The doDispatch source code is as follows:

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);
        }
    }
}

It can be seen from the above source code that before starting to execute the Controller , the preprocessing method applyPreHandle will be called first, and the implementation source code of the applyPreHandle method is as follows:

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;
}

Exception handling

Exception handling during requests is also a relatively common object of unified processing.

Unified exception handling is implemented using @ControllerAdvice @ExceptionHandler. @ControllerAdvice represents the controller notification class, and @ExceptionHandler is the exception handler. The combination of the two means to execute a certain function when an exception occurs. Notification, that is, the execution of a certain method event, the specific implementation code is as follows:

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 exceptionAdvie(Exception e) {
        HashMap result = new HashMap<>();
        result.put("code", "-1");
        result.put("msg", e.getMessage());
        return result;
    }
    @ExceptionHandler(ArithmeticException.class)
    @ResponseBody
    public HashMap arithmeticAdvie(ArithmeticException e) {
        HashMap result = new HashMap<>();
        result.put("code", "-2");
        result.put("msg", e.getMessage());
        return result;
    }
}

If an exception occurs at this time, no error will be reported, the code will continue to execute, but the customized exception information will be returned to front end!

Principle

@ControllerAdvice is spring's aop that slices all attributes of the Controller, including entry points and slice logic that needs to be woven in, and works with @ExceptionHandler to capture the specified type thrown in the Controller. Exceptions, so as to achieve the purpose of handling different types of exceptions differently.

Return data structure

The unified return data structure can be implemented using the @ControllerAdvice ResponseBodyAdvice interface. The specific implementation code is as follows:

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 result = new HashMap<>();
        result.put("state", 1);
        result.put("msg", "");
        result.put("data", body);
        return result;
    }
}

The above is the detailed content of How to implement SpringBoot unified processing function. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:yisu.com. If there is any infringement, please contact admin@php.cn delete