“SpringMVC:开发基础”的版本间差异

来自Wikioe
跳到导航 跳到搜索
(建立内容为“category:SpringMVC”的新页面)
 
 
(未显示同一用户的38个中间版本)
第1行: 第1行:
[[category:SpringMVC]]
[[category:SpringMVC]]
== 基础 ==
SpringMVC框架是一个开源的Java平台,属于[[Spring框架 Spring]]的一部分,是一个轻量级的web框架。<br/>
(Spring框架最初由Rod Johnson撰写,并于2003年6月根据Apache 2.0许可证首次发布。)<br/>
SpringMVC在三层架构(表示层UI、业务逻辑层BLL、持久层DAL)中处于表示层。
=== MVC ===
MVC框架用于开发灵活和松散耦合的Web应用程序的组件:
# 模型(Model):封装了应用程序数据,通常它们将由POJO(<code>Plain Ordinary Java Object</code>简单Java对象,即区别于EJB的普通JavaBean)类组成。
#: <code>pojo</code>、<code>action</code>、<code>service</code>、<code>dao</code>
# 视图(View):负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。
#: <code>jsp</code>、<code>pdf</code>、<code>excel</code>、<code>framework</code>
# 控制器(Controller):负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。
#: struts2中的<code>filter</code>
=== 架构 ===
{| class="wikitable"
|-
|
# 用户发送请求至'''<code>DispatcherServlet</code>''';
# '''<code>DispatcherServlet</code>'''收到请求调用'''<code>HandlerMapping</code>''';
# '''<code>HandlerMapping</code>'''根据请求'''<code>url</code>'''找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给'''<code>DispatcherServlet</code>''';
# '''<code>DispatcherServlet</code>'''通过'''<code>HandlerAdapter</code>'''调用处理器;
# 执行'''<code>Controller</code>''';
# '''<code>Controller</code>'''执行完成返回'''<code>ModelAndView</code>''';
# '''<code>HandlerAdapter</code>'''将'''<code>controller</code>'''执行结果'''<code>ModelAndView</code>'''返回给'''<code>DispatcherServlet</code>''';
# '''<code>DispatcherServlet</code>'''将'''<code>ModelAndView</code>'''传给'''<code>ViewReslover</code>'''视图解析器;
# '''<code>ViewReslover</code>'''解析后返回具体'''<code>View</code>''';
# '''<code>DispatcherServlet</code>'''对View进行渲染视图(即将模型数据填充至视图中);
# '''<code>DispatcherServlet</code>'''响应用户;
|
[[File:springMVC架构.png|800px]]
|}
=== 依赖包 ===
springMVC属于spring的一个部分,所以需要spring包的支持:
[[File:spring3.2.0的jar包.png|none|250px]]
=== 组件 ===
# '''<code>DispatcherServlet</code>'''(前端控制器):作用接收请求,响应结果,相当于转发器、中央处理器,减少其它组件之间的耦合度;
# '''<code>HandlerMapping</code>'''(处理器映射器):根据请求的url查找Handler;
# '''<code>HandlerAdapter</code>'''(处理器适配器):按照特定规则(<code>HandlerAdapter</code>要求的规则)去执行<code>Handler</code>;
# '''<code>Handler</code>'''(Controller:处理器):编写<code>Handler</code>时按照<code>HandlerAdapter</code>的要求去做,这样适配器才可以去正确执行<code>Handler</code>;
# '''<code>ViewReslover</code>'''(视图解析器):进行视图解析,根据逻辑视图名解析成真正的视图(<code>view</code>);
# '''<code>View</code>'''(视图):<code>View</code>是一个接口,实现类支持不同的视图类型(<code>jsp</code>、<code>pdf</code>、<code>excel</code>、<code>framework</code>);
=== 配置文件 ===
{| class="wikitable"
|-
! 配置文件 !! 说明 !! 图
|-
| web.xml
|
# 位置:“WEB-INF\web.xml”;
# 用于:配置'''<code>Filter</code>'''、'''<code>Listener</code>'''、'''<code>Servlet等</code>'''及Servlet拦截方式等;('''<code>DispatcherServlet</code>''')
| rowspan="2" | [[File:springMVC配置文件.png|300px]]
|-
| springmvc.xml
|
# 位置:默认加载'''<code>WEB-INF/[前端控制器的名字]-servlet.xml</code>''',也可以在前端控制器定义处指定加载的配置文件;
# 用于:配置'''<code>HandlerMapping</code>'''、'''<code>HandlerAdapter</code>'''、'''<code>Handler</code>'''(组件扫描)、'''<code>ViewResolver</code>'''等;
|}
==== web.xml示例 ====
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<!-- Web应用名称 -->
<display-name>springmvcfirst1208</display-name>
 
<!-- springmvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器、适配器等等)
如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml)
-->
<init-param>
<!-- 指定加载的配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
</servlet>
 
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--
第一种:*.action,访问以.action结尾 由DispatcherServlet进行解析
第二种:/,除jsp之外的全拦截。所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析
使用此种方式可以实现 RESTful风格的url
第三种:/*,真的全拦截。这样配置不对,使用这种配置,最终要转发到一个jsp页面时,
仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错。
-->
<url-pattern>*.action</url-pattern>
</servlet-mapping>
 
<!-- post乱码过虑器 -->
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
 
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
</syntaxhighlight>
==== springmvc.xml示例 ====
<syntaxhighlight lang="xml">
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 可以扫描controller、service、... 这里让扫描controller,指定controller的包 -->
<context:component-scan
base-package="cn.itcast.ssm.controller"></context:component-scan>
<!--注解映射器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->
<!--注解适配器 -->
<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->
<!-- 使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置 mvc:annotation-driven默认加载很多的参数绑定方法,
比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter
实际开发时使用mvc:annotation-driven -->
<mvc:annotation-driven
conversion-service="conversionService"></mvc:annotation-driven>
<!-- 视图解析器 解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 配置jsp路径的前缀 -->
<property name="prefix" value="/WEB-INF/jsp/" />
<!-- 配置jsp路径的后缀 -->
<property name="suffix" value=".jsp" />
</bean>
<!-- 自定义参数绑定 -->
<bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 转换器 -->
<property name="converters">
<list>
<!-- 日期类型转换 -->
<bean
class="cn.itcast.ssm.controller.converter.CustomDateConverter" />
</list>
</property>
</bean>
</beans>
</syntaxhighlight>
== 开发基础 ==
=== 建立项目 ===
Eclipse:Dynamic Web Project
=== 导入依赖包 ===
springmvc独立运行需要的jar:
# <code>commons-logging-1.1.1.jar</code>
# <code>jstl-1.2.jar</code>
# <code>spring-aop-3.2.0.RELEASE.jar</code>
# <code>spring-aspects-3.2.0.RELEASE.jar</code>
# <code>spring-beans-3.2.0.RELEASE.jar</code>
# <code>spring-context-3.2.0.RELEASE.jar</code>
# <code>spring-context-support-3.2.0.RELEASE.jar</code>
# <code>spring-core-3.2.0.RELEASE.jar</code>
# <code>spring-expression-3.2.0.RELEASE.jar</code>
# <code>spring-jdbc-3.2.0.RELEASE.jar</code>
# <code>spring-orm-3.2.0.RELEASE.jar</code>
# <code>spring-test-3.2.0.RELEASE.jar</code>
# <code>spring-tx-3.2.0.RELEASE.jar</code>
# <code>spring-web-3.2.0.RELEASE.jar</code>
# <code>spring-webmvc-3.2.0.RELEASE.jar</code>
=== 配置DispatcherServlet ===
(关于[[servlet]])<br/>
在'''<code>web.xml</code>'''中配置前端控制器:
<syntaxhighlight lang="xml">
<!-- springmvc前端控制器 -->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 指定加载的配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
 
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>
</syntaxhighlight>
其中:
# '''<code>contextConfigLocation</code>''':配置<code>springmvc</code>加载的配置文件(配置处理器映射器、适配器等等);
#: 如果不配置<code>contextConfigLocation</code>,默认加载的是'''<code>/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml)</code>''';
# '''<code>load-on-startup</code>''':表示容器启动优先级:
#: 当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
#: 非负数时,值越小优先级越高;
#: 负数时或未指定时,则指示容器在该servlet被选择时才加载;
<br/>
<code>DispathcerServlet</code>作为<code>springmvc</code>的中央调度器存在,<code>DispatcherServlet</code>创建时会默认从<code>DispatcherServlet.properties</code>(“Dspring-webmvc-3.2.0.RELEASE.jar”>>“org.springframework.web.servlet”>>“DispatcherServlet.properties”)文件加载<code>springmvc</code>所用的各各组件,如果在<code>springmvc.xml</code>中配置了组件则以<code>springmvc.xml</code>中配置的为准,<code>DispatcherServlet</code>的存在降低了<code>springmvc</code>各各组件之间的耦合度。<br/>
<br/>
DispatcherServlet.properties:
<syntaxhighlight lang="xml">
# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.
org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager
</syntaxhighlight>
==== Servlet拦截方式 ====
# '''<code>*.action</code>''':拦截固定后缀的<code>url</code>(如<code>*.do</code>、<code>*.action</code>),由DispatcherServlet进行解析;
#: 例如:<code>/user/add.action</code>,此方法最简单,不会导致静态资源(<code>jpg</code>、<code>js</code>、<code>css</code>)被拦截。
# '''<code>/</code>''':除jsp之外的全拦截。所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析;
#: (此方法可以实现<code>REST</code>风格的<code>url</code>)
#: 例如:<code>/user/add</code>、<code>/user/add.action</code>,但是会导致静态文件(<code>jpg</code>、<code>js</code>、<code>css</code>)被拦截后不能正常显示,需要特殊处理。
# '''<code>/*</code>''':全拦截;
#: 使用这种配置,最终要转发到一个<code>jsp</code>页面时,仍然会由<code>DispatcherServlet</code>解析<code>jsp</code>地址,不能根据<code>jsp</code>页面找到<code>handler</code>,会报错;
=== 配置 HandlerMapping ===
<code>HandlerMapping</code> 负责根据<code>request</code>请求找到对应的<code>Handler</code>处理器及<code>Interceptor</code>拦截器,将它们封装在<code>HandlerExecutionChain</code>对象中给前端控制器(DispatcherServlet)返回。<br/>
所有的映射器都实现'''<code>HandlerMapping</code>'''接口:
==== 非注解 ====
===== BeanNameUrlHandlerMapping =====
根据请求的url与spring容器中定义的bean的name进行匹配,从而从spring容器中找到bean实例。
<syntaxhighlight lang="xml">
<!-- 处理器映射器 将bean的name作为url进行查找 ,需要在配置Handler时指定beanname(就是url)
所有的映射器都实现 HandlerMapping接口。
-->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
</syntaxhighlight>
# 配置<code>Handler</code>时需要指定<code>name</code>属性,<code>BeanNameUrlHandlerMapping</code>会将<code>bean</code>的<code>name</code>作为<code>url</code>进行查找;
===== 简单url映射 =====
BeanNameUrlHandlerMapping的增强版本,它可以将url和处理器bean的id进行统一映射配置。
<syntaxhighlight lang="xml">
<!--简单url映射  -->
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<!-- 对itemsController1进行url映射,url是/queryItems1.action -->
<prop key="/queryItems1.action">itemsController1</prop>
<prop key="/queryItems2.action">itemsController1</prop>
<prop key="/queryItems3.action">itemsController2</prop>
</props>
</property>
</bean>
</syntaxhighlight>
==== 注解映射器 ====
注解式处理器映射器,对类中标记<code>@ResquestMapping</code>的方法进行映射,根据<code>ResquestMapping</code>定义的<code>url</code>匹配<code>ResquestMapping</code>标记的方法,匹配成功返回<code>HandlerMethod</code>对象给前端控制器,<code>HandlerMethod</code>对象中封装<code>url</code>对应的方法<code>Method</code>。
<syntaxhighlight lang="xml">
<!--注解映射器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
</syntaxhighlight>
# 与注解适配器'''<code>RequestMappingHandlerAdapter</code>'''搭配使用。
# 从spring3.1版本开始,废除了<code>DefaultAnnotationHandlerMapping</code>的使用,推荐使用<code>RequestMappingHandlerMapping</code>完成注解式处理器映射。
=== 配置 HandlerAdapter ===
<code>HandlerAdapter</code>会根据适配器接口对后端控制器进行包装(适配),包装后即可对处理器进行执行,通过扩展处理器适配器可以执行多种类型的处理器,这里使用了适配器设计模式。<br/>
所有处理器适配器都实现'''<code>HandlerAdapter</code>'''接口:
==== 非注解 ====
===== SimpleControllerHandlerAdapter =====
简单控制器处理器适配器,所有实现了'''<code>org.springframework.web.servlet.mvc.Controller</code>'''接口的Bean通过此适配器进行适配、执行。
<syntaxhighlight lang="xml">
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" />
</syntaxhighlight>
===== HttpRequestHandlerAdapter =====
<code>http</code>请求处理器适配器,所有实现了'''<code>org.springframework.web.HttpRequestHandler</code>'''接口的Bean通过此适配器进行适配、执行。
<syntaxhighlight lang="xml">
<bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
</syntaxhighlight>
Controller实现如下:
<syntaxhighlight lang="java">
public class ItemList2 implements HttpRequestHandler {
@Override
public void handleRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 商品列表
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone5  苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
// 填充数据
request.setAttribute("itemsList", itemsList);
// 视图
request.getRequestDispatcher("/WEB-INF/jsp/order/itemsList.jsp").forward(request, response);
}
}
</syntaxhighlight>
从上边可以看出此适配器器的<code>handleRequest</code>方法没有返回<code>ModelAndView</code>,可通过<code>response</code>修改定义响应内容,比如返回json数据:
<syntaxhighlight lang="java">
response.setCharacterEncoding("utf-8");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write("json串");
</syntaxhighlight>
==== 注解适配器 ====
<syntaxhighlight lang="xml">
<!--注解适配器 -->
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
</syntaxhighlight>
# 与注解映射器'''<code>RequestMappingHandlerMapping</code>'''搭配使用。
# 从spring3.1版本开始,废除了<code>AnnotationMethodHandlerAdapter</code>的使用,推荐使用<code>RequestMappingHandlerAdapter</code>完成注解式处理器适配。
=== <mvc:annotation-driven>使用 ===
<code><mvc:annotation-driven></code>会自动注册<code>RequestMappingHandlerMapping</code>、<code>RequestMappingHandlerAdapter</code>及<code>ExceptionHandlerResolver</code>,以支持使用带注释(如<nowiki>@RequestMapping</nowiki>、<nowiki>@ExceptionHandler</nowiki>)的控制器方法处理请求;<br/>
<pre>
It also enables the following:
Spring 3 style type conversion through a ConversionService instance in addition to the JavaBeans PropertyEditors used for Data Binding.
Support for formatting Number fields using the @NumberFormat annotation through the ConversionService.
Support for formatting Date, Calendar, Long, and Joda Time fields using the @DateTimeFormat annotation.
Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath.
HttpMessageConverter support for @RequestBody method parameters and @ResponseBody method return values from @RequestMapping or @ExceptionHandler methods.
并且提供了:
除了用于数据绑定的JavaBeans属性编辑器之外,还通ConversionService实例进行spring3样式的类型转换。(即:类型转换,编写ConversionService,配置conversion-service)
支持通过转换服务(ConversionService)使用@NumberFormat注释来格式化数字字段。(即:格式化数字,使用@NumberFormat)
支持使用@DateTimeFormat注释来格式化日期、日历、Long和Joda时间字段。(即:格式化日期时间,使用@DateTimeFormat)
如果在classpath中存在JSR-303 Provider,支持使用@Valid注释来验证@Controller的输入是否有效。(即:输入验证,使用@Valid)
HttpMessageConverter支持@RequestBody方法参数和@ResponseBody方法来自于@RequestMapping或@ExceptionHandler方法的返回值。(即:读写JSON的支持,使用@RequestBody、@ResponseBody)
</pre>
即:
# 支持使用 ConversionService 实例对表单参数进行类型转换
# 支持使用 @NumberFormat annotation、@DateTimeFormat注解完成数据类型的格式化
# 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
# 支持使用 @RequestBody 和 @ResponseBody 注解
<syntaxhighlight lang="xml">
<mvc:annotation-driven />
</syntaxhighlight>
<syntaxhighlight lang="xml">
<mvc:annotation-driven conversion-service="conversionService" validator="validator">
</mvc:annotation-driven>
</syntaxhighlight>
=== 配置 Handler ===
==== Handler配置 ====
<syntaxhighlight lang="xml">
<!-- 配置Handler -->
<bean id="itemsController1" name="/queryItems_test.action" class="cn.itcast.ssm.controller.ItemsController1" />
<bean id="itemsController2" class="cn.itcast.ssm.controller.ItemsController2" />
</syntaxhighlight>
# 用于单个Handler的配置;
# 仅配置Handler,映射在<code>HandlerMapping</code>配置;
# <code>name="/items1.action"</code>:使用<code>BeanNameUrlHandlerMapping</code>会将bean的name作为url进行查找,需要指定<code>name</code>属性;
==== 组件扫描 ====
使用<context:component-scan>自动扫描标记@controller的控制器类:
<syntaxhighlight lang="xml">
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
</syntaxhighlight>
# 开发中建议使用组件扫描;
# 可以扫描的组件:controller、service、...;
# <code>base-package</code>:指定扫描位置;
=== 配置 ViewReslover ===
# 无论请求处理方法的返回值类型是String、View或ModelMap,SpringMVC均会将其装配为ModelAndView对象,其包含逻辑视图的名称和模型对象信息;
# SpringMVC借助视图解析器(ViewResolver)获取最终的物理制图对象,其可以是JSP页面、Excel或JFreeChart等各种表现形式的视图;
# 视图解析器:将逻辑视图解析为物理视图;
<syntaxhighlight lang="xml">
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</syntaxhighlight>
# <code>InternalResourceViewResolver</code>:使用<code>InternalResourceViewResolver</code>作为视图解析器;
#: <code>InternalResourceViewResolver</code>支持<code>JSP</code>视图解析,SpringMVC会将逻辑视图解析为<code>InternalResourceView</code>对象;
# <code>viewClass</code>:指定视图对象类型;(不指定时,Jsp视图解析器默认使用jstl)
#: <code>JstlView</code>表示<code>JSP</code>模板页面需要使用<code>JSTL</code>标签库,所以<code>classpath</code>中必须包含<code>jstl</code>的相关jar 包;
# <code>prefix</code>、<code>suffix</code>:查找视图页面的前缀和后缀,最终视图的址为:“前缀+逻辑视图名+后缀”;
#: 逻辑视图名需要在<code>controller</code>中返回<code>ModelAndView</code>指定,如逻辑视图名为hello,则最终返回的jsp视图地址“WEB-INF/jsp/hello.jsp”;
=== Handler开发 ===
==== 非注解 ====
# 使用不同的HandlerAdapter(SimpleControllerHandlerAdapter、HttpRequestHandlerAdapter)需要Handler实现不同的接口(Controller、HttpRequestHandler);
# ModelAndView:包含了模型数据及逻辑视图名;
<syntaxhighlight lang="java">
public class ItemList1 implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) throws Exception {
//商品列表
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
//创建modelAndView准备填充数据、设置视图
ModelAndView modelAndView = new ModelAndView();
//填充数据
modelAndView.addObject("itemsList", itemsList);
//视图
modelAndView.setViewName("order/itemsList");
return modelAndView;
}
}
</syntaxhighlight>
==== 注解 ====
# 注解的Handler需要使用配对的HandlerMapping与HandlerAdapter(RequestMappingHandlerMapping、RequestMappingHandlerAdapter);
# 使用<code>@Controller</code>与<code>@RequestMapping("/queryItem.action")</code>进行注解说明,替换接口继承和映射配置;
# <code>@RequestMapping</code>:定义请求url到处理器功能方法的映射;
<syntaxhighlight lang="java">
@Controller
public class ItemList3 {
@RequestMapping("/queryItem.action")
public ModelAndView queryItem() {
// 商品列表
List<Items> itemsList = new ArrayList<Items>();
Items items_1 = new Items();
items_1.setName("联想笔记本");
items_1.setPrice(6000f);
items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
Items items_2 = new Items();
items_2.setName("苹果手机");
items_2.setPrice(5000f);
items_2.setDetail("iphone6苹果手机!");
itemsList.add(items_1);
itemsList.add(items_2);
// 创建modelAndView准备填充数据、设置视图
ModelAndView modelAndView = new ModelAndView();
// 填充数据
modelAndView.addObject("itemsList", itemsList);
// 视图
modelAndView.setViewName("order/itemsList");
return modelAndView;
}
}
</syntaxhighlight>
=== View开发 ===
创建视图页面“/WEB-INF/jsp/order/itemsList.jsp”:<br/>
(jsp放在WEB-INF下面,直接访问jsp发现找不到,避免直接访问jsp页面)
<syntaxhighlight lang="xml">
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>查询商品列表</title>
</head>
<body>
<form action="${pageContext.request.contextPath }/item/queryItem.action" method="post">
查询条件:
<table width="100%" border=1>
<tr>
<td><input type="submit" value="查询"/></td>
</tr>
</table>
商品列表:
<table width="100%" border=1>
<tr>
<td>商品名称</td>
<td>商品价格</td>
<td>生产日期</td>
<td>商品描述</td>
<td>操作</td>
</tr>
<c:forEach items="${itemsList }" var="item">
<tr>
<td>${item.name }</td>
<td>${item.price }</td>
<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
<td>${item.detail }</td>
<td><a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a></td>
</tr>
</c:forEach>
</table>
</form>
</body>
</html>
</syntaxhighlight>
=== 部署与测试 ===
部署到Tomcat,并通过<code>http://localhost:8080/springmvc_first/items1.action</code>进行访问,其中:
# <code>springmvc_first</code>:项目名称;
# <code>items1.action</code>:url映射;
== 与[[Struts2]]的区别 ==
{| class="wikitable"
|-
! SpringMVC !! Struts2
|-
| 入口是一个[[servlet]]即前端控制器
| 入口是一个[[filter]]过虑器
|-
| 基于'''方法'''开发(一个url对应Handler的一个方法),
| 基于'''类'''开发(一个url对应于一个Controller),
|-
| 通过方法的形参接收请求参数(),既可以是'''单例(建议)也可以是多例'''
| 通过类的成员变量接收参数,无法使用单例,'''只能使用多例'''
|-
|
# 通过'''参数解析器'''来解析request请求内容
# 通过将数据和视图封装成'''ModelAndView对象''',将ModelAndView中的模型数据通过reques域传输到页面进行响应
| 采用'''值栈'''存储请求和响应的数据,通过'''OGNL'''存取数据
|}
* springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括了一个method。方法执行结束,形参数据销毁【???】。

2020年10月6日 (二) 17:01的最新版本


基础

SpringMVC框架是一个开源的Java平台,属于Spring框架 Spring的一部分,是一个轻量级的web框架。
(Spring框架最初由Rod Johnson撰写,并于2003年6月根据Apache 2.0许可证首次发布。)
SpringMVC在三层架构(表示层UI、业务逻辑层BLL、持久层DAL)中处于表示层。

MVC

MVC框架用于开发灵活和松散耦合的Web应用程序的组件:

  1. 模型(Model):封装了应用程序数据,通常它们将由POJO(Plain Ordinary Java Object简单Java对象,即区别于EJB的普通JavaBean)类组成。
    pojoactionservicedao
  2. 视图(View):负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。
    jsppdfexcelframework
  3. 控制器(Controller):负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。
    struts2中的filter

架构

  1. 用户发送请求至DispatcherServlet
  2. DispatcherServlet收到请求调用HandlerMapping
  3. HandlerMapping根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet
  4. DispatcherServlet通过HandlerAdapter调用处理器;
  5. 执行Controller
  6. Controller执行完成返回ModelAndView
  7. HandlerAdaptercontroller执行结果ModelAndView返回给DispatcherServlet
  8. DispatcherServletModelAndView传给ViewReslover视图解析器;
  9. ViewReslover解析后返回具体View
  10. DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中);
  11. DispatcherServlet响应用户;

SpringMVC架构.png

依赖包

springMVC属于spring的一个部分,所以需要spring包的支持:

Spring3.2.0的jar包.png

组件

  1. DispatcherServlet(前端控制器):作用接收请求,响应结果,相当于转发器、中央处理器,减少其它组件之间的耦合度;
  2. HandlerMapping(处理器映射器):根据请求的url查找Handler;
  3. HandlerAdapter(处理器适配器):按照特定规则(HandlerAdapter要求的规则)去执行Handler
  4. Handler(Controller:处理器):编写Handler时按照HandlerAdapter的要求去做,这样适配器才可以去正确执行Handler
  5. ViewReslover(视图解析器):进行视图解析,根据逻辑视图名解析成真正的视图(view);
  6. View(视图):View是一个接口,实现类支持不同的视图类型(jsppdfexcelframework);

配置文件

配置文件 说明
web.xml
  1. 位置:“WEB-INF\web.xml”;
  2. 用于:配置FilterListenerServlet等及Servlet拦截方式等;(DispatcherServlet
SpringMVC配置文件.png
springmvc.xml
  1. 位置:默认加载WEB-INF/[前端控制器的名字]-servlet.xml,也可以在前端控制器定义处指定加载的配置文件;
  2. 用于:配置HandlerMappingHandlerAdapterHandler(组件扫描)、ViewResolver等;

web.xml示例

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
	<!-- Web应用名称 -->
	<display-name>springmvcfirst1208</display-name>
  
	<!-- springmvc前端控制器 -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<!-- contextConfigLocation配置springmvc加载的配置文件(配置处理器映射器、适配器等等)
		如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml)
		 -->
		<init-param>
			<!-- 指定加载的配置文件 -->
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
	</servlet>
	  
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<!-- 
		第一种:*.action,访问以.action结尾 由DispatcherServlet进行解析
		第二种:/,除jsp之外的全拦截。所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析
		使用此种方式可以实现 RESTful风格的url
		第三种:/*,真的全拦截。这样配置不对,使用这种配置,最终要转发到一个jsp页面时,
		仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错。
		 -->
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>
	  
	<!-- post乱码过虑器 -->
	<filter>
		<filter-name>CharacterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
			<init-param>
				<param-name>encoding</param-name>
				<param-value>utf-8</param-value>
			</init-param>
	</filter>
	<filter-mapping>
		<filter-name>CharacterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	  
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>

springmvc.xml示例

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
		http://www.springframework.org/schema/mvc 
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
		http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context-3.2.xsd 
		http://www.springframework.org/schema/aop 
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
		http://www.springframework.org/schema/tx 
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">

	<!-- 可以扫描controller、service、... 这里让扫描controller,指定controller的包 -->
	<context:component-scan
		base-package="cn.itcast.ssm.controller"></context:component-scan>


	<!--注解映射器 -->
	<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> -->
	<!--注解适配器 -->
	<!-- <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/> -->

	<!-- 使用 mvc:annotation-driven代替上边注解映射器和注解适配器配置 mvc:annotation-driven默认加载很多的参数绑定方法, 
		比如json转换解析器就默认加载了,如果使用mvc:annotation-driven不用配置上边的RequestMappingHandlerMapping和RequestMappingHandlerAdapter 
		实际开发时使用mvc:annotation-driven -->
	<mvc:annotation-driven
		conversion-service="conversionService"></mvc:annotation-driven>


	<!-- 视图解析器 解析jsp解析,默认使用jstl标签,classpath下的得有jstl的包 -->
	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<!-- 配置jsp路径的前缀 -->
		<property name="prefix" value="/WEB-INF/jsp/" />
		<!-- 配置jsp路径的后缀 -->
		<property name="suffix" value=".jsp" />
	</bean>

	<!-- 自定义参数绑定 -->
	<bean id="conversionService"
		class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
		<!-- 转换器 -->
		<property name="converters">
			<list>
				<!-- 日期类型转换 -->
				<bean
					class="cn.itcast.ssm.controller.converter.CustomDateConverter" />
			</list>
		</property>
	</bean>
</beans>

开发基础

建立项目

Eclipse:Dynamic Web Project

导入依赖包

springmvc独立运行需要的jar:

  1. commons-logging-1.1.1.jar
  2. jstl-1.2.jar
  3. spring-aop-3.2.0.RELEASE.jar
  4. spring-aspects-3.2.0.RELEASE.jar
  5. spring-beans-3.2.0.RELEASE.jar
  6. spring-context-3.2.0.RELEASE.jar
  7. spring-context-support-3.2.0.RELEASE.jar
  8. spring-core-3.2.0.RELEASE.jar
  9. spring-expression-3.2.0.RELEASE.jar
  10. spring-jdbc-3.2.0.RELEASE.jar
  11. spring-orm-3.2.0.RELEASE.jar
  12. spring-test-3.2.0.RELEASE.jar
  13. spring-tx-3.2.0.RELEASE.jar
  14. spring-web-3.2.0.RELEASE.jar
  15. spring-webmvc-3.2.0.RELEASE.jar

配置DispatcherServlet

(关于servlet
web.xml中配置前端控制器:

	<!-- springmvc前端控制器 -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<!-- 指定加载的配置文件 -->
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	  
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.action</url-pattern>
	</servlet-mapping>

其中:

  1. contextConfigLocation:配置springmvc加载的配置文件(配置处理器映射器、适配器等等);
    如果不配置contextConfigLocation,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml);
  2. load-on-startup:表示容器启动优先级:
    当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
    非负数时,值越小优先级越高;
    负数时或未指定时,则指示容器在该servlet被选择时才加载;


DispathcerServlet作为springmvc的中央调度器存在,DispatcherServlet创建时会默认从DispatcherServlet.properties(“Dspring-webmvc-3.2.0.RELEASE.jar”>>“org.springframework.web.servlet”>>“DispatcherServlet.properties”)文件加载springmvc所用的各各组件,如果在springmvc.xml中配置了组件则以springmvc.xml中配置的为准,DispatcherServlet的存在降低了springmvc各各组件之间的耦合度。

DispatcherServlet.properties:

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver

org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
	org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping

org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\
	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter

org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\
	org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
	org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator

org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver

org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

Servlet拦截方式

  1. *.action:拦截固定后缀的url(如*.do*.action),由DispatcherServlet进行解析;
    例如:/user/add.action,此方法最简单,不会导致静态资源(jpgjscss)被拦截。
  2. /:除jsp之外的全拦截。所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析;
    (此方法可以实现REST风格的url
    例如:/user/add/user/add.action,但是会导致静态文件(jpgjscss)被拦截后不能正常显示,需要特殊处理。
  3. /*:全拦截;
    使用这种配置,最终要转发到一个jsp页面时,仍然会由DispatcherServlet解析jsp地址,不能根据jsp页面找到handler,会报错;

配置 HandlerMapping

HandlerMapping 负责根据request请求找到对应的Handler处理器及Interceptor拦截器,将它们封装在HandlerExecutionChain对象中给前端控制器(DispatcherServlet)返回。
所有的映射器都实现HandlerMapping接口:

非注解

BeanNameUrlHandlerMapping

根据请求的url与spring容器中定义的bean的name进行匹配,从而从spring容器中找到bean实例。

	<!-- 处理器映射器 将bean的name作为url进行查找 ,需要在配置Handler时指定beanname(就是url) 
		所有的映射器都实现 HandlerMapping接口。
	-->
	<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
  1. 配置Handler时需要指定name属性,BeanNameUrlHandlerMapping会将beanname作为url进行查找;
简单url映射

BeanNameUrlHandlerMapping的增强版本,它可以将url和处理器bean的id进行统一映射配置。

	<!--简单url映射  -->
	<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
		<property name="mappings">
			<props>
				<!-- 对itemsController1进行url映射,url是/queryItems1.action -->
				<prop key="/queryItems1.action">itemsController1</prop>
				<prop key="/queryItems2.action">itemsController1</prop>
				<prop key="/queryItems3.action">itemsController2</prop>
			</props>
		</property>
	</bean>

注解映射器

注解式处理器映射器,对类中标记@ResquestMapping的方法进行映射,根据ResquestMapping定义的url匹配ResquestMapping标记的方法,匹配成功返回HandlerMethod对象给前端控制器,HandlerMethod对象中封装url对应的方法Method

	<!--注解映射器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/>
  1. 与注解适配器RequestMappingHandlerAdapter搭配使用。
  2. 从spring3.1版本开始,废除了DefaultAnnotationHandlerMapping的使用,推荐使用RequestMappingHandlerMapping完成注解式处理器映射。

配置 HandlerAdapter

HandlerAdapter会根据适配器接口对后端控制器进行包装(适配),包装后即可对处理器进行执行,通过扩展处理器适配器可以执行多种类型的处理器,这里使用了适配器设计模式。
所有处理器适配器都实现HandlerAdapter接口:

非注解

SimpleControllerHandlerAdapter

简单控制器处理器适配器,所有实现了org.springframework.web.servlet.mvc.Controller接口的Bean通过此适配器进行适配、执行。

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

http请求处理器适配器,所有实现了org.springframework.web.HttpRequestHandler接口的Bean通过此适配器进行适配、执行。

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

Controller实现如下:

public class ItemList2 implements HttpRequestHandler {

	@Override
	public void handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		// 商品列表
		List<Items> itemsList = new ArrayList<Items>();

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

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

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

		// 填充数据
		request.setAttribute("itemsList", itemsList);
		
		// 视图
		request.getRequestDispatcher("/WEB-INF/jsp/order/itemsList.jsp").forward(request, response);
	}
}

从上边可以看出此适配器器的handleRequest方法没有返回ModelAndView,可通过response修改定义响应内容,比如返回json数据:

	response.setCharacterEncoding("utf-8");
	response.setContentType("application/json;charset=utf-8");
	response.getWriter().write("json串");

注解适配器

	<!--注解适配器 -->
	<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/>
  1. 与注解映射器RequestMappingHandlerMapping搭配使用。
  2. 从spring3.1版本开始,废除了AnnotationMethodHandlerAdapter的使用,推荐使用RequestMappingHandlerAdapter完成注解式处理器适配。

<mvc:annotation-driven>使用

<mvc:annotation-driven>会自动注册RequestMappingHandlerMappingRequestMappingHandlerAdapterExceptionHandlerResolver,以支持使用带注释(如@RequestMapping、@ExceptionHandler)的控制器方法处理请求;

It also enables the following:

Spring 3 style type conversion through a ConversionService instance in addition to the JavaBeans PropertyEditors used for Data Binding.
Support for formatting Number fields using the @NumberFormat annotation through the ConversionService.
Support for formatting Date, Calendar, Long, and Joda Time fields using the @DateTimeFormat annotation.
Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath.
HttpMessageConverter support for @RequestBody method parameters and @ResponseBody method return values from @RequestMapping or @ExceptionHandler methods.

并且提供了:

除了用于数据绑定的JavaBeans属性编辑器之外,还通ConversionService实例进行spring3样式的类型转换。(即:类型转换,编写ConversionService,配置conversion-service)
支持通过转换服务(ConversionService)使用@NumberFormat注释来格式化数字字段。(即:格式化数字,使用@NumberFormat)
支持使用@DateTimeFormat注释来格式化日期、日历、Long和Joda时间字段。(即:格式化日期时间,使用@DateTimeFormat)
如果在classpath中存在JSR-303 Provider,支持使用@Valid注释来验证@Controller的输入是否有效。(即:输入验证,使用@Valid)
HttpMessageConverter支持@RequestBody方法参数和@ResponseBody方法来自于@RequestMapping或@ExceptionHandler方法的返回值。(即:读写JSON的支持,使用@RequestBody、@ResponseBody)

即:

  1. 支持使用 ConversionService 实例对表单参数进行类型转换
  2. 支持使用 @NumberFormat annotation、@DateTimeFormat注解完成数据类型的格式化
  3. 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
  4. 支持使用 @RequestBody 和 @ResponseBody 注解
	<mvc:annotation-driven />
	<mvc:annotation-driven conversion-service="conversionService" validator="validator">
	</mvc:annotation-driven>

配置 Handler

Handler配置

	<!-- 配置Handler -->
	<bean id="itemsController1" name="/queryItems_test.action" class="cn.itcast.ssm.controller.ItemsController1" />
	<bean id="itemsController2" class="cn.itcast.ssm.controller.ItemsController2" />
  1. 用于单个Handler的配置;
  2. 仅配置Handler,映射在HandlerMapping配置;
  3. name="/items1.action":使用BeanNameUrlHandlerMapping会将bean的name作为url进行查找,需要指定name属性;

组件扫描

使用<context:component-scan>自动扫描标记@controller的控制器类:

	<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
  1. 开发中建议使用组件扫描;
  2. 可以扫描的组件:controller、service、...;
  3. base-package:指定扫描位置;

配置 ViewReslover

  1. 无论请求处理方法的返回值类型是String、View或ModelMap,SpringMVC均会将其装配为ModelAndView对象,其包含逻辑视图的名称和模型对象信息;
  2. SpringMVC借助视图解析器(ViewResolver)获取最终的物理制图对象,其可以是JSP页面、Excel或JFreeChart等各种表现形式的视图;
  3. 视图解析器:将逻辑视图解析为物理视图;
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
		<property name="prefix" value="/WEB-INF/jsp/"/>
		<property name="suffix" value=".jsp"/>
	</bean>
  1. InternalResourceViewResolver:使用InternalResourceViewResolver作为视图解析器;
    InternalResourceViewResolver支持JSP视图解析,SpringMVC会将逻辑视图解析为InternalResourceView对象;
  2. viewClass:指定视图对象类型;(不指定时,Jsp视图解析器默认使用jstl)
    JstlView表示JSP模板页面需要使用JSTL标签库,所以classpath中必须包含jstl的相关jar 包;
  3. prefixsuffix:查找视图页面的前缀和后缀,最终视图的址为:“前缀+逻辑视图名+后缀”;
    逻辑视图名需要在controller中返回ModelAndView指定,如逻辑视图名为hello,则最终返回的jsp视图地址“WEB-INF/jsp/hello.jsp”;

Handler开发

非注解

  1. 使用不同的HandlerAdapter(SimpleControllerHandlerAdapter、HttpRequestHandlerAdapter)需要Handler实现不同的接口(Controller、HttpRequestHandler);
  2. ModelAndView:包含了模型数据及逻辑视图名;
public class ItemList1 implements Controller {

	@Override
	public ModelAndView handleRequest(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		
		//商品列表
		List<Items> itemsList = new ArrayList<Items>();
		
		Items items_1 = new Items();
		items_1.setName("联想笔记本");
		items_1.setPrice(6000f);
		items_1.setDetail("ThinkPad T430 联想笔记本电脑!");
		
		Items items_2 = new Items();
		items_2.setName("苹果手机");
		items_2.setPrice(5000f);
		items_2.setDetail("iphone6苹果手机!");
		
		itemsList.add(items_1);
		itemsList.add(items_2);
		
		//创建modelAndView准备填充数据、设置视图
		ModelAndView modelAndView = new ModelAndView();
		
		//填充数据
		modelAndView.addObject("itemsList", itemsList);
		//视图
		modelAndView.setViewName("order/itemsList");
		
		return modelAndView;
	}
}

注解

  1. 注解的Handler需要使用配对的HandlerMapping与HandlerAdapter(RequestMappingHandlerMapping、RequestMappingHandlerAdapter);
  2. 使用@Controller@RequestMapping("/queryItem.action")进行注解说明,替换接口继承和映射配置;
  3. @RequestMapping:定义请求url到处理器功能方法的映射;
@Controller
public class ItemList3 {

	@RequestMapping("/queryItem.action")
	public ModelAndView queryItem() {
		// 商品列表
		List<Items> itemsList = new ArrayList<Items>();

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

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

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

		// 创建modelAndView准备填充数据、设置视图
		ModelAndView modelAndView = new ModelAndView();

		// 填充数据
		modelAndView.addObject("itemsList", itemsList);
		// 视图
		modelAndView.setViewName("order/itemsList");

		return modelAndView;
	}
}

View开发

创建视图页面“/WEB-INF/jsp/order/itemsList.jsp”:
(jsp放在WEB-INF下面,直接访问jsp发现找不到,避免直接访问jsp页面)

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>查询商品列表</title>
	</head>
	<body> 
		<form action="${pageContext.request.contextPath }/item/queryItem.action" method="post">
		查询条件:
			<table width="100%" border=1>
				<tr>
					<td><input type="submit" value="查询"/></td>
				</tr>
			</table>
		商品列表:
			<table width="100%" border=1>
				<tr>
					<td>商品名称</td>
					<td>商品价格</td>
					<td>生产日期</td>
					<td>商品描述</td>
					<td>操作</td>
				</tr>
				<c:forEach items="${itemsList }" var="item">
					<tr>
						<td>${item.name }</td>
						<td>${item.price }</td>
						<td><fmt:formatDate value="${item.createtime}" pattern="yyyy-MM-dd HH:mm:ss"/></td>
						<td>${item.detail }</td>
						<td><a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a></td>
					</tr>
				</c:forEach>
			</table>
		</form>
	</body>
</html>

部署与测试

部署到Tomcat,并通过http://localhost:8080/springmvc_first/items1.action进行访问,其中:

  1. springmvc_first:项目名称;
  2. items1.action:url映射;

Struts2的区别

SpringMVC Struts2
入口是一个servlet即前端控制器 入口是一个filter过虑器
基于方法开发(一个url对应Handler的一个方法), 基于开发(一个url对应于一个Controller),
通过方法的形参接收请求参数(),既可以是单例(建议)也可以是多例 通过类的成员变量接收参数,无法使用单例,只能使用多例
  1. 通过参数解析器来解析request请求内容
  2. 通过将数据和视图封装成ModelAndView对象,将ModelAndView中的模型数据通过reques域传输到页面进行响应
采用值栈存储请求和响应的数据,通过OGNL存取数据
  • springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括了一个method。方法执行结束,形参数据销毁【???】。