Rumah  >  Artikel  >  Java  >  Bagaimana untuk melaksanakan fungsi pemprosesan bersatu SpringBoot

Bagaimana untuk melaksanakan fungsi pemprosesan bersatu SpringBoot

WBOY
WBOYke hadapan
2023-05-11 16:04:061289semak imbas

Apabila memproses permintaan rangkaian, beberapa fungsi perlu diekstrak dan diproses secara seragam, dipisahkan daripada perniagaan.

Pengesahan log masuk

Anda boleh menggunakan Interceptor Interceptor spring mvc untuk melaksanakan antara muka HandlerInterceptor. Selepas melaksanakan antara muka ini, permintaan akan dipintas sebelum dihantar kepada Pengawal.

Pelaksanaan pemintas terbahagi kepada dua langkah berikut:

  • Buat pemintas tersuai dan laksanakan praPemegang antara muka HandlerInterceptor (pra-pemprosesan sebelum melaksanakan kaedah tertentu) pemprosesan) kaedah.

  • Tambah pemintas tersuai pada kaedah addInterceptors WebMvcConfigurer.

Kami menggunakan sesi sebagai contoh pengesahan log masuk Pelaksanaannya adalah seperti berikut:

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

Daftarkan pemintas yang ⾃ditakrifkan ke dalam bekas melalui WebMvcConfigurer untuk membolehkan pemintasan. kod pelaksanaan khusus adalah seperti berikut:

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

Jika tiada objek disuntik, parameter addInterceptor() juga boleh terus mencipta objek baharu:

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

Prinsip

Semua Pengawal Pelaksanaan akan dilaksanakan melalui DispatcherServlet spring mvc Semua kaedah akan melaksanakan kaedah penjadualan doDispatch dalam DispatcherServlet Kod sumber doDispatch adalah seperti berikut:

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

Dari kod sumber di atas, dapat dilihat bahawa. sebelum mula melaksanakan Pengawal , kaedah prapemprosesan applyPreHandle akan dipanggil dahulu Kod sumber pelaksanaan kaedah applyPreHandle adalah seperti berikut:

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

Pengendalian pengecualian

Pengendalian pengecualian semasa permintaan juga merupakan satu objek biasa pemprosesan bersatu.

Pengendalian pengecualian bersatu dilaksanakan menggunakan @ControllerAdvice + @ExceptionHandler @ControllerAdvice mewakili kelas pemberitahuan pengawal, dan @ExceptionHandler ialah pengendali pengecualian. Pemberitahuan, iaitu, pelaksanaan acara kaedah tertentu Kod pelaksanaan khusus adalah seperti berikut:

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

Jika pengecualian berlaku pada masa ini, tiada ralat akan dilaporkan. tetapi maklumat pengecualian tersuai akan dikembalikan ke bahagian hadapan!

Prinsip

@ControllerAdvice ialah aop spring yang menghiris semua sifat Pengawal, termasuk titik masuk dan logik hirisan yang perlu dianyam. Ia berfungsi dengan @ExceptionHandler untuk menangkap jenis yang dilemparkan yang ditentukan dalam Pengecualian Pengawal, untuk mencapai tujuan mengendalikan pelbagai jenis pengecualian secara berbeza.

Struktur data pulangan

Struktur data pulangan bersatu boleh dilaksanakan menggunakan antara muka @ControllerAdvice + ResponseBodyAdvice Kod pelaksanaan khusus adalah seperti berikut:

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

Atas ialah kandungan terperinci Bagaimana untuk melaksanakan fungsi pemprosesan bersatu SpringBoot. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam