日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

spring 两次进入拦截器_4.SpringBoot 拦截器Fliter,Interceptor,Controller……

發(fā)布時(shí)間:2023/11/27 生活经验 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring 两次进入拦截器_4.SpringBoot 拦截器Fliter,Interceptor,Controller…… 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在項(xiàng)目的開發(fā)中,在某些情況下,我們需要對客戶端發(fā)出的請求進(jìn)行攔截,常用的API攔截方式有Fliter,Interceptor,ControllerAdvice以及Aspect。

上面的圖是Spring中攔截機(jī)制,請求從Filter-->>Controller的過程中,只要在指定的環(huán)節(jié)出現(xiàn)異常,可以通過對應(yīng)的機(jī)制進(jìn)行處理。反之在任何一個(gè)環(huán)節(jié)如果異常未處理則不會(huì)進(jìn)入下一個(gè)環(huán)節(jié),會(huì)直接往外拋,例如在ControllerAdvice驗(yàn)證發(fā)生異常則會(huì)拋給Filter,如果Filter未處理,則最終會(huì)由Tomcat容器拋出。

過濾器:Filter

可以獲得Http原始的請求和響應(yīng)信息,但是拿不到響應(yīng)方法的信息。
注冊Filter,在springboot當(dāng)中提供了FilterRegistrationBean類來注冊Filter

//通過注解實(shí)現(xiàn)
@Slf4j
@Component
@WebFilter(filterName = "TimerFilter",urlPatterns = "/*")
public class TimerFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info("" + getClass() + " init");}/*** 在這方法中進(jìn)行攔截* @param request* @param response* @param chain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {log.info("time filter start class is {}",getClass());long start = System.currentTimeMillis();chain.doFilter(request, response);log.info("time filter:{}"+(System.currentTimeMillis()-start));log.info("time filter finish");}@Overridepublic void destroy() {log.info("" + getClass() + " init");}
}
//通過configuration實(shí)現(xiàn)
//自定義 一個(gè)Servlet類型的Filter實(shí)現(xiàn)類
public class FilterDemo3 implements Filter {private final Logger log = LoggerFactory.getLogger(getClass());@Resourceprivate CommonConfig commonConfig;@Overridepublic void destroy() {log.info("" + getClass() + " destroy");}@Overridepublic void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {log.info("" + getClass() + " doFilter " + commonConfig);arg2.doFilter(arg0, arg1);}@Overridepublic void init(FilterConfig arg0) throws ServletException {log.info("" + getClass() + " init");}}/*** web 組件配置* * @author: yx.zh* @date: 2020-06-14 07:03*         自定義注入,并支持依賴注入,組件排序*/
@Configuration
public class WebComponent2Config   {@Beanpublic FilterRegistrationBean filterDemo3Registration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(filterDemo3());registration.addUrlPatterns("/*");registration.addInitParameter("paramName", "paramValue");registration.setName("filterDemo3");registration.setOrder(6);return registration;}@Beanpublic FilterRegistrationBean filterDemo4Registration() {FilterRegistrationBean registration = new FilterRegistrationBean();registration.setFilter(filterDemo4());registration.addUrlPatterns("/*");registration.addInitParameter("paramName", "paramValue");registration.setName("filterDemo4");registration.setOrder(7);return registration;}@Beanpublic Filter filterDemo3() {return new FilterDemo3();}@Beanpublic Filter filterDemo4() {return new FilterDemo4();}}

常用屬性

攔截器:Interceptor

可以獲得Http原始的請求和響應(yīng)信息,也拿得到響應(yīng)方法的信息,但是拿不到方法響應(yīng)中的參數(shù)的值。
在web開發(fā)中,攔截器是經(jīng)常用到的功能。它可以幫我們驗(yàn)證是否登陸、預(yù)先設(shè)置數(shù)據(jù)以及統(tǒng)計(jì)方法的執(zhí)行效率等。在spring中攔截器有兩種,第一種是HandlerInterceptor,第二種是MethodInterceptor。HandlerInterceptor是SpringMVC中的攔截器,它攔截的是Http請求的信息,優(yōu)先于MethodInterceptor。而MethodInterceptor是springAOP的。前者攔截的是請求的地址,而后者是攔截controller中的方法,因?yàn)橄旅嬉獙spect,就不詳細(xì)講述MethodInterceptor。

/*** @author: yx.zh* @date: 2020-06-14 08:06* Interceptor攔截器中。**/
@Component
@Slf4j
public class Interceptor implements HandlerInterceptor {/*** 控制器方法調(diào)用之前會(huì)進(jìn)行* 和上面的Filter一樣,繼承的某些接口方法中也加了default關(guān)鍵字,可以不用重寫,這里為了演示就都寫了** @param request* @param response* @param handler* @return true就是選擇可以調(diào)用后面的方法  如果后續(xù)有ControllerAdvice的話會(huì)去執(zhí)行對應(yīng)的方法等。* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {log.info(((HandlerMethod) handler).getBean().getClass().getName());log.info(((HandlerMethod) handler).getMethod().getName());request.setAttribute("startTime", System.currentTimeMillis());return true;}/*** 控制后方法執(zhí)行之后會(huì)進(jìn)行,拋出異常則不會(huì)被執(zhí)行** @param request* @param response* @param handler* @param modelAndView* @throws Exception*/@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {log.info("postHandle");Long start = (Long) request.getAttribute("startTime");log.info("time interceptor 耗時(shí):{}" , (System.currentTimeMillis() - start));}/*** 方法被調(diào)用或者拋出異常都會(huì)被執(zhí)行* @param request* @param response* @param handler* @param ex* @throws Exception*/@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("afterCompletion");Long start = (Long) request.getAttribute("startTime");log.info("time interceptor 耗時(shí){}", (System.currentTimeMillis() - start));}
}

ControllerAdvice(Controller增強(qiáng))

與ControllerAdvice相同作用的,還有RestControllerAdvice。主要是用于全局的異常攔截和處理,這里的異常可以使自定義異常也可以是JDK里面的異常用于處理當(dāng)數(shù)據(jù)庫事務(wù)業(yè)務(wù)和預(yù)期不同的時(shí)候拋出封裝后的異常,進(jìn)行數(shù)據(jù)庫事務(wù)回滾,并將異常的顯示給用戶。

/*** @author: yx.zh* @date: 2020-06-13 16:59**/
@Slf4j
@RestControllerAdvice
public class ControllerExceptionFilter {/*** 處理自定義異常*/@ExceptionHandler(FrameException.class)public Response handleFrameException(FrameException e) {log.error(e.getMessage(), e);return ResultUtil.exceptionResult(e);}/*** 方法參數(shù)校驗(yàn)*/@ExceptionHandler(MethodArgumentNotValidException.class)public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {log.error(e.getMessage());return ResultUtil.exceptionResult(new FrameException(ExceptionEnum.PARAMS_ERROR), e.getBindingResult().getFieldError().getDefaultMessage());}/*** ValidationException*/@ExceptionHandler(ValidationException.class)public Response handleValidationException(ValidationException e) {log.error(e.getMessage(), e);return ResultUtil.exceptionResult(new FrameException(ExceptionEnum.PARAMS_ERROR), e.getCause().getMessage());}/*** ConstraintViolationException*/@ExceptionHandler(ConstraintViolationException.class)public Response handleConstraintViolationException(ConstraintViolationException e) {log.error(e.getMessage(), e);return ResultUtil.exceptionResult(new FrameException(ExceptionEnum.PARAMS_ERROR), e.getMessage());}@ExceptionHandler(NoHandlerFoundException.class)public Response handlerNoFoundException(Exception e) {log.error(e.getMessage(), e);return ResultUtil.exceptionResult(new FrameException(ExceptionEnum.URLNOTFUOND), "路徑不存在,請檢查路徑是否正確");}@ExceptionHandler(DuplicateKeyException.class)public Response handleDuplicateKeyException(DuplicateKeyException e) {log.error(e.getMessage(), e);return ResultUtil.exceptionResult(new FrameException(ExceptionEnum.DUPLICATE_KEY_CODE), "數(shù)據(jù)重復(fù),請檢查后提交");}@ExceptionHandler(Exception.class)public Response handleException(Exception e) {log.error(e.getMessage(), e);return ResultUtil.exceptionResult(new FrameException(ExceptionEnum.SYSTEM_EXCEPTION), "系統(tǒng)繁忙,請稍后再試");}}

切面:Aspect

主要是進(jìn)行公共方法的可以拿得到方法響應(yīng)中參數(shù)的值,但是拿不到原始的Http請求和相對應(yīng)響應(yīng)的方法,屬于方法級別的攔截器。
執(zhí)行順序如下

正常異常AroundBeforeAfterReturningAfterThrowing
/*** @auther zhyx* @Date 2020/6/11 9:08* @Description*/
@Component
@Aspect
@Slf4j
public class HttpAspect {@Pointcut("execution(* com.universe.polaris.controller.*.*(..))")public void controllerPointcut(){}@Before("controllerPointcut()")public void before(JoinPoint joinPoint){ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();/*** url*/log.info("Before:url={}",request.getRequestURL());/*** ip*/log.info("Before:ip={}",request.getRemoteAddr());/*** 請求方式*/log.info("Before:method={}",request.getMethod());/*** 代理類*/log.info("Before:代理類調(diào)用的方法:{}",joinPoint.getSignature().getDeclaringTypeName() + "#" + joinPoint.getSignature().getName());StringBuilder sb=new StringBuilder();for(Object temp:joinPoint.getArgs()){sb.append(temp.toString());}/*** 參數(shù)*/log.info("params={}",sb.toString());}@Around("controllerPointcut()")public Object  around(ProceedingJoinPoint proceedingJoinPoint)   {try {log.info("Around: 環(huán)繞執(zhí)行");return proceedingJoinPoint.proceed();} catch (Throwable e) {e.printStackTrace();}return null;}@AfterReturning( pointcut = "controllerPointcut()",returning = "object")public void afterReturning(Object object){log.info("AfterReturning 執(zhí)行: response={}", JSON.toJSONString(object));}@AfterThrowing(throwing = "e", pointcut = "controllerPointcut()")public void afterThrowing(Throwable e) {log.error("系統(tǒng)異常:{}", e.getMessage());}
}

總結(jié)

以上是生活随笔為你收集整理的spring 两次进入拦截器_4.SpringBoot 拦截器Fliter,Interceptor,Controller……的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。