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一定要放行,且将它放在拦截器链接中第一个位置。
比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)