/*** Called by the servlet container to allow the servlet to respond to a* request.** <p>* This method is only called after the servlet's <code>init()</code> method* has completed successfully.** <p>* The status code of the response always should be set for a servlet that* throws or sends an error.*** <p>* Servlets typically run inside multithreaded servlet containers that can* handle multiple requests concurrently. Developers must be aware to* synchronize access to any shared resources such as files, network* connections, and as well as the servlet's class and instance variables.* More information on multithreaded programming in Java is available in <a* href* ="http://java.sun.com/Series/Tutorial/java/threads/multithreaded.html">* the Java tutorial on multi-threaded programming</a>.*** @param req* the <code>ServletRequest</code> object that contains the* client's request** @param res* the <code>ServletResponse</code> object that contains the* servlet's response** @exception ServletException* if an exception occurs that interferes with the servlet's* normal operation** @exception IOException* if an input or output exception occurs*/public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;/*** Called by the servlet container to allow the servlet to respond to a* request. See {@link Servlet#service}.* <p>* This method is declared abstract so subclasses, such as* <code>HttpServlet</code>, must override it.** @param req* the <code>ServletRequest</code> object that contains the* client's request* @param res* the <code>ServletResponse</code> object that will contain the* servlet's response* @exception ServletException* if an exception occurs that interferes with the servlet's* normal operation occurred* @exception IOException* if an input or output exception occurs*/@Overridepublic abstract void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
/*** Dispatches client requests to the protected* <code>service</code> method. There's no need to* override this method.** @param req the {@link HttpServletRequest} object that* contains the request the client made of* the servlet** @param res the {@link HttpServletResponse} object that* contains the response the servlet returns* to the client** @exception IOException if an input or output error occurs* while the servlet is handling the* HTTP request** @exception ServletException if the HTTP request cannot* be handled** @see jakarta.servlet.Servlet#service*/@Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {HttpServletRequest request;HttpServletResponse response;try {request = (HttpServletRequest) req;response = (HttpServletResponse) res;} catch (ClassCastException e) {throw new ServletException(lStrings.getString("http.non_http"));}service(request, response);}/*** Receives standard HTTP requests from the public* <code>service</code> method and dispatches* them to the <code>do</code><i>Method</i> methods defined in* this class. This method is an HTTP-specific version of the* {@link jakarta.servlet.Servlet#service} method. There's no* need to override this method.** @param req the {@link HttpServletRequest} object that* contains the request the client made of* the servlet** @param resp the {@link HttpServletResponse} object that* contains the response the servlet returns* to the client** @exception IOException if an input or output error occurs* while the servlet is handling the* HTTP request** @exception ServletException if the HTTP request* cannot be handled** @see jakarta.servlet.Servlet#service*/protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String method = req.getMethod();if (method.equals(METHOD_GET)) {long lastModified = getLastModified(req);if (lastModified == -1) {// servlet doesn't support if-modified-since, no reason// to go through further expensive logicdoGet(req, resp);} else {long ifModifiedSince;try {ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);} catch (IllegalArgumentException iae) {// Invalid date header - proceed as if none was setifModifiedSince = -1;}if (ifModifiedSince < (lastModified 1000 * 1000)) {// If the servlet mod time is later, call doGet()// Round down to the nearest second for a proper compare// A ifModifiedSince of -1 will always be lessmaybeSetLastModified(resp, lastModified);doGet(req, resp);} else {resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);}}} else if (method.equals(METHOD_HEAD)) {long lastModified = getLastModified(req);maybeSetLastModified(resp, lastModified);doHead(req, resp);} else if (method.equals(METHOD_POST)) {doPost(req, resp);} else if (method.equals(METHOD_PUT)) {doPut(req, resp);} else if (method.equals(METHOD_DELETE)) {doDelete(req, resp);} else if (method.equals(METHOD_OPTIONS)) {doOptions(req,resp);} else if (method.equals(METHOD_TRACE)) {doTrace(req,resp);} else {//// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.//String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[1];errArgs[0] = method;errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);}}
protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {String msg = lStrings.getString("http.method_post_not_supported");sendMethodNotAllowed(req, resp, msg);}private void sendMethodNotAllowed(HttpServletRequest req, HttpServletResponse resp, String msg) throws IOException {String protocol = req.getProtocol();// Note: Tomcat reports "" for HTTP/0.9 although some implementations// may report HTTP/0.9if (protocol.length() == 0 || protocol.endsWith("0.9") || protocol.endsWith("1.0")) {resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);} else {resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);}}
/*** Delegate POST requests to {@link #processRequest}.* @see #doService*/@Overrideprotected final void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {processRequest(request, response);}/*** Process this request, publishing an event regardless of the outcome.* <p>The actual event handling is performed by the abstract* {@link #doService} template method.*/protected final void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {long startTime = System.currentTimeMillis();Throwable failureCause = null;LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();LocaleContext localeContext = buildLocaleContext(request);RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();ServletRequestAttributes requestAttributes = buildRequestAttributes(request, response, previousAttributes);WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new RequestBindingInterceptor());initContextHolders(request, localeContext, requestAttributes);try {doService(request, response);}catch (ServletException | IOException ex) {failureCause = ex;throw ex;}catch (Throwable ex) {failureCause = ex;throw new NestedServletException("Request processing failed", ex);}finally {resetContextHolders(request, previousLocaleContext, previousAttributes);if (requestAttributes != null) {requestAttributes.requestCompleted();}logResult(request, response, failureCause, asyncManager);publishRequestHandledEvent(request, response, startTime, failureCause);}}/*** Exposes the DispatcherServlet-specific request attributes and delegates to {@link #doDispatch}* for the actual dispatching.*/@Overrideprotected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {logRequest(request);// Keep a snapshot of the request attributes in case of an include,// to be able to restore the original attributes after the include.Map<String, Object> attributesSnapshot = null;if (WebUtils.isIncludeRequest(request)) {attributesSnapshot = new HashMap<>();Enumeration<?> attrNames = request.getAttributeNames();while (attrNames.hasMoreElements()) {String attrName = (String) attrNames.nextElement();if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {attributesSnapshot.put(attrName, request.getAttribute(attrName));}}}// Make framework objects available to handlers and view objects.request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);request.setAttribute(THEME_SOURCE_ATTRIBUTE, getThemeSource());if (this.flashMapManager != null) {FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);if (inputFlashMap != null) {request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));}request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);}try {doDispatch(request, response);}finally {if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {// Restore the original attribute snapshot, in case of an include.if (attributesSnapshot != null) {restoreAttributesAfterInclude(request, attributesSnapshot);}}}}
/*** Process the actual dispatching to the handler.* <p>The handler will be obtained by applying the servlet's HandlerMappings in order.* The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters* to find the first that supports the handler class.* <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers* themselves to decide which methods are acceptable.* @param request current HTTP request* @param response current HTTP response* @throws Exception in case of any kind of processing failure*/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 = "GET".equals(method);if (isGet || "HEAD".equals(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);// 处理器拦截器在处理器方法执行后执行,可以对ModelAndView进行处理mappedHandler.applyPostHandle(processedRequest, response, mv);}catch (Exception ex) {dispatchException = ex;}catch (Throwable err) {// As of 4.3, we're 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);}}}}
判断该请求是否是包含多部件(文件)请求
根据请求查找处理器
根据处理器查找对应的适配器
处理器拦截器在处理器方法执行之前进行拦截处理
处理器适配器去执行处理器的方法
处理器拦截器在处理器方法执行后执行,可以对ModelAndView进行处理
处理分发的结果
处理器拦截器在处理器方法执行后执行
文章转载自Alleria Windrunner,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




