和大彪一起来学习-SpringMvc之第二回(控制器,适配器说明)

简述:

在上一篇文章中,我们学会了如何搭建一个简单SpringMvc HelloWorld程序,这篇文章主要是介绍一些常用的控制器,适配器学习和作用。

一、HandlerMapping处理器映射器

HandlerMapping 给前端控制器返回一个HandlerExecutionChain 对象(包含一个Handler (后端控制器)对象、多个HandlerInterceptor 拦截器)对象。 

1).BeanNameUrlHandlerMapping Bean别名路径映射器

BeanNameUrl,通过类的命名名称我们是否发现了些什么?对,没错,就是通过配置bean的时候,bean的name作为访问其对应Controller的路径。一般可以和SimpleControllerHandlerAdapter配合使用,你如果把上一篇文章里面的例子自己写了遍的话,就会发现我们是用他们两个实现的。(源码中,就是实现了其父类AbstractDetectingUrlHandlerMapping 的determineUrlsForHandler方法,在方法中根据Bean Name注册处理器)

springmvc-servlet.xml 一般可以这么配置使用它:

<span style="white-space:pre">		</span><!-- 通过 /helloworld.action  可以访问到具体处理方法 -->
		<bean name="/helloworld.action" class="com.billstudy.springmvc.controller.HelloWorldController"/>

2).SimpleUrlHandlerMapping 简单路径处理映射器

SimpleUrl,这个是比较有意思的映射器,就是将访问路径直接映射到具体Controller类的id,通过查看源码我们会发现其实类中有个Map,用来存放注入进去的路径和Bean的相关信息,然后通过其父类注册处理器处理相关请求,看看源码就能更好的理解了:

public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping {
	// 内部用了个map作为存放访问路径和beand的映射
	private final Map urlMap = new HashMap();
	// 由于这里有这个方法,那么我们在配置文件中就可以通过mappings,注入我们的数据
	public void setMappings(Properties mappings) {
		this.urlMap.putAll(mappings);
	}
	// 省略部分不相关方法....
</pre><pre name="code" class="java">	public void initApplicationContext() throws BeansException {
		super.initApplicationContext();
		registerHandlers(this.urlMap);
	}

	protected void registerHandlers(Map urlMap) throws BeansException {
		if (urlMap.isEmpty()) {
			logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
		}
		else {
			Iterator it = urlMap.keySet().iterator();
			while (it.hasNext()) {
				String url = (String) it.next();
				Object handler = urlMap.get(url);
				// 如果不是斜杠起始,那么带上斜杠
				if (!url.startsWith("/")) {
					url = "/" + url;
				}
				// 如果是字符串,那么处理掉空格,这个不错,小细节也值得我们学习,
				if (handler instanceof String) {
					handler = ((String) handler).trim();
				}
				// 调用父类 AbstractUrlHandlerMapping方法,进行URL路径注册处理器
				registerHandler(url, handler);
			}
		}
	}

}
springmvc-servlet.xml一般可以这么配置使用:

<!—简单url映射,可以将项目的路径统一放到这里配置,比较方便,多个范围路径可以映射到通过一个Controller上,类似Map(key-value) -->
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props><!-- key:访问路径   value:bean的id -->
				<prop key="/hello1.action">hello_controller</prop>
				<prop key="/hello2.action">hello_controller</prop>
			</props>
		</property>
	</bean>


二、HandlerAdapter处理器适配器

HandlerAdapter会把后端控制器包装为一个适配器,支持多种类型的控制器开发,这里使用了适配器设计模式。

1).SimpleControllerHandlerAdapter简单控制器处理器适配器

简单控制器处理器适配器所有实现了org.springframework.web.servlet.mvc.Controller 接口的Bean作为Springmvc的后端控制器,分析源码我们可以更好地发现这一点。
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
	// 判断目标类是否实现了Controller接口,为进一步执行handle方法做预判断
	public boolean supports(Object handler) {
		return (handler instanceof Controller);
	}

	// 处理方法
	public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// 使用简单,粗暴的方式 直接向上转型后执行 我们实现类bean里面的handleRequest方法,也就是Controller里面唯一的待实现方法。
		return ((Controller) handler).handleRequest(request, response);
	}
}
一般在配置文件中,直接配置该类即可支持实现了Controller接口的类正常使用

2).HttpRequestHandlerAdapter Http请求处理器适配器

HTTP请求处理器适配器将http请求封装成HttpServletResquest 和HttpServletResponse对象,和servlet接口类似。通过源码会发现这个和上面的SimpleController处理有点类似,上面是强转Controller,这里是强转HttpRequestHandler对象,所以我们想要使用这个适配器时,应该怎么做呢?你可能通过对比学习发现了,对,就是写个bean实现HttpRequestHandler这个接口就好了。 比较简单,有兴趣的同学自己先试着写一下,然后想进一步看看内部如何实现的话可以去读读该源码哦。

了,今天这些就是内容了,主要就是以上映射器和适配器的介绍了。大彪在这里只是简单地列出了几个,其实springmvc给咱们提供了很多映射器和适配器,如果小伙伴有更多的时间想对这些更深入地学习,可以继续看看别的类实现,如下图:


技术分享技术分享

推荐个学习框架小技巧,可以通过查看框架的api文档找到几个主要的类或者接口,然后弄懂大概整个的框架模型和基本架构(springmvc 组件架构去看看第一回),然后再通过这些主要的类,和接口去学习。其实像这种比较成熟的开源框架,类的命名和注释都是相当规范的,以及具体用的一些设计模式、代码哲学都是非常值得我们学习的。写几个小例子,跑跑,打个断点跟着框架走上几次,忒爽了。 这些有时候比啃书来的实际多了,当然作为IT人,技术图书也是必不可缺的,好拉。 下一篇打算写写,springmvc里面重点:注解的使用。


简单说明什么是映射器,适配器:

映射器:就是根据DispatcherServlet 拿过来的用户请求某部分路径去寻找处理器(就是我们写的具体的某个方法)和一些拦截器

适配器:具体执行处理器的对象,将ModelAndView返回给DispatcherServlet渲染视图用的


这里是 热爱生活,热爱技术,喜欢交友的大彪 .


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。