从DispatcherServlet说自定义访问处理

从DispatcherServlet说自定义访问处理

DispatcherServlet是springMvc处理请求的核心逻辑,简单描述一下处理流程,
首先需要在web.xml中配置该Servlet的服务路径,默认是/*所有路径,这样web请求就从Servlet
容器把控制权流转到DispatcherServlet,看一下DispatcherServlet的核心方法:

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
	//...省略部分代码,看到这里把请求委托给doDispatch
	try {
		doDispatch(request, response);
	}
	//...省略部分代码
}

继续看一下doDispatch:

//省略部分代码,根据用户的请求,查找对应得handler
mappedHandler = getHandler(processedRequest);
//根据handler查找对应得适配器
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

再来看一下:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
	//遍历handlerMappings查找符合的类
	if (this.handlerMappings != null) {
		for (HandlerMapping mapping : this.handlerMappings) {
			HandlerExecutionChain handler = mapping.getHandler(request);
			if (handler != null) {
				return handler;
			}
		}
	}
	return null;
}

再看一下handler适配器种类:

HandlerAdapter (org.springframework.web.servlet)
	HttpRequestHandlerAdapter (org.springframework.web.servlet.mvc)
	SimpleServletHandlerAdapter (org.springframework.web.servlet.handler)
	AbstractHandlerMethodAdapter (org.springframework.web.servlet.mvc.method)
		RequestMappingHandlerAdapter (org.springframework.web.servlet.mvc.method.annotation)
	SimpleControllerHandlerAdapter (org.springframework.web.servlet.mvc)

适配HttpRequestHandler,Servlet,Controller,@RequestMapping

接下来看一下如何把HandlerMapping和HandlerAdapter配置到spring中:

private void initHandlerMappings(ApplicationContext context) {
	this.handlerMappings = null;

	if (this.detectAllHandlerMappings) {
		//查找子父容器中所有类型是HandlerMapping的类
		Map matchingBeans =
				BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
		if (!matchingBeans.isEmpty()) {
			this.handlerMappings = new ArrayList<>(matchingBeans.values());
			// We keep HandlerMappings in sorted order.
			AnnotationAwareOrderComparator.sort(this.handlerMappings);
		}
	}
	else {
		try {
			HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
			//保存到字段中
			this.handlerMappings = Collections.singletonList(hm);
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Ignore, we'll add a default HandlerMapping later.
		}
	}
	//省略部分代码
}

初始化HandlerAdapter和上面类似:

private void initHandlerAdapters(ApplicationContext context) {
	this.handlerAdapters = null;

	if (this.detectAllHandlerAdapters) {
		// Find all HandlerAdapters in the ApplicationContext, including ancestor contexts.
		Map matchingBeans =
				BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
		if (!matchingBeans.isEmpty()) {
			this.handlerAdapters = new ArrayList<>(matchingBeans.values());
			// We keep HandlerAdapters in sorted order.
			AnnotationAwareOrderComparator.sort(this.handlerAdapters);
		}
	}
	else {
		try {
			HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class);
			this.handlerAdapters = Collections.singletonList(ha);
		}
		catch (NoSuchBeanDefinitionException ex) {
			// Ignore, we'll add a default HandlerAdapter later.
		}
	}

	//省略部分代码
}

来实践一下:
自定义一个类:

public class MyController implements HttpRequestHandler {

    @Override
    public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setHeader(HttpHeaders.CONTENT_TYPE, MimeTypeUtils.TEXT_PLAIN_VALUE);
        ServletOutputStream os = response.getOutputStream();
        BufferedOutputStream bos = new BufferedOutputStream(os);
        bos.write("my controller...".getBytes());
        bos.flush();
    }

}

适配器配置:

@Configuration
public class MyMappingConfig {

    @Bean
    public HandlerMapping handlerMapping(){
        SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
        Map map = new HashMap<>();
        map.put("/test/test.html", new MyController());
        mapping.setUrlMap(map);
        mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 100);
        return mapping;
    }

}

结果展示:

my controller...

可以通过这种方式在jar包中,配合自动注入,把自己的服务暴露出去.
比如:spring的actuator(当然,其应用比这里复杂很多)

你可能感兴趣的:(spring)