首页 > 技术文章 > SpringMVC框架理解

lone5wolf 2019-05-28 22:54 原文

    JavaEE体系结构包括四层,从上到下分别是应用层、Web层、业务层、持久层。Struts和SpringMVC是Web层的框架,Spring是业务层的框架,Hibernate和MyBatis是持久层的框架。
 
一、 Spring mvc介绍
   SpringMVC框架是以请求为驱动,围绕Servlet设计,将请求发给控制器,然后通过模型对象,分派器来展示请求结果视图。其中核心类是DispatcherServlet,它是一个Servlet,顶层是实现的Servlet接口。
    SpringMVC框架主要由DispatcherServlet、HandlerMapping、Controller、ViewResolver四个接口组成。
  
 1、前端控制器DispatcherServlet:是整个SpringMVC的核心。从名称来看,它是一个Servlet,负责统一分发所有请求。
 
  • 拦截符合特定格式的URL请求
  • 初始化DispatcherServlet上下文对应的WebApplicationContext,并与业务层、持久化层建立联系
  • 初始化SpringMVC的各个组件,并装配到DispatcherServlet中
在web.xml文件中进行配置,负责接收HTTP请求、组织协调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>
          <servlet-mapping>
             <servlet-name>springMVC</servlet-name>
             <url-pattern>/</url-pattern>
          </servlet-mapping>
      </servlet>
如果不指定<param-value>的值,则默认配置文件为/WEB-INF/<servlet-name>-servlet.xml。<load-on-startup>是启动顺序,通常让Servlet跟随Servlet容器一起启动。<url-pattern>定义要拦截的URL请求。
拦截规则:
  • *.xxx,指定要拦截的特定类型,最简单实用的方式,并且不会拦截静态文件
  • /,使用REST风格进行拦截,但是会导致静态文件被拦截不能正常显示
  • /*,不能像Struts那样使用,会导致不能访问jsp
如果使用/进行拦截,并且希望正常访问静态文件,可以在DispatcherServlet之前,使用DefaultServlet先拦截特定类型的请求(如:*.js、*.css等)。

  2、处理器映射HandlerMapping:负责完成请求到控制器的映射。在servlet的配置文件中,进行uri与控制器的映射。同时,还可以对控制器进行拦截。

    (1)配置SpringMVC映射处理器,默认是 BeanNameUrlHandlerMapping直接将uri与实现类进行绑定,书写方便,但是耦合性高。

        <bean id="defaultHandlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
    (2)配置SpringMVC处理器适配器: SimpleUrlHandlerMapping
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>
    (3)配置SpringMVC视图解析器:InternalResourceViewResolver
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"></bean> 

     3、控制器Controller:负责处理用户请求,完成之后返回ModelAndView对象给前端控制器。因为需要考虑并发,所以必须保证线程安全并且可重用。SpringMVC中的Controller与Struts中的Action基本相同。通过实现Controller接口或继承父类的方式编写控制器。

      (1)实现Controller接口
      (2)继承AbstractController类,该类与接口类似,需要重写里边的方法。
      (3)继承MultiActionController类,可以实现多个方法,处理多个请求。
 
   4、视图解析器ViewResolver: 负责对ModelAndView对象的解析,并查找对应的View对象。SpringMVC框架默认通过转发进行页面跳转
     
二、为什么要使用SpringMVC?
   很多应用程序的问题在于处理业务数据的对象和显示业务数据的视图之间存在紧密耦合,通常,更新业务对象的命令都是从视图本身发起的,使视图对任何业务对象更改都有高度敏感性。而且,当多个视图依赖于同一个业务对象时是没有灵活性的。
   SpringMVC是一种基于Java,实现了Web MVC设计模式,请求驱动类型的轻量级Web框架,即使用了MVC架构模式的思想,将Web层进行职责解耦。基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,SpringMVC也是要简化我们日常Web开发。
 
1、MVC模式:
 
 
 
2、SpringMVC架构: SpringMVC是Spring的一部分,如图:
  
          
 
   SpringMVC的核心架构:
     
 
 
 
 

三、具体流程:

  1、将客户端请求提交给DispatcherServlet
  2、根据<servlet-name>-servlet.xml的配置,查找HandlerMapping
  3、通过HandlerMapping找到处理请求的具体Controller
  4、Controller调用业务逻辑处理
  5、处理完成之后,返回ModelAndView对象给DispatcherServlet
  6、通过ViewResolver找到负责显示的具体View
  7、由View将结果渲染到客户端
 
四、核心原理:
   1、用户发送请求给服务器。url:user
   2、服务器收到请求。发现DispatcherServlet可以处理。于是调用DispatcherServlet
   3、DispatcherServlet内部通过HandleMapping检查这个url有没有对应的Controller。如果有则调用Controller
   4、Control开始执行
   5、Controller执行完毕后,如果返回字符串,则ViewResolver将字符串转化成相应的视图对象;如果返回ModelAndView对象,该对象本身就包含了视图对象信息。
   6、DispatcherServlet将执行视图对象中的数据,输出给服务器。
   7、服务器将数据输出给客户端
 
五、 相关jar包含义:
    1、org.springframework.aop.jar   ----->  spring的aop面向切面编程
    2、org.springframework.asm ----->  spring独立的asm字节码生成程序
    3、org.springframework.beans  ----->  IOC的基础实现
    4、org.springframework.context ----->  IOC基础上的扩展服务
    5、org.springframework.core    ----->  spring的核心包
    6、org.springframework.expression ----->  spring的表达式语言
    7、org.springframework.web ----->  web工具包
    8、org.springframework.webmvc  ----->  mvc工具包

六、SpringMVC入门程序:

  (一)基于非注解的  
     1、web.xml
  
               <web-app>
               <display-name>Archetype Created Web Application</display-name>
              <servlet>
        <!-- 加载前端控制器 -->
           <servlet-name>springmvc</servlet-name>
           <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 
       <!-- 加载配置文件 默认加载规范:
             * 文件命名:servlet-name-servlet.xml====springmvc-servlet.xml
             * 路径规范:必须在WEB-INF目录下面 修改加载路径:
         -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>*.do</url-pattern>
  </servlet-mapping>
</web-app>
 
   2、springmvc.xml
    
    <beans> 
        <!-- 配置映射处理器:根据bean(自定义Controler)的name属性的url去寻找hanler;
             springmvc默认的映射处理器是 BeanNameUrlHandlerMapping 
        --> 
      <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"> 
      </bean>
   
            <!-- 配置处理器适配器来执行Controlelr ,
           springmvc默认的是 SimpleControllerHandlerAdapter 
            --> 
      <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter">
      </bean>
 
      <!-- 配置自定义Controller -->
      <bean id="myController" name="/hello.do" class="org.controller.MyController"></bean>
 
      <!-- 配置sprigmvc视图解析器:解析逻辑试图;
           若后台返回逻辑试图:index
           视图解析器解析出真正物理视图:前缀+逻辑试图+后缀====/WEB-INF/jsps/index.jsp
       -->
          <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
               <property name="prefix" value="/WEB-INF/jsps/"></property> 
               <property name="suffix" value=".jsp"></property> 
          </bean> 
     </beans>
 
  3、定义Controller
 
  public class MyController implements Controller{ 
     public ModelAndView handleRequest(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception { 
     ModelAndView mv = new ModelAndView(); //创建视图          
     mv.addObject("hello", "欢迎学习springmvc!"); //设置视图内容 
     mv.setViewName("index"); //返回逻辑视图 
    return mv; 
   } 
}
 
   4、index页面
      <html>
         <body>
            <h1>${hello}</h1>
         </body>
      </html>
 
  5、测试地址:http://localhost:8080/springmvc/hello.do
   
(二)基于注解的
   
     1、web.xml:
       <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>
    </servlet>
    <servlet-mapping>
       <servlet-name>springmvc</servlet-name>
       <url-pattern>/</url-pattern>
    </servlet-mapping>
   
  2、springmvc.xml
    <beans xmlns="http://www.springframework.org/schema/beans"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:context="http://www.springframework.org/schema/context"
     xmlns:mvc="http://www.springframework.org/schema/mvc"
     xmlns:aop="http://www.springframework.org/schema/aop"
     xsi:schemaLocation="http://www.springframework.org/schema/mvchttp://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
 <!-- 配置自动扫描的包 -->
 <context:component-scan base-package="com.cn.mapper"></context:component-scan>
 <!-- 配置视图解析器 -->
 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
   <property name="prefix" value="/WEB-INF/views/"></property>
   <property name="suffix" value=".jsp"></property>
 </bean>
</beans>
3、定义Controller
@RequestMapping(value="/springmvc")
@Controller
public class HelloWorld {
     private static final String SUCCESS = "success";
     
     @RequestMapping(value="/hello")
     public String hello()
     {
          System.out.println("Hello World!");  
          return SUCCESS;
     }
     
     @RequestMapping(value="/testRequest")
     public String testRequestMapping()
     {
          System.out.println("testRequestMapping"); 
          return SUCCESS;
     }
     
     @RequestMapping(value="/testMethod",method=RequestMethod.POST)
     public String testMethod() {   
          System.out.println("TestMethod");
          return SUCCESS;
     }
}
4、index.jsp页面:
    <a href="springmvc/hello">HelloWorld</a>
     <br><br>
     <a href="springmvc/testRequest">TestRequest</a>
     <br><br>
     <form action="springmvc/testMethod" method="post">
       <input type="submit" value="Submit">
     </form>
5、WEB-INF下创建views文件夹用于存放页面文件(success.jsp)
      <h2>Success Page</h2>
6、测试:http://localhost:8080/springmvc/
7、目录结构如下:
附:springMVC中解决中文乱码问题  --- 在web.xml文件中配置过滤器(filter)
  <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> 
        <init-param> 
            <param-name>forceEncoding</param-name> 
            <param-value>true</param-value> 
        </init-param>
  </filter>
  <filter-mapping> 
        <filter-name>characterEncodingFilter</filter-name> 
        <url-pattern>/*</url-pattern> 
  </filter-mapping>

推荐阅读