SpringMVC浅谈

这里写图片描述

spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson创建。简单来说,Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架。它的主要目得是简化企业开发。

Spring框架包括什么?

这里写图片描述

Spring 框架是一个分层架构,由 7 个定义良好的模块组成。Spring 模块构建在核心容器之上,核心容器定义了创建、配置和管理 bean 的方式。

Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

MVC在B/S系统 下的应用

MVC是一个设计模式,MVC在B/S系统 下的应用:

这里写图片描述

SpringMVC框架

这里写图片描述

执行步骤:

第一步:发起请求到前端控制器(DispatcherServlet)

第二步:前端控制器请求HandlerMapping查找 Handler
可以根据xml配置、注解进行查找

第三步:处理器映射器HandlerMapping向前端控制器返回Handler

第四步:前端控制器调用处理器适配器去执行Handler

第五步:处理器适配器去执行Handler

第六步:Handler执行完成给适配器返回ModelAndView

第七步:处理器适配器向前端控制器返回ModelAndView
ModelAndView是SpringMVC框架的一个底层对象,包括 Model和view

第八步:前端控制器请求视图解析器去进行视图解析
根据逻辑视图名解析成真正的视图(jsp)

第九步:视图解析器向前端控制器返回View

第十步:前端控制器进行视图渲染
视图渲染将模型数据(在ModelAndView对象中)填充到request域

第十一步:前端控制器向用户响应结果

组件:

1、前端控制器DispatcherServlet(不需要程序员开发)
作用接收请求,响应结果,相当于转发器,中央处理器。
有了DispatcherServlet减少了其它组件之间的耦合度。

2、处理器映射器HandlerMapping(不需要程序员开发)
作用:根据请求的url查找Handler

3、处理器适配器HandlerAdapter
作用:按照特定规则(HandlerAdapter要求的规则)去执行Handler

4、处理器Handler(需要程序员开发)
注意:编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler

5、视图解析器View resolver(不需要程序员开发)
作用:进行视图解析,根据逻辑视图名解析成真正的视图(view)

6、视图View(需要程序员开发jsp)
View是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf…)

配置前端控制器

在web.xml中配置前端控制器。

<code class="hljs xml has-numbering">  <span class="hljs-comment"><!-- SpringMVC前端控制器 --></span>
  <span class="hljs-tag"><<span class="hljs-title">servlet</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>springmvc<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">servlet-class</span>></span>org.springframework.web.servlet.DispatcherServlet<span class="hljs-tag"></<span class="hljs-title">servlet-class</span>></span>
    <span class="hljs-comment"><!-- contextConfigLocation配置SpringMVC加载的配置文件(配置处理器映射器、适配器等等)
    如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml)
     --></span>
    <span class="hljs-tag"><<span class="hljs-title">init-param</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">param-name</span>></span>contextConfigLocation<span class="hljs-tag"></<span class="hljs-title">param-name</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">param-value</span>></span>classpath:springmvc.xml<span class="hljs-tag"></<span class="hljs-title">param-value</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">init-param</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span>

  <span class="hljs-tag"><<span class="hljs-title">servlet-mapping</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>springmvc<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span>
    <span class="hljs-comment"><!-- 
    第一种:*.action,访问以.action结尾 由DispatcherServlet进行解析
    第二种:/,所以访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析
    使用此种方式可以实现 RESTful风格的url
    第三种:/*,这样配置不对,使用这种配置,最终要转发到一个jsp页面时,
    仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错。

     --></span>
    <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>*.action<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
  <span class="hljs-tag"></<span class="hljs-title">servlet-mapping</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li></ul>

配置处理器适配器(非注解方式)

在classpath下的springmvc.xml中配置处理器适配器

<code class="hljs xml has-numbering">    <span class="hljs-comment"><!-- 处理器适配器 所有处理器适配器都实现 HandlerAdapter接口 --></span>
    <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"</span> /></span>
    <span class="hljs-comment"><!-- 另一个非注解的适配器 --></span>
    <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"</span>/></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

查看源码

SimpleControllerHandlerAdapter.java

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimpleControllerHandlerAdapter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">HandlerAdapter</span> 
{</span>
    <span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">handle</span>(HttpServletRequest request, HttpServletResponse response, Object handler)
            <span class="hljs-keyword">throws</span> Exception 
    {
        <span class="hljs-keyword">return</span> ((Controller) handler).handleRequest(request, response);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Controller</span> 
{</span>
    ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) <span class="hljs-keyword">throws</span> Exception;
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul>

HttpRequestHandlerAdapter.java

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HttpRequestHandlerAdapter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">HandlerAdapter</span> 
{</span>
    <span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">handle</span>(HttpServletRequest request, HttpServletResponse response, Object handler)
            <span class="hljs-keyword">throws</span> Exception 
    {
        ((HttpRequestHandler) handler).handleRequest(request, response);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">HttpRequestHandler</span> 
{</span>
    <span class="hljs-keyword">void</span> handleRequest(HttpServletRequest request, HttpServletResponse response)
            <span class="hljs-keyword">throws</span> ServletException, IOException;
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li></ul>

配置处理器Handler(非注解方式)

编写Handler类

方式①:需要实现 Controller接口,才能由org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter适配器执行。

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ItemsController1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Controller</span> 
{</span>
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">handleRequest</span>(HttpServletRequest request,
            HttpServletResponse response) <span class="hljs-keyword">throws</span> Exception 
    {

        <span class="hljs-comment">//调用Service查找 数据库,查询商品列表,这里使用静态数据模拟</span>
        List<Items> itemsList = <span class="hljs-keyword">new</span> ArrayList<Items>();
        <span class="hljs-comment">//向list中填充静态数据</span>

        Items items_1 = <span class="hljs-keyword">new</span> Items();
        items_1.setName(<span class="hljs-string">"联想笔记本"</span>);
        items_1.setPrice(<span class="hljs-number">6000</span>f);
        items_1.setDetail(<span class="hljs-string">"ThinkPad T430 联想笔记本电脑!"</span>);

        Items items_2 = <span class="hljs-keyword">new</span> Items();
        items_2.setName(<span class="hljs-string">"苹果手机"</span>);
        items_2.setPrice(<span class="hljs-number">5000</span>f);
        items_2.setDetail(<span class="hljs-string">"iphone6苹果手机!"</span>);

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

        <span class="hljs-comment">//返回ModelAndView</span>
        ModelAndView modelAndView =  <span class="hljs-keyword">new</span> ModelAndView();
        <span class="hljs-comment">//相当 于request的setAttribut,在jsp页面中通过itemsList取数据</span>
        modelAndView.addObject(<span class="hljs-string">"itemsList"</span>, itemsList);

        <span class="hljs-comment">//指定视图</span>
        modelAndView.setViewName(<span class="hljs-string">"/WEB-INF/jsp/items/itemsList.jsp"</span>);

        <span class="hljs-keyword">return</span> modelAndView;
    }
}
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li></ul>

方式②:需要实现 HttpRequestHandler接口,才能由org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter 适配器执行。

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ItemsController2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">HttpRequestHandler</span> 
{</span>
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">handleRequest</span>(HttpServletRequest request,
            HttpServletResponse response) <span class="hljs-keyword">throws</span> ServletException, IOException 
    {
        <span class="hljs-comment">//调用Service查找 数据库,查询商品列表,这里使用静态数据模拟</span>
        List<Items> itemsList = <span class="hljs-keyword">new</span> ArrayList<Items>();
        <span class="hljs-comment">//向list中填充静态数据</span>

        Items items_1 = <span class="hljs-keyword">new</span> Items();
        items_1.setName(<span class="hljs-string">"联想笔记本"</span>);
        items_1.setPrice(<span class="hljs-number">6000</span>f);
        items_1.setDetail(<span class="hljs-string">"ThinkPad T430 联想笔记本电脑!"</span>);

        Items items_2 = <span class="hljs-keyword">new</span> Items();
        items_2.setName(<span class="hljs-string">"苹果手机"</span>);
        items_2.setPrice(<span class="hljs-number">5000</span>f);
        items_2.setDetail(<span class="hljs-string">"iphone6苹果手机!"</span>);

        itemsList.add(items_1);
        itemsList.add(items_2);
        <span class="hljs-comment">//设置模型数据</span>
        request.setAttribute(<span class="hljs-string">"itemsList"</span>, itemsList);
        <span class="hljs-comment">//设置转发的视图</span>
        request.getRequestDispatcher(<span class="hljs-string">"/WEB-INF/jsp/items/itemsList.jsp"</span>).forward(request, response);

        <span class="hljs-comment">//使用此方法可以通过修改response,设置响应的数据格式,比如响应json数据</span>

        <span class="hljs-comment">/*
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write("json串");*/</span>
    }
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li></ul>

将编写Handler在spring容器加载。

<code class="hljs xml has-numbering"><span class="hljs-comment"><!-- 配置Handler --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"itemsController1"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"/queryItems.action"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"cn.itcast.ssm.controller.ItemsController1"</span> /></span>

<span class="hljs-comment"><!-- 配置另外一个Handler --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"itemsController2"</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"cn.itcast.ssm.controller.ItemsController2"</span> /></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

配置处理器映射器(非注解方式)

在classpath下的springmvc.xml中配置处理器映射器

处理器映射器:
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping

另一个映射器:
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping

<code class="hljs xml has-numbering"><span class="hljs-comment"><!-- 处理器映射器① 将bean的name作为url进行查找 ,需要在配置Handler时指定beanname(就是url) 
所有的映射器都实现 HandlerMapping接口。
--></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"</span> /></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
<code class="hljs xml has-numbering"><span class="hljs-comment"><!--处理器映射器② 简单url映射  --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"mappings"</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">props</span>></span>
                <span class="hljs-comment"><!-- 对itemsController1的Handler进行url映射,url是/queryItems1.action --></span>
                <span class="hljs-tag"><<span class="hljs-title">prop</span> <span class="hljs-attribute">key</span>=<span class="hljs-value">"/queryItems1.action"</span>></span>itemsController1<span class="hljs-tag"></<span class="hljs-title">prop</span>></span>
                <span class="hljs-tag"><<span class="hljs-title">prop</span> <span class="hljs-attribute">key</span>=<span class="hljs-value">"/queryItems2.action"</span>></span>itemsController1<span class="hljs-tag"></<span class="hljs-title">prop</span>></span>
                <span class="hljs-tag"><<span class="hljs-title">prop</span> <span class="hljs-attribute">key</span>=<span class="hljs-value">"/queryItems3.action"</span>></span>itemsController2<span class="hljs-tag"></<span class="hljs-title">prop</span>></span>
            <span class="hljs-tag"></<span class="hljs-title">props</span>></span>
        <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
<span class="hljs-tag"></<span class="hljs-title">bean</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li></ul>

配置视图解析器

需要配置解析jsp的视图解析器。

<code class="hljs xml has-numbering">    <span class="hljs-comment"><!-- 视图解析器
    解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包
     --></span>
    <span class="hljs-tag"><<span class="hljs-title">bean
</span>        <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.view.InternalResourceViewResolver"</span>></span>
        <span class="hljs-comment"><!-- 配置jsp路径的前缀 --></span>
        <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"prefix"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"/WEB-INF/jsp/"</span>/></span>
        <span class="hljs-comment"><!-- 配置jsp路径的后缀 --></span>
        <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"suffix"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">".jsp"</span>/></span>
    <span class="hljs-tag"></<span class="hljs-title">bean</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

DispatcherSerlvet.properties

这里写图片描述

前端控制器从上边的文件中加载处理映射器、适配器、视图解析器等组件,如果不在springmvc.xml中配置,使用默认加载的。

<code class="hljs avrasm has-numbering"><span class="hljs-preprocessor"># Default implementation classes for DispatcherServlet's strategy interfaces.</span>
<span class="hljs-preprocessor"># Used as fallback when no matching beans are found in the DispatcherServlet context.</span>
<span class="hljs-preprocessor"># Not meant to be customized by application developers.</span>

org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.LocaleResolver</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.i</span>18n<span class="hljs-preprocessor">.AcceptHeaderLocaleResolver</span>

org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.ThemeResolver</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.theme</span><span class="hljs-preprocessor">.FixedThemeResolver</span>

<span class="hljs-preprocessor">#处理器映射器</span>
org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.HandlerMapping</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.handler</span><span class="hljs-preprocessor">.BeanNameUrlHandlerMapping</span>,\
    org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.mvc</span><span class="hljs-preprocessor">.annotation</span><span class="hljs-preprocessor">.DefaultAnnotationHandlerMapping</span>

<span class="hljs-preprocessor">#处理器适配器</span>
org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.HandlerAdapter</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.mvc</span><span class="hljs-preprocessor">.HttpRequestHandlerAdapter</span>,\
    org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.mvc</span><span class="hljs-preprocessor">.SimpleControllerHandlerAdapter</span>,\
    org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.mvc</span><span class="hljs-preprocessor">.annotation</span><span class="hljs-preprocessor">.AnnotationMethodHandlerAdapter</span>

org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.HandlerExceptionResolver</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.mvc</span><span class="hljs-preprocessor">.annotation</span><span class="hljs-preprocessor">.AnnotationMethodHandlerExceptionResolver</span>,\
    org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.mvc</span><span class="hljs-preprocessor">.annotation</span><span class="hljs-preprocessor">.ResponseStatusExceptionResolver</span>,\
    org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.mvc</span><span class="hljs-preprocessor">.support</span><span class="hljs-preprocessor">.DefaultHandlerExceptionResolver</span>

org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.RequestToViewNameTranslator</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.view</span><span class="hljs-preprocessor">.DefaultRequestToViewNameTranslator</span>

<span class="hljs-preprocessor">#视图解析器</span>
org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.ViewResolver</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.view</span><span class="hljs-preprocessor">.InternalResourceViewResolver</span>

org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.FlashMapManager</span>=org<span class="hljs-preprocessor">.springframework</span><span class="hljs-preprocessor">.web</span><span class="hljs-preprocessor">.servlet</span><span class="hljs-preprocessor">.support</span><span class="hljs-preprocessor">.SessionFlashMapManager</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li></ul>

手动在配置文件中配置处理器Handler,处理器映射器HandlerMapping,如果在文件太多的情况下会比较麻烦。而且每次都要实现Controller接口和HttpRequestHandler接口,并且只有一个实现方法。每次为了一个方法去实现接口,会造成Handler类越来越多。太麻烦。SpringMVC提供了注解模式开发处理器Handler,大大降低了工作量,提高了易用性。

注解模式开发处理器Handler

注解模式的处理器映射器HandlerMapping和处理器适配器HandlerAdapter需要这样配置。

使用注解的映射器和注解的适配器。(注解的映射器和注解的适配器必须配对使用)

<code class="hljs xml has-numbering"><span class="hljs-comment"><!--注解映射器 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"</span>/></span>
<span class="hljs-comment"><!--注解适配器 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"</span>/></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>
<code class="hljs xml has-numbering"><span class="hljs-comment"><!-- 使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置
    mvc:annotation-driven默认加载很多的参数绑定方法,
    比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
    实际开发时使用mvc:annotation-driven
     --></span>
    <span class="hljs-comment"><!-- <mvc:annotation-driven></mvc:annotation-driven> --></span>
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>

编写Handler,无需继承任何接口,仅需加入@Controller注解

<code class="hljs java has-numbering"><span class="hljs-comment">//使用Controller标识 它是一个控制器</span>
<span class="hljs-annotation">@Controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ItemsController3</span> 
{</span>
    <span class="hljs-comment">//商品查询列表</span>
    <span class="hljs-comment">//@RequestMapping实现 对queryItems方法和url进行映射,一个方法对应一个url</span>
    <span class="hljs-comment">//一般建议将url和方法写成一样</span>
    <span class="hljs-annotation">@RequestMapping</span>(<span class="hljs-string">"/queryItems"</span>)
    <span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">queryItems</span>()<span class="hljs-keyword">throws</span> Exception
    {
        <span class="hljs-comment">//调用Service查找 数据库,查询商品列表,这里使用静态数据模拟</span>
        List<Items> itemsList = <span class="hljs-keyword">new</span> ArrayList<Items>();
        <span class="hljs-comment">//向list中填充静态数据</span>

        Items items_1 = <span class="hljs-keyword">new</span> Items();
        items_1.setName(<span class="hljs-string">"联想笔记本"</span>);
        items_1.setPrice(<span class="hljs-number">6000</span>f);
        items_1.setDetail(<span class="hljs-string">"ThinkPad T430 联想笔记本电脑!"</span>);

        Items items_2 = <span class="hljs-keyword">new</span> Items();
        items_2.setName(<span class="hljs-string">"苹果手机"</span>);
        items_2.setPrice(<span class="hljs-number">5000</span>f);
        items_2.setDetail(<span class="hljs-string">"iphone6苹果手机!"</span>);

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

        <span class="hljs-comment">//返回ModelAndView</span>
        ModelAndView modelAndView =  <span class="hljs-keyword">new</span> ModelAndView();
        <span class="hljs-comment">//相当 于request的setAttribut,在jsp页面中通过itemsList取数据</span>
        modelAndView.addObject(<span class="hljs-string">"itemsList"</span>, itemsList);

        <span class="hljs-comment">//指定视图</span>
        modelAndView.setViewName(<span class="hljs-string">"/WEB-INF/jsp/items/itemsList.jsp"</span>);

        <span class="hljs-keyword">return</span> modelAndView;
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li></ul>

在spring容器中加载Handler(使用注解扫描方式加载)

<code class="hljs xml has-numbering">    <span class="hljs-comment"><!-- 对于注解的Handler可以单个配置
    实际开发中建议使用组件扫描
     --></span>
    <span class="hljs-comment"><!-- <bean class="cn.itcast.ssm.controller.ItemsController3" /> --></span>
    <span class="hljs-comment"><!-- 可以扫描Controller、Service、...
    这里让扫描Controller,指定Controller的包
     --></span>
    <span class="hljs-tag"><<span class="hljs-title">context:component-scan</span> <span class="hljs-attribute">base-package</span>=<span class="hljs-value">"cn.itcast.ssm.controller"</span>></span><span class="hljs-tag"></<span class="hljs-title">context:component-scan</span>></span>
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

使用以上配置,就可以运行起来SpringMVC程序了。

注解方式开发总结

对标记@Controller类中标识有@RequestMapping的方法进行映射。在@RequestMapping里边定义映射的url。使用注解的映射器不用在xml中配置url和Handler的映射关系。

注解处理器适配器和注解的处理器映射器是配对使用。理解为不能使用非注解映射器进行映射。

<mvc:annotation-driven></mvc:annotation-driven>可以代替下边的配置:

<code class="hljs xml has-numbering"><span class="hljs-comment"><!--注解映射器 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"</span>/></span>
<span class="hljs-comment"><!--注解适配器 --></span>
<span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"</span>/></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li></ul>

视图解析器配置前缀和后缀:

<code class="hljs xml has-numbering">    <span class="hljs-comment"><!-- 视图解析器
    解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包
     --></span>
    <span class="hljs-tag"><<span class="hljs-title">bean
</span>        <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.servlet.view.InternalResourceViewResolver"</span>></span>
        <span class="hljs-comment"><!-- 配置jsp路径的前缀 --></span>
        <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"prefix"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"/WEB-INF/jsp/"</span>/></span>
        <span class="hljs-comment"><!-- 配置jsp路径的后缀 --></span>
        <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"suffix"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">".jsp"</span>/></span>
    <span class="hljs-tag"></<span class="hljs-title">bean</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

程序中不用指定前缀和后缀:

<code class="hljs cs has-numbering"><span class="hljs-comment">//没有前缀和后缀时</span>
modelAndView.setViewName(<span class="hljs-string">"/WEB-INF/jsp/items/itemsList.jsp"</span>);

<span class="hljs-comment">//有前缀和后缀时</span>
modelAndView.setViewName(<span class="hljs-string">"items/itemsList"</span>);
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

SpringMVC源码分析

通过前端控制器源码分析SpringMVC的执行过程。

第一步:前端控制器接收请求

调用doDiapatch

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DispatcherServlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">FrameworkServlet</span> 
{</span>
<span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doDispatch</span>(HttpServletRequest request, HttpServletResponse response) <span class="hljs-keyword">throws</span> Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">boolean</span> multipartRequestParsed = <span class="hljs-keyword">false</span>;

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

        <span class="hljs-keyword">try</span> {
            ModelAndView mv = <span class="hljs-keyword">null</span>;
            Exception dispatchException = <span class="hljs-keyword">null</span>;

            <span class="hljs-keyword">try</span> {
                processedRequest = checkMultipart(request);
                multipartRequestParsed = processedRequest != request;

                <span class="hljs-comment">// Determine handler for the current request.</span>
                mappedHandler = getHandler(processedRequest, <span class="hljs-keyword">false</span>);
                <span class="hljs-keyword">if</span> (mappedHandler == <span class="hljs-keyword">null</span> || mappedHandler.getHandler() == <span class="hljs-keyword">null</span>) {
                    noHandlerFound(processedRequest, response);
                    <span class="hljs-keyword">return</span>;
                }

                <span class="hljs-comment">// Determine handler adapter for the current request.</span>
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                <span class="hljs-comment">// Process last-modified header, if supported by the handler.</span>
                String method = request.getMethod();
                <span class="hljs-keyword">boolean</span> isGet = <span class="hljs-string">"GET"</span>.equals(method);
                <span class="hljs-keyword">if</span> (isGet || <span class="hljs-string">"HEAD"</span>.equals(method)) {
                    <span class="hljs-keyword">long</span> lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    <span class="hljs-keyword">if</span> (logger.isDebugEnabled()) {
                        String requestUri = urlPathHelper.getRequestUri(request);
                        logger.debug(<span class="hljs-string">"Last-Modified value for ["</span> + requestUri + <span class="hljs-string">"] is: "</span> + lastModified);
                    }
                    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">new</span> ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        <span class="hljs-keyword">return</span>;
                    }
                }

                <span class="hljs-keyword">if</span> (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    <span class="hljs-keyword">return</span>;
                }

                <span class="hljs-keyword">try</span> {
                    <span class="hljs-comment">// Actually invoke the handler.</span>
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                }
                <span class="hljs-keyword">finally</span> {
                    <span class="hljs-keyword">if</span> (asyncManager.isConcurrentHandlingStarted()) {
                        <span class="hljs-keyword">return</span>;
                    }
                }

                applyDefaultViewName(request, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            <span class="hljs-keyword">catch</span> (Exception ex) {
                dispatchException = ex;
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        <span class="hljs-keyword">catch</span> (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        <span class="hljs-keyword">catch</span> (Error err) {
            triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
        }
        <span class="hljs-keyword">finally</span> {
            <span class="hljs-keyword">if</span> (asyncManager.isConcurrentHandlingStarted()) {
                <span class="hljs-comment">// Instead of postHandle and afterCompletion</span>
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                <span class="hljs-keyword">return</span>;
            }
            <span class="hljs-comment">// Clean up any resources used by a multipart request.</span>
            <span class="hljs-keyword">if</span> (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li><li>76</li><li>77</li><li>78</li><li>79</li><li>80</li><li>81</li><li>82</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li><li>66</li><li>67</li><li>68</li><li>69</li><li>70</li><li>71</li><li>72</li><li>73</li><li>74</li><li>75</li><li>76</li><li>77</li><li>78</li><li>79</li><li>80</li><li>81</li><li>82</li></ul>

第二步:前端控制器调用处理器映射器查找 Handler

<code class="hljs java has-numbering">
<span class="hljs-comment">// Determine handler for the current request.</span>
mappedHandler = getHandler(processedRequest, <span class="hljs-keyword">false</span>);

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DispatcherServlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">FrameworkServlet</span> 
{</span>
    <span class="hljs-keyword">protected</span> HandlerExecutionChain <span class="hljs-title">getHandler</span>(HttpServletRequest request) <span class="hljs-keyword">throws</span> Exception {
        <span class="hljs-keyword">for</span> (HandlerMapping hm : <span class="hljs-keyword">this</span>.handlerMappings) {
            <span class="hljs-keyword">if</span> (logger.isTraceEnabled()) {
                logger.trace(
                        <span class="hljs-string">"Testing handler map ["</span> + hm + <span class="hljs-string">"] in DispatcherServlet with name '"</span> + getServletName() + <span class="hljs-string">"'"</span>);
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            <span class="hljs-keyword">if</span> (handler != <span class="hljs-keyword">null</span>) {
                <span class="hljs-keyword">return</span> handler;
            }
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
    }
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li></ul>

第三步:调用处理器适配器执行Handler,得到执行结果ModelAndView

<code class="hljs sql has-numbering">// Actually invoke the <span class="hljs-operator"><span class="hljs-keyword">handler</span>.
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());</span>
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>

第四步:视图渲染,将model数据填充到request域。

视图解析,得到view:

<code class="hljs java has-numbering">processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);

render(mv, request, response);

    <span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">render</span>(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) <span class="hljs-keyword">throws</span> Exception {
        <span class="hljs-comment">// Determine locale for request and apply it to the response.</span>
        Locale locale = <span class="hljs-keyword">this</span>.localeResolver.resolveLocale(request);
        response.setLocale(locale);

        View view;
        <span class="hljs-keyword">if</span> (mv.isReference()) {
            <span class="hljs-comment">// We need to resolve the view name.</span>
            view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
            <span class="hljs-keyword">if</span> (view == <span class="hljs-keyword">null</span>) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ServletException(
                        <span class="hljs-string">"Could not resolve view with name '"</span> + mv.getViewName() + <span class="hljs-string">"' in servlet with name '"</span> +
                                getServletName() + <span class="hljs-string">"'"</span>);
            }
        }
        <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// No need to lookup: the ModelAndView object contains the actual View object.</span>
            view = mv.getView();
            <span class="hljs-keyword">if</span> (view == <span class="hljs-keyword">null</span>) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ServletException(<span class="hljs-string">"ModelAndView ["</span> + mv + <span class="hljs-string">"] neither contains a view name nor a "</span> +
                        <span class="hljs-string">"View object in servlet with name '"</span> + getServletName() + <span class="hljs-string">"'"</span>);
            }
        }

        <span class="hljs-comment">// Delegate to the View object for rendering.</span>
        <span class="hljs-keyword">if</span> (logger.isDebugEnabled()) {
            logger.debug(<span class="hljs-string">"Rendering view ["</span> + view + <span class="hljs-string">"] in DispatcherServlet with name '"</span> + getServletName() + <span class="hljs-string">"'"</span>);
        }
        view.render(mv.getModelInternal(), request, response);
    }

<span class="hljs-comment">// We need to resolve the view name.</span>
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li></ul>

调用view的渲染方法,将model数据填充到request域

渲染方法:

<code class="hljs avrasm has-numbering">view<span class="hljs-preprocessor">.render</span>(mv<span class="hljs-preprocessor">.getModelInternal</span>(), request, response)<span class="hljs-comment">;</span>

    protected void exposeModelAsRequestAttributes(Map<String, Object> model, HttpServletRequest request) throws Exception 
    {
        for (Map<span class="hljs-preprocessor">.Entry</span><String, Object> entry : model<span class="hljs-preprocessor">.entrySet</span>()) {
            String modelName = entry<span class="hljs-preprocessor">.getKey</span>()<span class="hljs-comment">;</span>
            Object modelValue = entry<span class="hljs-preprocessor">.getValue</span>()<span class="hljs-comment">;</span>
            if (modelValue != null) {
                request<span class="hljs-preprocessor">.setAttribute</span>(modelName, modelValue)<span class="hljs-comment">;</span>
                if (logger<span class="hljs-preprocessor">.isDebugEnabled</span>()) {
                    logger<span class="hljs-preprocessor">.debug</span>(<span class="hljs-string">"Added model object '"</span> + modelName + <span class="hljs-string">"' of type ["</span> + modelValue<span class="hljs-preprocessor">.getClass</span>()<span class="hljs-preprocessor">.getName</span>() +
                            <span class="hljs-string">"] to request in view with name '"</span> + getBeanName() + <span class="hljs-string">"'"</span>)<span class="hljs-comment">;</span>
                }
            }
            else {
                request<span class="hljs-preprocessor">.removeAttribute</span>(modelName)<span class="hljs-comment">;</span>
                if (logger<span class="hljs-preprocessor">.isDebugEnabled</span>()) {
                    logger<span class="hljs-preprocessor">.debug</span>(<span class="hljs-string">"Removed model object '"</span> + modelName +
                            <span class="hljs-string">"' from request in view with name '"</span> + getBeanName() + <span class="hljs-string">"'"</span>)<span class="hljs-comment">;</span>
                }
            }
        }
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li></ul>

Controller的@RequestMapping

① url映射

定义Controller方法对应的url,进行处理器映射使用。

② 窄化请求映射

<code class="hljs java has-numbering"><span class="hljs-annotation">@Controller</span>
<span class="hljs-comment">// 为了对url进行分类管理 ,可以在这里定义根路径,最终访问url是根路径+子路径</span>
<span class="hljs-comment">// 比如:商品列表:/items/queryItems.action</span>
<span class="hljs-annotation">@RequestMapping</span>(<span class="hljs-string">"/items"</span>)
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ItemsController</span> 
{</span>

}
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li></ul>

③ 限制http请求方法

出于安全性考虑,对http的链接进行方法限制。
如果限制请求为post方法,进行get请求,则会报错。

<code class="hljs java has-numbering"><span class="hljs-comment">//限制http请求方法,只可以post</span>
<span class="hljs-annotation">@RequestMapping</span>(value=<span class="hljs-string">"/editItems"</span>,method={RequestMethod.POST})
<span class="hljs-keyword">public</span> ModelAndView <span class="hljs-title">editItems</span>()<span class="hljs-keyword">throws</span> Exception 
{
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

Controller方法的返回值

在编写控制器Handler可以有三种返回值。

  • 返回ModelAndView
  • 返回String
  • 返回void

① 返回ModelAndView

需要方法结束时,定义ModelAndView,将model和view分别进行设置。

② 返回String

如果Controller方法返回String,可以有以下三种形式。

(1)、表示返回逻辑视图名。

真正视图(jsp路径)=前缀+逻辑视图名+后缀

<code class="hljs java has-numbering"><span class="hljs-annotation">@RequestMapping</span>(value=<span class="hljs-string">"/editItems"</span>,method={RequestMethod.POST,RequestMethod.GET})
<span class="hljs-keyword">public</span> String <span class="hljs-title">editItems</span>(Model model)<span class="hljs-keyword">throws</span> Exception 
{
     <span class="hljs-comment">//调用Service根据商品id查询商品信息</span>
     ItemsCustom itemsCustom = itemsService.findItemsById(<span class="hljs-number">1</span>);

     <span class="hljs-comment">//将商品信息放到model</span>
     model.addAttribute(<span class="hljs-string">"itemsCustom"</span>, itemsCustom);

     <span class="hljs-keyword">return</span> <span class="hljs-string">"items/editItems"</span>;
}</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li></ul>

(2)、redirect重定向

redirect重定向特点:浏览器地址栏中的url会变化。修改提交的request数据无法传到重定向的地址。因为重定向后重新进行request(request无法共享)

<code class="hljs bash has-numbering"><span class="hljs-keyword">return</span> <span class="hljs-string">"redirect:items/queryItems.action"</span>;</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

(3)、forward页面转发

通过forward进行页面转发,浏览器地址栏url不变,request可以共享。

<code class="hljs bash has-numbering"><span class="hljs-keyword">return</span> <span class="hljs-string">"forward:items/queryItems.action"</span>;</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

③ 返回void

在Controller方法形参上可以定义request和response,使用request或response指定响应结果:

(1)、使用request转向页面,如下:

<code class="hljs vbscript has-numbering"><span class="hljs-built_in">request</span>.getRequestDispatcher(<span class="hljs-string">"页面路径"</span>).forward(<span class="hljs-built_in">request</span>, <span class="hljs-built_in">response</span>);</code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

(2)、也可以通过response页面重定向:

<code class="hljs avrasm has-numbering">response<span class="hljs-preprocessor">.sendRedirect</span>(<span class="hljs-string">"url"</span>)<span class="hljs-comment">;</span></code><ul style="" class="pre-numbering"><li>1</li></ul><ul style="" class="pre-numbering"><li>1</li></ul>

(3)、也可以通过response指定响应结果,例如响应json数据如下:

<code class="hljs avrasm has-numbering">response<span class="hljs-preprocessor">.setCharacterEncoding</span>(<span class="hljs-string">"utf-8"</span>)<span class="hljs-comment">;</span>
response<span class="hljs-preprocessor">.setContentType</span>(<span class="hljs-string">"application/json;charset=utf-8"</span>)<span class="hljs-comment">;</span>
response<span class="hljs-preprocessor">.getWriter</span>()<span class="hljs-preprocessor">.write</span>(<span class="hljs-string">"json串"</span>)<span class="hljs-comment">;</span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li></ul>

Controller参数绑定

SpringMVC参数绑定过程

从客户端请求key/value数据,经过参数绑定,将key/value数据绑定到Controller方法的形参上。

SpringMVC中,接收页面提交的数据是通过方法形参来接收。而不是在Controller类定义成员变量接收!!!!(与Struts2明显不同的实现逻辑)

这里写图片描述

(1) 默认支持的类型

直接在Controller方法形参上定义下边类型的对象,就可以使用这些对象。在参数绑定过程中,如果遇到下边类型直接进行绑定。

① HttpServletRequest

通过request对象获取请求信息

② HttpServletResponse

通过response处理响应信息

③ HttpSession

通过session对象得到session中存放的对象

④ Model/ModelMap

model是一个接口,modelMap是一个接口实现 。

作用:将model数据填充到request域。

(2) 简单类型

通过@RequestParam对简单类型的参数进行绑定。

如果不使用@RequestParam,要求request传入参数名称和Controller方法的形参名称一致,方可绑定成功。

如果使用@RequestParam,不用限制request传入参数名称和Controller方法的形参名称一致。

通过required属性指定参数是否必须要传入,如果设置为true,没有传入参数,则会报错。

<code class="hljs cs has-numbering">    <span class="hljs-comment">// @RequestParam里边指定request传入参数名称和形参进行绑定。</span>
    <span class="hljs-comment">// 通过required属性指定参数是否必须要传入</span>
    <span class="hljs-comment">// 通过defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定。</span>
    <span class="hljs-keyword">public</span> String <span class="hljs-title">editItems</span>(Model model,@<span class="hljs-title">RequestParam</span>(<span class="hljs-keyword">value</span> = <span class="hljs-string">"id"</span>, required = <span class="hljs-keyword">true</span>) Integer items_id) throws Exception 
    {

    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>

(3) pojo绑定

页面中input的name和Controller的pojo形参中的属性名称一致,将页面中数据绑定到pojo对应的属性。

页面定义:

这里写图片描述

Controller的pojo形参的定义:

这里写图片描述

需要说明的是:简单类型的参数绑定和pojo参数绑定互不影响。

<code class="hljs cs has-numbering">    <span class="hljs-comment">// @RequestParam里边指定request传入参数名称和形参进行绑定。</span>
    <span class="hljs-comment">// 通过required属性指定参数是否必须要传入</span>
    <span class="hljs-comment">// 通过defaultValue可以设置默认值,如果id参数没有传入,将默认值和形参绑定。</span>
    <span class="hljs-keyword">public</span> String <span class="hljs-title">editItems</span>(Model model,@<span class="hljs-title">RequestParam</span>(<span class="hljs-keyword">value</span> = <span class="hljs-string">"id"</span>, required = <span class="hljs-keyword">true</span>) Integer items_id, Items item) throws Exception 
    {

    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li></ul>

SpringMVC 和 Struts2 的区别

1、SpringMVC基于方法开发的,struts2基于类开发的。

SpringMVC将url和Controller方法映射。映射成功后SpringMVC生成一个Handler对象,对象中只包括了一个method。
方法执行结束,形参数据销毁。
SpringMVC的Controller开发类似Service开发。

2、SpringMVC可以进行单例开发,并且建议使用单例开发,struts2通过类的成员变量接收参数,无法使用单例,只能使用多例。(原因就是第一句)

3、经过实际测试,struts2速度慢,在于使用struts标签,如果使用struts建议使用jstl。

SpringMVC 上传文件

在页面form中提交enctype=”multipart/form-data”的数据时,需要SpringMVC对multipart类型的数据进行解析。

在springmvc.xml中配置multipart类型解析器。

<code class="hljs xml has-numbering">    <span class="hljs-comment"><!-- 文件上传 --></span>
    <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"multipartResolver"</span>
        <span class="hljs-attribute">class</span>=<span class="hljs-value">"org.springframework.web.multipart.commons.CommonsMultipartResolver"</span>></span>
        <span class="hljs-comment"><!-- 设置上传文件的最大尺寸为5MB --></span>
        <span class="hljs-tag"><<span class="hljs-title">property</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"maxUploadSize"</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">value</span>></span>5242880<span class="hljs-tag"></<span class="hljs-title">value</span>></span>
        <span class="hljs-tag"></<span class="hljs-title">property</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">bean</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>
<code class="hljs xml has-numbering"><span class="hljs-tag"><<span class="hljs-title">form</span> <span class="hljs-attribute">id</span>=<span class="hljs-value">"itemForm"</span> <span class="hljs-attribute">action</span>=<span class="hljs-value">"${pageContext.request.contextPath }/items/editItemsSubmit.action"</span> <span class="hljs-attribute">method</span>=<span class="hljs-value">"post"</span> <span class="hljs-attribute">enctype</span>=<span class="hljs-value">"multipart/form-data"</span>></span>
<span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"hidden"</span> <span class="hljs-attribute">name</span>=<span class="hljs-value">"id"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"${items.id }"</span>/></span>
修改商品信息:
<span class="hljs-tag"><<span class="hljs-title">table</span> <span class="hljs-attribute">width</span>=<span class="hljs-value">"100%"</span> <span class="hljs-attribute">border</span>=<span class="hljs-value">1</span>></span>

<span class="hljs-tag"><<span class="hljs-title">tr</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">td</span>></span>商品图片<span class="hljs-tag"></<span class="hljs-title">td</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">td</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">c:if</span> <span class="hljs-attribute">test</span>=<span class="hljs-value">"${items.pic !=null}"</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">img</span> <span class="hljs-attribute">src</span>=<span class="hljs-value">"/pic/${items.pic}"</span> <span class="hljs-attribute">width</span>=<span class="hljs-value">100</span> <span class="hljs-attribute">height</span>=<span class="hljs-value">100</span>/></span>
            <span class="hljs-tag"><<span class="hljs-title">br</span>/></span>
        <span class="hljs-tag"></<span class="hljs-title">c:if</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"file"</span>  <span class="hljs-attribute">name</span>=<span class="hljs-value">"items_pic"</span>/></span> 
    <span class="hljs-tag"></<span class="hljs-title">td</span>></span>
<span class="hljs-tag"></<span class="hljs-title">tr</span>></span>

<span class="hljs-tag"><<span class="hljs-title">tr</span>></span>
<span class="hljs-tag"><<span class="hljs-title">td</span> <span class="hljs-attribute">colspan</span>=<span class="hljs-value">"2"</span> <span class="hljs-attribute">align</span>=<span class="hljs-value">"center"</span>></span><span class="hljs-tag"><<span class="hljs-title">input</span> <span class="hljs-attribute">type</span>=<span class="hljs-value">"submit"</span> <span class="hljs-attribute">value</span>=<span class="hljs-value">"提交"</span>/></span>
<span class="hljs-tag"></<span class="hljs-title">td</span>></span>
<span class="hljs-tag"></<span class="hljs-title">tr</span>></span>
<span class="hljs-tag"></<span class="hljs-title">table</span>></span>

<span class="hljs-tag"></<span class="hljs-title">form</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li></ul>
<code class="hljs java has-numbering">    <span class="hljs-annotation">@RequestMapping</span>(<span class="hljs-string">"/editItemsSubmit"</span>)
    <span class="hljs-keyword">public</span> String <span class="hljs-title">editItemsSubmit</span>(Model model,HttpServletRequest request,Integer id,
            MultipartFile items_pic//接收商品图片
            ) <span class="hljs-keyword">throws</span> Exception 
    {
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

RESTful支持

RESTful架构,就是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用。

RESTful(即Representational State Transfer的缩写)其实是一个开发理念,是对http的很好的诠释。

1、对url进行规范,写RESTful格式的url

非REST的url:http://…../queryItems.action?id=001&type=T01
REST的url风格:http://…./items/001
特点:url简洁,将参数通过url传到服务端

2、http的方法规范

不管是删除、添加、更新。。使用url是一致的,如果进行删除,需要设置http的方法为delete,同理添加。。。

后台Controller方法:判断http方法,如果是delete执行删除,如果是post执行添加。

3、对http的contentType规范

请求时指定contentType,要json数据,设置成json格式的type。。

Controller中设置

定义方法,进行url映射使用REST风格的url,将查询商品信息的id传入Controller .

输出json使用@ResponseBody将java对象输出json。

<code class="hljs java has-numbering">    <span class="hljs-comment">//查询商品信息,输出json</span>
    <span class="hljs-comment">///itemsView/{id}里边的{id}表示占位符,通过@PathVariable获取占位符中的参数,</span>
    <span class="hljs-comment">//如果占位符中的名称和形参名一致,在@PathVariable可以不指定名称</span>
    <span class="hljs-annotation">@RequestMapping</span>(<span class="hljs-string">"/itemsView/{id}"</span>)
    <span class="hljs-keyword">public</span> @ResponseBody ItemsCustom <span class="hljs-title">itemsView</span>(@<span class="hljs-title">PathVariable</span>("id") Integer id)<span class="hljs-keyword">throws</span> Exception
    {
        <span class="hljs-comment">//调用Service查询商品信息</span>
        ItemsCustom itemsCustom = itemsService.findItemsById(id);
        <span class="hljs-keyword">return</span> itemsCustom;
    }</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

@RequestMapping(value=”/ itemsView/{id}”):{×××}占位符,请求的URL可以是“/viewItems/1”或“/viewItems/2”,通过在方法中使用@PathVariable获取{×××}中的×××变量。

@PathVariable用于将请求URL中的模板变量映射到功能处理方法的参数上。
如果RequestMapping中表示为”/ itemsView /{id}”,id和形参名称一致,@PathVariable不用指定名称。

REST方法的前端控制器配置

在web.xml配置:

<code class="hljs xml has-numbering"><span class="hljs-comment"><!-- SpringMVC前端控制器,rest配置 --></span>
    <span class="hljs-tag"><<span class="hljs-title">servlet</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>springmvc_rest<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">servlet-class</span>></span>org.springframework.web.servlet.DispatcherServlet<span class="hljs-tag"></<span class="hljs-title">servlet-class</span>></span>
        <span class="hljs-comment"><!-- contextConfigLocation配置SpringMVC加载的配置文件(配置处理器映射器、适配器等等) 如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml) --></span>
        <span class="hljs-tag"><<span class="hljs-title">init-param</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">param-name</span>></span>contextConfigLocation<span class="hljs-tag"></<span class="hljs-title">param-name</span>></span>
            <span class="hljs-tag"><<span class="hljs-title">param-value</span>></span>classpath:spring/springmvc.xml<span class="hljs-tag"></<span class="hljs-title">param-value</span>></span>
        <span class="hljs-tag"></<span class="hljs-title">init-param</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">servlet</span>></span>

    <span class="hljs-tag"><<span class="hljs-title">servlet-mapping</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">servlet-name</span>></span>springmvc_rest<span class="hljs-tag"></<span class="hljs-title">servlet-name</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">url-pattern</span>></span>/<span class="hljs-tag"></<span class="hljs-title">url-pattern</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">servlet-mapping</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li></ul>

对静态资源的解析

配置前端控制器的url-pattern中指定/,对静态资源的解析出现问题:

在springmvc.xml中添加静态资源解析方法。

<code class="hljs xml has-numbering">    <span class="hljs-comment"><!-- 静态资源解析
    包括 :js、css、img、..
     --></span>
     <span class="hljs-tag"><<span class="hljs-title">mvc:resources</span> <span class="hljs-attribute">location</span>=<span class="hljs-value">"/js/"</span> <span class="hljs-attribute">mapping</span>=<span class="hljs-value">"/js/**"</span>/></span>
     <span class="hljs-tag"><<span class="hljs-title">mvc:resources</span> <span class="hljs-attribute">location</span>=<span class="hljs-value">"/img/"</span> <span class="hljs-attribute">mapping</span>=<span class="hljs-value">"/img/**"</span>/></span>
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>

SpringMVC拦截器

拦截定义

定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HandlerInterceptor1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">HandlerInterceptor</span> 
{</span>
    <span class="hljs-comment">//进入 Handler方法之前执行</span>
    <span class="hljs-comment">//用于身份认证、身份授权</span>
    <span class="hljs-comment">//比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行</span>
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">preHandle</span>(HttpServletRequest request,
            HttpServletResponse response, Object handler) <span class="hljs-keyword">throws</span> Exception 
    {
        <span class="hljs-comment">//return false表示拦截,不向下执行</span>
        <span class="hljs-comment">//return true表示放行</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    }

    <span class="hljs-comment">//进入Handler方法之后,返回modelAndView之前执行</span>
    <span class="hljs-comment">//应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里传到视图,也可以在这里统一指定视图</span>
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">postHandle</span>(HttpServletRequest request,
            HttpServletResponse response, Object handler,
            ModelAndView modelAndView) <span class="hljs-keyword">throws</span> Exception 
    {

    }

    <span class="hljs-comment">//执行Handler完成执行此方法</span>
    <span class="hljs-comment">//应用场景:统一异常处理,统一日志处理</span>
    <span class="hljs-annotation">@Override</span>
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">afterCompletion</span>(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception ex)
            <span class="hljs-keyword">throws</span> Exception 
    {

    }
}
</code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li></ul>

拦截器配置

SpringMVC配置类似全局的拦截器,SpringMVC框架将配置的类似全局的拦截器注入到每个HandlerMapping中。

<code class="hljs xml has-numbering"><span class="hljs-comment"><!--拦截器 --></span>
<span class="hljs-tag"><<span class="hljs-title">mvc:interceptors</span>></span>
    <span class="hljs-comment"><!--多个拦截器,顺序执行 --></span>
    <span class="hljs-comment"><!-- 登陆认证拦截器 --></span>
    <span class="hljs-tag"><<span class="hljs-title">mvc:interceptor</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">mvc:mapping</span> <span class="hljs-attribute">path</span>=<span class="hljs-value">"/**"</span>/></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"cn.itcast.ssm.interceptor.LoginInterceptor"</span>></span><span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">mvc:interceptor</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">mvc:interceptor</span>></span>
        <span class="hljs-comment"><!-- /**表示所有url包括子url路径 --></span>
        <span class="hljs-tag"><<span class="hljs-title">mvc:mapping</span> <span class="hljs-attribute">path</span>=<span class="hljs-value">"/**"</span>/></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"cn.itcast.ssm.interceptor.HandlerInterceptor1"</span>></span><span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">mvc:interceptor</span>></span>
    <span class="hljs-tag"><<span class="hljs-title">mvc:interceptor</span>></span>
        <span class="hljs-tag"><<span class="hljs-title">mvc:mapping</span> <span class="hljs-attribute">path</span>=<span class="hljs-value">"/**"</span>/></span>
        <span class="hljs-tag"><<span class="hljs-title">bean</span> <span class="hljs-attribute">class</span>=<span class="hljs-value">"cn.itcast.ssm.interceptor.HandlerInterceptor2"</span>></span><span class="hljs-tag"></<span class="hljs-title">bean</span>></span>
    <span class="hljs-tag"></<span class="hljs-title">mvc:interceptor</span>></span>
<span class="hljs-tag"></<span class="hljs-title">mvc:interceptors</span>></span></code><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li></ul><ul style="" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li></ul>

根据测试结果,对拦截器应用。

比如:统一日志处理拦截器,需要该 拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。

比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)

参考文献

http://v.itcast.cn/course/8.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值