模式-视图-控制器(MVC)是UI设计中常见的设计模式, 该模式区分应用程序中的模式、视图和控制器三个角色,消除了业务逻辑与UI的耦合。模式负责封装视图展示的应用数据。视图应该只显示数据,不包含任何业务逻辑。控制器负责接受用户请求并调用后端服务进行业务逻辑。处理之后,后端服务可能返回某些数据供视图显示。控制器收集这些数据并准备视图的显示模式。MVC模式的核心思想是分离业务逻辑与UI,使它们能够独立修改,互不影响。

对与Web端的开发,从最开始的CGI,model1,以及现在的由model2演化而来的Web MVC模式, 逐渐形成这三个角色的概念,servlet作为控制器,模型采用javabean的形式,而视图展示,我们常见的是jsp页面。springmvc也是服务到工作者模式的实现,DispatchServlet作为前端控制器,由处理映射器HandlerMapping管理处理器,视图解析器进行视图的管理,其还提供了强大的约定大于配置的契约式编程支持。如下图所示:

DispatcherServlet被称为调度servlet,也是所谓的前端控制器,每个web请求都会经过它,比便使它能管理整个请求处理过程。如图当一个web用户发送请求,前端控制器收到请求将其委托给其他解析器,映射处理器HandlerMapping会将请求映射成HandlerExecutionChain对象,其找到特定的页面控制器controller,而后处理适配器HandlerAdapter调用controller内的功能方法完成处理,返回一个ModelAndView对象,视图解析器ViewResolver将这种逻辑视图名转换为特定的view,view再根据model的模型数据进行渲染,最后返回给前端控制器,由其响应用户。

我们知道web程序都会有个入口点,而springmvc的核心是DispatcherServlet,其实质上也是HttpServlet的子类,该servlet默认使用WebApplicationContext作为上下文,其会引导容器加载spring的配置信息,如图一般如下:

<servlet>

        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

我们也可以添加该servlet的参数配置,当然spring为我们提供了默认配置,contextClass默认使用XmlApplicationContext作为WebApplicationContext的接口,contextConfigLocation指定需要加载其他配置文件的地方,默认会在classpath里寻找[servletName]-servlet.xml的文件,我们可以自己contextConfigLocation里添加配置文件指定要添加的配置信息。

简单使用:我们进行springmvc进行web开发时,一般有两种方式。

我们可以自己实现Controller接口,然后自己编写我们自己的逻辑,然后这样会很复杂。我们可以根据的自己的需求实现和修改相应的类,下图展示类的层次结构:

如上图的各个类,现在该方式不推荐使用了。spring2.5之后增加了注解功能,spring3.0以后又丰富了注解的使用,该方法已成为事实上的标准了。

我们只需要简单地添加@Controlller,@RequestMapping等就可以指定相关的设置了,当然前提是我们需要使程序认得我们的设置,通过<context:component-scan>元素开启Spring的自动检测注解的组件扫描功能,还要在上下文中注册一个DefaultAnnotationHandlerMapping和一个AnnotationMethodHandlerAdapter实例处理@RequestMapping注解。如下:

<context:component-scan base-package="xxx.yyy.zzz"

        use-default-filters="false">
        <context:include-filter expression="org.springframework.stereotype.Controller"
            type="annotation" />
    </context:component-scan>
    <bean class="org.springframework.web.serlvet.mvc.annotation.DefaultAnnotationHandlerMapping"/>
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>

如果我们不开启组件扫描功能的话,需要在xml配置文件中,自己注入各个controller。上述配置的后两个bean,我们可以通过添加如下配置来替代他们:

<mvc:annotation-driven/>

使用注解的springmvc的controller的形式,大概如下:

@Controller

    @RequestMapping("/welcome")
    public class WelcomeController{
     @RequestMapping(method=RequestMethod.GET)
      public String welcome(Model model){
         Date today = new Date();
       model.addAttribute("today",today);
       return "welcome";
     } 

}

我们也可以直接定义Mapping的格式为 @RequestMapping(value="/welcome",method=RequestMethod.GET)。剩下的我们再配置一个视图解析器就可以了,springmvc支持很多不同表现技术的视图,使用较多的是jsp模板。如下一个简单配置:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

   	 <property name="prefix" value="/WEB-INF/jsp/" />
     <property name="suffix" value=".jsp" />

</bean>

请求映射,使用@RequestMapping注解,如下所示:

@RequestMapping("/member/add")

@RequestMapping(value={"/member/remove","/member/delete"},method=RequestMethod.GET)

@RequestMapping("/member/*") 这种一般配置Controller的。

@RequestMapping(“/member/display/{user}”) 其中user是要传入的变量,我们需要指定它如:@PathVariable("user") String user.这种方式以后传入的user变量都会代替user。

@RequestMapping(“/member/get”) 和 @RequestMapping(value="/member/get",method=RequestMethod.POST) 通过区分http不同的方法来定义不同的映射。

拦截器,拦截Web请求进行预先和事后处理, 我们可以为特定的URL映射注册处理程序拦截器,这样它只拦截映射到某些URL的请求。每个处理程序都要实现HandlerInterceptor接口,这个接口包含3个回调方法,preHandle(),postHandle(),afterCompletion()。最后一个方法是在所有请求处理完成之后(也就是显示视图之后)调用的。

如果我们实现了HandlerInterceptor接口的话,即使不需要全部方法也必须实现,因此我们可以使用继承HandlerInterceptorAdapter类来代替。这个类默认实现了所有拦截器犯法,与Java AWT的机制类似,我们需要覆盖哪个方法可以自己覆盖其内容就行了。可以将其配置和DefaultAnnotationHandlerMapping Bean放在一起就可以了。

视图解析器,我们可以在Web应用上下文声明一个或者多个视图解析器Bean,这些Bean必须实现ViewResolver接口,spring自带了很多解析器实现。

InternalResourceViewResolver 将利用前缀和后缀声明将每个视图名称映射到一个应用程序目录中。如下所示:

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

          <property name="order" value="2" />
          <property name="viewClass"     value="org.springframework.web.servlet.view.JstlView" />
          <property name="prefix" value="/WEB-INF/views/" />
          <property name="suffix" value=".jsp" />

</bean>

这个解析器很简单,但是只能解析可内部资源视图,对于外部资源,可以它们声明为Bean,通过加载xml文件来解析的XmlViewResolver,默认加载/WEB-INF/views.xml,但是可以自己指定如:

<bean class="org.springframework.web.servlet.view.XmlViewResolver">

        <property name="location">
                    <value>/WEB-INF/xxx-view.xml</value>
        </property>

</bean>

spring还提供了从资源集中加载视图,这样利用资源集功能从不同的资源集加载用于不同区域的视图Bean。配置如下:

<bean class="org.springframework.web.servlet.view.ResourceBundleViewResolver">

            <property name="basename" value="views"/>
    </bean>

指定了资源集文件名为views.properties,在资源集中我们可以自己定义哪个页面使用哪个解析器了。文件内容大概如下:

welcome.(class)=org.springframework.web.servlet.view.JstlView

welcome.url=/WEB-INF/jsp/welcome.jsp

........

如果我们配置多个视图的话,还需要指定每个视图的优先级顺序,可通过order属性类设置,越低的顺序值代表越高的优先级。spring还提供了内容协商的视图策略,视图解析Bean为ContentNegotiatingViewResolver, 配置mediaTypes属性指定相应的视图解析器。

有时候我们需要导出Excel或者Pdf格式的文件,还需要配置特殊类型的视图解析器,SpringMVC支持Apache POI和JExcelAPI生成Excel文件,对应视图类为AbstractExcelView 和AbstractJExcelView, 支持iText程序库生成pdf文件,视图类是AbstractPdfView。

我们需要自己完成文件的创建过程,调用类库中的API编写我们自己的视图解析器类,可以使用ResourceBundleViewResolver解析器在properties文件中自定义视图解析类,还可同时使用视图内容协商方式。可在拦截器中添加文件的创建日期生成带时间的Excel或Pdf文件。

Spring还提供了标签和SpEL表达式语言,在此就不介绍了因为本人使用的少。

此外,spring还提供了区域解析器Locale resolver来识别用户区域,自带了多个该接口的实现,也可以自己创建一个区域解析器,可通过显示调用LocaleResolver.setLocale()来修改用户区域。如果我们不想为不同区域创建相同页面的不同版本,可以使用spring message来解析文本信息,jsp中使用<spring:messsage>标记来实现。spring还提供了对异常视图的解析,解析器Bean须实现HandlerExceptionResolver接口。而对于文件上传,spring提供了MultipartResolver接口,可以使用CommonsMultipartResolver,其使用Commons FileUpload类库实现。

下面介绍Springmvc常见注解及一些新特性 :

@Controller:用于标识是处理器类;

@RequestMapping:请求到处理器功能方法的映射规则;
@RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;
@ModelAttribute:请求参数到命令对象的绑定;
@SessionAttributes:用于声明session级别存储的属性,放置在处理器类上,通常列出模型属性(如@ModelAttribute)对应的名称,则这些属性会透明的保存到session中;
@InitBinder:自定义数据绑定注册支持,用于将请求参数转换到命令对象属性的对应类型;
@CookieValue:cookie数据到处理器功能处理方法的方法参数上的绑定;
@RequestHeader:请求头(header)数据到处理器功能处理方法的方法参数上的绑定;
@RequestBody:请求的body体的绑定(通过HttpMessageConverter进行类型转换);
@ResponseBody:处理器功能处理方法的返回值作为响应体(通过HttpMessageConverter进行类型转换);
@ResponseStatus:定义处理器功能处理方法/异常处理器返回的状态码和原因;
@ExceptionHandler:注解式声明异常处理器;
@PathVariable:请求URI中的模板变量部分到处理器功能处理方法的方法参数上的绑定,从而支持RESTful架构风格的URI;

JSR-303验证框架的无缝支持(通过@Valid注解定义验证元数据);

ConversionService进行类型转换(PropertyEditor依然有效),支持使用@NumberFormat 和 @DateTimeFormat来进行数字和日期的格式化;
HttpMessageConverter(Http输入/输出转换器,比如JSON、XML等的数据输出转换器);
ContentNegotiatingViewResolver,内容协商视图解析器,它还是视图解析器,只是它支持根据请求信息将同一模型数据以不同的视图方式展示(如json、xml、html等),RESTful架构风格中很重要的概念(同一资源,多种表现形式);
<mvc:annotation-driven>:自动注册基于注解风格的处理器需要的DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter
<mvc:interceptors>:注册自定义的处理器拦截器;
<mvc:view-controller>:和ParameterizableViewController类似,收到相应请求后直接选择相应的视图;
<mvc:resources>:逻辑静态资源路径到物理静态资源路径的支持;
<mvc:default-servlet-handler>:当在web.xml 中DispatcherServlet使用<url-pattern>/</url-pattern> 映射时,能映射静态资源(当Spring Web MVC框架没有处理请求对应的控制器时(如一些静态资源),转交给默认的Servlet来响应静态文件,否则报404找不到资源错误,)。

最好的指南是spring本身的文档,建议多看看文档!

Spring3之MVC的更多相关文章

  1. Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码)

    Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码) 备注: 之前在Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合中 ...

  2. [转]基于全注解的Spring3.1 mvc、myBatis3.1、Mysql的轻量级项目

    摘要 对于现在主流的j2ee企业级开发而言,ssh(struts+hibernate+spring)依然是一个事实的标准.由struts充当的mvc调度控制:hibernate的orm持久化映射:sp ...

  3. Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合

    项目环境背景: 操作系统:win7 JDK:1.7 相关依赖包,截图如下:

  4. spring MVC之返回JSON数据(Spring3.0 MVC)

    方式一:使用ModelAndView的contentType是"application/json" 方式二:返回String的            contentType是&qu ...

  5. Spring3 MVC使用@ResponseBody的乱码问题及解决办法

    近日用Spring3的MVC写东西,深感其之于Webwork/Struts2的便利,但是在通过@ResponseBody这个annotation输出一个json字符串的时候,发现页面上获得的json字 ...

  6. 基于spring mvc的注解DEMO完整例子

    弃用了struts,用spring mvc框架做了几个项目,感觉都不错,而且使用了注解方式,可以省掉一大堆配置文件.本文主要介绍使用注解方式配置的spring mvc,之前写的spring3.0 mv ...

  7. Spring MVC体系结构

    [Spring MVC类图]<Spring实战>中:<Spring3.0就这么简单>中:[http://blog.csdn.net/gstormspire/article/de ...

  8. Spring MVC 注解[转]

    [学习笔记]基于注解的spring3.0.x MVC学习笔记(九) 摘要: 本章节,仅为@SessionAttributes的功能扩展介绍介绍,结合@requestparam注解进行简易无数据库分页. ...

  9. spring MVC做form提交Neither BindingResult nor plain target object for bean name 'command' available

    这两天在做spring3.0 MVC+hibernate3.2的练习中,做简单的form提交, 一直报java.lang.IllegalStateException: Neither BindingR ...

随机推荐

  1. 基于MongoDB分布式存储进行MapReduce并行查询

    中介绍了如何基于Mongodb进行关系型数据的分布式存储,有了存储就会牵扯到查询.虽然用普通的方式也可以进行查询,但今天要介绍的是如何使用MONGODB中提供的MapReduce功能进行查询.     ...

  2. alibaba笔试2

    11. 12.C 13.C 14.C 关联:http://www.codingnow.com/2000/download/lua_manual.html 15.A

  3. sqlserver 2008 R2 分区表测试

    有一张表期中有100多w条数据 程序执行起来比较慢,想用分区表的办法,使查询变快一些. 方案如下 --查看分区信息SELECT * FROM sys.partition_range_values -- ...

  4. MSP430F149流水灯闪烁以及数码管的显示

    今天下午写了一个流水灯闪烁的实验,总的来说,不难,因为这块板子集合的电路图没有上一块那么复杂,所以总的来说,还是比较顺手,开始的时候,出现流水灯没有流转的现象,原来是没有加入延时函数,后来经过调整,结 ...

  5. algorithm: heap sort in python 算法导论 堆排序

    An Python implementation of heap-sort based on the detailed algorithm description in Introduction to ...

  6. STL(pair map set vector priority_queue) poj 3297

    POJ 3297 算法竞赛初级杂烩包 题意:学生选课,没个学生只能选一门课.大写字符是课的名字,小写是人名.如果课程后面有多个相同名字算一个,如果一个人选多门课,则他选不上课,输出课和每门课选课人数 ...

  7. Windows下ffmpeg的完美编译

    纠结了好几天,终于搞定了,小结一下. 1.下载ffmpeg源码,官网 2.编译环境Msys的安装配置,http://blog.csdn.net/jszj/article/details/4028716 ...

  8. POJ1149 PIGS

    想了好久啊...(#-.-) 开始想到m*n个点的构图,明显超时,于是考虑压缩节点个数 我们发现每个猪圈最后被有且只有一个人调整,于是想到对于一个人,连接他能调整的每个猪圈的上一个控制人.(不懂可以开 ...

  9. 基于Qt的P2P局域网聊天及文件传送软件设计

    基于Qt的P2P局域网聊天及文件传送软件设计 zouxy09@qq.com http://blog.csdn.net/zouxy09         这是我的<通信网络>的课程设计作业,之 ...

  10. Uber将在泰国首推"优步摩托"服务

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...