“SpringMVC:开发基础”的版本间差异
(建立内容为“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应用程序的组件:
- 模型(Model):封装了应用程序数据,通常它们将由POJO(
Plain Ordinary Java Object
简单Java对象,即区别于EJB的普通JavaBean)类组成。pojo
、action
、service
、dao
- 视图(View):负责渲染模型数据,一般来说它生成客户端浏览器可以解释HTML输出。
jsp
、pdf
、excel
、framework
- 控制器(Controller):负责处理用户请求并构建适当的模型,并将其传递给视图进行渲染。
- struts2中的
filter
- struts2中的
架构
|
依赖包
springMVC属于spring的一个部分,所以需要spring包的支持:
组件
DispatcherServlet
(前端控制器):作用接收请求,响应结果,相当于转发器、中央处理器,减少其它组件之间的耦合度;HandlerMapping
(处理器映射器):根据请求的url查找Handler;HandlerAdapter
(处理器适配器):按照特定规则(HandlerAdapter
要求的规则)去执行Handler
;Handler
(Controller:处理器):编写Handler
时按照HandlerAdapter
的要求去做,这样适配器才可以去正确执行Handler
;ViewReslover
(视图解析器):进行视图解析,根据逻辑视图名解析成真正的视图(view
);View
(视图):View
是一个接口,实现类支持不同的视图类型(jsp
、pdf
、excel
、framework
);
配置文件
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:
commons-logging-1.1.1.jar
jstl-1.2.jar
spring-aop-3.2.0.RELEASE.jar
spring-aspects-3.2.0.RELEASE.jar
spring-beans-3.2.0.RELEASE.jar
spring-context-3.2.0.RELEASE.jar
spring-context-support-3.2.0.RELEASE.jar
spring-core-3.2.0.RELEASE.jar
spring-expression-3.2.0.RELEASE.jar
spring-jdbc-3.2.0.RELEASE.jar
spring-orm-3.2.0.RELEASE.jar
spring-test-3.2.0.RELEASE.jar
spring-tx-3.2.0.RELEASE.jar
spring-web-3.2.0.RELEASE.jar
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>
其中:
contextConfigLocation
:配置springmvc
加载的配置文件(配置处理器映射器、适配器等等);- 如果不配置
contextConfigLocation
,默认加载的是/WEB-INF/servlet名称-serlvet.xml(springmvc-servlet.xml)
;
- 如果不配置
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拦截方式
*.action
:拦截固定后缀的url
(如*.do
、*.action
),由DispatcherServlet进行解析;- 例如:
/user/add.action
,此方法最简单,不会导致静态资源(jpg
、js
、css
)被拦截。
- 例如:
/
:除jsp之外的全拦截。所有访问的地址都由DispatcherServlet进行解析,对于静态文件的解析需要配置不让DispatcherServlet进行解析;- (此方法可以实现
REST
风格的url
) - 例如:
/user/add
、/user/add.action
,但是会导致静态文件(jpg
、js
、css
)被拦截后不能正常显示,需要特殊处理。
- (此方法可以实现
/*
:全拦截;- 使用这种配置,最终要转发到一个
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" />
- 配置
Handler
时需要指定name
属性,BeanNameUrlHandlerMapping
会将bean
的name
作为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"/>
- 与注解适配器
RequestMappingHandlerAdapter
搭配使用。 - 从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"/>
- 与注解映射器
RequestMappingHandlerMapping
搭配使用。 - 从spring3.1版本开始,废除了
AnnotationMethodHandlerAdapter
的使用,推荐使用RequestMappingHandlerAdapter
完成注解式处理器适配。
<mvc:annotation-driven>使用
<mvc:annotation-driven>
会自动注册RequestMappingHandlerMapping
、RequestMappingHandlerAdapter
及ExceptionHandlerResolver
,以支持使用带注释(如@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)
即:
- 支持使用 ConversionService 实例对表单参数进行类型转换
- 支持使用 @NumberFormat annotation、@DateTimeFormat注解完成数据类型的格式化
- 支持使用 @Valid 注解对 JavaBean 实例进行 JSR 303 验证
- 支持使用 @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" />
- 用于单个Handler的配置;
- 仅配置Handler,映射在
HandlerMapping
配置; name="/items1.action"
:使用BeanNameUrlHandlerMapping
会将bean的name作为url进行查找,需要指定name
属性;
组件扫描
使用<context:component-scan>自动扫描标记@controller的控制器类:
<context:component-scan base-package="cn.itcast.ssm.controller"></context:component-scan>
- 开发中建议使用组件扫描;
- 可以扫描的组件:controller、service、...;
base-package
:指定扫描位置;
配置 ViewReslover
- 无论请求处理方法的返回值类型是String、View或ModelMap,SpringMVC均会将其装配为ModelAndView对象,其包含逻辑视图的名称和模型对象信息;
- SpringMVC借助视图解析器(ViewResolver)获取最终的物理制图对象,其可以是JSP页面、Excel或JFreeChart等各种表现形式的视图;
- 视图解析器:将逻辑视图解析为物理视图;
<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>
InternalResourceViewResolver
:使用InternalResourceViewResolver
作为视图解析器;InternalResourceViewResolver
支持JSP
视图解析,SpringMVC会将逻辑视图解析为InternalResourceView
对象;
viewClass
:指定视图对象类型;(不指定时,Jsp视图解析器默认使用jstl)JstlView
表示JSP
模板页面需要使用JSTL
标签库,所以classpath
中必须包含jstl
的相关jar 包;
prefix
、suffix
:查找视图页面的前缀和后缀,最终视图的址为:“前缀+逻辑视图名+后缀”;- 逻辑视图名需要在
controller
中返回ModelAndView
指定,如逻辑视图名为hello,则最终返回的jsp视图地址“WEB-INF/jsp/hello.jsp”;
- 逻辑视图名需要在
Handler开发
非注解
- 使用不同的HandlerAdapter(SimpleControllerHandlerAdapter、HttpRequestHandlerAdapter)需要Handler实现不同的接口(Controller、HttpRequestHandler);
- 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;
}
}
注解
- 注解的Handler需要使用配对的HandlerMapping与HandlerAdapter(RequestMappingHandlerMapping、RequestMappingHandlerAdapter);
- 使用
@Controller
与@RequestMapping("/queryItem.action")
进行注解说明,替换接口继承和映射配置; @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
进行访问,其中:
springmvc_first
:项目名称;items1.action
:url映射;
与Struts2的区别
SpringMVC | Struts2 |
---|---|
入口是一个servlet即前端控制器 | 入口是一个filter过虑器 |
基于方法开发(一个url对应Handler的一个方法), | 基于类开发(一个url对应于一个Controller), |
通过方法的形参接收请求参数(),既可以是单例(建议)也可以是多例 | 通过类的成员变量接收参数,无法使用单例,只能使用多例 |
|
采用值栈存储请求和响应的数据,通过OGNL存取数据 |
- springmvc将url和controller方法映射。映射成功后springmvc生成一个Handler对象,对象中只包括了一个method。方法执行结束,形参数据销毁【???】。