Spring MVC

Posted xue_yun_xiang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring MVC相关的知识,希望对你有一定的参考价值。

一、概述

mvc:MVC 设计模式,m(model 模型) v(view 视图) c(controller 控制器)
在这里插入图片描述
springmvc:就是 spring 按照mvc 模式开发的一个轻量级 mvc 框架,。它与Struts2框架一样,都属于MVC框架
Struts2 也是实现 mvc ,但是springmvc 替代Struts2

springmvc 就等价于以前用到的BaseServlet ,BaseServlet用于路径的分发,在springmvc也有类似的Servlet 叫做DispatcherServlet,用于路径分发
区别:整个应用中只有一个DispatcherServlet,不存在其他Servlet

Spring MVC具有以下特点

  • 是Spring框架的一部分,可以方便的利用Spring所提供的其他功能。
  • 灵活性强,易于与其他框架集成。
  • 提供了一个前端控制器DispatcherServlet,使开发人员无需额外开发控制器对象。
  • 可自动绑定用户输入,并能正确的转换数据类型。
  • 内置了常见的校验器,可以校验用户输入。如果校验不能通过,那么就会重定向到输入表单。
  • 支持国际化。可以根据用户区域显示多国语言。
  • 支持多种视图技术。它支持JSP、Velocity和FreeMarker等视图技术。
  • 使用基于XML的配置文件,在编辑后,不需要重新编译应用程序。

2、入门实例

1、创建maven的web工程

在这里插入图片描述
在这里插入图片描述

2、导入依赖

 <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>

    <!--在当前pom 或者父类pom 中声明属性  -->
    <spirng.version>5.0.16.RELEASE</spirng.version>
  </properties>



  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>



    <!--  添加 servlet 依赖 -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>

   <!--  spring 核心-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spirng.version}</version>
    </dependency>

    <!--
        spring  aop
    -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spirng.version}</version>
    </dependency>

    <!--
       spring aop aspectj
    -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.6.12</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.6.12</version>
    </dependency>

  <!--
    spring mvc 相关
  -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spirng.version}</version>
    </dependency>


  </dependencies>

3、配置web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  
  
  <!--
  
    声明DispatcherServlet
   -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
    <!--
      配置该sever 对应的 springmvc 路径
    -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <!--
        路径是  servlet-name-servlet.xml 标准格式 
      
      -->
      <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--
      如果 访问台服务器的资源 找不到对应的路径 ,springmvc servlet
      
      localhost:8080/test  没有
                    将/test 给到 DispatcherServlet ,找对应的 /test 对应处理方法
      
    -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  
</web-app>

4、在resource 下创建springmvc-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--
        在容器加入后端控制器 并设置id 为/hellController
                该控制器中的  public ModelAndView handleRequest()对应 路径为 /hellController
                当前方法 handleRequest() 可以处理前端浏览器发起的请求 localhost:8080/hellController

    -->
    <bean id="/hellController" class="com.qfedu.controller.HellController"></bean>

</beans>

5、创建HellController

/**
 * 创建一个后端控制器 控制类
 *
 * 实现controller
 */
public class HellController implements Controller {


    @Override// handleRequest 处理请求   当前方法就是一个 处理器
    public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws Exception {

        // 封装了 模型 和 视图
        ModelAndView modelAndView = new ModelAndView();

        // 设置视图的路径
        // 从 webapp 下根路径开始算
        modelAndView.setViewName("/hello.jsp");

        //相当于在 httpServletRequest设置 属性
        modelAndView.addObject("msg", "HellController");

        return modelAndView;
    }
}

6、在webapp 创建hello.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" isELIgnored="false" %>
<html>
<head>
    <title>Title</title>
</head>
<body>


msg:${msg}


</body>
</html>

7、添加tomcat运行

在这里插入图片描述

三、springmvc 请求流程

在这里插入图片描述

DistpacherServlet:前端控制器 一个servelt 用来分发请求 相当于BaseServelet
HelloController:后端控制器 一个类 用来处理前端请求
public ModelAndView handleRequest: 处理器(hander) 用来处理前端请求,响应数据
BeanNameUrlHandlerMapping:处理器映射器 map<“路径”,“控制器 及处理器方法 还有参数”>
SimpleControllerHandlerAdapter:处理器适配器 兼容处理器(根据处理器类型不同,调用他方法)
InternalResourceViewResolver:视图解析器 解析处理器返回的结果集 转化为视图jsp

顺序

1、用户发送请求至前端控制器DispatcherServlet。
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器。
3、处理器映射器找到具体的处理器(可以根据xml配置、注解进行查找),生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet。
4、 DispatcherServlet调用HandlerAdapter处理器适配器。
5、HandlerAdapter经过适配调用具体的处理器(Controller,也叫后端控制器)。
6、Controller执行完成返回ModelAndView。
7、HandlerAdapter将controller执行结果ModelAndView返回给DispatcherServlet。
8、DispatcherServlet将ModelAndView传给ViewReslover视图解析器。
9、ViewReslover解析后返回具体View.
10、DispatcherServlet根据View进行渲染视图(即将模型数据填充至视图中)。
11、DispatcherServlet响应用户。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <!--
        在容器加入后端控制器 并设置id 为/hellController
                该控制器中的  public ModelAndView handleRequest()对应 路径为 /hellController
                当前方法 handleRequest() 可以处理前端浏览器发起的请求 localhost:8080/hellController

    -->
    <bean id="/hellController" class="com.qfedu.controller.HellController"></bean>


    <!--
          处理器映射器  map <路径,HellController对象 及处理器方法(handleRequest) >

          如果我们不显示写,容器也会为我们加载
    -->
    <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"></bean>

    <!--
          处理器适配器  兼容各种处理器,调用处理器方法(handleRequest 只是一种处理器)

          插排:墙上插孔只有一个三叉, 如果需要手机充电 需要一个 插排 手机插在插排 两插孔
          以上就是一种适配
                可以驱动 三插  两插 欧规插座
          墙上的插排:只能三插
    -->
    <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"></bean>

    
    <!--
        视图解析器: 作用就是用来解析 处理器返回的结果(ModelAndView ) 转换为视图(jsp)   
        
        如果我们不显示写,容器也会为我们加载 
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        
    </bean>
</beans>

在这里插入图片描述

4、springmvc 核心类 及注解

DispatcherServlet

DispatcherServlet:前端控制器,是整个springmvc 的中枢,负责路径分发道不同的处理器,需要在web.xml声明

  <!--
  
    声明DispatcherServlet
   -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
    <!--
      配置该sever 对应的 springmvc 路径
    -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <!--
        路径是  servlet-name-servlet.xml 标准格式 
      
      -->
      <param-value>classpath:springmvc-servlet.xml</param-value>
    </init-param>
  </servlet>
  
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <!--
      如果 访问台服务器的资源 找不到对应的路径 ,springmvc servlet
      
      localhost:8080/test  先找对应的Servlet 没有
                    将/test 给到 DispatcherServlet ,找对应的 /test 对应处理器方法
                    
      / 再找不到其他路径时的 默认处理 叫给DispatcherServlet
    -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

@Controller注解

实现处理器两种方式
1.实现Controller接口 重写 public ModelAndView handleRequest(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
2.创建一个类使用 @Controller 标记 在其内部的方法中使用 @RequestMapping 标记方法,这个方法就是处理器

/**
 * 第一个 控制器
 */
@Controller // 1.将当前类加入到容器 2.标记当前类是一个 控制器 类
public class FirstController {



//    @RequestMapping("/test1") // 标记当前方法是处理器  对应路径 为 /test1
//    @RequestMapping(value = {"/test1_a","/test1_b"}) // 为当前处理器配置多个路径
//    @RequestMapping(path = {"/test1_c","/test1_d"}) // 为当前处理器配置多个路径 path value 不能同时设置
    @RequestMapping(path = {"/test1_c","/test1_d"},method = {RequestMethod.POST}) // 当前处理器支持 get post
    public ModelAndView test1(){


        ModelAndView modelAndView = new ModelAndView();

        modelAndView.setViewName("/hello.jsp");
        modelAndView.addObject("msg", "test1");

        return modelAndView;
    }
}

激活mvc 功能

  <!--
        包扫描器 将com.qfedu.controller 所有 生成bean的注解 和 注入属性的注解 生效
    -->
    <context:component-scan base-package="com.qfedu.controller"></context:component-scan>

    <!--
        激活 注解mvc 相关功能
    -->
    <mvc:annotation-driven></mvc:annotation-driven>

在这里插入图片描述

@RequestMapping

两种用法
标记在方法上 ,该方法就是一个处理器 必须的写
标记在类上,所有访问该控制器下的处理器 都必须补全当前@RequestMapping 内的路径
​ 可以不写

/**
 * 第一个 控制器
 */
@Controller // 1.将当前类加入到容器 2.标记当前类是一个 控制器 类
@RequestMapping("/first") // 标记在控制器上面 所有访问该 控制器下的处理器路径时都必须补全当前 @RequestMapping("/first")
                            // /first/test1_c   /first/test2
public class FirstController {



//    @RequestMapping("/test1") // 标记当前方法是处理器  对应路径 为 /test1
//    @RequestMapping(value = {"/test1_a","/test1_b"}) // 为当前处理器配置多个路径
//    @RequestMapping(path = {"/test1_c","/test1_d"}) // 为当前处理器配置多个路径 path value 不能同时设置
    @RequestMapping(path = {"/test1_c","/test1_d"},method = {RequestMethod.POST}) // 当前处理器支持 get post
    public ModelAndView test1(){


        ModelAndView modelAndView = new ModelAndView();

        modelAndView.setViewName("/hello.jsp");
        modelAndView.addObject("msg", "test1");

        return modelAndView;
    }

    @RequestMapping("/test2") // 标记在方法上 该方法就是一个处理器
    public ModelAndView test2(){


        ModelAndView modelAndView = new ModelAndView();

        modelAndView.setViewName("/hello.jsp");
        modelAndView.addObject("msg", "test2");

        return modelAndView;
    }

}

组合注解

Spring框架的4.3版本中,引入了新的组合注解,来帮助简化常用的HTTP方法的映射,并更好的表达被注解方法的语义。

  • @GetMapping:匹配GET方式的请求;
  • @PostMapping:匹配POST方式的请求;
  • @PutMapping:匹配PUT方式的请求;
  • @DeleteMapping:匹配DELETE方式的请求;
  • @PatchMapping:匹配PATCH方式的请求。
    在这里插入图片描述
//    @RequestMapping(value = "/test3",method = RequestMethod.GET) // 表明当前处理器支持 get 请求
    @GetMapping("/test3") // 复合注解  等价于  @RequestMapping(value = "/test3",method = RequestMethod.GET)
    public ModelAndView test3(){


        ModelAndView modelAndView = new ModelAndView();

        modelAndView.setViewName("/hello.jsp");
        modelAndView.addObject("msg", "test3");

        return modelAndView;
    }

    @PostMapping("/test4")// 复合注解 当前请求支持 post 请求
    public ModelAndView test4(){


        ModelAndView modelAndView = new ModelAndView();

        modelAndView.setViewName("/hello.jsp");
        modelAndView.addObject("msg", "test4");

        return modelAndView;
    }

请求处理方法自带的参数和返回类型

处理器返回值类型有三种
ModelAndView: 数据和视图的混合体
String : 返回字符串
​ jsp路径
​ 以 forward:/路径 转发
​ 以redirect:/路径 重定向
void: 没有返回值

处理器方法 中默认传递的参数:

javax.servlet.ServletRequest / javax.servlet.http.HttpServletRequest  请求相关
javax.servlet.ServletResponse / javax.servlet.http.HttpServletResponse  响应相关
javax.servlet.http.HttpSession  会话先关
java.util.Map / org.springframework.ui.Model /org.springframework.ui.ModelMap  和request中属性相关

    /**
     *
     * Map map
     * Model map
     * ModelMap map
     *  都是向request 中添加属性
     *
     *
     * @param request
     * @param map
     * @return
     */
    @RequestMapping("/test5") // 当前处理器中的 默认参数如果写了 Dispatcher 调用是会给传进来
    public String test5(HttpServletRequest request, Model model){

        // 在请求中写入属性
//        request.setAttribute("msg", "test5");

        // 相当于 request.setAttribute("msg", "test5");

//        ModelMap map
//         map.put("msg", "test5");

        model.addAttribute("msg", "test5");

        // jsp 路径
        return "/hello.jsp";
    }

    /**
     * 没有返回结果
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("/test6") // 当前处理器中的 默认参数如果写了 Dispatcher 调用是会给传进来
    public void test6(HttpServletRequest request, HttpServletResponse response) throws IOException {

        //从请求得到 参数
        String msg = request.getParameter("msg");

        response.getWriter().write("/test6-msg:"+msg);

    }


    /**
     * 返回字符串  以forward:开头进行转发
     * @return
     */
    @RequestMapping("/test7")
    public String test7(){

        // 转发到 test6 处理器中
        return "forward:/first/test6";
    }



    /**
     * 返回字符串  以redirect:开头进行重定向
     * @return
     */
    @RequestMapping("/test8")
    public String test8(){

        // 转发到 test6 处理器中
        return "redirect:/first/test6";
    }

在这里插入图片描述
在这里插入图片描述

ViewResolver视图解析器

视图解析器:作用就是将处理器返回的数据(String ModelAnView)转换视图
​ 附件功能 可以为我们自动补全 jsp 的路径

 <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!--
            后续所有 处理器返回的 jsp 路径 会自动补全前缀和后缀

            配置jsp 路径前缀  /jsp/
            /jsp/message.jsp
           -->
        <property name="prefix" value="/jsp/"></property>

        <!--
            配置jsp 路径后缀
        -->
        <property name="suffix" value=".jsp"></property>
    </bean>

常见错误:
在这里插入图片描述

5、数据绑定介绍

数据绑定 就是处理器如何接受 前端传递的数据
在这里插入图片描述

接受基本类型参数

  /**
     *
     * int id  接受基本类型数据
     * @param id
     * @param model
     * @return
     */
    // http://localhost:8080/findStudentById?id=100  id 必须传递 否则有类型转换错

以上是关于Spring MVC的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC 教程

ASP.net MVC 代码片段问题中的 Jqgrid 实现

spring 国际化 js怎么设置

通过 Spring MVC 框架包含其他 JSP 是个好主意吗?

java代码spring-mvc模式怎样实现从后台直接定时发送邮件

Spring MVC异常处理代码完整实例