一 MVC设计模式简介
MVC设计模式(Model-View-Controller)是常见的一种软件架构模式,
该模式把软件系统分为三个基本部分:模型(Model)、视图(View)和 控制器(Controller)
使用MVC模式有很多优势,例如:简化后期对项目的修改、扩展等维护操作;使项目的某一部分变得可以重复利用;使项目的结构更加直观。
具体来讲,MVC模式可以将项目划分为模型(M)、视图(V)和控制器(C)三分部分,并赋予各个部分不同的功能,方便开发人员进行分组。
(1)视图(View):负责界面的显示,以及与用户的交互功能,例如表单、网页等。
(2)控制器(Controller):可以理解为一个分发器,用来决定对于视图发来的请求,需要用哪一个模型来处理,以及处理完以后需要跳回到哪一个视图。即用来连接视图和模型。
实际开发中,通常用控制器对客户端的请求数据进行封装(如将form表单发来的若干个表单字段值,封装到一个实体对象中),然后调用某一个模型来处理此请求,最后再转发请求(或重定向)到视图(或另一个控制器)。
(3)模型(Model):模型持有所有的数据、状态和程序逻辑。模型接受视图数据的请求,并返回最终的处理结果。
1.1 MVC优缺点
1、 MVC的优点
(1) 可以为一个模型在运行时同时建立和使用多个视图。变化-传播机制可以确保所有相关的视图及时得到模型数据变化,从而使所有关联的视图和控制器做到行为同步。
(2) 视图与控制器的可接插性,允许更换视图和控制器对象,而且可以根据需求动态的打开或关闭、甚至在运行期间进行对象替换。
(3) 模型的可移植性。因为模型是独立于视图的,所以可以把一个模型独立地移植到新的平台工作。需要做的只是在新平台上对视图和控制器进行新的修改。
(4) 潜在的框架结构。可以基于此模型建立应用程序框架,不仅仅是用在设计界面的设计中。
2、 MVC的不足之处
(1) 增加了系统结构和实现的复杂性。对于简单的界面,严格遵循MVC,使模型、视图与控制器分离,会增加结构的复杂性,并可能产生过多的更新操作,降低运行效率。
(2) 视图与控制器间的过于紧密的连接。视图与控制器是相互分离,但确实联系紧密的部件,视图没有控制器的存在,其应用是很有限的,反之亦然,这样就妨碍了他们的独立重用。
(3) 视图对模型数据的低效率访问。依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。对未变化数据的不必要的频繁访问,也将损害操作性能。
(4) 目前,一般高级的界面工具或构造器不支持MVC模式。改造这些工具以适应MVC需要和建立分离的部件的代价是很高的,从而造成使用MVC的困难。
二 Spring MVC是什么
1.SpringMVC 是一种基于 Java 的实现 MVC 设计模型的请求驱动类型的轻量级 Web 框架,属于SpringFrameWork的后续产品,已经融合在 Spring Web Flow 中。****
2.SpringMVC = Spring +MVC
- spring mvc类似于struts的一个MVC开框架,其实都是属于spring,spring mvc需要有spring的架包作为支撑才能跑起来.
spring是一个一站式的框架,提供了表现层(springmvc)到业务层(spring)再到数据层(springdata)的全套解决方案;spring的两大核心IOC(控制反转)和AOP(面向切面编程)更是给我们的程序解耦和代码的简介提供了支持。
Spring框架图:
三 创建一个Spring MVC程序
3.1 创建项目需要依赖的jar
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.linpeng</groupId>
<artifactId>SpringDemo</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>SpringDemo Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- spring需要的jar包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.4.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>3.2.4.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4.RELEASE</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.2.4.RELEASE</version>
<type>jar</type>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.8.7</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.7</version>
</dependency>
</dependencies>
<build>
<finalName>SpringDemo</finalName>
</build>
</project>
3.2后台controller测试代码
@Controller
public class HelloController {
/*
* @RequestMapping("/test") public ModelAndView doAndView(){ ModelAndView mv
* =new ModelAndView("hello"); mv.addObject("spring", "spring mvc");
* //mv.setViewName("hello"); mv.addObject("key",new Date()); return mv; }
*
* 拦截 /test 时 会找到 hello.jsp
*/
// 拦截 /hello 时 默认会找到 hello.jsp
@RequestMapping("/hello")
public ModelAndView hello() {
ModelAndView mv = new ModelAndView();
mv.addObject("spring", "spring mvc");
// mv.setViewName("hello");
mv.addObject("key", new Date());
return mv;
}
/*
* http://localhost:8080/SpringDemo/ok
* 对应转到 “hello.jsp”
*/
@RequestMapping("/ok")
public String randomMethodName() {
return "hello";
}
/*
* 四,自动匹配参数
* http://localhost:8080/SpringDemo/param?name=linpeng&age=19
* 跳转到hello.jsp 方法里面会接收到参数name age
* 打印 ====linpeng==19
* */
@RequestMapping("/param")
public String paramMethod(String name,Integer age){
System.out.println("===="+name+"=="+age);
return "hello";
}
/*
* 五、自动装箱
* 创建Student对象 属性名:name,age
* http://localhost:8080/SpringDemo/student?name=linpeng&age=19
* 打印 linpeng 19
*
* ps:前提是Student的属性一定生成要get set否则注入失败
*/
@RequestMapping("/student")
public String student(Student stu){
System.out.println(stu.name+" "+stu.age);
return "hello";
}
/*
* 向前台传递参数
* http://localhost:8080/SpringDemo/show
* show.jsp:<body>hello:${p.name} </body>
*/
@RequestMapping("/show")
public String date(Map<String, Object>map){
Student student = new Student();
map.put("p",student);
student.setAge(20);
student.setName("linpeng");
return "show";
}
/*
* 重定向跳转到show.jsp
*/
@RequestMapping("/redirect")
public String redirect(){
return "redirect:show";
}
/*
* 处理局部异常(Controller内)
* 该控制器里面 捕获异常对应的(跳转error.jsp)处理
*/
@ExceptionHandler
public ModelAndView exceptionHandler(Exception ex){
ModelAndView mv = new ModelAndView("error");
mv.addObject("exception", ex);
System.out.println("in testExceptionHandler");
return mv;
}
//测试上面的异常
@RequestMapping("/error")
public String error(){
int i = (int) (5/0);//抛出异常
return "hello";
}
}
四 Spring MVC和Struts2的区别
4.1. 机制:
spring mvc的入口是servlet,而struts2是filter,这样就导致了二者的机制不同。
4.2. 性能:
spring会稍微比struts快。spring mvc是基于方法的设计,而sturts是基于类,每次发一次请求都会实例一个action,每个action都会被注入属性,而spring基于方法,粒度更细,但要小心把握像在servlet控制数据一样。spring3 mvc是方法级别的拦截,拦截到方法后根据参数上的注解,request数据注入进去,在spring3 mvc中,一个方法对应一个request上下文。而struts2框架是类级别的拦截,每次来了请求就创建一个Action,然后调用setter getter方法把request中的数据注入;struts2实际上是通setter getter方法与request打交道的;struts2中,一个Action对象对应一个request上下文。
4.3 参数传递:
struts是在接受参数的时候,可以用属性来接受参数,这就说明参数是让多个方法共享的。struts更加符合oop(面向对象编程)的编程思想, spring就比较谨慎,在servlet上扩展。
五 Spring MVC视图解析器
5.1 什么是视图解析器
视图解析器是用来接收经过处理器适配器调用具体的controller后生成的逻辑视图的,它接受 DispatcherServlet传过来的ModelAndView,然后将ModelAndView数据填充到相应的视图中,然后返回一个带有数据的视图再传给DispatcherServlet.
5.2 视图解析器的处理流程
1、调用目标方法,SpringMVC将目标方法返回的String、View、ModelMap或是ModelAndView都转换为一个ModelAndView对象;
2、然后通过视图解析器(ViewResolver)对ModelAndView对象中的View对象进行解析,将该逻辑视图View对象解析为一个物理视图View对象;
3、最后调用物理视图View对象的render()方法进行视图渲染,得到响应结果。
5.3 视图解析器返回类型
视图解析器不仅可以返回物理视图,还可以返回一个模板。
它会解析逻辑视图配置,返回一种Freemarker模板或者thymelea模板,该模板负责将数据模型中的数据合并到模板中,从而生成标准的输出,可以生成各种文本,包括HTML,XML,java源码等。
5.4视图解析器的配置
5.4.1.返回物理视图的配置
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp"></property>
<property name="suffix" value=".jsp"></property>
</bean>
5.4.2.返回模板的视图解析器的配置
<!--视图解析器-->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<property name="prefix" value="fm_"></property>
<property name="suffix" value=".ftl"></property>
<property name="order" value="1"></property>
</bean>
<!--模板文件的路径以及其他配置-->
<bean class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<property name="templateLoaderPath" value="/WEB-INF/freemarker"></property>
</bean>
maven依赖
<dependency>
<!--在spring中使用Freemarker这个必不可少,否则报错-->
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>4.3.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.28</version>
</dependency>