Java SpringMVC基础知识总结《上》

275 阅读6分钟

一 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>