从上一篇的springmvc入门中已经看到,springmvc.xml中的配置了映射器和适配器,是使用非注解的方式来配置的,这是非注解方式的一种,这里再复习一下:
1. 非注解方式
1.1 处理器适配器
上一节中使用的处理器适配器是:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter。即:
SimpleControllerHandlerAdapter适配器能执行实现了Controller接口的Handler,所以我们所写的Handler需要实现Controller接口。
除了这个适配器外,还有另一个适配器,叫org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter。即可以配置:
HttpRequestHandlerAdapter适配器能执行实现了HttpRequestHandler接口的Handler,所以我们所写的Handler需要实现HttpRequestHandler接口,这跟实现Controller接口稍微有点不同,比如我们写一个Handler:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ItemsController2</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">implements</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">HttpRequestHandler</span> {</span>
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">handleRequest</span>(HttpServletRequest request, HttpServletResponse response)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> ServletException, IOException {
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//实际中是调用service查找数据库,查询商品列表,这里直接使用静态数据来模拟了</span>
List<Items> itemsList = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<Items>();
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//向list中填充静态数据</span>
Items items_1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Items();
items_1.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"联想笔记本"</span>);
items_1.setPrice(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6000</span>f);
items_1.setDetail(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ThinkPad T430 联想笔记本电脑!"</span>);
Items items_2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Items();
items_2.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苹果手机"</span>);
items_2.setPrice(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5000</span>f);
items_2.setDetail(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iPhone6苹果手机!"</span>);
itemsList.add(items_1);
itemsList.add(items_2);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置模型数据</span>
request.setAttribute(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"itemsList"</span>, itemsList);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//设置转发的视图</span>
request.getRequestDispatcher(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/WEB-INF/jsp/items/itemsList.jsp"</span>).forward(request, response);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">/*
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");*/</span>
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li></ul>
前面获取数据都是一模一样的,后面转到视图部分和实现Controller接口是不同的,实现HttpRequestHandler接口的话,最后这里处理和原来的servlet是一样的,往request域中存入数据,然后跳转到新的jsp视图页面。不过这种方式还可以修改response,设置响应的数据格式等。
不管是用那个适配器,一个相同点就是:每个Handler中只能有一个方法,因为要继承Controller或者HttpRequestHandler,就要重写相对应的那个方法,在那个方法中处理逻辑。也就是说一个Handler中不能有两个方法或两个以上的来处理不同的逻辑,这是弊端,但是也有它的好处,限定了程序员的编程,比较规范。
这两个适配器可以同时使用,我测试了一下,不会冲突,我配了两个适配器,写了两个Handler,分别去实现Controller和HttpRequestHandler接口,都可以被执行。
1.2 处理器映射器
上一节中使用的映射器是:org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping。即:
这个映射器根据名字也可以看得出,是根据bean的name作为url进行查找,所以配置Handler的bean的时候,要配置一下name属性,设置为要请求的url即可正确映射。
还有一种处理器映射器叫简单映射器:org.springframework.web.servlet.handler.SimpleUrlHandlerMapping。它的映射方式是直接根据url来的,如下:
这种可以直接配url,然后对应的url指定一个Handler,使用的是该Handler对应bean的id,所以只要在bean中配好id,然后将url和这个id对应上即可。
经测试,这两个映射器也可以一起使用,互不冲突,匹配到哪个就用哪个。
2. 注解方式
2.1 处理器适配器和映射器
在spring3.1之前使用:
注解映射器:org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
注解适配器:org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
在spring3.1之后使用:
注解映射器:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
注解适配器:org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
毫无疑问,现在都已经到了版本4以上了,肯定有后者了,如果使用了注解方式的适配器和映射器,就不需要前面那些非注解的适配器和映射器了,所以只需要两行代码即可:
我们可以看到,上面还配了个Handler,那么url的映射怎么办?我怎么知道对应到哪个Handler呢?不着急,这些全交给注解!下面来写这个Handler:
<code class="language-java hljs has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Controller</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">ItemsController3</span> {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 商品查询列表</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// @RequestMapping实现 对queryItems方法和url进行映射,一个方法对应一个url</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 一般建议将url和方法写成一样</span>
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@RequestMapping</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/queryItems"</span>)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> ModelAndView <span class="hljs-title" style="box-sizing: border-box;">queryItems</span>() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 实际中是调用service查找数据库,查询商品列表,这里直接使用静态数据来模拟了</span>
List<Items> itemsList = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<Items>();
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 向list中填充静态数据</span>
Items items_1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Items();
items_1.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"联想笔记本"</span>);
items_1.setPrice(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6000</span>f);
items_1.setDetail(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ThinkPad T430 联想笔记本电脑!"</span>);
Items items_2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Items();
items_2.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苹果手机"</span>);
items_2.setPrice(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5000</span>f);
items_2.setDetail(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iPhone6苹果手机!"</span>);
itemsList.add(items_1);
itemsList.add(items_2);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 返回ModelAndView</span>
ModelAndView modelAndView = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ModelAndView();
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 相当于request的setAttribute,在jsp页面中通过itemsList取数据</span>
modelAndView.addObject(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"itemsList"</span>, itemsList);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 指定视图</span>
modelAndView.setViewName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/WEB-INF/jsp/items/itemsList.jsp"</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> modelAndView;
}
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@RequestMapping</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/queryItems2"</span>)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> ModelAndView <span class="hljs-title" style="box-sizing: border-box;">queryItems2</span>() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Exception {
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 实际中是调用service查找数据库,查询商品列表,这里直接使用静态数据来模拟了</span>
List<Items> itemsList = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ArrayList<Items>();
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 向list中填充静态数据</span>
Items items_1 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Items();
items_1.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"联想笔记本2"</span>);
items_1.setPrice(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">6000</span>f);
items_1.setDetail(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"ThinkPad T430 联想笔记本电脑!"</span>);
Items items_2 = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> Items();
items_2.setName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"苹果手机2"</span>);
items_2.setPrice(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">5000</span>f);
items_2.setDetail(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"iPhone6苹果手机!"</span>);
itemsList.add(items_1);
itemsList.add(items_2);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 返回ModelAndView</span>
ModelAndView modelAndView = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ModelAndView();
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 相当于request的setAttribute,在jsp页面中通过itemsList取数据</span>
modelAndView.addObject(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"itemsList"</span>, itemsList);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 指定视图</span>
modelAndView.setViewName(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"/WEB-INF/jsp/items/itemsList.jsp"</span>);
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> modelAndView;
}
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li></ul>
从上面的代码中可以看出,首先,我一个Handler中可以写多个方法了,现在是两个,逻辑一模一样,就是item的名字稍微变了一下好用来测试。在类的上面加上@Controller注解,可以指定bean的名字,也可以不指定,默认为类名首字母小写。然后url映射交给@RequestMapping类处理,可以指定url,一个url对应一个方法。
这样就很清晰了,前台传了个url进来,映射器根据这个url找到Handler,然后根据Handler选择一个适配器去执行,这里全部用的都是注解,这样就将url和这个Handler连到一起了,也把url和具体的处理方法连到一起了,由此可见,使用注解的开发方式比较方便。开发中常用的是注解的方式。
2.2 继续优化注解
使用注解要注意一个问题,就是注解适配器和映射器必须配对使用,也就是说,不能一个用注解,一个用非注解。要用一起用,要么都不用。其实在springmvc中还有更加简便的注解:
只要这一个注解即可,适配器和映射器就可以省略不配了。另外,如果Controller很多的话,我们还得针对这些Controller配好多个bean,也不方便,所以springmvc中也提供了扫描包的方式来配置,如下:
所以到最后,使用注解的方法,适配器、映射器、Controller等的配置加在一起就两行代码!搞定!当然,视图解析器还是和上一节一样,自己配一下即可。
到这就基本总结完了springmvc中使用非注解方式和注解方式的适配器和映射器了,很明显,开发中我们使用最后面的那个注解配置,非常方便。