Java深入 - servlet和Spring的DispatcherServlet详解

Servlet是什么

1. Servlet是服务器端运行的一个程序,是一个被编译好的Java类。它不是框架等。

2. Web容器的启动,需要依赖Servlet。当web服务器开始执行时,servlet类就被初始化

3. 当用户通过浏览器访问的时候,会输入URI,这个时候,web服务器就通过Servlet来分发请求执行不同的内容。



一般我们会使用Tomcat来运行Java的web项目。通常我们可以在web项目的目录中可以看到WEB-INF这样的文件夹。这个文件夹是受保护的,外部无法通过url来访问的。文件夹里面包含了web.xml以及class和libs目录。我们要将web项目运行起来,就得在web.xml中定义一个Servlet,因为定义了Servlet,web容器才能知道需要如何去分发请求进行业务处理的。


Servlet是有一个Jar包,里面包含了一些Servlet的相关设计和细节。
在这里插入图片描述
一个使用Spring的Servlet的web.xml配置例子:

<servlet>
	<servlet-name>apiServlet</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath:spring-common.xml</param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>apiServlet</servlet-name>
	<url-pattern>/api/*</url-pattern>
</servlet-mapping>

HttpServlet

1. HttpServlet是一个抽象类,具体的实现自己需要的Servlet需要通过继承该类来实现 。

HttpServlet中主要的几个方法:

方法 用途
doGet 处理HTTP GET请求
doPost 处理HTTP POST请求
doPut 处理HTTP PUT请求
doDelete 处理HTTP DELETE请求

Servlet最终调用的是service方法,这个方法中会根据request的Method来判断具体是执行doGet还是doPost。具体可以看HttpServlet类源码。

2. HttpServlet最上层是继承Servlet这个接口类。Servlet这个接口类非常简单,只定义了5个方法。具体可以看Servlet接口源码。

package javax.servlet;
import java.io.IOException;
 
public interface Servlet {
    
    
 
    //容器初始化
    public void init(ServletConfig config) throws ServletException;
    
    //获取配置信息
    public ServletConfig getServletConfig();
    
    //具体的service 请求分发
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
	
   //获取servlet信息
    public String getServletInfo();
    
    //容器销毁的时候
    public void destroy();
}

Spring的DispatcherServlet

Spring主要通过DispatcherServlet实现了Servlet。DispatcherServlet最上层也是继承的是HttpServlet这个类。

我们主要看下DispatcherServlet两个比较重要的方法:

@Override
	protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
		if (logger.isDebugEnabled()) {
    
    
			String requestUri = urlPathHelper.getRequestUri(request);
			logger.debug("DispatcherServlet with name '" + getServletName() + "' processing " + request.getMethod() +
					" request for [" + requestUri + "]");
		}
 
		// 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)) {
    
    
			logger.debug("Taking snapshot of request attributes before include");
			attributesSnapshot = new HashMap<String, Object>();
			Enumeration<?> attrNames = request.getAttributeNames();
			while (attrNames.hasMoreElements()) {
    
    
				String attrName = (String) attrNames.nextElement();
				if (this.cleanupAfterInclude || attrName.startsWith("org.springframework.web.servlet")) {
    
    
					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());
 
		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); //这边最终也是调用了doDispatch方法,该方法主要用来处理SPring框架的具体业务分发逻辑。
		}
		finally {
    
    
			// Restore the original attribute snapshot, in case of an include.
			if (attributesSnapshot != null) {
    
    
				restoreAttributesAfterInclude(request, attributesSnapshot);
			}
		}
	}
        
    //Spring框架最终的分发都是通过该方法的
	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    
    
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		int interceptorIndex = -1;
 
		try {
    
    
			ModelAndView mv;
			boolean errorView = false;
 
			try {
    
    
				processedRequest = checkMultipart(request);
 
				// Determine handler for the current request.
				mappedHandler = getHandler(processedRequest, false);
				if (mappedHandler == null || mappedHandler.getHandler() == 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 (logger.isDebugEnabled()) {
    
    
						String requestUri = urlPathHelper.getRequestUri(request);
						logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
					}
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
    
    
						return;
					}
				}
 
				// 这里是处理前置拦截器
				HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
				if (interceptors != null) {
    
    
					for (int i = 0; i < interceptors.length; i++) {
    
    
						HandlerInterceptor interceptor = interceptors[i];
						if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
    
    
							triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
							return;
						}
						interceptorIndex = i;
					}
				}
 
				//处理最终的Action逻辑
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
 
				// Do we need view name translation?
				if (mv != null && !mv.hasView()) {
    
    
					mv.setViewName(getDefaultViewName(request));
				}
 
                                //处理后置拦截器
				if (interceptors != null) {
    
    
					for (int i = interceptors.length - 1; i >= 0; i--) {
    
    
						HandlerInterceptor interceptor = interceptors[i];
						interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
					}
				}
			}
			catch (ModelAndViewDefiningException ex) {
    
    
				logger.debug("ModelAndViewDefiningException encountered", ex);
				mv = ex.getModelAndView();
			}
			catch (Exception ex) {
    
    
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(processedRequest, response, handler, ex);
				errorView = (mv != null);
			}
 
			// Did the handler return a view to render?
			if (mv != null && !mv.wasCleared()) {
    
    
				render(mv, processedRequest, response);
				if (errorView) {
    
    
					WebUtils.clearErrorRequestAttributes(request);
				}
			}
			else {
    
    
				if (logger.isDebugEnabled()) {
    
    
					logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
							"': assuming HandlerAdapter completed request handling");
				}
			}
 
			// Trigger after-completion for successful outcome.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
		}
 
		catch (Exception ex) {
    
    
			// Trigger after-completion for thrown exception.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
			throw ex;
		}
		catch (Error err) {
    
    
			ServletException ex = new NestedServletException("Handler processing failed", err);
			// Trigger after-completion for thrown exception.
			triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
			throw ex;
		}
 
		finally {
    
    
			// Clean up any resources used by a multipart request.
			if (processedRequest != request) {
    
    
				cleanupMultipart(processedRequest);
			}
		}
	}

猜你喜欢

转载自blog.csdn.net/weixin_42950079/article/details/105671217