网站建设推进会,塘沽软件开发,网站备案 注意,表白网页在线生成制作源码一个请求在Spring中处理流程是有多种方式拦截处理的#xff0c;而且#xff0c;请求是可以拆分为进入和响应2个操作的#xff0c;进入我们通常会对请求参数做处理#xff0c;而响应我们通常会对响应参数做处理#xff0c;Spring提供了多种方式给开发者。
一、HandlerInte…一个请求在Spring中处理流程是有多种方式拦截处理的而且请求是可以拆分为进入和响应2个操作的进入我们通常会对请求参数做处理而响应我们通常会对响应参数做处理Spring提供了多种方式给开发者。
一、HandlerInterceptor
我们写的controller在Spring中被定义为handler拦截controller的拦截器被定义为org.springframework.web.servlet.HandlerInterceptor。
拦截器的拦截逻辑是在org.springframework.web.servlet.DispatcherServlet中写的需要注意的是如果入口拦截顺序是a-b-c的话那么出口拦截顺序是c-b-a这个逻辑可以看org.springframework.web.servlet.HandlerExecutionChain里的一段逻辑。 protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {HttpServletRequest processedRequest request;HandlerExecutionChain mappedHandler null;boolean multipartRequestParsed false;WebAsyncManager asyncManager WebAsyncUtils.getAsyncManager(request);try {ModelAndView mv null;Exception dispatchException null;try {processedRequest checkMultipart(request);multipartRequestParsed (processedRequest ! request);// Determine handler for the current request.mappedHandler getHandler(processedRequest);if (mappedHandler null) {noHandlerFound(processedRequest, response);return;}// Determine handler adapter for the current request.HandlerAdapter ha getHandlerAdapter(mappedHandler.getHandler());// Process last-modified header, if supported by the handler.String method request.getMethod();boolean isGet HttpMethod.GET.matches(method);if (isGet || HttpMethod.HEAD.matches(method)) {long lastModified ha.getLastModified(request, mappedHandler.getHandler());if (new ServletWebRequest(request, response).checkNotModified(lastModified) isGet) {return;}}if (!mappedHandler.applyPreHandle(processedRequest, response)) {return;}// Actually invoke the handler.mv ha.handle(processedRequest, response, mappedHandler.getHandler());if (asyncManager.isConcurrentHandlingStarted()) {return;}applyDefaultViewName(processedRequest, mv);mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException ex;}catch (Throwable err) {// As of 4.3, were processing Errors thrown from handler methods as well,// making them available for ExceptionHandler methods and other scenarios.dispatchException new NestedServletException(Handler dispatch failed, err);}processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);}catch (Exception ex) {triggerAfterCompletion(processedRequest, response, mappedHandler, ex);}catch (Throwable err) {triggerAfterCompletion(processedRequest, response, mappedHandler,new NestedServletException(Handler processing failed, err));}finally {if (asyncManager.isConcurrentHandlingStarted()) {// Instead of postHandle and afterCompletionif (mappedHandler ! null) {mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);}}else {// Clean up any resources used by a multipart request.if (multipartRequestParsed) {cleanupMultipart(processedRequest);}}}}
这里能很清晰的看到循环使用的次序。 boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {for (int i 0; i this.interceptorList.size(); i) {HandlerInterceptor interceptor this.interceptorList.get(i);if (!interceptor.preHandle(request, response, this.handler)) {triggerAfterCompletion(request, response, null);return false;}this.interceptorIndex i;}return true;}void applyPostHandle(HttpServletRequest request, HttpServletResponse response, Nullable ModelAndView mv)throws Exception {for (int i this.interceptorList.size() - 1; i 0; i--) {HandlerInterceptor interceptor this.interceptorList.get(i);interceptor.postHandle(request, response, this.handler, mv);}} org.springframework.web.servlet.HandlerInterceptor
public interface HandlerInterceptor {/*** Interception point before the execution of a handler. Called after* HandlerMapping determined an appropriate handler object, but before* HandlerAdapter invokes the handler.* pDispatcherServlet processes a handler in an execution chain, consisting* of any number of interceptors, with the handler itself at the end.* With this method, each interceptor can decide to abort the execution chain,* typically sending an HTTP error or writing a custom response.* pstrongNote:/strong special considerations apply for asynchronous* request processing. For more details see* {link org.springframework.web.servlet.AsyncHandlerInterceptor}.* pThe default implementation returns {code true}.* param request current HTTP request* param response current HTTP response* param handler chosen handler to execute, for type and/or instance evaluation* return {code true} if the execution chain should proceed with the* next interceptor or the handler itself. Else, DispatcherServlet assumes* that this interceptor has already dealt with the response itself.* throws Exception in case of errors*/default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {return true;}/*** Interception point after successful execution of a handler.* Called after HandlerAdapter actually invoked the handler, but before the* DispatcherServlet renders the view. Can expose additional model objects* to the view via the given ModelAndView.* pDispatcherServlet processes a handler in an execution chain, consisting* of any number of interceptors, with the handler itself at the end.* With this method, each interceptor can post-process an execution,* getting applied in inverse order of the execution chain.* pstrongNote:/strong special considerations apply for asynchronous* request processing. For more details see* {link org.springframework.web.servlet.AsyncHandlerInterceptor}.* pThe default implementation is empty.* param request current HTTP request* param response current HTTP response* param handler the handler (or {link HandlerMethod}) that started asynchronous* execution, for type and/or instance examination* param modelAndView the {code ModelAndView} that the handler returned* (can also be {code null})* throws Exception in case of errors*/default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,Nullable ModelAndView modelAndView) throws Exception {}/*** Callback after completion of request processing, that is, after rendering* the view. Will be called on any outcome of handler execution, thus allows* for proper resource cleanup.* pNote: Will only be called if this interceptors {code preHandle}* method has successfully completed and returned {code true}!* pAs with the {code postHandle} method, the method will be invoked on each* interceptor in the chain in reverse order, so the first interceptor will be* the last to be invoked.* pstrongNote:/strong special considerations apply for asynchronous* request processing. For more details see* {link org.springframework.web.servlet.AsyncHandlerInterceptor}.* pThe default implementation is empty.* param request current HTTP request* param response current HTTP response* param handler the handler (or {link HandlerMethod}) that started asynchronous* execution, for type and/or instance examination* param ex any exception thrown on handler execution, if any; this does not* include exceptions that have been handled through an exception resolver* throws Exception in case of errors*/default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,Nullable Exception ex) throws Exception {}}
二、HandlerMethodArgumentResolver
上面的HandlerInterceptor可以清楚的看到接收的参数是HttpServletRequest这是最早期的参数紧接着Spring会从HttpServletRequest里把参数读取到controller定义的请求参数里面此时用到的类型是HttpMessageConverter他把参数写入controller中此时是可以在参数写入前后做一些操作的。
三、RequestBodyAdvice
org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdvice
org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice
这2个可以直接修改请求参数可以看到写入之后就得到了controller定义的参数类型。
public interface RequestBodyAdvice {/*** Invoked first to determine if this interceptor applies.* param methodParameter the method parameter* param targetType the target type, not necessarily the same as the method* parameter type, e.g. for {code HttpEntityString}.* param converterType the selected converter type* return whether this interceptor should be invoked or not*/boolean supports(MethodParameter methodParameter, Type targetType,Class? extends HttpMessageConverter? converterType);/*** Invoked second before the request body is read and converted.* param inputMessage the request* param parameter the target method parameter* param targetType the target type, not necessarily the same as the method* parameter type, e.g. for {code HttpEntityString}.* param converterType the converter used to deserialize the body* return the input request or a new instance (never {code null})*/HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter,Type targetType, Class? extends HttpMessageConverter? converterType) throws IOException;/*** Invoked third (and last) after the request body is converted to an Object.* param body set to the converter Object before the first advice is called* param inputMessage the request* param parameter the target method parameter* param targetType the target type, not necessarily the same as the method* parameter type, e.g. for {code HttpEntityString}.* param converterType the converter used to deserialize the body* return the same body or a new instance*/Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter,Type targetType, Class? extends HttpMessageConverter? converterType);/*** Invoked second (and last) if the body is empty.* param body usually set to {code null} before the first advice is called* param inputMessage the request* param parameter the method parameter* param targetType the target type, not necessarily the same as the method* parameter type, e.g. for {code HttpEntityString}.* param converterType the selected converter type* return the value to use, or {code null} which may then raise an* {code HttpMessageNotReadableException} if the argument is required*/NullableObject handleEmptyBody(Nullable Object body, HttpInputMessage inputMessage, MethodParameter parameter,Type targetType, Class? extends HttpMessageConverter? converterType);}
public interface ResponseBodyAdviceT {/*** Whether this component supports the given controller method return type* and the selected {code HttpMessageConverter} type.* param returnType the return type* param converterType the selected converter type* return {code true} if {link #beforeBodyWrite} should be invoked;* {code false} otherwise*/boolean supports(MethodParameter returnType, Class? extends HttpMessageConverter? converterType);/*** Invoked after an {code HttpMessageConverter} is selected and just before* its write method is invoked.* param body the body to be written* param returnType the return type of the controller method* param selectedContentType the content type selected through content negotiation* param selectedConverterType the converter type selected to write to the response* param request the current request* param response the current response* return the body that was passed in or a modified (possibly new) instance*/NullableT beforeBodyWrite(Nullable T body, MethodParameter returnType, MediaType selectedContentType,Class? extends HttpMessageConverter? selectedConverterType,ServerHttpRequest request, ServerHttpResponse response);}
四、整体时序
HandlerInterceptor preHandle - RequestBodyAdvice - HandlerMethodArgumentResolver - RequestBodyAdvice - controller - AOP afterReturning - ResponseBodyAdvice beforeBodyWrite - HttpMessageConverter转JSON - HandlerInterceptor postHandle - HandlerInterceptor afterCompletion