Apabila memproses permintaan rangkaian, beberapa fungsi perlu diekstrak dan diproses secara seragam, dipisahkan daripada perniagaan.
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 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!
@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 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!