네트워크 요청을 처리할 때 일부 기능을 업무와 분리하여 균일하게 추출하여 처리해야 합니다.
Spring mvc의 인터셉터 Interceptor를 사용하여 HandlerInterceptor 인터페이스를 구현할 수 있습니다. 이 인터페이스를 구현한 후 요청은 컨트롤러로 전송되기 전에 차단됩니다.
인터셉터의 구현은 다음 두 단계로 나뉩니다.
사용자 정의 인터셉터를 생성하고 HandlerInterceptor 인터페이스의 preHandle(특정 메소드를 실행하기 전 전처리) 메소드를 구현합니다.
WebMvcConfigurer의 addInterceptors 메서드에 사용자 정의 인터셉터를 추가합니다.
로그인 확인의 예시로 세션을 사용합니다.
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; } }
웹MvcConfigurer를 통해 작성된 ⾃정의 인터셉터를 컨테이너에 등록하여 인터셉터를 유효하게 만듭니다.
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 } }
객체가 주입되지 않은 경우 addInterceptor()의 매개변수는 새 객체를 직접 생성할 수도 있습니다.
@Configuration // 一定不要忘记 public class MyConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns("/**") // 拦截所有请求 .excludePathPatterns("/user/login"); // 排除不拦截的 url } }
Principle
모든 컨트롤러 실행은 spring mvc 스케줄러 DispatcherServlet을 통해 구현되며 모든 메소드는 doDispatch 스케줄링을 실행합니다. DispatcherServlet 메소드의 doDispatch 소스 코드는 다음과 같습니다.
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); } } }
위의 소스 코드를 보면 Controller 실행을 시작하기 전에 전처리 메소드인 applyPreHandle이 먼저 호출되는 것을 알 수 있습니다. applyPreHandle 메소드의 구현 소스 코드는 다음과 같습니다.
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; }
요청 시간 기반 예외 처리도 통합 처리의 공통 개체입니다.
통합된 예외 처리는 @ControllerAdvice + @ExceptionHandler를 사용하여 구현됩니다. @ControllerAdvice는 컨트롤러 알림 클래스를 나타내고, @ExceptionHandler는 예외 핸들러를 의미하며, 이 둘의 조합은 예외가 발생할 때 특정 알림이 실행된다는 의미입니다. 특정 메소드 이벤트를 실행하기 위한 구체적인 구현 코드는 다음과 같습니다.
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; } }
이때 예외가 발생하면 오류가 보고되지 않지만 코드는 계속 실행되지만 사용자 정의된 예외 정보가 전면으로 반환됩니다. 끝!
@ControllerAdvice는 진입점과 짜여져야 하는 패싯 로직을 포함하여 컨트롤러의 모든 속성을 잘라내는 스프링의 AOP입니다. @ExceptionHandler와 함께 작동하여 컨트롤러에 던져진 특정 유형의 예외를 캡처하므로 다양한 유형의 예외 처리 목적을 달성하기 위해.
통일된 반환 데이터 구조는 @ControllerAdvice + ResponseBodyAdvice 인터페이스를 사용하여 구현할 수 있습니다. 구체적인 구현 코드는 다음과 같습니다.
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; } }
위 내용은 SpringBoot 통합 처리 기능 구현 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!