Spring MVC之注解与非注解映射器和适配器

在Spring MVC中涉及到的处理器映射器和处理器适配器分为注解处理器映射器和处理器适配器与非注解处理器映射器和处理器适配器,这些远远不止上篇文章中介绍到的那几个,本篇文章的目的就是为了介绍更多的处理器映射器和处理器适配器。毕竟我们是革命者,了解更多的知识才是王道。

写在前面的话:本篇文章在前篇文章开发的代码基础上继续进行开发。

1.非注解映射器和非注解适配器

1.1BeanNameUrlHandlerMapping(映射器)

就是上文中我们用到的处理器映射器,根据请求url(XXXX.action)匹配spring容器bean标签的name属性找到对应的Handler(通过class属性找到程序员编写的那个Handler),详情配置见上篇文章。

1.2SimpleUrlHandlerMapping(映射器)

简单url映射器,是BeanNameUrlHandlerMapping的增强版,在springmvc.xml配置文件中这样配置SimpleUrlHandlerMapping:

1
2
3
4
5
6
7
8
9
10
11
12
<!--简单url映射
几种配置bean的id对应的url
key:用户请求的url
标签内容:程序员编写的Handler在此配置文件中的id-->

<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/items1.action">itemController1</prop>
<prop key="/items2.action">itemController1</prop>
</props>
</property>
</bean>

SimpleUrlHandlerMapping的配置中需要用到Handler在springmvc.xml中的配置id,所以这里我们需要给Handler的配置加上一个标签:

1
2
3
<!--配置Handler
由于使用了BeanNameUrlHandlerMapping处理映射器,所以name要配置为url。另外不需要id属性-->

<bean id="itemController1" name="/itemList.action" class="controller.ItemController1"></bean>

此时两个处理器映射器对应三个不同的url地址,但却指向的是同一个Controller(即Handler),运行程序,发现输入http://localhost:8080/SpringMvc/itemList.actionhttp://localhost:8080/SpringMvc/items1.actionhttp://localhost:8080/SpringMvc/items2.action访问的都是同一个页面,说明:若在springmvc.xml配置文件中配置了多个处理器映射器,多个映射器可以共存。

1.3SimpleControllerHandlerAdapter(适配器)

就是上文中我们用到的处理器适配器,要求前端控制器通过这个适配器找到的Handler(Controller)需要实现 Controller接口。

1.4HttpRequestHandlerAdapter(适配器)

HttpRequestHandlerAdapter在配置文件中这样配置:

1
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>

要求前端控制器使用这个适配器找到的Handler需要实现HttpRequestHandler接口

使用这个适配器开发的Handler代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class ItemController2 implements HttpRequestHandler
{

@Override
public void handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException {

//使用静态的数据将商品信息显示在jsp页面
List<Items> itemsList = new ArrayList<>();

Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setCreatetime(new Date());
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");

Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");

itemsList.add(items_1);
itemsList.add(items_2);

httpServletRequest.setAttribute("itemsList",itemsList);
httpServletRequest.getRequestDispatcher("/WEB-INF/jsp/itemsList.jsp").forward(httpServletRequest,httpServletResponse);

}

}

实现HttpRequestHandler需要实现的方法返回值为void,不能给处理器适配器返回ModelAndView对象,所以代码中我们要使用request域进行注入值。

然后是Handler在springmvc.xml中的配置,这里我们让该Handler使用SimpleUrlHandlerMapping处理器映射器,所以不需要给该Handler设置id:

1
<bean id="itemController2" class="controller.ItemController2"></bean>

然后修改SimpleUrlHandlerMapping在配置:

1
2
3
4
5
6
7
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/items2.action">itemController2</prop>
</props>
</property>
</bean>

运行服务器,然后便可以通过http://localhost:8080/SpringMvc/items2.action进行访问。

2.注解映射器和注解适配器

2.1注解映射器

在spring3.1版本之前,系统默认加载DispatcherServlet.properoties文件中的org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping注解映射器,3.1版本之后要使用org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping这个注解映射器。在springmvc.xml中进行RequestMappingHandlerMapping的配置:

1
2
<!--注解处理器映射器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>

使用RequestMappingHandlerMapping需要在Handler 中使用@controller标识此类是一个控制器,使用@requestMapping指定Handler方法所对应的url。

2.2注解适配器

pring3.1之前默认加载DispatcherServlet.properoties中的注解适配器是
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter,3.1版本之后要使用:
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter这个注解适配器。在springmvc.xml中进行如下配置:

1
2
<!--注解的适配器-->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>

RequestMappingHandlerAdapter,不要求Handler实现任何接口,它需要和RequestMappingHandlerMapping注解映射器配对使用,主要解析Handler方法中的形参。

2.3利用注解开发Handler

利用注解开发的Handler不需要实现任何接口,java代码为如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@org.springframework.stereotype.Controller
public class ItemController3
{

//商品列表:@RequestMapping中url建议和方法名一样,方便开发维护
@RequestMapping("/queryItems")
public ModelAndView queryItems() {
//使用静态的数据将商品信息显示在jsp页面
List<Items> itemsList = new ArrayList<>();

Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setCreatetime(new Date());
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");

Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setCreatetime(new Date());
items_2.setDetail("iphone6苹果手机!");

itemsList.add(items_1);
itemsList.add(items_2);

ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("itemsList",itemsList);
modelAndView.setViewName("/WEB-INF/jsp/itemsList.jsp");
return modelAndView;
}
}

然后在springmvc.xml中对该Handler进行配置:

1
2
3
<!--注解的Handler
不用id,url在@RequestMapping注解中已经声明-->

<bean class="controller.ItemController3"/>

上面我们通过对单个注解Handler的配置,也可以使用组件扫描<context:component-scan base-package="包名"/>对整个包下的Handler进行配置。
然后运行服务器输入网址http://localhost:8080/SpringMvc/queryItems.action,正常访问,这里的url为@RequestMapping中的参数。组件扫描还可以可以扫描@Controller、@Service、@component、@Repsitory。

3.Spring MVC处理流程的源码分析

  1. 用户发送请求到DispatherServlet前端控制器。
  2. DispatherServlet调用HandlerMapping(处理器映射器)根据url查找Handler。
  3. DispatherServlet调用HandlerAdapter(处理器适配器)对HandlerMapping找到Handler进行包装、执行。HandlerAdapter执行Handler完成后,返回了一个ModleAndView(springmvc封装对象)。DispatherServlet 找一个合适的适配器:
    然后适配器执行Handler:
  4. DispatherServlet拿着ModelAndView调用ViewResolver(视图解析器)进行视图解析,解析完成后返回一个View(很多不同视图类型的View):视图解析:
  5. 进行视图渲染,将Model中的数据 填充到request域:

至此,Spring MVC的工作流程我便通过源码的解析为你们阐释清楚了,当然看不懂源码也无所谓,我这里只是为了让你们对底层知识有更深的了解。通过这两篇文章便可以入门Spring MVC了,下篇文章我将为你们讲解Spring、Spring MVC与Mybatis的整合了,不用怕,很简单的!

2018.3.19更

欢迎加入我的Java交流1群:659957958。

2018.4.21更:如果群1已满或者无法加入,请加Java学习交流2群:305335626

4.联系

If you have some questions after you see this article,you can tell your doubts in the comments area or you can find some info by clicking these links.

记得扫一扫领一下红包再走哦